.github/workflows | ||
.vscode | ||
asm/main/psxsdk | ||
bin | ||
config | ||
include | ||
src | ||
tools | ||
.clang-format | ||
.gitignore | ||
.gitmodules | ||
CNAME | ||
diff_settings.py | ||
go.work | ||
Makefile | ||
README.md | ||
slus00067.sha |
Castlevania: Symphony of the Night Decompilation
A work-in-progress decompilation of Castlevania Symphony of the Night for PlayStation 1. It aims to recreate the source code from the existing binaries using static and/or dynamic analysis. The code compiles the same binaries of the game, byte-for-byte to the same binaries of the game, effectively being a matching decompilation. Currently it only supports the US version of the game SLUS-00067
.
The game is divided into three modules:
SLUS_000.67
the main executable. It contains all the hardware API (eg. gamepad, CD, memory card, GPU renderer) of the PlayStation 1 console. It does not contain any game logic.DRA
the game engine. It contains the business logic (eg. gameloop, API to draw maps, entities, load levels, handle entities, animations and collisions) and some data such as Alucard's sprites or the loading/save rooms.ST/
the overlays for each area. An area (eg. Castle's entrance, Alchemy Laboratory, etc.) contains all the unique logic to handle map specific events, cutscenes, enemy AI, collisions and more. It also contains the rooms and entities layout. Each overlay can be considered as its own mini-game. The title screenSEL.BIN
is an example of how a stage overlay can act very differently.
This repo does not include any assets or assembly code necessary for compiling the binaries. A prior copy of the game is required to extract the required assets.
Bins decomp progress
Setup the project
This assumes you have Ubuntu, Debian or WSL in Windows.
- Inside the folder of your choice
git clone https://github.com/Xeeynamo/sotn-decomp.git
- Run
sudo apt-get install -y $(cat tools/requirements-debian.txt)
- Run
make update-dependencies
- Inside the newly created repo, create a new
iso/
folder, and extract the game content from the ISO or disc
Build
- Run
make extract
to generate the assembly files for the functions not yet decompiled. - Run
make all
to compile the binaries in thebuild/
directory.
In case there are any changes in the config/
folder, you might need to run make clean
to reset the extraction.
Some non-matching functions are present in the source preprocessed by the macro NON_MATCHING
. You can still compile the game binaries by running CPP_FLAGS=-DNON_MATCHING make
. In theory they might be logically equivalent in-game, but I cannot promise that. Few of them could match by tuning or changing the compiler.
Start decompilation
- Run
make clean extract all expected
at least once - After setup and build, choose an overlay (eg.
ST/WRP
) - Look for one of those functions which hasn't successfully decompiled yet (eg.
INCLUDE_ASM("asm/st/wrp/nonmatchings/6FD0", func_801873A0);
) - Run
./tools/decompile.py func_801873A0
to decompile the function in the C source code where the function is supposed to be located - If the function does not compile, try addressing the compilation errors until
make
compiles - If the function does not match, invoke
python3 ./tools/asm-differ/diff.py -mwo --overlay st/wrp func_801873A0
and refactor the code until it matches - If the function matches, try refactoring to keep the code clean while checking if the function still matches once in a while
There are a few tricks to make the process more streamlined:
- Use decomp.me with PSY-Q 4.0. Be aware that the repo is using GCC 2.6.x, so decomp.me will sometimes give a slightly different output.
- The “context” section of decomp.me, is provided by the cmd
SOURCE=src/dra/42398.c make context
as mentioned in the how to decompile. - Use decomp-permuter to solve some mismatches.
- Use this and this guide to understand how some compiler patterns work.
- Use the
#ifndef NON_MATCHING
if your code is logically equivalent but you cannot yet fully match it.
Resources:
- List of resource for sotn https://github.com/TalicZealot/SotN-Utilities (speedrun oriented, but still very useful).
- PS1’s CPU R3000 instruction manual and cheat sheet
- SOTN map viewer written in C
- PCSX emulator with debugger
- NO$PSX emulator with debugger
- Beginner friendly MIPS video lectures 1, 2
To do:
The project is very barebone at the moment and there is a massive room of improvement, mostly in the infrastructure:
- Not all the zone overlays (
ST/{ZONE}/{ZONE}.BIN
) are disassembled - Integrate ASPSX instead of GNU AS
- Split binary data (eg. map layout, graphics, other assets) into individual files
Notes
- The debug room overlay
ST/MAD.BIN
was compiled earlier than the first retail release of the game. All the offsets that refers to DRA.BIN points to invalid portions of data or to the wrong API calls, effectively breaking the majority of its original functionalities. That is why the debug room does not contain any object. By compiling the debug room with make mad_fix you can restore it by redirecting the old pointers to the retail version of the game. Be aware that not all the offsets have been yet redirected, so it will still be not entirely functional until further update. - I suspect that GCC 2.6.x / PSY-Q 3.4 have been used to originally compile DRA.BIN
main.exe
uses PS-X libraries that might have been created with a different compiler and with-O1
rather than-O2