ipatix/agbplay

Possible error in checksum calculation? Misdetects Sonic Advance (Japan) (En,Ja) (Rev 1) as having bad checksum.

Closed this issue · 4 comments

I have a clean Sonic Advance (Japan) (En,Ja) (Rev 1).gba (No-Intro ROM naming) with md5sum 9e02f1c9f26f40905d43188b2bd2d98e, which matches No-Intro. When trying to open it with agbplay, I get the following error:

Loading ROM...
Loaded ROM successfully
ROM verification: Bad Header Checksum: 2D - expected 2E

For the sake of interest, I edited the checksum to 2E as agbplay wanted, and it happily opens the (now hacked, bad) ROM.

EDIT: Highly likely not related to the above, but subsong 0013 in Sonic Advance (with above ROM and hacked checksum 2E) also sounds really off-key and unpleasant.

I'm not sure what's wrong with the ROM you have, but I'd guess that the No-Intro database might have a bad one. Does your game boot up with an original GBA BIOS? Because if the checksum is bad, the game shouldn't boot on console / on emulator with BIOS.

And I am pretty certain the checksum calculation is right.

On the other hand, I could just ignore the checksum all the way, but because I was pretty lazy back then I remember the code not having a lot of file consistency checks yet. So in this case the code would probably need some more code rework.

Update: So I played around a bit and found an image having the correct header checksum of 0x2E.
It's md5 is: b62f11b1d014d5c5c2dd703676cb443d

That md5 appears in No-Intro as Sonic Advance (Japan) (En,Ja). The Japanese version of Sonic Advance received a second pressing (the Rev 1 ROM I'm using) with a relatively major bug fix; see TCRF. Checksum issue aside, I'm aware sometimes a bad dump will make its way into a DAT as a "second revision", but this is not one of those cases. There are definite, deliberate changes in the Rev 1 ROM like the updated revision and build date as seen on TCRF. This doesn't rule out that it's a bad dump of a revised pressing of the game, but this next might:

I'm able to confirm that the Rev 1 ROM as it exists in No-Intro launches through the BIOS on both emulators (tested endrift's mGBA) and hardware (tested a Nintendo DS Lite with GBA flash cart and Sonic Advance (Japan) (En,Ja) (Rev 1).gba). It probably goes without saying that my hacked Rev 1 ROM with checksum 2E does not work through the BIOS on either mGBA or hardware. I don't mean to question your expertise, but it does seem like agbplay is the outlier in this case, other sources all seem to confirm that No-Intro's ROM is correct.

@zowayix from the mGBA IRC channel was able to get this solved.

    // check checksum
    uint8_t checksum = (*data)[0xBD];
    int check = 0;
    for (size_t i = 0xA0; i < 0xBC; i++) {
        check -= (*data)[i];
    }

The problem here is that the checksum calculation correctly spans from 0xA0 to 0xBC. To quote from GBATEK:

0BDh - Complement check, 1 Byte
Header checksum, cartridge won't work if incorrect. Calculate as such:
chk=0:for i=0A0h to 0BCh:chk=chk-[i]:next:chk=(chk-19h) and 0FFh

Your code is checking up to < 0xBC, which is not inclusive of 0xBC. And what's in 0xBC?

0BCh - Software version number
Version number of the game. Usually zero.

Usually zero, but not in revised editions like Sonic Advance (Japan) (En,Ja) (Rev 1).

So it's just an off-by-one where you should be checking < 0xBD instead of < 0xBC. I made this change on my end and it seems like nothing broke, everything that worked yesterday still works, plus so does my clean Sonic Advance ROM.

Thanks again to zowayix for figuring this out.