-
Notifications
You must be signed in to change notification settings - Fork 0
hiscore codes tutorial
eadmaster edited this page Apr 9, 2021
·
31 revisions
example datfile entry:
nes,smb: ; mame softlist rom name
nes,Super Mario Bros. (World): ; nointro rom name
nes,Super Mario Bros. (W) [!]: ; goodtools rom name
nes,crc32=d445f698: ; rom crc32
@:maincpu,program,7d7,6,0,0,ff ; same format of the MAME datfile: "@<cputag>,<addressspace>,<address>,<length>,<value to wait for in the first byte/word>,<value to wait for in the last byte/word>,<optional prefill>"
; free comment here on the code, issues, etc.
This is the general hiscore loading logic:
- when the game is started the loader routine will start checking the start and end bytes at the
<address>
specified. When their values match the ones in the datfile the hiscore is considered "initialized" by the game and we move onto the next step. - if there is an hiscore file saved on disk matching the current game, it is loaded in RAM at the same address and becomes visible ingame.
- the loader routine will then keep monitoring that same address to see if the previous stored value changes (any alteration counts, regardless of the actual value itself). When it does it will immediately backup the new value to the associated hiscore file and repeat step 3 until the emulation is terminated.
This simple logic works fine with many arcade games, and it is easy to implement from scratch.
Note that some games may require multiple memory addresses to check and/or may need to check multiple initialization bytes. For the latter case you may want to break a single memory region in 2+ smaller consecutive regions.
You can try looking for the memory address/range the way you prefer. Here i will describe the method i am using currently.
requirements:
- a savestate of the game you want to add with the default hiscore beaten (to minimize incorrect matches make one where the actual hiscore is not shown on screen)
- a screenshot of the actual hiscore
- an hex editor or sfk
- python3
- my state2hi script
- RetroArch + retroarch_hiscore_companion script (install guide here)
walkthrough:
- extract a 1:1 RAW memory dump from the savestate with the command
STATE2HI_DEBUG=1 python state2hi.py AnyGame.state
- an
AnyGame.state.mem
file will be created, open it with an hex editor. - try searching for the numeric value of the hiscore as hex digits, or run from the cmdline:
sfk hexfind "AnyGame.state.mem" -bin "/01234567/"
(you may need to add a0
in front of the string in order to have an even number of digits).
- if there are no matches try converting the hiscore value from a decimal to an hex base. You can use your system calculator app or
sfk hex 01234567
. - if there are no matches try again adding or removing some trailing zeroes.
- try to guess the number of bytes used by the memory location, based on the space you see on the screenshot for the digits. Convert this value to hex and this will go in the
<length>
field. - if you find only 1 memory address match at step 3 it is very likely the correct one, if you find more than 1 match you will have to try all of them to find the correct one.
- start the game again with Retroarch and make another savestate with a fresh new game. Then run
state2hi
again on this state and check the values at the address you find at step 3: the hex value at<address>
will go in and the value at<address>+<length>
will go in<last byte>
. - At this point you can add an entry in the datfile:
nes,AnyGame: ; make sure the system and filename matches here
@:maincpu,program,<address>,<length>,<first byte>,<last byte>
- run
python state2hi.py AnyGame.state
again. AnAnyGame.hi
file will be generated. - you can now test the generated hiscore file with
retroarch_hiscore_companion
and see if it works correctly.
- If you cannot find any address try looking in GameHacking.org and RetroAchievements.
- for a quick lookup in the MAME softlist you can use this bash function:
messfind() { mame -listsoftware $1 | awk -v 'IGNORECASE=1' -v RS="<software" '/'"$2"'/ { print $0 }' | less ; }