Repository navigation
Reference Projects PSXRecomp
| Repo | mstan/psxrecomp |
| Author | Matthew Stan |
| License | PolyForm Noncommercial 1.0.0 |
| Console | PlayStation 1 |
| Reference game | Tomba! (SCUS-94236) — playable end-to-end (gameplay + menu + FMV + audio) |
| Local clone | PS1Recomp-workspace/psxrecomp/ |
The closest project to ours architecturally — another PS1 static recompiler, with a fully functional game shipping on top of it (TombaRecomp). Different threading model and stub strategy, but a goldmine of practical patterns.
psxrecomp/
recompiler/ MIPS → C (exe → serial_full.c + serial_dispatch.c)
runner/ Native runtime (linked by the game project)
src/
runtime.c Memory map, BIOS stubs, fiber scheduler
gpu_interpreter.cpp GP0/GP1 parser
opengl_renderer.cpp OpenGL 3.3 backend
gte.cpp GTE coprocessor
spu.cpp 24-voice ADPCM
xa_audio.cpp XA-ADPCM streaming
fmv_player.cpp STR v2 FMV decoder (via FFmpeg)
cdrom_stub.cpp Just opens the ISO and reads sectors
overlay_manager.cpp Overlay management
main_runner.cpp GLFW loop, frame throttling
tools/
pcsx_redux_mcp/ MCP server for PCSX-Redux
Each game is its own repository that uses psxrecomp as a submodule and
exposes a game_extras.h interface (display thread entry, EXE filename,
expected CRC, per-frame hook).
| Aspect | psxrecomp | ps1-recomp |
|---|---|---|
| Target | Windows (Win32 Fibers, MinGW) | Linux (pthreads) |
| Threading | Cooperative fibers (4 native fibers) | Multithreading + drainPendingCallbacks
|
| BIOS | Inline stubs in runtime.c
|
Separate bios.cpp module |
| Overlays | Embedded MIPS interpreter for non-compiled addresses |
OverlayManager with separate dispatch |
| Recompiler |
rabbitizer + ELFIO |
Custom MIPS decoder (rabbitizer lacks GTE) |
| GPU backend | OpenGL 3.3 | OpenGL 3.3 |
| MIPS decoder | rabbitizer |
Custom |
PSX TestEvent returns "fired" immediately. On real hardware it would
wait; psxrecomp returns 1, which breaks the CdInit retry loop. We do the
same — see Architecture-BIOS.
The GPU always reports ready (bits 28/27/26 = GP0 ready, DMA ready, ready). A non-ready response would loop the game polling.
Scratchpad (0x1F800000-0x1F8003FF) must be a separate 1 KB buffer, not
g_ram[addr & 0x1FFFFF] — that would alias the low end of RAM and corrupt
both. See Architecture-Runtime.
In psxrecomp, every time the display fiber yields to main = 1 VBlank.
That's more reliable than time-based counting. We use a dedicated VBlank
thread that increments psyq_state().vsyncCounter at 60 Hz; same result,
different mechanism. See Architecture-Integration.
psxrecomp lets each game ship a CSV mapping addresses to comments that
appear in the generated C as /* [NOTE] */. We do not have this — TODO
worth considering once we have more games.
psxrecomp's spu.cpp has a working 24-voice ADPCM decoder with proper
loop / end-of-sample handling. When we tackle the SPU accuracy gap
(envelope, reverb, pitch modulation) this is a primary reference. See
Architecture-SPU.
xa_audio.cpp handles streaming compressed audio off the disc. We do not
have this yet; relevant for any title that uses CD-DA-style BGM (Tomba,
Crash level music).
runtime.c saves to C:\temp\memcard\ — basic but functional. We have no
memcard UI yet (the save-state machinery exists in save_state.cpp but is
not surfaced).
F6 saves RAM + VRAM; F7 restores. Enables test automation — capture a known-good state, run, diff. Worth adopting.
PolyForm Noncommercial 1.0.0 — free for non-commercial use with attribution. We can study and learn from it; we cannot copy code directly. All borrowed patterns are re-implemented from scratch (clean-room) here.
ps1-recomp • Licensed under GPL v3 • Current release: v0.1.0-alpha