Skip to content

Basic Decompilation

emoose edited this page Dec 12, 2025 · 5 revisions

This is a basic guide for using decomp.me to create matching function decompilations. For functions inside map files refer to the map tool guide for information about sharing functions between maps.

Fetch function assembly

Look for the INCLUDE_ASM macro of the function you're interested in:

INCLUDE_ASM("asm/bodyprog/nonmatchings/bodyprog_80070B84", func_80071620)

The first parameter is the folder containing the assembly file, in that folder you should find a file with the function name with a *.s extension, copy the contents of that file and follow the next section.

You can also run ./tools/func_rater.py to see the current unmatched functions ranked by estimated difficulty. Some of the easier ones near the bottom could be good starting points for learning to decompile.

decomp.me allows decompiling functions using m2c, while providing a live diff view that compares the compiled C code against the original assembly, letting you edit C code directly in the browser and see the changes in real time.

Each scratch is also publicly viewable and forkable, making it easy to collaborate on the same function.

Note

If you have a GitHub account you may want to login to it on decomp.me first, so scratches can be credited to you.

Warning

It's recommended to try searching decomp.me for the function you want to work on first, others may have already made some progress on it.

  • On the decomp.me page, head to New scratch > Click PlayStation option > Under Presets, select Silent Hill

  • Ignore the Diff Label field for now.

  • Paste the function assembly (.s file) into the Target Assembly box.

    • .s files are generated after running make setup in the decomp project.
    • Diff Label field should auto-fill after pasting it in.
  • In the Context box, paste in the ctx.c content for the .c file that includes the function:

    • Run tools/m2ctx.py src/bodyprog/bodyprog.c (change to the .c file that has INCLUDE_ASM line for the function)
    • Copy the contents of the generated ctx.c into the box
  • Click Create Scratch

This will try to create a scratch for you with decompiled output using m2c. The result tend to variate, sometimes it can make very closely matching C code, most of the time it create a decently enough result to get an idea to start working from and in case of a large function or one that uses many macros or inlinement it can require too much work.

Note

When working on non-engine overlay functions, add the overlay name to the beginning of the scratch (a comment like // MAP0_S00, or a #define MAP0_S00 define), this will help keep track of each function.

Jump tables

In some cases where the function uses jump tables, decomp.me/m2c may ask for jtbl data before it can decompile:

  • In this case, delete the scratch and start over with a new one.

  • Before the function's assembly, include the jtbl_XXXX data that m2c requested (can usually be found either as a separate .s file, or in one of the .rodata.s file for the .c):

    .set noat      /* allow manual use of $at */
    .set noreorder /* don't insert nops after branches */
    
    .section .rodata, "a"
    ; jump table data here (`dlabel jtbl_XXXX` line through `.size jtbl_XXXX`)
    
    .section .text, "a"
    ; original function code here (`glabel func_XXXX` through `.size func_XXXX`)

.rodata / code offset mismatch

The context from m2ctx will also contain function code from the input .c file, this code can cause rodata / code offsets to be mismatched from the original assembly, causing them to appear in blue, and sometimes affecting the match percentage.

This is an easy fix: simply edit the context and remove all function code after the function and struct declarations. Note that static inlines can usually be left in the context, unless those also cause decompilation issues.

Code offsets can also be affected by the same thing, causing branch targets to appear in blue despite pointing to the same code. The same fix can resolve them.

Clone this wiki locally