forked from vgmstream/vgmstream
-
Notifications
You must be signed in to change notification settings - Fork 0
saturn re
bnnm edited this page Oct 24, 2021
·
2 revisions
Simple stuff I figured out while poking around, may contain errors.
Steps are for Ghidra but IDA may work too (SH3/SH4 CPUs may be backwards-compatible?).
Beware! Ghidra's decompilated pseudo-code is rather wonky (for Saturn at least) and will sometimes skip important instructions (like a buf increasing +1). Mainly seems to be confused by delayed instructions(?) after return, like rts; _add 0x2,r2
. Also sometimes Ghidra identifies 2 functions where there is only one:
- function1 does: (op cluster1), then (op cluster2), optionally jumps to (op cluster2) in the beginning
- Ghidra sets (op cluster2) as a function2, but also shows both clusters as part of function1
- renaming labels get quite strange as it affects both function1 and function2
So, just ok as a guide for the disassembly.
- get latest Ghidra
- load main exe (first file in CD, like 00LOAD.BIN) in Ghidra
- manually select processor: SH2
- manually select load address in options, usually 06004000
- could be 06001000, 06010000... see below for savestate tips = correct addresses
- wrong values still allow decompiles, but jumps/offsets may be wrong (exes may store fixed 060xxxxx values)
- Ghidra may be able to autodetect
- if autodetect failed (gives wonky/few functions):
- move to entry function (usually at 0), press D to decompile
- if that fails, probably means that isn't the entry point, must find
- SH2 instructions seem to be always size 16b
- go to a bunch of 16-bit values, press D at an aligned address (try align 0x04 just in case) and see if Ghidra figures out
- Ghidra seems to figure out ok based on jumps etc even if not set at a function start, keep mashing that D
- often Saturn games have multiple exes (.BIN) so this isn't too useful
- probably can be fixed by manually loading more exes in proper locations, see below instead
- get and install Ghidra's Saturn plugin
- make a mednamed emu savestate
- open file with mednafen
- drag and drop .cue into exe works
- play until desired point
- press F5
- go to "
mcm
" (what) dir and get .mcm savestate - unzip savestate
- open file with mednafen
- load unzipped savestate in Ghidra
- see "Work_RAM_High" area for (most likely) code
- try autoanalysis or move to entry point, press D
- also see emu tips below for actual addresses
- yabause save states also work, may be less correct?
- savestate loading + seeing debug addresses = easier Ghidra decompilations
- open file with mednafen
- move to desired debug moment
- press ALT+D, this starts debugger (while game is running)
- font is tiny!
- close mednafen
- open mednafen.cfg
- change
ss.debugger.disfontsize
to 6x13 or 9x18 (registers will be tiny still)
- basic debugger controls:
- press S to step (execute single intruction)
- R to continue (play until next breakpoint)
- SPACE to set a breakpoint (stops when CPU goes there
- T to change CPU
- T changes between Saturn's two SH2 CPUs
- sometimes one SH2 does graphics, other audio
- so one CPU won't reach certain code places/breakpoints
- where to look?
- there is a "jump address list" below (as NNNNNN > NNNNNN ... NNNNNNN > NNNNNN and so on)
- press S at random times and see which address it stops
- you can use this as a reference in Ghidra, go there, press D, etc
- ex. in MvsSF, T to change to audio SH2, S usually lands in ~0600d1xx,
- that seems to be a control function, and jump addresses/steps would land into 0600d676 = decoder
- mix ghidra and debugger for better results
- ghidra decompiles some function, pseudocode get
- step that function in emu to see register values