Save data structure in Generation I

The save data structure for Generation I is stored in the cartridge's volatile battery-backed RAM chip (SRAM), or as a ".sav" file from most emulators. The structure consists of 32 KB of data divided between 4 banks each 8KB or 0x2000 and overall contains potentially hundreds of variables, though there are quite a few areas that are either completely left alone, only read from, or only written to. There are also a number of areas that are only used in certain game states that can't ever be saved in including various runtime-only data and thus useless in save data since it will just be either immediately be overwritten on gameplay or when the game reaches a certain state.

Most areas, therefore, can freely be written to with custom data or at the very least cleared out. Most of these areas will never be touched by the game unless the hidden "Clear Save Dialog" is triggered on the title screen, some sections of the data will even load untouched into the in-game memory during gameplay and re-saved back on each save. The "Clear Save Dialog" is the only way to truly format all bytes in the data to zero and will never be called automatically, otherwise only used areas are cleared out making many areas immune to even starting a new game or when corruption is detected.

3 Sections of the data are protected with a simple integrity check using a checksum to verify data corruption such as the battery dying or power cut during save, potential hardware failure or issues, etc... Of course data can be corrupted in many other ways including triggering various game glitches. PC boxes have additional checksums for each box contents on the bank in addition to the normal whole-bank checksum. The Hall of Fame is the only section of used data which doesn't have a checksum and furthermore lies on an unusual bank number because it's so large.

Banks Overview
''Note: These values apply to the North American Pokémon Red, Blue, and Yellow games. They could be different for other releases.''

The 32KB save data is divided into 4 banks each 8KB in size or 0x2000

 Bank 0 - Scratch and Hall of Fame

Consists of 3 sprite buffers which seem to contain misc or varying data and the Hall of Fame because of its size (4,800 bytes).

 Bank 1 - Main

The primary bank for just about all data across the game, most is directly loaded into the in-game memory byte-by-byte. It contains hundreds of variables including a full byte-by-byte copy of the current PC box.

 Bank 2 - Boxes 1-6

Storage for PC boxes 1-6

 Bank 3 - Boxes 7-12

Storage for PC Boxes 7-12

Loading
When it comes to loading, the game only mainly focuses on bank #1, and much of it's contents are directly loaded byte-by-byte directly into WRAM at different addresses, as such, different offsets can be applied to convert from WRAM to the save data and back. Those are provided where possible.

Other banks are loaded either on certain game states, on certain events, or as needed. Upon switching Pokémon boxes, for example, the contents of the new bank are copied to bank 1 from either bank 2 or 3 and events that use hall of fame data causes either one of or the latest Hall of Fame record to be loaded into WRAM.

Checksum
Used to validate the integrity of saved data.

The checksum in Generation I is only 8 bits and has a single copy of it. If this value is incorrect, the error message "The file data is destroyed!" will appear after the title screen, and the continue option will not appear in the menu.

The algorithm used to calculate the checksum is as follows:


 * Initialize the checksum to 0
 * For every byte from 0x2598 to 0x3522, inclusive, add its value to the checksum
 * Invert the bits of the result

An equivalent way to achieve the same result is:


 * Initialize the checksum to 255
 * For every byte from 0x2598 to 0x3522, inclusive, subtract its value from the checksum

The checksum neatly validates the data it encomapsses but there are several checksums for different sections of data in different banks. Those are all described below.

Bank 0
This is the Hall of Fame and scratch bank. It can essentially be regarded mostly as a misc bank with some large data, various scratch buffers used only occasionally during run-time, and lots and lots of unused space. None of the data in this bank is validated or checked for corruption.

The bank starts at address 0x0000 and is 0x2000 in size.

 Scratch Buffers

During gameplay, the game sometimes uses these buffers as extra graphical buffers for misc stuff. As far as has been observed, they can safely by cleared, although they are used occasionally during gameplay so anything cleared or written to them will just be overwritten.

 Unused

Unused here refers to data that the game completely does not touch in any way. Also none of the data is ever loaded from or saved to. The only way the game can ever be made to wipe or do anything to these areas is by invoking the hidden "Clear Save File" dialog manually yourself at the title screen.

 Hall of Fame

Refer to the Hall of Fame data structure above which goes into all the detail. The Hall of Fame code is a bit messy and it's memory structure the same, memory load addresses can't be provided well.

Bank 1
This is the prime bank that all of the information is stored in that's ever needed or used in gameplay. Bank 2 and 3 really pull into data into Bank 1 when needed or are occasionally updated.

Furthermore most sections in this bank directly correspond byte-by-byte to their counterparts in in-game memory meaning you can apply a simple offset to translate the save data address to and from the in-game memory address. It also means unused areas in such sections will be loaded and available in-game and even saved back to save data.

As such, this is a mammoth of a bank and contains hundreds of variables.

The bank starts at address 0x2000 and is 0x2000 in size.

 Unused

Unused here refers to data that the game completely does not touch in any way. Also none of the data is ever loaded from or saved to. The only way the game can ever be made to wipe or do anything to these areas is by invoking the hidden "Clear Save File" dialog manually yourself at the title screen.

 Player Name

Player name, even though the game allocates space for 10 characters + Terminator, oddly enough, the in-game prompt only allows typing 7 possibly to fit within certain dialogue maybe.

 Main Data

This area contains most of the entire memory state from WRAM and is copied byte-by-byte.

 Sprite Data

This area contains detailed sprite information in 2 section for the map and is copied byte-by-byte. It's not the only sprite information, there are actually 2 other areas which contain more sprite information for the current map located in "Main Data"

 Party Data

Contains information on the players current party and is copied byte-by-byte

 Current box data

A byte-by-byte copy of the current PC box from either bank 2 or 3 and is byte-by-byte copied to memory on each load. In this way, the game only deals with 1 PC box in-memory at anytime and that PC box is copied here for easy and quick transfer back to memory on each load.

 Tileset Type

The current tileset of where you are such as a specific place, store, dungeon, or just in the outside world.

 Main Data Checksum

This checksums from Player Name to Tileset Type, basically the only things which are not checksummed is the unused areas.

Main Data
Goes over all the elements inside of Main Data, one of the most comprehensive areas in the save data. To translate the offset to in-game memory and/or back simply use the difference number mentioned in the above table, 0xAD54.

 Padding

Padding is essentially extra space assigned to an area in memory. In other words, the space is larger than the variables makeup and it could be at the start, end, middle, or some combination. It's unknown truly if the padding is ever used, there are certainly many ways for it to be used such as in various game unions with shared space. Therefore it could be considered possibly unused.

<span id="bank1_main_pokedex"> Pokédex Seen/Owned

Represents the specific Pokédex entries that have been either seen or owned during gameplay.

Pokémon are indexed by their usual Pokédex order, meaning the order is the same as in the National Pokédex. However, indexes begin counting at 0, rather than 1.

1 bit is used to represent whether a given Pokémon has been seen/owned. Bits are ordered within bytes from lowest to highest, starting with the first byte. Therefore, the exact bit can be extracted from the list using the following formula:

Bit = ( Data[ RoundDown(PokéNum / 8) ] / 2 ^ (PokéNum Mod 8) ) AND 1

Or in C-style code (shift occurs before other bitwise operations):

Bit = Data[PokéNum >> 3] >> (PokéNum & 7) & 1;

Example:

Let us say that we want to know whether #120 has been seen/owned:


 * PokéNum becomes 119, since it is 0-based.
 * The byte of the list in which bit 119 is located is = 119 / 8 = 14
 * The bit within that byte is = 119 Mod 8 = 7
 * Dividing the byte value by 2 ^ Bit, or shifting right by Bit, moves the bit to the least-significant position
 * Performing a bitwise AND with 1 will remove all but the least-significant bit

Entry #152:

As the bit lists are packed into 19 bytes, there is actually space for 152 entries. The last entry, bit 7 of byte 18, does in fact represent an entry #152 in the Pokédex. However, it is simply a copy of.

<span id="bank1_main_bag"> Bag Items

Follows Item List Data Structure with a capacity of 20.

<span id="bank1_main_money"> Money

This is in Binary Coded Decimal, in other words, it's interpreted as decimal even if viewed as hexadecimal so don't use Hexadecimal A-F.

Represents how much money the character has. The figure is a 6-digit number, 2 digits per byte, encoded as, where each digit is allocated a full 4 bits.

This figure is still big-endian.

Essentially it's interpreted as decimal even if viewed as hexadecimal so don't use Hexadecimal A-F.

<span id="bank1_main_rival"> Rival Name

Rival name, even though the game allocates space for 10 characters + Terminator, oddly enough, the in-game prompt only allows typing 7 possibly to fit within certain dialogue maybe.

<span id="bank1_main_options"> Game Options

Options are stored in one byte:
 * bit 7 (MSB): battle effects ('1' for <sc>No</sc>, '0' for <sc>Yes</sc>)
 * bit 6: battle style ('1' for <sc>Set</sc>, '0' for <sc>Switch</sc>)
 * bit 4: sound ('0' for <sc>Mono</sc>, '1' for <sc>Stereo</sc>)
 * bit 2-0: text speed ('001' for <sc>Fast</sc>, '011' for <sc>Normal</sc>, '101' for <sc>Slow</sc>)

In Pokémon Yellow:
 * bit 5-4: sound ('00' for <sc>Mono</sc>, '01' for <sc>Earphone1</sc>, '10' for <sc>Earphone2</sc>, '11' for <sc>Earphone3</sc>)

<span id="bank1_main_badges"> Badges

The eight badges are stored on eight bits, one bit for each badge, being '1' is the badge is acquired, '0' otherwise.

From MSB to LSB, badges are in this order: Boulder, Cascade, Thunder, Rainbow, Soul, Marsh, Volcano, Earth.

<span id="bank1_main_pikachu"> Pikachu Friendship

Represents the friendship level of the starter. For Red and Blue, this value is unused.

<span id="bank1_main_letter"> Letter Delay

bit 0: If 0, limit the delay to 1 frame. Note that this has no effect if      the delay has been disabled entirely through bit 1 of this variable or bit 6 of Various Flags 5 bit 1: If 0, no delay.

<span id="bank1_main_playerid"> Player ID

Randomly generated 16-bit id for the player and their Pokémon most used in Trades and whatnot.

<span id="bank1_main_musicid"> Music ID

Which music or sound plays in this map

<span id="bank1_main_musicbnk"> Music Bank

Which bank the music or sound is in

<span id="bank1_main_contrast"> Contrast ID

The game contrast, really it's ever only used for the one cave that requires flash because without flash in the cave the contrast would be really bad.

Offset subtracted from FadePal4 to get the background and object palettes for the current map. Normally, it is 0. it is 6 when Flash is needed, causing FadePal2 to be used instead of FadePal4

<span id="bank1_main_curmap"> Current Map

Current Map ID the player was last at

<span id="bank1_main_ulcorner"> UL Corner Cur View Tile Block Ptr

pointer to the upper left corner of the current view in the tile block map

<span id="bank1_main_xycoord"> X/Y Coord

Player X & Y Coordinates

<span id="bank1_main_xyblockcoord"> X/Y Block Coord

Same as X & Y Coord but in blocks instead

<span id="bank1_main_lastmap"> Last Map

Last map the player visited

<span id="bank1_main_curtileset"> Current Tileset

Current tileset in map

<span id="bank1_main_mapsize"> Map Height/Width Blocks

Height and width of the map in blocks

<span id="bank1_main_mapptrs"> Map Data/Text/Script Pointers

Pointers to various code for the current map to function as expected

<span id="bank1_main_mapconn"> Map Connections and NSEW Connections

A bit field describing the connections for the current map, are there any connecting maps to the map your on?

If there are, the details will be in the specific connection data mentioned in the connection data structure.

I must forewarn that maps and map connections can be a very complicated subject and often requiring some specific math formulas.

<span id="bank1_main_spritesetid"> Sprite Set ID(s)

Sprite set for the current map (11 sprite picture ID's) followed by sprite set ID for the current map

<span id="bank1_main_objdataptr"> Object Data Pointers Tmp

Unknown, most likely just a scratch 16-bit value for various object pointers.

<span id="bank1_main_oob"> Out of Bounds Tile

You have a map defined and then you have the are outside the map that will crash the game if moved to. This is the tile used to fill in all invalid areas of the current map.

The tile shown outside the boundaries of the map

<span id="bank1_main_warpcount"> Warp Count

Number of warps on the current map

<span id="bank1_main_warpentry"> Warp Entries

List of warp entries on the current map, specific format unknown

<span id="bank1_main_warpdest"> Warp Destination ID

Unknown but here's the description which talks about a particular value of this id.

If $ff, the player's coordinates are not updated when entering the map

<span id="bank1_main_signcount"> Sign Count

Number of signs on the map, up to 16

<span id="bank1_main_signcoord"> Coordinates of the signs

Follows sign coordinate data structure, allows for up to 16 signs.

<span id="bank1_main_signtxtids"> Sign Text Ids

Text ID of each sign, format is unknown but there are 16 bytes so it's assumed that each byte refers to a single text block.

<span id="bank1_main_spritecount"> Sprite Count

Number of sprites on the current map

<span id="bank1_main_xyofflastwarp"> X/Y Offset since last special warp

These two variables track the X and Y offset in blocks from the last special warp used they don't seem to be used for anything

<span id="bank1_main_spritedata"> Sprite Data/Extra

Various sprite data for up to 16 sprites, follows data structure on sprite data.

<span id="bank1_main_map22metasize"> Map 2x2 Meta Height and Width

Map height and width in 2x2 meta tiles

<span id="bank1_main_vramptr"> Map View VRAM Pointer

The address of the upper left corner of the visible portion of the BG tile map in VRAM

<span id="bank1_main_playerdir"> Player Direction

"moving" refers to both walking and changing facing direction without taking a step.

Player Moving

if the player is moving, the current direction. If the player is not moving, zero. Map scripts write to this in order to change the player's facing direction

Plater Last Stop Direction

The direction in which the player was moving before the player last stopped

Player Direction

If the player is moving, the current direction, if the player is not moving, the last the direction in which the player moved

<span id="bank1_main_tilesetbnk"> Tileset Bank

Bank current tileset can be found in

<span id="bank1_main_tilesetptrs"> Tileset Pointers

Various pointers to how the tiles should be managed and treated in-game. Some extra descriptions are quoted below:

Tileset Block Pointer

Maps blocks (4x4 tiles) to tiles

Tileset Collision Pointer

List of all walkable tiles

<span id="bank1_main_tilesettalk"> Tileset Talking over Tiles

Tiles that can be talked over, as in, a tile between you and an NPC where you can still interact with the NPC even though your not directly in front of them. List of such valid tiles.

<span id="bank1_main_tilesetgrass"> Tileset Grass Tiles

Unknown, presumably tiles where wild Pokémon can be found and which engages in a battle since more than just grass triggers a wild battle such as the mansion floor or cave floor.

<span id="bank1_main_boxitems"> Box Items

Items found in your PC's item box, follows the item box data structure and has a capacity of 50.

<span id="bank1_main_curpcbox"> Current PC Box

Indicates which PC box is currently selected, minus 1. That is to say, box 1 is represented as 0, and box 12 is represented as 11.

bits 0-6: box number bit 7: whether the player has changed boxes before

<span id="bank1_main_hofrecordcnt"> Hall of Fame Record Count

Hall many hall of fame victories you've had in this save file. The game can have up to 50 before it starts over and begins erasing the oldest records.

When loading the hall of fame record data it only pulls this record number temporarily into RAM and clears it out when done since it shares data space with important variables.

<span id="bank1_main_slotcoins"> Slot Coins

How much coins player has left to gamble with

Represents how much coins the character has. The figure is a 4-digit number, 2 digits per byte, encoded as, where each digit is allocated a full 4 bits.

This figure is still big-endian.

Essentially it's interpreted as decimal even if viewed as hexadecimal so don't use Hexadecimal A-F.

<span id="bank1_main_missobjs"> Missable Objects

bit array of missable objects. set = removed

<span id="bank1_main_scratch"> Scratch

Temp copy of c1x2 (sprite facing/anim)

<span id="bank1_main_misslsts"> Missable List

Follows the missable list data structure

<span id="bank1_main_complscripts"> Completed Scripts

Long array of completed scripts for all maps and even some NPCs, broken down further below.

<span id="bank1_main_ownedhidnitms"> Owned Hidden Items/Coins

Bit array of hidden items and coins player has found

<span id="bank1_main_walkbiksurf"> Walking, Biking, or Surfing

Is the player walking, biking, or surfing currently?

<span id="bank1_main_townsvis"> Towns visited

Bit array of towns player has ever visited

<span id="bank1_main_safsteps"> Safari Steps

Number of steps for the safari zone taken so far

Starts at 502

<span id="bank1_main_fossgiven"> Fossil Given and Result

Item given to cinnabar lab and Pokémon that will result from the item

<span id="bank1_main_enmpkmtrn"> Enemy Pokémon or Trainer Class

Shared space between 2 variables


 * 1) Enemy Pokémon ID in Wild Pokémon Battle
 * 2) Trainer class of Trainer Battle

<span id="bank1_main_jumpingyscrn"> Player Jumping Y Screen Coords

Unknown really, pertains to the sections of code that deal with the jumping mechanic.

<span id="bank1_main_rivalst"> Rival Starter

Pokémon Rival Picked

<span id="bank1_main_plrstart"> Player Starter

Pokémon Player Picked

<span id="bank1_main_bouldsprite"> Boulder Sprite Index

Sprite index of the boulder the player is trying to push

<span id="bank1_main_lstblkmap"> Last Blackout Map

Unknown

<span id="bank1_main_dstmap"> Destination Map

Destination map (for certain types of special warps, not ordinary walking)

<span id="bank1_main_tileinfrntorcoll"> Tile in front of Boulder or Collision

Used to store the tile in front of the boulder when trying to push a boulder. Also used to store the result of the collision check ($ff for a collision and $00 for no collision)

<span id="bank1_main_dgnwarpdest"> Dungeon Warp Destination

Destination map for dungeon warps

<span id="bank1_main_whichdgnwarp"> Which dungeon warp used

Which dungeon warp within the source map was used

<span id="bank1_main_flags1"> Various Flags 1

bit 0: using Strength outside of battle bit 1: set by IsSurfingAllowed when surfing's allowed, but the caller resets it after checking the result bit 3: received Old Rod bit 4: received Good Rod bit 5: received Super Rod bit 6: gave one of the Saffron guards a drink bit 7: set by ItemUseCardKey, which is leftover code from a previous implementation of the Card Key

<span id="bank1_main_defgyms"> Defeated Gyms

Redundant because it matches Earned Badges used to determine whether to show name on statue and in two NPC text scripts

<span id="bank1_main_flags2"> Various Flags 2

Bit 0: if not set, the 3 minimum steps between random battles have passed Bit 1: prevent audio fade out

<span id="bank1_main_flags3"> Various Flags 3

This variable is used for temporary flags and as the destination map when warping to the Trade Center or Colosseum.

bit 0: sprite facing directions have been initialised in the Trade Center bit 3: do scripted warp (used to warp back to Lavender Town from the top of the Pokémon tower) bit 4: on a dungeon warp bit 5: don't make NPCs face the player when sPokén to Bits 6 and 7 are set by scripts when starting major battles in the storyline, but they do not appear to affect anything. Bit 6 is reset after all battles and bit 7 is reset after trainer battles (but it's only set before trainer battles anyway).

<span id="bank1_main_flags4"> Various Flags 4

bit 0: the player has received Lapras in the Silph Co. building bit 1: set in various places, but doesn't appear to have an effect bit 2: the player has healed Pokémon at a Pokémon center at least once bit 3: the player has a received a Pokémon from Prof. Oak bit 4: disable battles bit 5: set when a battle ends and when the player blacks out in the overworld due to poison bit 6: using the link feature bit 7: set if scripted NPC movement has been initialised

<span id="bank1_main_flags5"> Various Flags 5

bit 0: NPC sprite being moved by script bit 5: ignore joypad input bit 6: print text with no delay between each letter bit 7: set if joypad states are being simulated in the overworld or an NPC's movement is being scripted

<span id="bank1_main_flags6"> Various Flags 6

bit 0: play time being counted bit 1: remnant of debug mode? not set by the game code. if it is set 1. skips most of Prof. Oak's speech, and uses NINTEN as the player's name and SONY as the rival's name 2. does not have the player start in floor two of the player's house (instead sending them to Last Map) 3. allows wild battles to be avoided by holding down B bit 2: the target warp is a fly warp (bit 3 set or blacked out) or a dungeon warp (bit 4 set) bit 3: used warp pad, escape rope, dig, teleport, or fly, so the target warp is a "fly warp" bit 4: jumped into hole (Pokémon Mansion, Seafoam Islands, Victory Road) or went down waterfall (Seafoam Islands), so the target warp is a "dungeon warp" bit 5: currently being forced to ride bike (cycling road) bit 6: map destination is Last Blackout Map (usually the last used Pokémon center, but could be the player's house)

I will say don't get your hopes up with debug mode, it may work by setting it here given the timeline it loads the save data but the game may try to unset it since there are numerous measures in place particular when starting the game to ensure it's not set.

<span id="bank1_main_flags7"> Various flags 7

bit 0: running a test battle bit 1: prevent music from changing when entering new map bit 2: skip the joypad check in CheckWarpsNoCollision (used for the forced warp down the waterfall in the Seafoam Islands) bit 3: trainer wants to battle bit 4: use variable Current Map Script instead of the provided index for next frame's map script (used to start battle when talking to trainers) bit 7: used fly out of battle

<span id="bank1_main_deflore"> Defeated Lorelei

Bit 1: set when you beat Lorelei and reset in Indigo Plateau lobby, the game uses this to tell when Elite 4 events need to be reset

<span id="bank1_main_flags8"> Various Flags 8

bit 0: check if the player is standing on a door and make him walk down a step if so bit 1: the player is currently stepping down from a door bit 2: standing on a warp bit 6: jumping down a ledge / fishing animation bit 7: player sprite spinning due to spin tiles (Rocket hideout / Viridian Gym)

<span id="bank1_main_ingmtrades"> In-Game Trades

Bitset of completed in-game trades

<span id="bank1_main_warpedfrom"> Warped from warp/map

The warp or map you warped from

<span id="bank1_main_cardkeyxy"> Card key door x/y

Unknown

<span id="bank1_main_trash"> First/Second Trash Can Lock

Lt. Surge Trash Can lock puzzle to battle surge, these are where the switches are located. It's unknown the data format or even if they'll regenerate upon reloading the game.

<span id="bank1_main_complgameevents"> Completed Game Events

Bitfield of game events completed

<span id="bank1_main_grassrate"> Grass Rate

Wild Pokémon encounter rate for the "grass" areas of the game

<span id="bank1_main_linktrainer"> Link Trainer

Unknown

<span id="bank1_main_grasspkmn"> Grass Pokémon

This is actually a 20 byte list of Wild Pokémon in order from most common to least common (Rarest) but the last 9 bytes cross-over into a shared space used for link battles using the game link since you're obviously not going to find wild battles there.

<span id="bank1_main_lnkdata"> Link Data

Unknown

<span id="bank1_main_enmypartycount"> Enemy Party Count

How many Pokémon does the enemy have

<span id="bank1_main_enemypkmn"> Enemy Party Pokémon

Unknown since it's only 7 bytes. Perhaps the Species ID's

<span id="bank1_main_waterrate"> Water Rate

Chance of running into a wild Pokémon battle in the water areas of the current map.

<span id="bank1_main_waterpkmn"> Water Pokémon

Unknown since it's only 1 byte

<span id="bank1_main_enemypartydata"> Enemy partial party data

This follows the enemy partial party data structure

<span id="bank1_main_trainerhead"> Trainer Header Pointer

Unknown

<span id="bank1_main_oppidwrong"> Opponent ID after wrong answer

The trainer the player must face after getting a wrong answer in the Cinnabar gym quiz

<span id="bank1_main_curmapscr"> Current Map Script

Index of current map script, mostly used as index for function pointer array and mostly copied from map-specific map script pointer and written back later.

<span id="bank1_main_playtm"> Playtime

Counts Hours, Minutes, Seconds, and Frames of playtime and includes a byte that determines whether the counter has hit the maximum time and therefore no longer counts. The maximum time countable is


 * 255 Hours, 59 Minutes, 59 Seconds, and 59 Frames or
 * 10 days, 15 hours, 59 minutes, 59 seconds, and 59 frames.

The maximum byte can be any number, if the game detects it's not zero it essentially disables the counter entirely. Internally the game sets it to 255 when the timer has reached the maximum count. Whatever value set here only effects enabling or disabling the playtime and is not calculated into the playtime.

Setting Minutes, Seconds, or Frames 60 or above will simply increment the next byte by 1 and reset the value. In other words setting seconds to 120 will only increment minutes by 1, not 2.

It's also important to note that the timer is always ticking even on the initial load/new game menu or when it's paused.

<span id="bank1_main_safgmovr"> Safari Game Over

Safari Game over or not, the format and any further details are unknown

<span id="bank1_main_safballcnt"> Safari Ball Count

Amount of Safari Balls the player has

<span id="bank1_main_daycare"> Daycare

The daycare has 4 variables


 * In-Use to determine if it's in use or not
 * Pokémon Name following standard naming
 * Original Trainer name - follow standard naming of the Original Trainer
 * Pokémon - Pokémon stored in the daycare, just uses the Box Data format alone

Completed Scripts
The details aren't fully understood but for all areas of the game it covers the completed scripts and is possibly bit flags.

Sprite Data
Covers sprite data on map. To translate the offset to in-game memory and/or back simply use the difference number mentioned in the above table, 0x93D4.

This goes into quite a bit more detail than some of the other sprite data in Main Data.

These follow the Sprite Data Structure

These follow the Sprite Extra Data Structure

Party Data
Trainers current party. To translate the offset to in-game memory and/or back simply use the difference number mentioned in the above table, 0xA237.

Basically refer to the full party data structure

Current Box Data
a full byte-by-byte copy of the current box which is then loaded directly into memory every time for quick access. To translate the offset to in-game memory and/or back simply use the difference number mentioned in the above table, 0xA9C0.

Basically refer to the full box data structure

Normally, Pokémon are deposited and withdrawn from the Current Box data, which is within the checksum-validated region of the save data. When switching boxes, the data from the Current Box is copied to the corresponding PC Box data, then the data from the switched-to PC Box is transferred into the Current Box data.

Bank 2
This bank only contains boxes 1-6, when a box is selected its contents are copied and cached in bank 1. Think of bank 2 and 3 as warehouses where information is copied over to the more important areas when needed and only updated on save in case anything changed in the copied versions. Furthermore Bank 2 and 3 and completely 100% identical in structure.

Bank 2 and 3 have 2 different checksums, theres a whole-bank checksum similar to bank 1 that encompasses all used data on the bank and 6 individual checksums for the individual boxes data.

All Pokémon boxes follow the full box data structure

Bank 2 starts at address 0x4000 and is 0x2000 in size.

Unused

Unused here refers to data that the game completely does not touch in any way. Also none of the data is ever loaded from or saved to. The only way the game can ever be made to wipe or do anything to these areas is by invoking the hidden "Clear Save File" dialog manually yourself at the title screen.

Bank 3
This bank only contains boxes 7-12, when a box is selected its contents are copied and cached in bank 1. Think of bank 2 and 3 as warehouses where information is copied over to the more important areas when needed and only updated on save in case anything changed in the copied versions. Furthermore Bank 2 and 3 and completely 100% identical in structure.

Bank 2 and 3 have 2 different checksums, theres a whole-bank checksum similar to bank 1 that encompasses all used data on the bank and 6 individual checksums for the individual boxes data.

All Pokémon boxes follow the full box data structure

Bank 3 starts at address 0x6000 and is 0x2000 in size.

Unused

Unused here refers to data that the game completely does not touch in any way. Also none of the data is ever loaded from or saved to. The only way the game can ever be made to wipe or do anything to these areas is by invoking the hidden "Clear Save File" dialog manually yourself at the title screen.

Data Types
There are a few notable data types found in the save data, Unless otherwise noted, integer values occupy the specified number of bytes, and are and either unsigned or.

Text
Text data is stored in a proprietary encoding. Fixed-length user-input strings are terminated with 0x50. If a fixed-length string is terminated before using its full capacity, the contents of the remaining space are ignored and can be considered unused.

Hall of Fame
The Hall of Fame has an interesting data structure because it's the only Pokémon data structure that's so stripped down.

The game allocates space for 50 Hall of Fame Records, each record contains 6 entries for each Pokémon and each Pokémon entry contains 16 bytes. In code, it only uses the first 13 bytes oout of 16 so it's assumed the last 3 are unused or padding.

Hall of Fame Structure

Hall of Fame Record Entry Structure

Hall of Fame Pokémon Structure

Lists
Lists have 3 parts to them, a count of list entries, the list entries themselves, and the list ending. If the list has a count of 0 then there won't be a list of entries and thus the list count will read 0 followed immediately by the terminator which is 0xFF

A list entry consists of 2 bytes, the item id and the amount of such item from 1-99.

List

List Entry

Index refers to the item's index number.

Amount refers to the amount of the item that the player possesses and has valid values from 1 to 99.

Missable Lists
There is a varion of the standard list format above for the missable lists, it's the same as above only instead of id and amount it's instead id and index. Furthermore there's no count byte and thus there may not be a terminator byte. The details aren't fully understood beyond the list structure and it's found in only 1 place in the code within bank 1.

Map Connection Entry
A great deal of various map information is stored within the Save Data, in 1 place there exists connection data for North, South, East, and West connecting maps where applicable.

Note: Maps can be a very complicated subject most especially when it comes to connecting maps. Instead the data structure will simply be presented as-is.

Sign Coordinates
Amongst the map information is a section to hold the locations of signs, this is the data format for that.

Sprite Data
The save data has an entire section dedicated to the current state of the sprites on screen. Furthermore there are a couple of extra areas for sprites on the map noted further below. Here is the 2 structures found in the sprite section.

Note: Sprite Data is also a pretty complicated topic, and like maps, the data structure itself will just be given here.

Basic Sprite Data

Extra Sprite Data

Map Sprite Data
There are 2 kinds of sprite data structures the map uses, one for basic information and one for extended information. They're always side-by-side.

Sprite Basic Data Entry

Sprite Extended Data Entry

Pokémon
Pokémon data structures is quite large and comprehensive and there are actually 2 kinds of Pokémon data structures.

When a Pokémon is in a PC or in the Day Care (Since the Daycare follows the same PC Box data structure), it's given the base data structure which is 33 bytes and contains base information needed to calculate other information (To save space).

When you withdraw a Pokémon out of the PC that information is calculated and placed in an extended data structure that's a total of 44 bytes from the original 33 so it's immediately ready when needed. This calculated information gets destroyed when the Pokémon is placed back into the PC.

Lists of in the save data follow the same basic format, but there are slight variations of the list that are found in the save data. These types differ in their maximum capacity and in the way they store the main Pokémon data.


 * 1) The player's party and has a capacity of 6 and uses the full Pokémon data structure (with a size of 44 bytes).
 * 2) A PC Box and has a capacity of 20 and uses a truncated version of the Pokémon data structure (only the first 33 bytes).
 * 3) The Daycare is treated as a single Pokémon capacity box and thus contains only the Pokémon Data structure and none of the "list" aspects to it.

Full Box Data
Pokémon Box Data Structures is sometimes used alone such as at the Daycare however when dealing with a PC that can handle 20 Pokémon per box, there is some additional data around that.

Pokémon count This is the number of Pokémon entries actually being used in the list.

Species ID

This is a list of species indexes for each Pokémon in this list, 1 byte per index, with a  terminator following the last used entry in the list.

This list of species is used by the party screen and the PC's Box management interface.

Pokémon Box Data This is a list of Pokémon data structures for each Pokémon in this list, 44 or 33 bytes per index depending on if the whole list is for the party or a PC Box.

OT names This is a list of text strings for the Original Trainer of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

Name

Pokémon Nicknames is any name given to the Pokémon, if the name perfectly matches up with the species name (case-sensitive) it will be treated as if it had no nickname.

This is a list of text strings for the name of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

A Pokémon's name is a nickname if it does not perfectly match the default name for a Pokémon (typically all uppercase) with any unused bytes of the entry's 11-byte capacity filled with  terminators.

Full Party Data
This is exactly the same as the Full Box data but formatted for a party of up to 6.

Pokémon Party Data This is a list of Pokémon data structures for each Pokémon in this list, 44 or 33 bytes per index depending on if the whole list is for the party or a PC Box.

OT names This is a list of text strings for the Original Trainer of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

Name

Pokémon Nicknames is any name given to the Pokémon, if the name perfectly matches up with the species name (case-sensitive) it will be treated as if it had no nickname.

This is a list of text strings for the name of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

A Pokémon's name is a nickname if it does not perfectly match the default name for a Pokémon (typically all uppercase) with any unused bytes of the entry's 11-byte capacity filled with  terminators.

Partial Party Data
There does exist one area which features a stripped down full party data. It's mostly just missing much of the upper data.

Pokémon Party Data This is a list of Pokémon data structures for each Pokémon in this list, 44 or 33 bytes per index depending on if the whole list is for the party or a PC Box.

OT names This is a list of text strings for the Original Trainer of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

Name

Pokémon Nicknames is any name given to the Pokémon, if the name perfectly matches up with the species name (case-sensitive) it will be treated as if it had no nickname.

This is a list of text strings for the name of each Pokémon in this list, 11 bytes per name. Each name can contain from 1 to 10 characters, terminated by.

A Pokémon's name is a nickname if it does not perfectly match the default name for a Pokémon (typically all uppercase) with any unused bytes of the entry's 11-byte capacity filled with  terminators.

Item Box
The PC Box for items follows the same rules as a regular list only instead of 20 items, it's space allotted for 50 items with 50 being the maximum count.

Credits
Massive credit goes to the Pokémon Red/Blue source code found here. Specifically 2 files greatly helped wram and sram. But several source code files needed to be referenced in the project for better understanding.

Much of the descriptions were also used from there and those 2 files.

Permission was directly obtained from the team and project admins for these references.

Apart from educational references to the project and the references descriptions all other content is completely original.