Powered by
NYEN
A matching decompilation of Digimon World 2 for the Sony PlayStation.
The goal is to recover readable C that, when compiled with a period-correct toolchain, produces a binary byte-identical to the original executable, then a moddable full-source tree.
| Item | Value |
|---|---|
| Platform | PlayStation (PSX / PS1) |
| Target | USA main executable SLUS_011.93 + 7 stage overlays |
| Disc (USA) | SLUS-01193 |
| Exe SHA-1 | e55ed5bf354def07f0cbf4e1fb7fb5f99204f220 (651264 bytes) |
| Overlays | STAG0000/1000/1100/2000/3000/3500/4000.PRO, loaded at 0x80063360 |
| Compiler | GCC 2.8.1 (PSX cc1) + maspsx |
| Structure | main exe + 7 stage overlays (AAA/3.PRO/STAG*.PRO) |
| License (project code) | CC0 1.0 |
You must own the game. This repository contains no ROMs, disc images, or copyrighted assets.
rom/ assets/ build/are made from your own disc and are gitignored. Obtain a legal dump of your own disc.
asm/andlinkers/are splat output. They are still committed today so the progress CI can build without a disc. That covers only the PsyQ library asm (code and data); the game's data in the exe and the overlays is C. Opaque content inside C units (bitmaps, CLUTs, tables such as the CD file table, a few padding bytes) is copied from your disc at build time (configs/USA/include_bin.txt,configs/USA/image_bytes.txt). They will move out of the repo (see issue #6).
All 1088 game functions are matched C. The C rebuilds the retail executable and all 7 stage overlays byte-identical.
Naming is done. Functions, globals and struct fields have real names where the code proves
them. A few keep their func_ / D_ names on purpose (empty stubs, unreferenced filler
words). The source is split into one file per module, along the retail file boundaries
(src/main/sys.c, src/main/savedata.c, src/stag3000/battle.c, src/stag4000/floor.c ...).
Every global has one layout and a documented owner: doc/STATE_MAP.md
lists each global of the exe and the overlays as player, world, engine, constant or debug
state, with its writers and readers, the memory map and the game mode to overlay table.
The build is shiftable, and that is the modding build. No code or data holds a fixed address:
every pointer is a symbol, and the exe and the overlays link against each other by name.
python3 tools/build_dw2.py --shift-test pads main and STAG1000.PRO so every address
moves, and that image boots. So you can change the C, add code or data and relink; the SHA-1
check then no longer applies. The one fixed limit on growth: the heap starts at 0x80075000
(Mem_HeapStart), right after the largest overlay (STAG3000.PRO), so move it if main and
that overlay together grow by more than 0xF5C bytes.
The last two functions:
Task_Run(the task scheduler) runs every update and draw callback on a stack in the scratchpad RAM. C cannot move the stack pointer, so the switch is two small__asm__statements around the calls, the rest is plain C. The original most likely did the same.stag4000:func_8006D418returns the same field on both sides of a flag test. The test does nothing, but GCC 2.8.1 only merges the two arms after register allocation, and retail's code has exactly that allocation. No form without the test produces it.
A function counts as matched only when its C reproduces the retail bytes with the compiler
setup of its translation unit and no asm rewrites: GCC 2.8.1-psx -O2, main game -G8 with
maspsx --aspsx-version=2.81, overlays -G0 with 2.77, plus a few per-unit flags in
tools/build_dw2.py. Functions that still need a per-function flag set or asm rewrites are
listed separately and are not counted. PsyQ library code (PsyQ 4.7 in the exe, libpress 4.6 in
STAG1000.PRO) is not game code and is excluded from progress
(configs/USA/psyq_funcs.txt). Counts come from tools/strict_report.py, which builds each
function with and without the post-processing and compares it against the target. See
issue #5.
| Component | Functions | Matched | Progress | Flags per function | Asm rewrites | Asm |
|---|---|---|---|---|---|---|
Main executable (SLUS_011.93, game code) |
368 | 368 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
Stage overlays (AAA/3.PRO) |
720 | 720 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG0000.PRO |
69 | 69 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG1000.PRO |
17 | 17 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG1100.PRO |
55 | 55 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG2000.PRO |
133 | 133 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG3000.PRO |
123 | 123 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG3500.PRO |
108 | 108 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
└ STAG4000.PRO |
215 | 215 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
| Total (game code) | 1088 | 1088 | ▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰ 100.00% |
0 | 0 | 0 |
| PsyQ libraries (not counted) | 558 |
DW2 has the main exe plus 7 stage overlays on the disc, AAA/3.PRO/STAG0000.PRO to
STAG4000.PRO. The main exe loads one at a time to 0x80063360 (func_80013308, indexed by
the game mode), so they share one address range. Each overlay is split into its own unit
(src/stagXXXX, asm/USA/stagXXXX) and relinks byte-identical to the retail file.
The AAA directory is left out of the disc's root directory record, so a plain ISO extract
only shows SLUS_011.93 and SYSTEM.CNF. dumpsxiso -pt (path table walk) extracts the full
tree.
PsyQ library code stays as split asm, as in other PS1 decomps. The crt0 startup is the PsyQ
SNMAIN hand asm.
| Path | What |
|---|---|
src/ / include/ |
decompiled C and headers |
configs/ |
splat config + symbol maps |
doc/ |
STATE_MAP.md: global state map, memory map, scene table |
tools/ |
gcc-psx, maspsx, m2c, decomp-permuter, asm-differ, mkpsxiso, build scripts |
Supply your own Digimon World 2 (SLUS-01193) disc and extract it with dumpsxiso -pt to
dumps/disc/ (SLUS_011.93 plus AAA/3.PRO/STAG*.PRO). Then:
python3 -m venv venv # venv\Scripts on Windows
pip install -r requirements.txt
python3 -m splat split configs/USA/SLUS_011.93.yaml # regenerate asm/ and linkers/
python3 -m splat split configs/USA/stag1000.yaml # same for each stagXXXX.yaml
python3 tools/build_dw2.py # expect: SLUS_011.93: OK + 7x STAGxxxx.PRO: OK
tools/build_dw2.py preprocesses and compiles src/**/*.c through the PSX cc1 + maspsx
pipeline, assembles the remaining split asm, links with the splat linker script plus the
auto-detected hardware and kernel symbols, then checks the SHA-1 against your disc's exe.
build/USA/out/SLUS_011.93: OK means the whole exe still reproduces byte-for-byte. Each
overlay is then linked with its own script and checked the same way
(build/USA/out/STAGxxxx.PRO: OK); --overlays-only builds just the overlays.
python3 tools/rename.py func_XXXXXXXX Module_VerbNounrenames a main exe function or global everywhere (--unit stagXXXXfor an overlay,--batch filefor many).python3 tools/rename_field.py --batch filerenames struct fields with the compiler as the checker.- Only name what the code proves. A wrong name is worse than
func_. - Verify with
python3 tools/build_dw2.py. OnlyOKfor every file counts as done.
Workflow and toolchain derived from the Parasite Eve 2 decomp. DW2 file-format documentation by RmBeastbow. Thanks to ThirstyWraith for pointing out the stage overlays (issue #3) and for their STAG3000 battle notes and decomp.me scratches (issue #4), which seeded the matches of the battle status and item functions.