Skip to content
sozud edited this page Jan 9, 2025 · 23 revisions

Start decompiling and contribute

This page aims to help newcomers to help contributing into the project.

Set-up

Be sure to follow the Build guide first.

Open your ~/.zshrc or ~/.bashrc and add the following aliases to make the process more streamlined:

alias sotn="make clean && make -j extract && make -j build && make expected"
alias dec=".venv/bin/python3 ./tools/decompile.py"
alias differ=".venv/bin/python3 ./tools/asm-differ/diff.py -mow3 --overlay"

Choosing a function to decompile

  1. We have a list of all of the functions in the repository sorted by approximate difficulty here.
  2. The length of the function and number of branches gives an estimate of the difficulty. Generally, if the function is longer and has more complex control flow, it's going to be harder to get a match.
  3. Jtbl indicates that the function uses jump tables. These require a special process to decompile, explained here.
  4. A decomp.me scratch may already exist for the file you are interested in. These are listed in the last column and can be used as a starting point for your work.
  5. Check if the function is a duplicate before starting it. You may be able to either use the decompiled version as-is, or with minor adjustments. See here.

Function decompilation example

  1. Run sotn at least once and ensure to get all OK
  2. Choose a function to decompile
  3. Check if the function is a duplicate
  4. With a CTRL+Shift+F search the function name. You will find a line which targets its assembly counterpart (eg. INCLUDE_ASM("st/wrp/nonmatchings/6FD0", func_801873A0);)
  5. Run dec func_801873A0 to decompile the function in the C code
  6. Do a differ OVERLAY_NAME FUNCTION_NAME and check if you have to fix any compilation error before proceeding (eg. differ st/wrp func_801873A0)
  7. When differ succeeds, you will get a screen that shows on the left how the original assembly looks like and on the right how your decompiled version translates into.
  8. Keep refactoring the code until the two assemblies match.
  9. Try refactoring and perform clean-ups while ensuring your C function still matches the original assembly code.
  10. Create a commit on your fork and make a PR!

Decompiling with decomp.me

These steps involve the website https://decomp.me/ which gives an easy user interface for decompiling.

  1. Figure out the file that contains your function and run SOURCE=path/to/my/function.c make context
  2. Click "Start Decompiling" on decomp.me
  3. Select "PlayStation"
  4. The compiler should be gcc 2.6.3-psx + maspsx and the preset should be Castlevania: Symphony of the Night.
  5. Paste ctx.c into the "Context" pane.
  6. Paste the assembly for your function into the "Target assembly" pane.
  7. Click "Create scratch".

Switch between the different game builds

Currently the decomp supports the following SOTN builds:

  • us
  • hd
  • pspeu
  • saturn

To switch to a different game build, simply invoke on a terminal export VERSION=GAME_BUILD_ID (e.g. to decompile the PSP build, do export VERSION=pspeu). By default the version is set to us, which is the US build of SOTN for PSX.

To restore the default version in your environment, run unset VERSION .

Tips and tricks

  1. Use decomp.me with the "Castlevania: Symphony of the Night" preset.
  2. The “context” section of decomp.me, is provided by the cmd SOURCE=src/dra/42398.c make context.
  3. Use decomp-permuter to solve some mismatches.
  4. Use this and this guide to understand how some compiler patterns work.
  5. Use the #ifndef NON_MATCHING if your code is logically equivalent but you cannot yet fully match it.
  6. Some SotN specific register tricks can be found here.

Jump tables

See Decompiling functions with jump tables

The rodata section and strings

TODO

Duplicate functions

Due to how the game is structured, a lot of duplicate code can be found across the different overlays. We track a live list of duplicate functions. If you aim to decompile a duplicated function you might get around by just copy&pasting it into the right overlay

Add new overlay

The game has multiple overlays, one for each stage, boss, and familiar. Adding new overlays to the decompilation requires prior agreement, either through GitHub Issues or via our Discord Server. This is because adding a new overlay significantly increases the project scope. Gradually adding overlays allows us to better tackle duplicate code and identify common patterns to automate the process.

If you're interested in adding a new overlay, please contact us. You can also add the same overlay from another version of the game. The reference version is us, but we're open to overlays from hd, pspeu, eu, hk and so on.

Below are the steps to add a new overlay, using cen with version hd as an example. You can also refer to this pull request for guidance.

Get an OK with a new overlay

  1. Generate the splat config (e.g. VERSION=hd tools/make-config.py cen).
  2. Add the SHA1 checksum of the targeted overlay in config/check.{VERSION}.sha.
  3. Add the binary build step in Makefile (search for cen: as an example).
  4. Update the build step build_{VERSION} in the Makefile`.
  5. Update .PHONY: at the end of Makefile.

If you're adding a PSX overlay, you'll also need to:

  1. Add the overlay to Makefile.psx.mk (see PSX_KSTAGES and similar for reference).
  2. Add the overlay to the extract_assets list in Makefile.psx.mk.
  3. Add the overlay to the build_assets list in Makefile.psx.mk.

After these steps, running VERSION=hd make -j should complete the process and give you an 🆗. Be sure the build path matches the version and overlay name of what you're targeting. Though time-consuming, this is just the first part.

Add the overlay to the toolchain

  1. In the Makefile add the new overlay to the format-symbol.
  2. In the Makefile add the new overlay to the force_symbols.
  3. In the Makefile add the new overlay to the disk_prepare.
  4. Add the overlay as a new SrcAsmPair object in tools/dups/main.rs.

Add the overlay to the Progress Page

  1. Add the overlay as a new DecompProgressStats object in tools/progress.py.
  2. Update the README.md to include the progress shield icon by copying an existing link and changing the overlay name.

After completing these steps, submit a pull request with your changes.Additionally, make a separate pull request targeting the docs branch after adding the overlay to gamemeta.js.

Resources