# PS1Recomp **Static recompiler for PlayStation 1 games -- translates MIPS R3000A machine code to native C++ for PC.** ## Overview PS1Recomp converts PS1 game binaries into native PC executables through static recompilation. Instead of interpreting each MIPS instruction at runtime like a traditional emulator, it translates the entire game binary to C++ at compile time and links it against a hardware simulation runtime. The result is a standalone native executable that runs at full CPU speed. ``` PS1 ISO/BIN | v ps1Analyzer -> game_config.toml (function boundaries, PsyQ signatures) | v ps1Recomp -> recompiled_out.cpp (MIPS -> C++, ~150k lines per game) | v ps1Runtime -> Native PC executable (SDL2 + OpenGL) ``` ## Architecture | Component | Directory | Description | |-----------|-----------|-------------| | **ps1Analyzer** | `ps1Analyzer/` | Parses PS1 ELF/BIN, detects function boundaries, identifies PsyQ SDK signatures, generates TOML config | | **ps1Recomp** | `ps1Recomp/` | Decodes MIPS R3000A instructions and emits literal C++ translation (1:1 per instruction), handles GTE coprocessor and jump tables | | **ps1Runtime** | `ps1Runtime/` | Simulates PS1 hardware: BIOS HLE, GPU (OpenGL 3.3), SPU (SDL2 audio), CD-ROM, DMA, GTE, MDEC, Timers, Input | | **ps1Interface** | `ps1Interface/` | GUI studio for loading ELFs, exploring functions, editing configs, and previewing recompiled C++ (ImGui + SDL2) | | **ps1Test** | `ps1Test/` | 557 unit + integration tests covering all runtime subsystems | ## Project Structure ``` ps1-recomp/ +-- ps1Analyzer/ ELF parser, function finder, PsyQ signature DB, disc reader +-- ps1Recomp/ MIPS decoder, C++ emitter, GTE emitter, overlay handler +-- ps1Runtime/ Full PS1 hardware simulation + SDL2/OpenGL host | +-- src/ | +-- bios/ BIOS HLE (syscall tables A/B/C, heap, events, file I/O) | +-- cdrom/ CD-ROM emulation (ISO 9660, CUE/BIN, virtual FS) | +-- gpu/ GPU state machine + OpenGL renderer | +-- spu/ Sound Processing Unit (24-voice ADPCM) | +-- mdec/ Motion Picture Decoder (FMV video) | +-- dma/ DMA controllers (Ch0-Ch6) | +-- timers/ Hardware timers | +-- psyq/ PsyQ middleware HLE (VSync, DrawSync, DrawOTag, etc.) | +-- main_host.cpp SDL2 host: game loop, input, VBlank thread +-- ps1Interface/ GUI studio (ImGui docking): ELF explorer, function inspector, | | C++ preview, config editor, Ghidra CSV import | +-- include/ | | +-- StudioState.hpp Async state management (analysis, config, exports) | | +-- GUI.hpp 4 dockable panels + menu bar | | +-- ui/StyleManager.hpp Dark/Light/Custom themes and font scaling | +-- src/ | +-- main.cpp SDL2 + OpenGL3 entry point with ImGui docking | +-- StudioState.cpp ps1Analyzer backend integration | +-- GUI.cpp Panel rendering and keyboard shortcuts | +-- ui/StyleManager.cpp +-- ps1Test/ Unit tests (GTest): 557 tests across all subsystems +-- third_party/ External dependencies: ELFIO, toml11, fmt, googletest +-- tools/ | +-- extract_psyq_signatures.py Build the PsyQ signature DB from PsyQ SDK .LIB files | +-- psyq_lib_extract.py Split SN Systems .LIB archives into per-function .OBJ | +-- ps1_mcp_server.py MCP server for AI-assisted debugging | +-- run_and_report.py Automated game diagnostics (VRAM, frame rate, logs) | +-- validate_game.py Pixel-content validation against a frame budget | +-- demo_build.sh Quick-start demo script | +-- ghidra/ Ghidra integration scripts | | +-- ExportPS1Functions.py Export function list from Ghidra to CSV | | +-- ExportPS1Functions.java Same, Java version (headless mode) | | +-- start_ghidra_mcp.sh Launch Ghidra with GhidraMCP on port 8080 | +-- pcsx_redux_mcp/ PCSX-Redux emulator integration (MCP server) +-- .github/workflows/ci.yml CI/CD: build + test on every push +-- CMakeLists.txt C++20 / CMake 3.20+ build system +-- LICENSE GPLv3 ``` ## Building ### Prerequisites ```bash # Ubuntu / Debian sudo apt install cmake build-essential libsdl2-dev libgl-dev # macOS brew install cmake sdl2 ``` ### Clone and Build ```bash git clone --recurse-submodules https://github.com/Dellareti/ps1-recomp.git cd ps1-recomp cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc) ``` ### Build with GUI Studio (optional) ```bash cmake -B build -DCMAKE_BUILD_TYPE=Release -DPS1RECOMP_BUILD_INTERFACE=ON cmake --build build -j$(nproc) ./build/ps1Interface/ps1Interface ``` ### Run Tests ```bash ctest --test-dir build --output-on-failure -j$(nproc) ``` ## Running a Game (Rayman example) > **Note:** Game disc images (ROMs/ISOs) are not included in this repository for legal > reasons. You need your own legal copy of the game. The disc path is configured per-game > and can point to **any folder on your system** -- there is no required directory name. 1. Place your disc image anywhere and note the path: ``` # Example paths -- use whatever works for you: /home/user/games/Rayman (USA).cue ~/roms/Rayman (USA).cue ./my_games/Rayman (USA).cue ``` 2. Analyze the binary and generate config: ```bash ./build/ps1Analyzer/ps1Analyzer "/path/to/Rayman (USA) (Track 01).bin.boot.exe" rayman_config.toml ``` 3. Edit `rayman_config.toml` to set your disc path: ```toml [disc] cue_path = "/path/to/Rayman (USA).cue" ``` 4. Recompile MIPS -> C++: ```bash ./build/ps1Recomp/ps1Recomp rayman_config.toml ps1Runtime/src/recompiled_out.cpp ``` 5. Build and run: ```bash cmake --build build -j$(nproc) ./build/ps1Runtime/ps1Runtime --config rayman_config.toml ``` ## Controls The keyboard stands in for a PS1 digital pad. The runtime prints this table on startup, so it is always visible in the log of a run. | Keyboard | PS1 pad | Keyboard | PS1 pad | |---|---|---|---| | Arrow keys | D-Pad | Q | L1 | | Z | Cross | W | R1 | | X | Circle | E | L2 | | A | Square | R | R2 | | S | Triangle | C | L3 | | Enter | Start | V | R3 | | Right Shift or Backspace | Select | Esc | quit | Each press is echoed to stderr as `[pad] ->