-
Notifications
You must be signed in to change notification settings - Fork 32
Tooling
List of tools used for the decompilation process and guides to their usage.
TODO (Unfinished Description)
Converts any Q format integer (0x7CCC, -0x1444, 0xFFFE0DDD, 4096) into float equivalents and convert small code lines to a project specific macros or inline functions that produces the same code (for example: g_SavegamePtr->eventFlags_168[X] expressions to Savegame_EventFlagGet(Z) / Savegame_EventFlagSet / Savegame_EventFlagClear)
Q12 is used by default, but can be specified by including it in the line (4096 Q8 or Q8(0x1337) to convert to Q8)
May need to round the result afterward
Emoose please add details
TODO (Unfinished Description)
Tool to assist with the recognition of function shared among overlays. maptool.py main mode compares the assembly of functions from map1 folder against map2, and prints matching filenames.
Funcs are compared by removing any block-comments and data/func refs, and then checking Levenshtein distance. Any with distance = 0 will then be printed.
If a matching func is found which is named as sharedFunc_XXXXXXXX_0_s00 in map1 folder (where 0_s00 is map number, eg. map0_s00) It will also print out lines to add in map2 sym.txt file and #includes to add in *.c file, to allow the func to be shared.
The tool also allows parsing/listing map file headers, and searching map files for specific character IDs
For it usage write: python3 maptool.py [options] [map1] [map2]
Map comparison options (map1/map2 required):
-
--matchingsOnly compare map1 'matchings' against map2 'nonmatchings' -
--nonmatchingsOnly compare map1 'nonmatchings' against map2 'nonmatchings' ** If none of above are set, will compare both against map2 'nonmatchings' -
--replaceReplace INCLUDE_ASM for 'sharedFunc' funcs in map2 .c with #include -
--updsymsUpdate and reorder map2 sym.txt with shared functions -
--when [funcName]Only apply --replace / --updsyms if funcName has been matched in this map (to help with sub-function false-positives)
Map header options:
-
--list [MAP_NAME]List character spawns from MAP_NAME map headers -
--searchChara [CHAR_ID]Search and list any maps that contain CHAR_ID
(more info at https://github.com/Vatuu/silent-hill-decomp/issues/74#issuecomment-2816256817)
TODO
A Python script is provided to rearrange registered symbol in *.sym.txt files based on addresses. Prior to committing, run it with python3 tools/configs_formatter.py.
Several tools can be used to help disassemble and analyze the game. This guide covers loading the game's overlays into both Ghidra and IDA Pro.
Ghidra is recommended over IDA due to its simple support for overlays, but it's useful to have other tools for cross-comparison.
Ghidra supports MIPS disassembly/decompilation, but a loader extension is needed to allow loading in PSX executables.
-
Make sure the decomp repo has been cloned and setup with
make setup. -
Copy our LoadSHOverlays.py script into Ghidra/Features/Jython/ghidra_scripts/ folder.
-
Download the latest loader extension for your Ghidra version: https://github.com/lab313ru/ghidra_psx_ldr
-
Copy the ZIP into Ghidra/Extensions/Ghidra/ folder.
-
In Ghidra, go to File > Install Extensions and install the loader, then restart Ghidra.
-
Load the main executable
SLUS_007.07into Ghidra and open it in the code browser, when prompted to analyze, cancel. -
Head to Window > Script Manager, open the PSX section, click on LoadSHOverlays.py, and press the play button.
-
When prompted for a file to load, select the assets/filetable.c.inc file in the decomp repo, which was generated by
make setupearlier. -
It'll then ask if you want to load overlays/symbols, select Yes to both.
-
After the script has finished, go to Analysis > Auto Analyze.
-
If you loaded symbols above make sure PsyQ Signatures is unchecked, then start analysis.
If successful the LoadSHOverlays.py script should load in all the overlays for you, and also load in our symbol names from the decomp.
After analysis has completed most functions should be identified and viewable in the decompiler view, though some may still be left undefined, needing to be set as code manually (especially map functions, which are often only referenced by data).
Ghidra includes the ability to parse C headers into datatypes that are usable in the disassembly. However, it is unable to match functions with the function definitions from the header by itself, requiring a script to make use of them.
-
Copy the silent-hill-decomp.prf file from the repo to Ghidra's
parserprofilesfolder.- (
%AppData%/ghidra/ghidra_XXX_PUBLIC/parserprofiles/orGhidra/Features/Base/data/parserprofiles/)
- (
-
Copy the LoadSHFuncdefs.py script into the Ghidra/Features/Jython/ghidra_scripts/ folder.
-
After loading Silent Hill in with the
LoadSHOverlays.pyscript above, go to File > Parse C Source. -
Select
silent-hill-decomp.prfin the Parse Configuration dropdown menu. -
In the Include Paths section, double-click each of the paths and change them to use the correct repo path.
-
Click Parse to Program. If asked about open archives, pick Don't Use Open Archives.
-
Once the headers have been parsed, go to Window > Script Manager > PSX, click on LoadSHFuncdefs.py, and press the green Play icon.
-
Allow script to run. Once finished, most functions will have the correct definition applied.
Currently, global data variables such as g_SysWork/g_GameWork still need to be set up manually, though the structs for them will be loaded by the Ghidra parser.
The paid version of IDA Pro supports MIPS disassembly/decompilation, and has support for PSX executables built-in.
Overlays are apparently supported but it's not clear how well that works, using separate databases per-map-overlay (a base database with main/bodyprog loaded, and then copies of that for each map) may be more reliable for now.
-
Open
SLUS_007.07in IDA, it should be automatically detected as a PSX EXE. -
Once the main EXE is loaded, go to File > Load File > Additional binary file
-
Select the overlay file and enter its start address.
- Note: IDA requires addresses in 16-byte blocks (divide by
0x10). For example,0x80012340-> Enter0x8001234 - For
BODYPROG.BIN, use start address0x80024B6 - For
OPTIONS.BIN,SAVELOAD.BIN,STF_ROLL.BIN,STREAM.BIN, use start address0x801E260
- Note: IDA requires addresses in 16-byte blocks (divide by
-
Unfortunately as the address of map overlays/b_konami ends in
8, these need a workaround to load in:- Open Segments view
- Resize the
bodyprogsegment to end at0x800C9570 - Add 8 bytes of padding (
00) to the start of the map overlay file - Load it at
0x800C957 - Resize the
bodyprogsegment to end at0x800C9578again
This should allow everything to line up correctly despite the alignment restriction.