Sabitlenmiş Tweet
龙紫熏Torn | Lóng Zĭxūn
14K posts

龙紫熏Torn | Lóng Zĭxūn
@LugiAXETomXV
純日本人です。 呼び名:トム&トロン ドラゴンとイルカと爬虫類好き。 4カ国語いける人。 創作垢🎨: @Lave_KunewRyu VRCID:龙紫熏Torn
Nagano / Aichi Katılım Mayıs 2020
562 Takip Edilen485 Takipçiler
龙紫熏Torn | Lóng Zĭxūn retweetledi

Steam Machineの価格計画は、Steam Deckの値上げより先に崩れていた。
リーカーのブラッド・リンチ氏が2カ月前に聞いた内部目標は、すでにSteam Deck OLED(現在949ドル)を超えていたという。
AI需要でメモリ価格が高騰し、Valveのハードウェア計画を圧迫している。
「手頃なリビングルームPC」で出せるのか。
Valveの沈黙は続く。
joho-todai.com/steam-machine-…
Brad Lynch@SadlyItsBradley
Take this with a grain of salt, because it was just whispers in my ear But back when I was told a figure for what Valve’s estimated price they’d have to set the starting price of Steam Machine, it was still higher than today’s Steam Deck prices.. And that was 2 months ago..
日本語


One day, I tried to open Minecraft Note Block Studio, but nothing appeared on screen.
At first, it looked like the application simply failed to launch. However, when I checked Task Manager, the process was definitely running in the background. The program existed, but the main window never appeared.
Reinstalling did not help. Restarting did not help. The app would “run”, but it would never become usable.
After some debugging, I found that the problem was not really in the UI startup code itself.
Note Block Studio is built with GameMaker, and it uses an external native DLL for MIDI input: `midiinput.dll`.
That DLL talks to the Windows legacy MIDI API, WinMM, through functions such as `midiInOpen()`.
When I attached WinDbg to the stuck process, the call stack pointed toward MIDI initialization.
The process was entering `midiInOpen()`, then going into the newer Windows MIDI Services path on recent Windows 11 builds. In my case, it ended up waiting inside the MIDI service initialization path and never returned.
So the visible symptom was:
“The process is running, but no window appears.”
But the actual cause was closer to:
“The application is blocked while initializing MIDI input.”
This also explained why the issue seemed related to MIDI devices, old MIDI drivers, virtual MIDI devices, or recent Windows MIDI Services changes.
The app was not necessarily crashing. It was hanging before it could finish startup and show the window.
A temporary workaround was to disable Windows MIDI Service, but that is not a great long-term fix because it affects the whole system and may break other MIDI applications.
So I looked at the original `midiinput.dll`.
The original DLL was written in C++ and came from:
github.com/stuffbydavid/m…
It worked as a lightweight GameMaker MIDI input bridge, but the risky area was exactly the kind of code where manual lifetime and threading mistakes are easy:
- WinMM device handles
- asynchronous MIDI callbacks
- hot-plug cleanup
- shared state accessed from both the WinMM callback thread and the GameMaker thread
- raw pointers and callback instance data
My goal was not to change the API that Note Block Studio sees.
Instead, I wanted to keep the same GameMaker-facing exported function surface, while replacing the internals with a safer and more predictable implementation.
In other words, from GameMaker’s point of view, it should still be the same `midiinput.dll`.
Internally, however, the device management, callback state, and cleanup behavior are rewritten.
The replacement DLL is written in Rust.
The main reason I chose Rust was not just “because Rust is cool”.
The bug-prone parts of this DLL are mostly about ownership, lifetime, shared mutable state, and cleanup order. Those are exactly the areas where Rust gives stronger guarantees than C++ by default.
WinMM FFI still requires `unsafe` code. There is no way around that when calling low-level Windows APIs.
But the unsafe boundary can be kept small.
In the Rust version, the device state is managed with Rust types such as `Arc` and `Mutex`.
That means the MIDI callback thread and the GameMaker thread no longer freely mutate shared state without synchronization.
Each MIDI input device owns its own state, and the callback receives a stable pointer to that state rather than relying on fragile indexing into a vector.
This reduces the chance of lifetime bugs when devices are added or removed.
I also fixed cleanup behavior.
When a MIDI device disappears, the replacement DLL calls:
- `midiInStop`
- `midiInReset`
- `midiInClose`
This is important because `midiInClose()` can wait for callbacks to finish, and `midiInReset()` helps ensure no callbacks remain pending.
The goal is to avoid leaving a half-open MIDI device or a callback that can still touch invalid state.
Another difference is pitch wheel handling.
The original implementation appeared to use only part of the pitch wheel data. MIDI pitch wheel messages are 14-bit values, using both data bytes.
The Rust version combines them correctly:
`(data2 << 7) | data1`
So the returned value is `0..16383`, with center at `8192`.
The important part is that this is still a native DLL.
I also considered C#, but for this specific use case, Rust is a better fit.
This DLL needs to be loaded by GameMaker as a native external library. It should expose a C ABI, be small, have minimal runtime dependencies, and behave like the original DLL.
C# would introduce more complexity around .NET runtime requirements, NativeAOT, and unmanaged exports.
Rust can produce a small `cdylib` with no managed runtime dependency, which makes it much easier to use as a drop-in replacement.
So the final result is:
- same GameMaker-facing DLL API
- rewritten internal MIDI device handling
- less risky memory and lifetime management
- synchronized callback state access
- proper device cleanup
- corrected pitch wheel value
- no .NET runtime dependency
- built as a 32-bit Windows DLL for GameMaker compatibility
I published the replacement DLL here:
github.com/TomXV/midiinpu…
The release asset is built by GitHub Actions, not manually uploaded from my local machine.
The project itself is here:
github.com/TomXV/midiinput
In short:
I ran into a case where Note Block Studio was running in the background but never opened a window.
Debugging showed that the startup was blocked around MIDI initialization, likely due to the interaction between legacy WinMM MIDI APIs and newer Windows MIDI Services behavior.
Instead of only applying a small patch to the original C++ DLL, I rewrote the DLL in Rust while keeping the same external API.
The reason was practical: this code sits exactly at the intersection of native handles, callbacks, shared mutable state, and cleanup order. Rust gives a stricter structure for those parts while still allowing a small unsafe FFI boundary where WinMM calls are required.
English







