Daytona USA 2 High Scores

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome. Not for end-user support.
Forum rules
Keep it classy!
  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!
MO-120FF
Posts: 13
Joined: Thu Mar 27, 2025 8:44 am

Re: Daytona USA 2 High Scores

Post by MO-120FF »

Regarding the settings, I would just like to disable throttling (Alt + T), but it doesn't work for me. Supermodel always throttles to 60fps. Are there any settings that allow me to disable throttling using Alt + T? (The command line option -no-throttle also doesn't work for me.)
Bart
Site Admin
Posts: 176
Joined: Tue Nov 07, 2023 5:50 am

Re: Daytona USA 2 High Scores

Post by Bart »

I believe that you have to disable Vsync in your graphics driver as well for this to work.
MO-120FF
Posts: 13
Joined: Thu Mar 27, 2025 8:44 am

Re: Daytona USA 2 High Scores

Post by MO-120FF »

I've put together a webpage that reads the NV file and displays the high scores using both of the calculation methods you found in the source:

function calculateTime1(nFrameCount) {
const nSeconds = Math.floor(nFrameCount / FPS);
const nFrameCount_subSecond = nFrameCount - (nSeconds * FPS);
const nCentiSeconds = Math.floor( (nFrameCount_subSecond * 100) / FPS);
const nMinutes = Math.floor(nSeconds / 60);
const nRemainingSeconds = nSeconds - (nMinutes * 60);
return `${nMinutes}:${nRemainingSeconds.toString().padStart(2, '0')}:${nCentiSeconds.toString().padStart(2, '0')}`;
}

function calculateTime2(nFrameCount) {
const nTotalCentiseconds = Math.floor((nFrameCount * 100.0) / FPS);
const nWholeSeconds = Math.floor(nTotalCentiseconds / 100);
const nCentiseconds = nTotalCentiseconds - (nWholeSeconds * 100);
const nWholeMinutes = Math.floor(nWholeSeconds / 60);
const nSeconds = nWholeSeconds - (60 * nWholeMinutes);
const nWholeHours = Math.floor(nWholeMinutes / 60);
const nMinutes = nWholeMinutes - (60 * nWholeHours);
return `${nMinutes}:${nSeconds.toString().padStart(2, '0')}:${nCentiseconds.toString().padStart(2, '0')}`;
}

As you expected, the results of both functions are the same. Some times match the game-displayed times exactly; others differ by a ms. This also happens with new entries in the high-score list.

But I noticed something interesting while trying to zero out some bytes in the high-score list:
- Zeroing 0x22E6/E7 (and the same bytes at 0x22EC/ED) - no change in game-displayed times
- Zeroing 0x22E8/E9 (and the same bytes at 0x22EA/EB) - some displayed times change

Zeroing the yellow-marked bytes in the attached screenshot caused the game to add 1ms to some times. Now the previously mismatched times match the calculation, but the ones that matched before are now too high.

Code: Select all

Rank  |Initials  |Frame Count   |Time (Calc)     |Actual Time / time with zeroed bytes
----  |--------  |-----------   |------------    |----------- 
1     |ZER       |0x1E60        |2:16:42         |2:16:41 / 2:16:42   
2     |ZER       |0x1E73        |2:16:75         |2:16:74 / 2:16:75  
3     |ZER       |0x1E76        |2:16:80         |2:16:80 / 2:16:81 
4     |ZER       |0x1E78        |2:16:84         |2:16:84 / 2:16:84     
5     |ZER       |0x1E87        |2:17:10         |2:17:10 / 2:17:11
CR    |ZER       |0x03BB        |0:16:75         |0:16:74 / 0:16:75
It seems those 4 bytes might have some influence on the time calculation. Guess requires again to take a closer look at the memory region around 0x00106F50 in the debugger to see how they are accessed. I noticed the sources include debugger files — do you use the internal one?
Attachments
daytona_20250421_nv.jpg
daytona_20250421_nv.jpg (90.26 KiB) Viewed 28389 times
Bart
Site Admin
Posts: 176
Joined: Tue Nov 07, 2023 5:50 am

Re: Daytona USA 2 High Scores

Post by Bart »

Yes I do. You'll need to build Supermodel with ENABLE_DEBUGGER set. On Windows, for me, this looks like:

Code: Select all

make -f Makefiles/Makefile.Win32 clean
make -f Makefiles/Makefile.Win32 ENABLE_DEBUGGER=1
Then you can run as:

Code: Select all

supermodel daytona2.zip -enter-debugger
There is a help command. "c" will continue execution and Alt+B breaks back into the debugger. Note that you will not easily find the game accessing NVRAM. It doesn't access it directly as far as I can tell. Rather, it keeps a score table in memory with an entirely different format and (I presume), writes it to NVRAM only when something has changed.

You can set breakpoints in the debugger but I don't think we have watches (for memory access or other conditions). I disassembled the entire Daytona 2 program code and looked through it manually, searching for relevant magic numbers. I think I also looked at the RAM dump directly searching for the high score strings.

In Model3.cpp, near the bottom of the file, there is code to dump RAM and other memory. Uncomment that. On exit, you'll get a file called "ram", which is the lower 8MB of the PowerPC address space. This is where game code is copied to and executed from. You can open it in a hex editor. To disassemble it, build Src/CPU/PowerPC/PPCDisasm.cpp as a standalone application, like so:

Code: Select all

g++ Src/CPU/PowerPC/PPCDisasm.cpp -o ppcd.exe -DSTANDALONE -ISrc -ISrc/OSD/SDL
Now you can disassemble the ram file:

Code: Select all

ppcd ram -l 1000000 >daytona2.txt
Bart
Site Admin
Posts: 176
Joined: Tue Nov 07, 2023 5:50 am

Re: Daytona USA 2 High Scores

Post by Bart »

I just pushed a change to master that builds ppcd.exe automatically in the bin64 directory (alongside supermodel.exe), so if you build Supermodel as normal, you should now also get a ppcd.exe.
MO-120FF
Posts: 13
Joined: Thu Mar 27, 2025 8:44 am

Re: Daytona USA 2 High Scores

Post by MO-120FF »

I've tried the MAME debugger so far - it's pretty extensive, and you can set memory watches. The ROM set is compatible, i.e. the 0x4D4B4 function is at the same address, as is the in-memory high score list at 0x00106F50. The game runs, but unfortunately isn't playable. Also the NV dump is in a different format (though the two "time bytes" for each entry are the same).

Thanks for your detailed instructions on compiling the source and using the debugger. I need to set up a build environment first - that might take some time.

Actually, I play this game just for fun and only wanted a quick way to compare top times with friends. Didn't expect to end up disassembling and debugging the source code for that. 😉
Post Reply