Skip to content

Basic Decompilation

IWILLCRAFT-M0d edited this page Nov 9, 2025 · 5 revisions

This is a really basic guide for using decomp.me to create matching function decompilations. In case of working in map functions we recommend looking to map tool guides as maps contain shared function among each other.

Get function assembly

Look for function of your interest that is inserted through a macro named INCLUDE_ASM.

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

Go to the repo folder and follow the path indicated by the function, there you will find a file with the function name with the *.s extension, copy the content of the file and follow to the next section.

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 is recommended to check if the function you are working on haven't been previously decompiled and matched.

  • 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

In case of working in a function not from the engine overlay add the overlay name at the beginning of the scratch. This help keep track of each function (a comment like // MAP0_S00)

Jump tables

If the function uses jump tables, decomp.me/m2c will 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 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`)

The file the INCLUDE_ASM points to always include this, however, the assembly counterpart of the C files (used for Objdiff comparison) doesn't come with them.

.rodata / code offset mismatch

If the function makes use of .rodata, you may notice the .rodata offsets can be wildly different compared to the original ASM. If they appear in blue, this happens because the context includes code for other functions that have their own .rodata, causing that to be added before the .rodata of the function you're working on.

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 are causing 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