Awesome
<!-- markdownlint-disable-next-line MD043 -->Castlevania Decompilation
<!-- markdownlint-disable-next-line MD033 --> <div align="center"> </div>About
This repository contains a work-in-progress decompilation project for Castlevania (Nintendo 64).
[!IMPORTANT] This repository DOES NOT contain any of the assets required to build the ROM. All data, including the original assembly code and assets, requires a legally obtained copy of the original game to extract all of this data from.
The main objective of this project is to rewrite C code that, when compiled, results in matching assembly code found in the game's ROM. Besides this, the project also aims to extract and convert all assets from binary data to a higher-level format understood by the console.
At the moment, this project cannot be used to create mods on a large scale due to issues with shiftability (i.e. hardcoded addresses), therefore it's only useful for documentation of the game's code for now.
Acknowledgements
Tools
These tools are instrumental in the decompilation process of Castlevania 64.
People
These people make this project possible and successful.
- @moisesPC for his research efforts and the creation/upkeep of the Castlevania 64 - Research Spreadsheets
- @LiquidCat64 and @Fluvian for reversing the LZKN64 compression algorithm used by Konami
- @decompals for the ultralib repository, which we took the Ultra64 headers from.
Getting started
Requirements
- Your own (legally obtained) copy of Castlevania for the Nintendo 64 (USA v1.0)
(
sha1: 989A28782ED6B0BC489A1BBBD7BEC355D8F2707E
) - CMake
- Git
- Make/Ninja
Docker
There is a Dockerfile for convenience. If you want to have your development environment on your system, continue to Linux or Windows.
[!NOTE] You may need to prefix
docker
commands withsudo
if your user is not part of the docker user group.
You can build the Docker image as follows.
docker build . -t c64
And then, you can interactively spin up a docker container.
docker run --rm -ti -v $(pwd):/c64 c64
Linux (Debian/Ubuntu offshoots)
- cmake
- build-essential
- binutils-mips-linux-gnu
- python3/pip3 (We recommend managing this through mise)
- ninja-build
- libbz2-dev
Windows
- MinGW
Building
[!WARNING] If the compilation process fails, go to the
castlevania.yaml
file and set the optiondissasemble_all
toTrue
, then clean and build again. It should then end up with an error. At this point, change said option back toFalse
, clean and build again and the project should build successfully.
Place a Castlevania 64 (USA v1.0) ROM in the root of the project, and rename it
to baserom.z64
.
Now, you must configure the CMake project by running the following...
cmake -S . -B build -G "Ninja"
[!TIP] Or run
mise run c
if you are already using mise
The above snippet produces a Ninja-based build system under the hood. This seems to be faster than Make, but if you still prefer Make over Ninja, you can run the following...
cmake -S . -B build -G "Unix Makefiles"
[!TIP] You can also use
mise run cdec
if you are already using mise, orcmake -S . -B build -Dcompress=FALSE
to skip compressing files and checking the ROM's sha1sum. This is only useful for debugging non-matching compressed files at the moment.
Afterwards, to build the project, run the following...
cmake --build build
[!TIP] Or run
mise run b
if you are already using mise
Cleaning
Run the following to clean up the build artifacts.
./scripts/clean
[!TIP] Or run
mise run cl
if you are already using mise
Context generation
You can generate a ctx.c
context file for use with mips2c
or decomp.me.
This will contain all headers within a given source file
python3 ./tools/m2ctx.py <your_C_file>
[!TIP] Or run
mise run ctx <your_C_file>
if you are already using mise.
Using permuter
You can use permuter to assist on matching functions that are close to completion, but are problematic to work with, such as when there registers are allocated differently or when instructions are placed in a different order than the target assembly.
-
Go to a scratch from decomp.me and click
Export
, which saves a ZIP file named the same as the function in that scratch. Ensure the ZIP file is placed in~/Downloads
. -
From the root of the repo, run:
./scripts/perm putFunctionNameHere
This will create a directory called
perm
in the root of the project.
[!TIP] Or run
mise r pp putFunctionNameHere
if you are already using mise.
-
From the root of the repo, run:
python tools/decomp-permuter/permuter.py perm
Add the
-j
option to utilize multiple cores, followed by the number of cores.
[!TIP] Or run
mise r p perm
if you are already using mise.