# tpm-decomp A decompilation of **Star Wars Episode I: The Phantom Menace** for the PlayStation (Big Ape Productions / LucasArts, 1999), USA Rev 1 (`SLUS_008.84`). Two goals, in this order: 1. a **matching** decompilation: C that compiles with the original compiler (PSY-Q 4.3's GCC 2.8.1) back to the byte-identical executable; 2. a **native port** of that C, built against [psyz](https://github.com/Xeeynamo/psyz) (a PlayStation SDK reimplementation with a software GPU) for the M5Stack Tab5 (ESP32-P4) in [tab5-emu](https://github.com/esp-cpp/tab5-emu), the way its Metal Gear Solid port runs [mgs_reversing](https://github.com/FoxdieTeam/mgs_reversing). **The game runs** (natively, on the desktop and the Tab5) through a static recompilation of the whole executable: see [recomp/](recomp/README.md). The recompiler translates the executable mechanically into C, so its output is the game's code in another form. It is generated at build time from your own copy of `SLUS_008.84` and is never committed or distributed. That is a stopgap: the aim is the matching decompilation below, which can replace the recompiled code one function at a time until the port builds entirely from hand-written source. Contributions are very welcome. https://github.com/user-attachments/assets/a1001e13-553d-4048-aa23-dba5409316e3

On the M5Stack Tab5 (ESP32-P4, two 360 MHz RISC-V cores) it plays at about 27 fps in the levels against the game's 30, with sound, music, speech, the full-motion movies (MDEC + XA) and save states. The decompilation below continues alongside it; decompiled functions can replace recompiled ones one at a time. Decompilation status: the executable is split (splat) and rebuilds byte-identical from `INCLUDE_ASM` stubs; PSY-Q library functions are identified by signature; the disc's file system is understood. First C: `main` and the file layer (`File_Init` and its table rebasing), correct but a few instructions off matching, so they build under `NON_MATCHING` (the port build) only. See [docs/LAYOUT.md](docs/LAYOUT.md) for everything known about the image and the disc, and [docs/PLAN.md](docs/PLAN.md) for the road map. ## You need your own copy of the game Nothing from the game is in this repository: no code, no data, no names derived from the disc beyond what is needed to describe its layout. Bring your own disc image. ## Building ```sh tools/setup_toolchain.sh # venv, mips binutils, GCC 2.8.1, maspsx python3 tools/extract_disc.py ".bin" disc/ # ISO9660 -> files cp disc/SLUS_008.84 disks/us/ make setup # split the executable make # rebuild and compare: "OK" ``` `make setup` regenerates `asm/` and, **only for files that do not exist yet**, the `src/*.c` stubs: splat never overwrites C. To find the PSY-Q functions again (after changing the split, say): ```sh git clone https://github.com/lab313ru/psx_psyq_signatures /tmp/sigs tools/psyq_match.py disks/us/SLUS_008.84 /tmp/sigs --union --symbols config/symbols.psyq.us.txt ``` ## Decompiling a function 1. pick an `INCLUDE_ASM` line in `src/*.c`; its asm is in `asm/us/nonmatchings//.s`; 2. replace it with C (m2c is a good first draft: `m2c asm/us/nonmatchings/game/func_XXXXXXXX.s`); 3. `make`: it must still print `OK`. `tools/fdiff.py ` shows the built function against the original, instruction by instruction. 4. if it will not match after reasonable effort, keep the C anyway, guarded: `#ifndef NON_MATCHING` / `INCLUDE_ASM(...)` / `#else` / C / `#endif`. The port builds with `NON_MATCHING`; correct C is what it needs. Renaming a function: add it to `config/symbols.us.txt`, rename its `INCLUDE_ASM` line in `src/`, then `rm -rf asm && make setup` (splat files the asm of functions it does not see in an `INCLUDE_ASM` under `asm/us/matchings/`). ## Tools | | | |---|---| | `tools/extract_disc.py` | list / extract the ISO9660 files of a raw `.bin`, all or the ones named (Form 2 files as raw 2336-byte sectors) | | `tools/tpm_files.py` | the game's own file table: list / extract `FILE.000` by name | | `tools/psyq_match.py` | find PSY-Q library objects by signature, write splat symbols | | `tools/gte_words.py` | post-split pass: GTE commands as raw `.word`s (their encodings are not all canonical) | | `tools/setup_toolchain.sh` | fetch / build the toolchain | | `tools/fdiff.py` | one function of the build against the original, instruction by instruction | | `tools/recomp.py` | the static recompiler (see [recomp/](recomp/README.md)) | ## License MIT (see [LICENSE](LICENSE)) for the code in this repository. The game itself is not covered: it stays the property of its owners and is not here. ## Credits splat / spimdisasm / rabbitizer (decompals, ethteck, AngheloAlf), maspsx (mkst), old-gcc (decompals), psx_psyq_signatures (lab313ru), and the OpenPhantom project's work on the PC version.