A reusable stack for PC ports of decompiled PlayStation games: the host runtime (memory arena, overlay manager, interrupt pump, software and hardware rendering, SPU, input, memory cards, settings, crash reports, debug channel, save states), a Psy-Q shim, a launcher (SDL3, Dear ImGui) with mod manifests, and the build and packaging scripts. A game repo (a matching decompilation) adds a small adapter and gets a Linux and Windows port, a launcher and a release.
It grew out of the Digimon World 2003 decompilation's port/ and
launcher/, which consume it as a git submodule since v0.1.0.
Status: v0.3.6 (a write_mem script step, a clean fiber stack under ASan; v0.3.5 a game that needs its disc says so in game.json; v0.3.4 the launcher self-test's rate, the GPU's known differences; v0.3.3 LIBC2's rand and the nominal rates; v0.3.2 a checkpoint without an image; v0.3.1 brought the second game's shim: LIBGTE, LIBGPU, LIBGS, LIBAPI, LIBCD, LIBSND, LIBCARD; v0.3.0 brought
an optional heap, the stack's own Psy-Q declarations, fibers for a game's tasks, the replay runners; v0.2.0 brought the hardware renderer on D3D12, sub-pixel precision, filters,
texture packs, a wide canvas and save states). Everything a game needs is here: the contract (docs/GAME_CONTRACT.md), the game description
and its generator (schema/game.schema.json, tools/game_gen.py), the runtime and the Psy-Q shim (runtime/,
psyq/), the build (cmake/psxstack.cmake), the launcher (launcher/), the tools and the docs. One game builds on
it so far; the second will widen the shim and the contract (releases follow semver, PSXSTACK_API counts
incompatible contract changes).
scripts/setup.sh sdl3 imgui # or scripts/dev_link_tools.sh ../dw2003recomp/tools to reuse built tools
cmake -S launcher -B build/launcher -G Ninja [-DPSXSTACK_GAME_JSON=path/to/game.json] && cmake --build build/launcher
SDL_VIDEO_DRIVER=offscreen build/launcher/dw2003-launcher --self-test build/selftest
python3 tests/game_gen_test.py # the description generator's test
python3 tests/psyq_test.py [--sanitize] # the shim's LIBGTE and LIBGPU functions on their own| Path | Contents |
|---|---|
runtime/ |
The host runtime (C): arena, overlay manager, pump, video, the hardware renderer, SPU, audio, input, memory cards, settings, mods engine, json, sha1, crash report, debug channel, frame log, platform, reset, save states, fibers (a game's own tasks) |
include/psxstack/ |
The hook macros' host side (hooks.h), the adapter interface (game.h, mods.h), the Psy-Q declarations the shim implements (psyq/), the runtime's headers |
psyq/ |
The Psy-Q shim: one file per library, plus the hardware models gpu.c, gte.c, mdec.c, xa.c; check.sh. Its declarations are include/psxstack/psyq/*.h |
shaders/ |
The hardware renderer's HLSL (DXC to SPIR-V, for Windows also DXIL, at build time) |
mods/fast_forward/ |
The one mod every game has |
launcher/ |
The launcher (C++): settings, disc check, mods, input bindings, self-test; branding from the game description |
cmake/ |
psxstack.cmake (psxstack_add_game()), version.cmake, embed.cmake, windows-x86_64.cmake (the llvm-mingw toolchain) |
windows/ |
The game's Windows resource and manifest templates |
tools/ |
game_gen.py (the description to a header), port_gen.py (the build's generators), port_inventory.py (the host-compile gate, configured by a game), psyq_decls.py (a game's Psy-Q declarations against the stack's), replay/ (the emulator and port replay runners a game configures: emulator.py, run.lua, boot_check.lua, port_test.py, redux.sh), mcp/ (the debug channel's MCP server, client and symbols) |
scripts/ |
setup.sh (SDL3, ImGui, DXC, llvm-mingw, SDL3 for Windows, cmake), dev_link_tools.sh |
schema/ |
game.schema.json: the game description |
examples/ |
dw2003.game.json (the first game's description); hello/, a disc-free Psy-Q program built through the stack: its smoke test; tasks/, the same with its work in tasks on the stack's fibers |
docs/ |
GAME_CONTRACT.md, PORT.md, RUNTIME.md, LAUNCHER.md, DECISIONS.md, THIRD_PARTY.md |
tests/ |
The stack's own tests: hello_test.py, tasks_test.py (the fibers, with save states), game_gen_test.py, psyq_test.py (the shim's LIBGTE and LIBGPU, its C in tests/psyq/), shim_test.py (the shim's deterministic pieces on their own: events, the memory card's BIOS calls, CdSearchFile; its C in tests/shim/), the launcher's fixtures (launcher --self-test, tools/mcp/selftest.py) |
include(psxstack/cmake/psxstack.cmake) # the submodule, pinned at a tag
psxstack_add_game(mygame GAME_JSON port/game/game.json UNITS build/gen/units.txt MAIN_UNIT src/main.c
OVERLAYS build/gen/overlays.txt INCLUDE_DIRS include . ADAPTER port/game/state.c ...)cmake/psxstack.cmake documents every argument; docs/GAME_CONTRACT.md what the game provides; examples/hello is
the smallest consumer (examples/tasks the same with its work in tasks on the stack's fibers), dw2003recomp's
port/CMakeLists.txt the first real one. The launcher is its own project:
cmake -S psxstack/launcher -B build/launcher -DPSXSTACK_GAME_JSON=... -DPSXSTACK_VERSION_ROOT=....
Built in five phases out of dw2003recomp's port (its docs/DECISIONS.md "The port stack lives in psxstack"): the
contract first, the port split in place behind it, the runtime and the launcher moved here against a scratch copy
of the game, the game converged on the submodule, then v0.1.0. docs/DECISIONS.md has the decisions.
MIT (LICENSE). The stack contains no game code and no game data.