News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: unable to correctly calculate checksum for one SNES game  (Read 1179 times)

tetrismegistus

  • Newbie
  • *
  • Posts: 1
    • View Profile
unable to correctly calculate checksum for one SNES game
« on: March 01, 2018, 03:02:08 pm »
Hi,

So I made myself a little SNES rom info tool:

https://github.com/tetrismegistus/snes_rom_info

It seems to be working as intended so far, except when I try to verify the Checksum on two different Final Fantasy III roms.

Code: [Select]
Game Title: b'FINAL FANTASY 3     '
SMC Header: No
Rom Mapping: HiRom + FastROM
Rom Type: ROM and Save RAM
Rom Size: 32 MegaBits
SRAM Size: 64 Kilobits
Country: USA
Licensee: Nintendo
Game Version: 1
Checksum Complement: 759f
Specified Checksum: 8a60
Calculated checksum: 9606

000ffc0  46 49 4e 41 4c 20 46 41  4e 54 41 53 59 20 33 20  |FINAL FANTASY 3 |
000ffd0  20 20 20 20 20 31 02 0c  03 01 33 01 9f 75 60 8a  |     1....3..u`.|

Code: [Select]
Game Title: b'FINAL FANTASY 3     '
SMC Header: No
Rom Mapping: HiRom + FastROM
Rom Type: ROM and Save RAM
Rom Size: 32 MegaBits
SRAM Size: 64 Kilobits
Country: USA
Licensee: Nintendo
Game Version: 0
Checksum Complement: a0cd
Specified Checksum: 5f32
Calculated checksum: 6ad8

000ffc0  46 49 4e 41 4c 20 46 41  4e 54 41 53 59 20 33 20  |FINAL FANTASY 3 |
000ffd0  20 20 20 20 20 31 02 0c  03 01 33 00 cd a0 32 5f  |     1....3...2_|

In both examples the Specified Checksum (the one in the ROM Header) differs from Calculated checksum.

In every other game I've tried, those with and without SMC headers:

Breath of Fire II (USA).sfc
Final Fantasy II (USA).sfc
Secret of Mana (USA).sfc
Shadowrun (USA).sfc
Super Mario World (USA).sfc
Super Metroid (Japan, USA) (En,Ja).sfc

I get the expected checksum.  What could I be doing wrong with Final Fantasy III?

See the link above to see the source code, the checksum calculation is basically:

Code: [Select]


    def calculate_checksum(self):
        f = open(self.filename, 'rb')
        f.seek(self.smc_offset)
        chunk_sums = []
        for chunk in read_in_chunks(f):
            total = 0
            for byte in chunk:
                total += byte
            chunk_sums.append(total)

        total = 0

        for csum in chunk_sums:
            total += csum

        return '{:04x}'.format(total & int('FFFF', 16))


def read_in_chunks(file_object, chunk_size=500000):
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data


MathOnNapkins

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 628
  • Who ya gonna call
    • View Profile
    • Arc-Nova - Rohmackin' and Chiptunin'
Re: unable to correctly calculate checksum for one SNES game
« Reply #1 on: March 02, 2018, 10:41:21 am »
Looking around elsewhere suggests to me that you probably need to sum the first 16 megabits (2 megabytes) as normal, but double the sum you calculate on the last 8 megabits. Why should you need to do this? Best I can tell, Nintendo wanted developers to visualize their game image as a power of 2 in terms of megabits. So imagine creating a mapping that takes Final Fantasy III into a 32 megabit file. The first 16 megabits would go at the beginning, as you'd expect, then you'd add the remaining 8 megabits, then duplicate that same 8 megabits across the last part of the file. Other sources refer to this as "mirroring".

References:
https://www.zophar.net/forums/showthread.php?t=6153
https://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map

Also note that according to the internal header the FF III rom is 32 megabits, even though the game is only 24 megabits in actuality. Thus this is consistent with the preceding in some sense. You could also conclude from this that Nintendo's format for expressing game image size is glaringly limited...

phonymike

  • Jr. Member
  • **
  • Posts: 10
    • View Profile
Re: unable to correctly calculate checksum for one SNES game
« Reply #2 on: May 28, 2018, 01:35:01 am »
Hey you probably figured it out by now, but I just did a quick checksum with a hex editor and got FF3 checksum correct. Totally ignore (or just delete) the 0x200 byte copier header on smc files, that's not from Nintendo.
Code: [Select]
first 16 mbit: 0x767E
  next 8 mbit: 0xF45A
----------------------
16 bit result: 0x6AD8 WRONG

That's the checksum for 24 mbits, the header says 32 mbit. So let's add that up again and fill in so it's 32 mbits.
Code: [Select]
  first 16 mbit: 0x767E
    next 8 mbit: 0xF45A
mirrored 8 mbit: 0xF45A
-----------------------
  16 bit result: 0x5F32 YES!

Fullsnes has some good info and some weird sized roms

https://problemkaputt.de/fullsnes.htm#snescartridgeromheader