dciabrin / ngdevkit

Open source development for Neo-Geo
GNU Lesser General Public License v3.0
273 stars 26 forks source link

Save on MVS backup RAM #70

Closed totologic closed 2 years ago

totologic commented 3 years ago

Hi

About saving in the MVS backup RAM.

From what I figured out, the header must contain: https://wiki.neogeodev.org/index.php?title=68k_program_header

$10E | longword | Pointer to backup RAM data block (in 68k user RAM). The first 2 bytes are the debug DIPs. $112 | word | Size of the required game save data in bytes.

Then, data pointed at memory block should be loaded/saved automatically by the BIOS.

But I worry because in the CRT I see this:

dc.l 0x00100000 / Debug DIP pointer / dc.w 0x0000 / Size of DIP data /

In this condition, may I expect the backup RAM system to work ?

dciabrin commented 3 years ago

Hmm you're right, in fact this part of the crt is a placeholder and has never been thoroughly tested... I'll try to support that in the devkit as soon as possible. Meanwhile you may get what you want by doing something like: . create a global variable of type u8[size] that will hold the DIP data in your program. Put this global in a separate C file. . when you link all your object files, make sure to pass this separate file first. This way, the linkscript will always allocate the very same address for that variable in the ROM . double check with nm yourprogram.elf the address allocated for this global variable. Chances are that it will be 0x100000. If not, recall the value. . patch the generated ROM file to tweak the DIP pointer and DIP data according to the address your saw earlier and the size of your buffer.

It's tedious but this should normally be a repeatable process, as long as you link your variable first.

totologic commented 3 years ago

I just finished an attempt, it is a bit different. In my mind this should work, but in fact it doesn't. Maybe you can spot what is wrong.

I started with "attract-and-game" example, to have a clean bios sequence.

I created a u8 save[5] variable, getting his address (0x1000a4), simply using the fix layer to log it.

Each time I pass in the title_mode function, I increment the save[0] value and I log it on the fix layer. So I just expect to manage a counter saved in backup RAM.

I compiled. I tried to hardcode the address 0x1000a4 and size value 5 directly in the ROM header.

Sadly my counter doesn't increment as expected, even after passing the demo-title-game-gameover sequence, it always come back to 0.

dciabrin commented 3 years ago

Hmmm, maybe it's the c runtime that keeps overwriting save[5] with zeros, as it's an uninitialized global and gets stores in BSS. I don't recall when the crt initializes the global variables in memory: i.e is it only once at boot or each time the attract mode loops. Maybe you could try something different: you create a dummy global variable at the end of your link script u8 end, and right after that you manage a pointer u8* save whose value in RAM is hardcoded to something available (after all the globals). And you patch your ROM to use this variable as well.

That's my best guess so far as I never played with backup RAM :/

totologic commented 3 years ago

I tried many different things, but none of them work. I think I reach the limits of my skills. Maybe I missed something easy and obvious, but I can't see what.

dciabrin commented 3 years ago

So I did a small test in https://github.com/dciabrin/ngdevkit-examples/tree/backup-ram. I think the idea is similar to what you did except I explicitly did not create a global variable in the program to make sure the link script won't screw this up. I'm arbitrarily using memory address 0x104000 to save my game data, and I only use 1 byte out of the allowed 0x1000 bytes. In the Makefile I patched the PROM to configure those settings in the ROM header.

What I can see is that every time the demo mode runs, the data is being saved in the backup RAM, and I can increment a byte and print it on the screen. If I restart the ROM, the counter start again from where it was before.

To avoid any surprise, I removed previous ~/.gngeo/puzzledp.nv to start from a fresh backup RAM data.

Can you check whether it does what you initially wanted? If so, I will tweak the link script to allow you to define a proper C structure and mark it as "to-be-backed-up by the BIOS".

totologic commented 2 years ago

Yesss it works ! Both on Mame and real hardware (a MVS slot).

Actually the Makefile (printf '\x00\x10\x40\x00\x00\x01') didn't work, it wrote as text in the header. So I manually changed the header with 10 00 00 40 01 00 starting at address 10E and it was fine.

I took time to test the other features on my MVS slot (credits, game loop and softdips). EVERYTHING work !!!