Save File Format

Revision as of 17:56, 29 April 2021 by Seil (talk | contribs)

This page describes the save file format of Battle For Bikini Bottom.

Structure

If you're editing a GCI file (exported from Dolphin -> Memory Card Manager), it'll begin with the GCI header and banner + icon data. Assuming that's all still the default, the actual save file data should start at offset 0x5880.

Starting at 0x5880 is 512 null (0) bytes, then the string "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan", followed by 599 more null bytes.

The rest of the save file is structured in blocks, which have the following format:

Offset Size Type Name
0 4 int id (GDAT, LEDR, ROOM, etc.)
4 4 int blockSize (size of the whole block, which includes padding bytes for alignment)
8 4 int bytesUsed (number of bytes actually used)

Blocks are padded with the value 0xBF.

Block Types

GDAT

Offset Size Type Name
12 4 int checksum (CRC-32)

blockSize is usually just 1, i'm not sure what that means checksum is calculated using the CRC-32 algorithm on the rest of the save file, starting from the LEDR block. The checksum HAS to be correct or else you'll get a "load failed!" screen. I don't know what the parameters are supposed to be for the algorithm yet, but I made an AR code to disable the bypass the checksum validation altogether (GameCube NTSC version only):

0403ed94 60000000

Use that and you can freely edit your save file without worrying about the checksum

LEDR

Offset Size Type Name
12 32 char[] gameLabel (string. The text to show for the save file. Bikini Bottom, Jellyfish Fields, etc.)
44 4 int progress (The percentage of the game completed. Can be negative :O)
48 12 null unknown
60 1 char thumbIconIdx (which game thumbnail to show on the right)

0 - Bikini Bottom
1 - Jellyfish Fields
2 - Downtown Bikini Bottom
3 - Goo Lagoon
4 - Poseidome
5 - Rock Bottom
6 - Mermalair
7 - Sand Mountain
8 - Industrial Park
9 - Kelp Forest
10 - Flying Dutchman's Graveyard
11 - SpongeBob's Dream
12 - Chum Bucket Lab
13 or higher - Bikini Bottom

ROOM

Offset Size Type Name
12 4 int sceneid (the last level you were in)

PREF

Offset Size Type Name
12 4 int soundMode (0 = mono, 1 = stereo)
16 4 float musicVolume
20 4 float sfxVolume
24 4 int rumble (0 = off, 1 = on)

SVID

Offset Size Type Name
12 4 int version (idk what this is)

Other Blocks

After this is a bunch of blocks containing "serialized" data, which are the game's way of storing persistent scene states as well as player and global counter states. The format is very weird, and not easily editable with a hex editor because values are sometimes written as single bits, which offsets future values by the number of bits written, which causes values to cross byte boundaries, and yeah it's kind of a mess. I'll explain more of this soon

Scene IDs

These can be B101, DB01, JF01, etc.

Contains saved states for every object with the Persistent flag set (look in Industrial Park). The last value of a counter, the pressed/unpressed state of a button, the enabled/disabled state of a dispatcher, etc.

PLYR

Max health, shinies, spatulas, socks, collectibles

CNTR

Cheats, encountered robots, other stuff


After this is the following block:

SFIL

Offset Size Type Name
12 8 char[] "RyanNeil"
20 31200 byte[] Padding