Ruby/Sapphire Save Data Map
This is a map of the Save data from Pokemon Ruby & Sapphire where the save file data blocks have been concatonated. See Pokemon GBA Save Format for more details.
If you have any information not listed, or you'd like to correct something I've gotten wrong, send me a note at firstname.lastname@example.org.
Bear in mind that I've not been consistent with wording here. Words/Ints are 32-bit, half-words are 16-bit. Also note that bytes are stored little-endian for 16-bit/32-bit values.
Ruby/Sapphire Data Map --------------------- === BLOCK 0 (0x0000 - 0x0F79) === === Trainer data, Pokedex status, Battle Tower stats === 0x0000 - Trainer Name (7Bytes) 0x0007 - 0xFF terminating byte? 0x0009 - Bit 0 = Gender - 0=Male, 1=Female 0x000A - Trainer ID (4Bytes) ... 0x0028 - Pokedex Owned flags (49 Bytes / 386 bits) 0x005C - Pokedex Seen flags (49 Bytes / 386 bits) ... 0x0098 - Adventure Start Time This is according to the RTC module, which seems to only start running when you first power it up. The format is 1 byte per value: DD, H, M, S - with DD being a 16-bit value. None of these are BCD, they're just integers. My tests suggest this isn't a straight up dump of the RTC at adventure start though. 0x00A0 - Save Timestamp (5 bytes) - In-game time. Same format as the Offset If the value of the RTC (+/- offset) is lower than the timestamp then it will not update any in-game timer-based events. For more details see Pokemon Ruby/Sapphire New Battery Glitch ... 0x00A8 - Battle Tower Data - (6 x 164 Bytes) ... 0x0498 - Mossdeep Trainer Data (188 Bytes) ... === BLOCK 1 (0x0F80 - 0x1EFF) === === Part Pokemon, Inventory, Pokeblock case === 0x0F80 - Your Y Position on the current map (short) 0x0F82 - Your X Position on the current map (short) 0x0F84 - The address of the current map (word) 0x0xFB4 - Map data from when you last saved. It looks like this stores actual GBA tilemap data The intention was probably to use this for temporary event rooms. 1 short per tile. Not sure what the limit is on tiles. ... 0x11B4 - Number of pokémon in party (Byte) 0x11B8 - Party Position #1 (100Bytes) 0x121C - Party Position #2 (100Bytes) 0x1280 - Party Position #3 (100Bytes) 0x12E4 - Party Position #4 (100Bytes) 0x1348 - Party Position #5 (100Bytes) 0x13AC - Party Position #6 (100Bytes) ... 0x1410 - Money (Word) 0x1414 - Coins (Halfword) ... 0x1418 - Start of Inventory Each entry consists of one short for the item ID and one short for the item quantity. In FireRed, LeafGreen and Emerald, the quantity value is XOR'd with an encryption key stored in Block 0. This is not the case for Ruby/Sapphire though. ... 0x1778 - Pokeblocks (n x 8 bytes) 0x00 - Colour 0x01 - Spicy 0x02 - Dry 0x03 - Sweet 0x04 - Bitter 0x05 - Sour 0x06 - Feel 0x07 - ??? The 'level' shown in the menu is the highest value out of the different flavours. ... === BLOCK 2 (0x1F00 - 0x2E79) === === Some item/environment variables, loamy soil status === 0x2308 - Pretty sure this is the Mirage Island random value. If the last two bytes of a pokemon you're carrying match this value then Mirage Island will appear on Route 130. ... 0x2350 - Amount of Volcanic Ash (Halfword?) ... 0x2590 - Loamy Soil (88 x 8 Bytes) These don't appear to be in any particular order... 0x00 - Berry ID (1-42) Byte 0x01 - State Byte The 3 least significant bits are used to determine plant state 1 - mound/just planted 2 - sprouting 3 - growing taller 4 - flowering 5 - fruiting In the trees that you find throught Hoenn initially, these trees have the most significant bit set to prevent them from dying. 0x02 - Minutes remaining Halfword This is the number of minutes left of the current phase (ie: sprouting) 0x04 - Number of berries Byte Obviously this is only set if the tree is fruiting. 0x05 - Water/Regrowing Byte The higher nibble's bits are set starting with the LSB to show whether the plant was watered during each phase. The lower nibble keeps count of the number of times the plant has died/expired and a berry has regrown in its place. 0x06 - Unknown. Byte 0x07 - Unknown. Byte These two may just be padding. ... 0x2988 - Start of Secret Base Data 20 x 160 Bytes ... === BLOCK 3 (0x2E80 - 0x3DFF) === === Television & Contest data === 0x377C - Television Show Data Unsure of format as yet - research needed ... 0x3D7C - Contest Hall Winner Paintings (13 x 32 Bytes) First 8 are Contest Hall Winner Paintings Last 5 are Lilycove Museum Paintings and will be blank if player has not entered any paintings yet. 0x00 - Pokemon's personality (Word) 0x04 - Pokemon's OT ID (Word) 0x08 - Pokemon's species (Halfword) 0x0A - Padding (Byte) 0x0B - Pokemon's name (10 Bytes) 0x16 - Trainer's name (7 Bytes) This is the trainer who won the contest using this pokemon, not the original trainer === BLOCK 4 Daycare, eCard related data === 0x3F1C - Daycare Pokemon #1 (80 bytes) 0x3F6C - Daycare Pokemon #2 (80 bytes) ... 0x4038 - Link Battle Results (5 x 16 Bytes) 0x00 - Name (7 Bytes) 0x07 - Padding (1 Byte) 0x08 - Unknown (Halfword?) 0x0A - Wins (Halfword) 0x0C - Losses (Halfword) 0x0E - Draws (Halfword) ... 0x4610 - Start of Mystery Event Data (0x3E7 bytes?) Mystery Event data consists of a 2byte checksum, 2 bytes of padding and then Event data. I am currently examining the Eon Ticket event in hopes of understanding how it works. From what I can tell, whenever you talk to Norman in Petalburg Gym, the game checks if an event is stored here before either displaying his default NPC text or the text saved in the Mystery Event data. I'm guessing that the event is rather specifically structured and can only provide Norman with text and an item to give you such as the Eon Ticket or Enigma Berry. For Trainer Battle e-cards see this page. If you would like to examine a save that contains the Mystery Event data drop me an email and I'll send you a copy of the .sav file. ... === BLOCK 5-13 - 0x3E00 - 0xD8FF) === === PC Box Pokemon, Box settings - spans multiple data blocks === 0x4D80 - Currently Selected Box? (Byte) 0x4D84 - Start of Box Pokemon data (80Bytes x 30 PKMN x 14 Boxes) ... 0xD0C4 - Start of Box Names (9Bytes x 14 Boxes) 0xD142 - Box Wallpaper (14 Bytes) ...
There is an additional block of save data positioned after the main 2 save files. This block contains the data on the Hall of Fame PC.
There's some bits and bobs that I've spotted in the data but have no idea of the structure, while some other things I haven't a clue about.
- TV Programme Data
- Trainers' Eyes
- A way of determining version
There's much more of course.
Ribbons aren't really documented anywhere else so I'd probably better cover them here.
In the 'Misc' data block of each pokemon, there is a single Word value that stores the ribbons attached to that pokemon. It's a bit odd as there are significantly more that 32 ribbons so I'll try to break it down here.
The first 15 bits tell us what contest ribbons the pokemon holds, but it's not a case of it being 1 bit per ribbon. Instead, what he have is 3 bits per ribbon, each showing a value representing the number of ranks that pokemon has achieved per contest type:
- 0 - 2 -> Cool Rank
- 3 - 5 -> Beauty Rank
- 6 - 7 -> Cute Rank
- 9 -11 -> Smart Rank
- 12-14 -> Tough Rank
Each value gives us from 0 - 4, 0 being no rank, 4 being master rank. When a pokemon is any rank higher than 1, they will have all the ribbons for earlier ranks as well.
The next few bits give specific ribbons:
- Bit 15 -> Champion Ribbon
- Bit 18 -> Artist Ribbon
- Bit 19 -> Effort Ribbon
- Bit 24 -> Cleared All Difficulties Ribbon (Purified on Colusseum)
There are a number of other ribbons that seem impossible to fit here. I'm currently investigating these.