Save data structure (Generation I): Difference between revisions

Terrible table for Pokemon lists... Since there's only two options, let's just list them both explicitly
m (Header is unnecessary)
(Terrible table for Pokemon lists... Since there's only two options, let's just list them both explicitly)
Line 166: Line 166:
At minimum, a list is a count followed by a terminator.
At minimum, a list is a count followed by a terminator.
{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
|- style="background: #cccccc"
|- style="background: #ccc"
! Offset
! Offset
! Size
! Size
! Contents
! Contents
|- style="background: #eeeeee"
|- style="background: #eee"
| 0x00
| 0x00
| 1
| 1
| Count
| Count
|- style="background: #dddddd"
|- style="background: #ddd"
| 0x01
| 0x01
| 1
| 1
Line 183: Line 183:


{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
|- style="background: #cccccc"
|- style="background: #ccc"
! Offset
! Offset
! Size
! Size
! Contents
! Contents
|- style="background: #eeeeee"
|- style="background: #eee"
| 0x00
| 0x00
| 1
| 1
| Count
| Count
|- style="background: #dddddd"
|- style="background: #ddd"
| 0x01
| 0x01
| 2 * Count
| 2 * Count
| Entries
| Entries
|- style="background: #eeeeee"
|- style="background: #eee"
| ''<0x01 + 2*Count>''
| ''<0x01 + 2*Count>''
| 1
| 1
Line 205: Line 205:


{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="text-align: center; border: 1px solid #999; border-collapse: collapse;"
|- style="background: #cccccc"
|- style="background: #ccc"
! Offset
! Offset
! Size
! Size
! Contents
! Contents
|- style="background: #eeeeee"
|- style="background: #eee"
| 0x00
| 0x00
| 1
| 1
| Index
| Index
|- style="background: #dddddd"
|- style="background: #ddd"
| 0x01
| 0x01
| 1
| 1
Line 224: Line 224:


==Pokémon lists==
==Pokémon lists==
Lists of [[Pokémon]] in the save data follow a particular format.
Lists of {{OBP|Pokémon|species}} in the save data follow the same basic format, but there are two slightly different types of list that found in the save data. These two types differ in their maximum capacity and in the way they store the main [[Pokémon data structure in Generation I|Pokémon data]]. One type describes the player's [[party]] and has a capacity of 6 and uses the full Pokémon data structure (with a size of 44 bytes). The other type describes 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).
 
Lists have entries of varying sizes, and a capacity. The total size of the list data, in bytes, is:
 
Capacity * (Size + 23) + 2
 
For example, your Pokémon team contains 6 entries and each entry is 44 bytes in size, so the size of that list is 6 * (44 + 23) + 2 = 404 bytes.


{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
|- style="background: #cccccc; text-align: center;"
|- style="background: #ccc; text-align: center;"
! colspan=2 | Party list
! rowspan=2 | Contents
! colspan=2 | Box list
|- style="background: #ccc; text-align: center;"
! Offset
! Offset
! Size
! Size
! Contents
! Size
|- style="background: #eeeeee; text-align: center;"
! Offset
|- style="background: #eee; text-align: center;"
| 0x0000
| 0x0000
| 1
| 1
| Count
| Entries used
|- style="background: #dddddd; text-align: center;"
| 1
| 0x0000
|- style="background: #ddd; text-align: center;"
| 0x0001
| 7
| Species list
| 21
| 0x0001
| 0x0001
| Capacity + 1
|- style="background: #eee; text-align: center;"
| Species
| 0x0008
|- style="background: #eeeeee; text-align: center;"
| 264
| ... + 0x0000
| [[Pokémon data structure in Generation I|Pokémon]] list
| Capacity * Size
| 660
| Pokémon
| 0x0016
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| ... + 0x0000
| 0x0110
| Capacity * 11
| 66
| OT Names
| OT names
|- style="background: #eeeeee; text-align: center;"
| 220
| ... + 0x0000
| 0x02AA
| Capacity * 11
|- style="background: #eee; text-align: center;"
| Names
| 0x0152
| 66
| Pokémon names
| 220
| 0x0386
|}
|}


===Count===
;Entries used
The number of Pokémon entries actually being represented in the list.
This is the number of Pokémon entries actually being used in the list.  
 
===Species===
A list of [[List_of_Pok%C3%A9mon_by_index_number_%28Generation_I%29|species indexes]], one for each Pokémon in the list. This is used by the team menu as well as the PC management interface.
 
The byte following the last species entry, according to ''Count'', must always be a terminator, which is byte value <code>0xFF</code>.
 
''Editor's Note: This field is used in Generation II to specify whether the corresponding Pokémon is still in its egg.''
 
===Pokémon===
The exact data for each Pokémon entry in the list. For the format, please refer to: [[Pokémon data structure in Generation I]]


*For team Pokémon, the entry size is the full 44 bytes as documented in that article.
;Species list
*For PC Pokémon, only the first 33 bytes are used, meaning everything after ''Move 4's PP values'' is not included. Instead, those values are regenerated upon withdrawing a Pokémon from the PC. This is the basis of the [[Box trick]].
This is a list of [[List of Pokémon by index number (Generation I)|species indexes]] for each Pokémon in this list, 1 byte per index, with a <code>0xFF</code> terminator following the last used entry in the list.


===OT names===
This list of species is used by the party screen and the PC's Box management interface.
[[#Text data|Text strings]] representing the names of the original trainers for each Pokémon entry. Each name can contain from 1 to 10 characters.


===Names===
;Pokémon list
[[#Text data|Text strings]] representing the names for each Pokémon entry. Each name can contain from 1 to 10 characters.
This is a list of [[Pokémon data structure in Generation I|Pokémon data structures]] for each Pokémon in this list, 44 or 33 bytes per index depending on if the the whole list is for the party or a PC Box.


A name is considered a "nickname" if it does not perfectly match the default name for a Pokémon. The default name follows these rules:
;OT names
This is a list of [[#Text data|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 <code>0x50</code>.


*The first however many characters must match the species name exactly. This is typically all-uppercase.
;Pokémon names
*The remainder of the string must be all terminator characters, aka <code>0x50</code>.
This is a list of [[#Text data|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 <code>0x50</code>.


Therefore, if a Pokémon with a 9- or 10-letter species name, such as [[Charmander (Pokémon)|Charmander]], is given a nickname that matches the species name, the nickname will not be retained should that Pokémon evolve.
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 <code>0x50</code> terminators.


==File structure==
==File structure==
Known data within the save file can be found at the following offsets within the data, such that offset 0 is the first byte of the emulator ".sav" file:
Known data within the save file can be found at the following offsets within the data, such that offset 0 is the first byte of the emulator ".sav" file:


''Editor's Note: This applies to the North American Red, Blue and Yellow for sure, but whether any of it is different in other releases has yet to be seen.''
''Note: These values apply to the North American Pokémon Red, Blue, and Yellow games. They could be different for other releases.''
 
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
|- style="background: #cccccc; text-align: center;"
|- style="background: #ccc; text-align: center;"
! Offset
! Offset
! Size
! Size
! Contents
! Contents
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x2598
| 0x2598
| 11
| 11
| [[#Player name, rival name|Player name]]
| [[#Player name, rival name|Player name]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x25A3
| 0x25A3
| 19
| 19
| [[#Pokédex owned, Pokédex seen|Pokédex owned]]
| [[#Pokédex owned, Pokédex seen|Pokédex owned]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x25B6
| 0x25B6
| 19
| 19
| [[#Pokédex owned, Pokédex seen|Pokédex seen]]
| [[#Pokédex owned, Pokédex seen|Pokédex seen]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x25C9
| 0x25C9
| 42
| 42
| [[#Pocket item list|Pocket item list]]
| [[#Pocket item list|Pocket item list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x25F3
| 0x25F3
| 3
| 3
| [[#Money|Money]]
| [[#Money|Money]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x25F6
| 0x25F6
| 11
| 11
| [[#Player name, rival name|Rival name]]
| [[#Player name, rival name|Rival name]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x2601
| 0x2601
| 1
| 1
| [[#Options|Options]]
| [[#Options|Options]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x2602
| 0x2602
| 1
| 1
| [[#Badges|Badges]]
| [[#Badges|Badges]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x2605
| 0x2605
| 2
| 2
| Player Trainer ID
| Player Trainer ID
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x271C
| 0x271C
| 1
| 1
| [[#Pikachu Friendship|Pikachu Friendship]]{{sup/1|Y}}
| [[#Pikachu Friendship|Pikachu Friendship]]{{sup/1|Y}}
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x27E6
| 0x27E6
| 102
| 102
| [[#PC item list|PC item list]]
| [[#PC item list|PC item list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x284C
| 0x284C
| 1
| 1
| [[#Current PC Box|Current PC Box]]
| [[#Current PC Box|Current PC Box]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x2850
| 0x2850
| 2
| 2
| [[#Casino coins|Casino coins]]
| [[#Casino coins|Casino coins]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x2CEE
| 0x2CEE
| 4
| 4
| [[#Time played|Time played]]
| [[#Time played|Time played]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x2F2C
| 0x2F2C
| 404
| 404
| [[#Team Pokémon list|Team Pokémon list]]
| [[#Team Pokémon list|Team Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x30C0
| 0x30C0
| 1122
| 1122
| [[#PC Box Pokémon lists|Current Box Pokémon list]]
| [[#PC Box Pokémon lists|Current Box Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x3523
| 0x3523
| 1
| 1
| [[#Checksum|Checksum]]
| [[#Checksum|Checksum]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x4000
| 0x4000
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 1 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 1 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x4462
| 0x4462
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 2 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 2 Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x48C4
| 0x48C4
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 3 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 3 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x4D26
| 0x4D26
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 4 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 4 Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x5188
| 0x5188
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 5 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 5 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x55EA
| 0x55EA
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 6 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 6 Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x6000
| 0x6000
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 7 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 7 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x6462
| 0x6462
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 8 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 8 Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x68C4
| 0x68C4
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 9 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 9 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x6D26
| 0x6D26
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 10 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 10 Pokémon list]]
|- style="background: #eeeeee; text-align: center;"
|- style="background: #eee; text-align: center;"
| 0x7188
| 0x7188
| 1122
| 1122
| [[#PC Box Pokémon lists|PC Box 11 Pokémon list]]
| [[#PC Box Pokémon lists|PC Box 11 Pokémon list]]
|- style="background: #dddddd; text-align: center;"
|- style="background: #ddd; text-align: center;"
| 0x75EA
| 0x75EA
| 1122
| 1122
Line 509: Line 507:


Normally, Pokémon are deposited and withdrawn from the Current Box list, which is within the [[#Checksum|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.
Normally, Pokémon are deposited and withdrawn from the Current Box list, which is within the [[#Checksum|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.
''Editor's Note: The curious operation of box switching indicates that originally, the PC only had a capacity for 20 Pokémon. The means by which the boxes function would have been easy to implement on top of that.''


===Checksum===
===Checksum===
Line 523: Line 519:
*Invert the bits of the result
*Invert the bits of the result


Alternately, you can start at 255 and subtract for each byte, meaning you won't have to perform the bit inversion at the end.
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 all of the data starting at [[#Player name, rival name|player name]] through the end of [[#PC Box Pokémon lists|Current Box Pokémon list]].
The checksum neatly validates all of the data starting at [[#Player name, rival name|player name]] through the end of [[#PC Box Pokémon lists|Current Box Pokémon list]].