profi200 / open_agb_firm

open_agb_firm is a bare metal app for running GBA homebrew/games using the 3DS builtin GBA hardware.
GNU General Public License v3.0
860 stars 42 forks source link

Sonic The Hedgehog - Genesis not saving #34

Closed HTV04 closed 3 years ago

HTV04 commented 3 years ago

I know, it's an absolutely horrible port, but bear with me.

Sonic The Hedgehog - Genesis doesn't seem to be able to save. According to No-Intro, it uses EEPROM_v124, like Mario & Luigi: Superstar Saga does.

Upon booting the game, the effects of the game being unable to save start to appear. The music and sound options are set to off, and the game has a "Resume" button that isn't supposed to appear yet.

When playing the game, the "Saving..." pop-up still appears as if saving were working, but it's probably in vain, because after I turned the game off and checked my SD card, there was no .sav file.

I guess this has something to do with the buggy EEPROM detection. Can this be fixed at all before a save type database is implemented?

Speaking of save type databases, I believe VBA-M has one. Not sure about mGBA though.

profi200 commented 3 years ago

You can add an override here and compile it: https://github.com/profi200/open_agb_firm/blob/kernel_experiments/source/arm11/open_agb_firm.c#L211-L215

HTV04 commented 3 years ago

Sounds good. I'll just encountered a similar issue with Mega Man & Bass, which saves using the wrong type. I might make an extended list of exceptions on my fork and create a pull request for it.

HTV04 commented 3 years ago

I think I found the culprit. EEPROM v122 and EEPROM v124 appear to be set to the wrong values), they should be 64k and 8k respectively, instead of 8k and 64k. I made a commit on my fork, would you be willing to compile it for me? I don't have the compilation setup for open_agb_firm ready yet.

If I'm right, all of the official games in the exception list can be removed, with the obvious exception of the Classic NES titles. EDIT: On second thought, I think it just varies between the two. According to this, GBA EEPROM save types are known for not being consistent, and the best course of action is to use a save type database. In the meantime, I would recommend changing the "confirmed" status for the EEPROM save types, because they aren't concrete.

Also, why is EEPROM 4k referred to as 8k instead? I don't think there is an EEPROM 8k.

GBA save database used for reference: https://github.com/mamedev/mame/blob/master/hash/gba.xml

profi200 commented 3 years ago

The V strings don't say anything about the actual save type. It's just SDK strings.

8k because the hardware actually simulates an 8k EEPROM but it's compatible with 4k.

HTV04 commented 3 years ago

Are you sure? No-Intro and the MAME DB only contain references to EEPROM 4k, and the save type discussion post I linked before says there are only two types of EEPROM saves, 512B and 8KB.

Forgive me if I'm wrong though, I'm just confused on what you mean by "the hardware simulates an 8k EEPROM."

Anyways, I'm currently looking into how to detect EEPROM saves better based on VBA-M's code, in order to fix this whole issue.

EDIT:

So VBA-M's source didn't seem to help much for me. However, I found this: https://densinh.github.io/DenSinH/emulation/2021/02/01/gba-eeprom.html

The "EEPROM size detection" section was of interest:

This n is what you can deduce the EEPROM size from. A trick to detect the EEPROM size is to keep it ambiguous until the first (read) request is made. Requests have to be done by DMA, since normal transfers via LDRH/STRH are too slow, and don’t keep the right bits set during the transfer.

Since DMA channel 3 is the only DMA channel that can access ROM, you could, on the first (read) access, check the transfer length of DMA channel 3. If it’s of length 9, a 6 bit address will be sent, and the EEPROM is (likely) a 512 byte EEPROM. If it’s of length 17, a 14 bit address will be sent, and the EEPROM is (likely) an 8KB EEPROM.

This method is not perfect though. Some games, like the NES classic series, try to trick you into thinking it’s the wrong EEPROM size, by doing a transfer of the “wrong” length. Your best bet will be a game database, or some sort of hybrid approach.

I have no idea how to implement this though, as the save functions seem to be weird. Could this help at all?

profi200 commented 3 years ago

This is not emulation. The whole GBA including the cart (the ROM is stored in FCRAM) is actual hardware inside the 3DS SoC. The 3DS side just captures video frames, rotates them and outputs that to the LCD. There is no way to auto detect the save type at runtime. I also tried searching for common patterns in the code before but there are too many differences between SDKs/games. I want something solid without false positives.

HTV04 commented 3 years ago

I see. Anyways, I think it's safe to close this and move discussion to #9.