Re-engineering the th06 Chassis: Ripping Out D3D8 for SDL2/OpenGL
Up front: I didn’t write this from scratch. It’s a fork of happyhavoc/th06, a project where a group of people ground through the binary and reverse-engineered the source of Touhou: Embodiment of Scarlet Devil v1.02h byte by byte. The reverse engineering credit is entirely theirs. I did exactly one thing: tore out the low-level Direct3D 8 / Win32 stack and swapped in SDL2 + OpenGL.
Why touch it. The original project aims to be “byte-for-byte identical to the original exe,” so it faithfully carries that 2002-era antique stack: D3D8 for rendering, DirectSound for audio, Win32 for windowing. I respect the rigor, but the cost is being nailed to old Windows. It runs awkwardly even on my own machine, let alone Linux. Scarlet Devil’s logic isn’t complicated; the bottleneck is entirely in those few antique APIs, which makes it a perfect target for a “chassis swap” experiment.
The approach is to abstract the platform-dependent parts into interfaces, each with its own implementation. Rendering: D3D8 out, SDL2 + OpenGL in, with desktop running plain OpenGL. I also wrote an OpenGL ES 2.0 backend, RendererGLES, that uses an FBO for full-screen scaling to lean toward mobile, all sitting under an IRenderer abstraction. Audio: DirectSound out, SDL2_mixer in; textures handed to SDL2_image; windowing and frame timing folded into GameWindow. I also threw in runtime encoding detection: the program figures out GBK vs Shift-JIS on its own, so there’s no need to build separate versions for the Chinese and Japanese releases. For the practice side, I hooked up a thprac overlay, so stage select and debugging work out of the box.
Build moved to CMake. On Windows the SDL2 libraries drop into 3rdparty/ and link automatically; on Linux you just install them through the system package manager.
# Windows (Win32, GLES renderer enabled)
cmake -B build_sdl2 -A Win32 -DUSE_GLES=ON
cmake --build build_sdl2 --config Release
To run it you still need the original data (the 東方紅魔郷.exe v1.02h set) placed next to the executable. This is just a shell with a new engine; the assets are still ZUN’s originals. Right now Windows (x86/x64) and Linux (x86/x64 GLES) run; Android is still a work in progress.
Honest disclosure: this pile of C++ grunt work, API replacement, and rendering stitching leaned heavily on LLM assistance. Read the commits and you’ll probably catch the AI smell. I’m not hiding it. What I care about isn’t how pretty the code is, it’s whether the idea holds up: decoupling the reverse-engineering work from the antique APIs so it can run flat out with OpenGL acceleration on modern hardware. It runs now, so the experiment counts as a success. The game itself belongs to ZUN, the reverse-engineered source belongs to happyhavoc/th06, and I just swapped out the chassis while standing on other people’s shoulders.