Pokémon data structure (Generation IV): Difference between revisions

From Bulbapedia, the community-driven Pokémon encyclopedia.
Jump to navigationJump to search
m (Text replacement - "}}<br>↵{{Project Games notice" to "}} {{Project Games notice")
 
(44 intermediate revisions by 28 users not shown)
Line 1: Line 1:
Boxed Pokémon in the games [[Pokémon Diamond and Pearl|Diamond and Pearl]] are stored in a 136-byte structure. All unencrypted values are stored in little-endian format. The game encrypts the data when it is stored into [[Save data structure in the DS|save data]]. In-party Pokémon have additional values appended to them to hold calculated stats. The information below describes the boxed Pokémon data format.
Boxed Pokémon in the games {{v2|Diamond and Pearl|s}} are stored in a 136-byte structure. All unencrypted values are stored in little-endian format. The game encrypts the data when it is stored into the {{OBP|Save data structure|Generation IV|save data}}. In-party Pokémon have additional values appended to them to hold calculated stats. The information below describes the boxed Pokémon data format.


== Checksum ==
==Checksum==


The checksum serves two purposes:
The checksum serves two purposes:
Line 12: Line 12:
# Truncate the sum to sixteen bits.
# Truncate the sum to sixteen bits.


== Block Shuffling ==
==Block shuffling==


The 128 bytes of Pokémon data are split into four 32-byte blocks for shuffling. The blocks are shuffled according to a shift value derived from the [[personality value]]. Given the personality value ''pv'', the expression yielding the shift value is:
The 128 bytes of Pokémon data are split into four 32-byte blocks for shuffling. The blocks are shuffled according to a shift value derived from the [[personality value]]. Given the personality value ''pv'', the expression yielding the shift value is:
: ''((pv >> 0xD) & 0x1F) % 24''
The right shifting (pv >> 0xD) is equivalent to a division for 8192.


To shuffle the blocks, take the four blocks of unencrypted data to be ''A'', ''B'', ''C'', and ''D''.  The blocks shall be rearranged in the encrypted data according to this table:
<code>((pv & 0x3E000) >> 0xD) % 24</code>


{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
The right shifting (>> 0xD) is equivalent to a division of 8192.
|- style="background: #ccc;" align="center"
 
To shuffle the blocks, take the four blocks of unencrypted data, ''A'', ''B'', ''C'', and ''D''. The blocks shall be rearranged in the encrypted data according to the Block Order column of the following table. (To unshuffle, use the Inverse column.)
 
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;"
! Shift Value (decimal)
! Shift Value (decimal)
! Block Order
! Block Order
|- style="background: #eee;" align="center"
! Inverse
|- style="background: #eee;"
| 00
| 00
| ABCD
| ABCD
|- style="background: #ddd;" align="center"
| ABCD
|- style="background: #ddd;"
| 01
| 01
| ABDC
| ABDC
|- style="background: #eee;" align="center"
| ABDC
|- style="background: #eee;"
| 02
| 02
| ACBD
| ACBD
|- style="background: #ddd;" align="center"
| ACBD
|- style="background: #ddd;"
| 03
| 03
| ACDB
| ACDB
|- style="background: #eee;" align="center"
| ADBC
|- style="background: #eee;"
| 04
| 04
| ADBC
| ADBC
|- style="background: #ddd;" align="center"
| ACDB
|- style="background: #ddd;"
| 05
| 05
| ADCB
| ADCB
|- style="background: #eee;" align="center"
| ADCB
|- style="background: #eee;"
| 06
| 06
| BACD
| BACD
|- style="background: #ddd;" align="center"
| BACD
|- style="background: #ddd;"
| 07
| 07
| BADC
| BADC
|- style="background: #eee;" align="center"
| BADC
|- style="background: #eee;"
| 08
| 08
| BCAD
| BCAD
|- style="background: #ddd;" align="center"
| CABD
|- style="background: #ddd;"
| 09
| 09
| BCDA
| BCDA
|- style="background: #eee;" align="center"
| DABC
|- style="background: #eee;"
| 10
| 10
| BDAC
| BDAC
|- style="background: #ddd;" align="center"
| CADB
|- style="background: #ddd;"
| 11
| 11
| BDCA
| BDCA
|- style="background: #eee;" align="center"
| DACB
|- style="background: #eee;"
| 12
| 12
| CABD
| CABD
|- style="background: #ddd;" align="center"
| BCAD
|- style="background: #ddd;"
| 13
| 13
| CADB
| CADB
|- style="background: #eee;" align="center"
| BDAC
|- style="background: #eee;"
| 14
| 14
| CBAD
| CBAD
|- style="background: #ddd;" align="center"
| CBAD
|- style="background: #ddd;"
| 15
| 15
| CBDA
| CBDA
|- style="background: #eee;" align="center"
| DBAC
|- style="background: #eee;"
| 16
| 16
| CDAB
| CDAB
|- style="background: #ddd;" align="center"
| CDAB
|- style="background: #ddd;"
| 17
| 17
| CDBA
| CDBA
|- style="background: #eee;" align="center"
| DCAB
|- style="background: #eee;"
| 18
| 18
| DABC
| DABC
|- style="background: #ddd;" align="center"
| BCDA
|- style="background: #ddd;"
| 19
| 19
| DACB
| DACB
|- style="background: #eee;" align="center"
| BDCA
|- style="background: #eee;"
| 20
| 20
| DBAC
| DBAC
|- style="background: #ddd;" align="center"
| CBDA
|- style="background: #ddd;"
| 21
| 21
| DBCA
| DBCA
|- style="background: #eee;" align="center"
| DBCA
|- style="background: #eee;"
| 22
| 22
| DCAB
| DCAB
|- style="background: #ddd;" align="center"
| CDBA
|- style="background: #ddd;"
| 23
| 23
| DCBA
| DCBA
| DCBA
|}
|}


== Encryption ==
==Encryption==
The encryption uses a [[Pseudorandom number generation|pseudorandom number generator (PRNG)]], a 32-bit linear congruential generator to be exact.
 
The order of the ABCD blocks is irrelevant when encrypting or decrypting, because the data is treated as a bit stream, so the algorithm is the same in both cases.
 
First, the PRNG is seeded with the checksum of the Pokémon:
 
<code>X[0] = checksum</code>
 
Then, we loop over the 64 2-byte words of ABCD block data by advancing the PRNG and XORing the top 16 bits of each new state with each 16 bits of data:


The encryption uses the pseudorandom number generator (PRNG), a linear congruential generator.  Elements of the PRNG can be described with the recursive function:
<code>X[n+1] = 0x41C64E6D * X[n] + 0x6073</code>
: ''X[n+1] = (0x41C64E6D * X[n] + 0x6073)''


To decrypt the data, given a function ''rand()'' which returns the upper 16 bits of consecutive results of the above given function:
<code>D[n] = D[n] XOR (X[n+1] >> 16)</code>
# Seed the PRNG with the checksum (let ''X[n]'' be the checksum),
# Sequentially, for each 2-byte word ''Y'' from 0x08 to 0x87, apply the transformation: ''unencryptedByte = Y xor rand()''
# Un-shuffle the blocks using the block shuffling algorithm above.


To encrypt the data:
To read from or write to an encrypted Pokémon's ABCD block data, the game first decrypts the data as a whole, then determines what the block order is from the personality value and figures out the offset it needs to use to read from or write to either block.
# Shuffle the blocks using the block shuffling algorithm above.
# Seed the PRNG with the checksum (let ''X[n]'' be the checksum),
# Sequentially, for each 2-byte word ''Y'' from 0x08 to 0x87, apply the transformation: ''unencryptedByte = Y xor rand()''


== Unencrypted bytes ==
==Unencrypted bytes==
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;" align="center"
|- style="background: #ccc;"
! Offset
! Offset
! Contents
! Contents
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x00-0x03
| 0x00-0x03
| [[Personality value]]
| [[Personality value]]
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x04-0x05
| 0x04-0x05
| ''Unknown''
| Bit 0-1: If set, skip checksum checks<br/>Bit 2: Bad egg flag<br/>Bit 3-7: ''Unused''
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x06-0x07
| 0x06-0x07
| Checksum
| Checksum
|}
|}


== Encrypted bytes ==
==Encrypted bytes==
=== Block A ===
===Block A===


{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;" align="center"
|- style="background: #ccc;"
! Offset
! Offset
! Contents
! Contents
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x08-0x09  
| 0x08-0x09
| Species ID
| Species ID
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x0A-0x0B  
| 0x0A-0x0B
| Held Item
| Held Item
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x0C-0x0D
| 0x0C-0x0D
| OT ID
| OT ID
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x0E-0x0F  
| 0x0E-0x0F
| OT Secret ID
| OT Secret ID
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x10-0x13
| 0x10-0x13
| [[Experience|Experience points]]
| [[Experience|Experience points]]
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x14
| 0x14
| Friendship/Egg Steps to Hatch
| Friendship/Egg Steps to Hatch
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x15
| 0x15
| [[Ability]]
| [[Ability]]
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x16
| 0x16
| Markings
| [[Marking]]s
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x17
| 0x17
| Country of Origin
| [[Language of origin]]
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x18-0x1D
| 0x18
| [[Effort values]]
| HP EVs
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x1E-0x23
| 0x19
| Contest stats
| Attack EVs
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x1A
| Defense EVs
|- style="background: #eee;"
| 0x1B
| Speed EVs
|- style="background: #ddd;"
| 0x1C
| Sp. Atk EVs
|- style="background: #eee;"
| 0x1D
| Sp. Def. EVs
|- style="background: #ddd;"
| 0x1E
| Cool Contest stat
|- style="background: #eee;"
| 0x1F
| Beauty Contest stat
|- style="background: #ddd;"
| 0x20
| Cute Contest stat
|- style="background: #eee;"
| 0x21
| Smart Contest stat
|- style="background: #ddd;"
| 0x22
| Tough Contest stat
|- style="background: #eee;"
| 0x23
| [[Sheen]]
|- style="background: #ddd;"
| 0x24-0x27
| 0x24-0x27
| Ribbons
| Sinnoh Ribbons Set 1
|}
|}


=== Block B ===
===Block B===
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;" align="center"
|- style="background: #ccc;"
! Offset
! Offset
! Contents
! Contents
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x28-0x2F  
| 0x28-0x2F
| Moveset
| Moveset
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x30-0x33  
| 0x30-0x33
| Move PP
| Move PP
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x34-0x37
| 0x34-0x37
| Move PP Ups
| Move PP Ups
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x38-0x3B
| 0x38-0x3B
| Bits 0-29 - [[Individual values]]<br>Bit 30 - IsNicknamed Flag<br>Bit 31 - IsEgg Flag  
| Bits 0-29 - [[Individual values]]<br/>HP ( [0-31] << 0 )<br>Attack ( [0-31] << 5 )<br>Defense ( [0-31] << 10 )<br>Speed ( [0-31] << 15 )<br>Sp. Atk. ( [0-31] << 20 )<br>Sp. Def. ( [0-31] << 25 )<br>Bit 30 - IsEgg Flag<br>Bit 31 - IsNicknamed Flag
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3C-0x3F
| 0x3C-0x3F
| Ribbons 2
| Hoenn Ribbon Set
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x40-0x41
| 0x40
| Bit 0 - Fateful Encountered Flag<br>Bit 1 - Female<br>Bit 2 - Genderless<br>Bit 3-15 - Alternate Forms (Form Index << 3)
| Bit 0 - [[Fateful encounter]] Flag<br>Bit 1 - Female<br>Bit 2 - Gender unknown<br>Bit 3-7 - Alternate Forms (Form Index << 3)
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x41
| Shiny Leaves (HGSS)<br>Bit 5 - Leaf Crown<br>Bits 0–4 - Leaves A–E (bit 0 is leftmost)
|- style="background: #ddd;"
| 0x42-0x43
| 0x42-0x43
| ''Unknown''
| ''Unused''
|- style="background: #ddd;" align="center"
|- style="background: #eee;"
| 0x44-0x45
| 0x44-0x45
| Platinum Egg Location
| Platinum Egg Location
|- style="background: #eee;" align="center"
|- style="background: #ddd;"
| 0x46-0x47
| 0x46-0x47
| Platinum Met at Location
| Platinum Met at Location
|}
|}


=== Block C ===
===Block C===
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;" align="center"
|- style="background: #ccc;"
! Offset
! Offset
! Contents
! Contents
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x48-0x5D
| 0x48-0x5D
| Nickname
| Nickname
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x5E-0x5F
| 0x5E
| Hometown
| ''Unused''
|- style="background: #ddd;" align="center"
|- style="background: #eee;"
| 0x5F
| [[Game of origin]]
|- style="background: #ddd;"
| 0x60-0x63
| 0x60-0x63
| Contests
| Sinnoh Ribbons Set 2
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x64-0x67
| 0x64-0x67
| ''Unknown''
| ''Unused''
|}
|}


=== Block D ===
===Block D===
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;" align="center"
|- style="background: #ccc;"
! Offset
! Offset
! Contents
! Contents
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x68-0x77  
| 0x68-0x77
| OT Name
| OT Name
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x78-0x7A  
| 0x78-0x7A
| Date Egg Received
| Date Egg Received
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x7B-0x7D
| 0x7B-0x7D
| Date Met
| Date Met
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x7E-0x7F
| 0x7E-0x7F
| Diamond/Pearl Egg Location
| Diamond/Pearl Egg Location
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x80-0x81
| 0x80-0x81
| Diamond/Pearl Met At Location
| Diamond/Pearl Met At Location
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x82
| 0x82
| [[Pokérus]]
| [[Pokérus]]
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x83
| 0x83
| Poké Ball
| Poké Ball
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x84
| 0x84
| Bit 0-6 - Met At Level<br>Bit 7 - Female OT Gender
| Bit 0-6 - Met At Level<br>Bit 7 - Female OT Gender
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x85
| 0x85
| Encounter Type
| Encounter Type
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x86-0x87
| 0x86
| HG/SS Poké Ball
|- style="background: #eee;"
| 0x87
| Walking Pokémon Mood (unused in DPPt)
|}
 
==Battle stats==
The battle stats are encrypted in the same manner, however the seed is not the checksum, it is the [[personality value]], and the bytes are not shuffled.
 
===Encrypted bytes===
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
|- style="background: #ccc;"
! Offset
! Contents
|- style="background: #eee;"
| 0x88
| Bits 0-2 - Asleep (0-7 rounds)<br>Bit 3 - Poisoned<br>Bit 4 - Burned<br>Bit 5 - Frozen<br>Bit 6 - Paralyzed<br>Bit 7 - Toxic
|- style="background: #ddd;"
| 0x89
| ''Unknown'' - Flags - Max Value 0xF0
|- style="background: #eee;"
| 0x8A-0x8B
| ''Unknown''
| ''Unknown''
|- style="background: #ddd;"
| 0x8C
| Level
|- style="background: #eee;"
| 0x8D
| Capsule Index (Seals)
|- style="background: #ddd;"
| 0x8E-0x8F
| Current HP
|- style="background: #eee;"
| 0x90-0x91
| Max HP
|- style="background: #ddd;"
| 0x92-0x93
| Attack
|- style="background: #eee;"
| 0x94-0x95
| Defense
|- style="background: #ddd;"
| 0x96-0x97
| Speed
|- style="background: #eee;"
| 0x98-0x99
| Special Attack
|- style="background: #ddd;"
| 0x9A-0x9B
| Special Defense
|- style="background: #eee;"
| 0x9C-0xD3
| Mail data
|- style="background: #ddd;"
| 0xD4-0xEB
| Seal Coordinates
|}
==Language of origin==
{{main|Language of origin}}
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Value
! Language
|- style="background: #eee;"
| 0x1
| 日本語 (Japanese)
|- style="background: #ddd;"
| 0x2
| English
|- style="background: #eee;"
| 0x3
| Français (French)
|- style="background: #ddd;"
| 0x4
| Italiano (Italian)
|- style="background: #eee;"
| 0x5
| Deutsch (German)
|- style="background: #ddd;"
| 0x7
| Español (Spanish)
|- style="background: #eee;"
| 0x8
| 한국어 (Korean)
|}
==Markings==
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Bit
! Marking
|- style="background: #eee;"
| 0x01
| Circle
|- style="background: #ddd;"
| 0x02
| Triangle
|- style="background: #eee;"
| 0x04
| Square
|- style="background: #ddd;"
| 0x08
| Heart
|- style="background: #eee;"
| 0x10
| Star
|- style="background: #ddd;"
| 0x20
| Diamond
|}
==Alternate forms==
Alternate [[form]]s are stored at offset 0x40 of the Pokémon structure. Each form follows the pattern of <code>index << 3</code> where index starts at zero for the main form.
{{p|Rotom}}'s alternate forms, {{p|Giratina}}'s Origin Forme, and {{p|Shaymin}}'s Sky Forme will only be displayed in Pokémon Platinum, HeartGold and SoulSilver. Rotom may be traded among Pokémon Diamond, Pearl, and Platinum without losing its alternate form.
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align: center"
! Byte || {{p|Unown}} || {{p|Deoxys}} || {{p|Burmy}}/{{p|Wormadam}} || {{p|Shellos}}/{{p|Gastrodon}} || {{p|Rotom}} || {{p|Giratina}} || {{p|Shaymin}} || {{p|Arceus}} || {{p|Pichu}} (HGSS only)
|- style="background: #eee"
| 0x00 || A || Normal || Plant || West || Normal || Altered || Land || Normal || Normal
|- style="background: #ddd"
| 0x08 || B || Attack || Sandy || East || Heat || Origin || Sky || Fighting || Spiky-eared
|- style="background: #eee"
| 0x10 || C || Defense || Trash || || Wash || || || Flying ||
|- style="background: #ddd"
| 0x18 || D || Speed || || || Frost || || || Poison ||
|- style="background: #eee"
| 0x20 || E || || || || Fan || || || Ground ||
|- style="background: #ddd"
| 0x28 || F || || || || Mow || || || Rock ||
|- style="background: #eee"
| 0x30 || G || || || || || || || Bug ||
|- style="background: #ddd"
| 0x38 || H || || || || || || || Ghost ||
|- style="background: #eee"
| 0x40 || I || || || || || || || Steel ||
|- style="background: #ddd"
| 0x48 || J || || || || || || || ??? ||
|- style="background: #eee"
| 0x50 || K || || || || || || || Fire ||
|- style="background: #ddd"
| 0x58 || L || || || || || || || Water ||
|- style="background: #eee"
| 0x60 || M || || || || || || || Grass ||
|- style="background: #ddd"
| 0x68 || N || || || || || || || Electric ||
|- style="background: #eee"
| 0x70 || O || || || || || || || Psychic ||
|- style="background: #ddd"
| 0x78 || P || || || || || || || Ice ||
|- style="background: #eee"
| 0x80 || Q || || || || || || || Dragon ||
|- style="background: #ddd"
| 0x88 || R || || || || || || || Dark ||
|- style="background: #eee"
| 0x90 || S || || || || || || || ||
|- style="background: #ddd"
| 0x98 || T || || || || || || || ||
|- style="background: #eee"
| 0xA0 || U || || || || || || || ||
|- style="background: #ddd"
| 0xA8 || V || || || || || || || ||
|- style="background: #eee"
| 0xB0 || W || || || || || || || ||
|- style="background: #ddd"
| 0xB8 || X || || || || || || || ||
|- style="background: #eee"
| 0xC0 || Y || || || || || || || ||
|- style="background: #ddd"
| 0xC8 || Z || || || || || || || ||
|- style="background: #eee"
| 0xD0 || ! || || || || || || || ||
|- style="background: #ddd"
| 0xD8 || ? || || || || || || || ||
|}
==Encounter types==
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Value
! Encounter
|- style="background: #eee;"
| 0x0
| Pal Park, Egg, Hatched, Special Event
|- style="background: #ddd;"
| 0x2
| Tall Grass
|- style="background: #eee;"
| 0x4
| Dialga/Palkia In-Game Event
|- style="background: #ddd;"
| 0x5
| Cave, Hall of Origin
|- style="background: #eee;"
| 0x7
| Surfing, Fishing
|- style="background: #ddd;"
| 0x9
| Building
|- style="background: #eee;"
| 0xA
| Great Marsh (Safari Zone)
|- style="background: #ddd;"
| 0xC
| Starter, Fossil, Gift (Eevee) (D/P)
|-
|0x18
|Starter, Fossil, Gift (Eevee) (HGSS/Pt)
|}
|}


== Ribbons ==
==Ribbons==
DP stores the ribbon data as bitfields in 16-bit words. Given below are the bytewise representations of the ribbon bitfields:
Pokémon Diamond, Pearl, and Platinum store the [[Ribbon]] data as bitfields in 16-bit words. Given below are the bytewise representations of the ribbon bitfields:


{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
===Sinnoh Ribbon Set 1===
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Bit
! Bit
! Ribbon
! Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x25 & 0x01
| 0x24 & 0x01
| Sinnoh Champ Ribbon
| Sinnoh Champ Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x25 & 0x02
| 0x24 & 0x02
| Ability Ribbon
| Ability Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x25 & 0x04
| 0x24 & 0x04
| Great Ability Ribbon
| Great Ability Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x25 & 0x08
| 0x24 & 0x08
| Double Ability Ribbon
| Double Ability Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x25 & 0x10
| 0x24 & 0x10
| Multi Ability Ribbon
| Multi Ability Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x25 & 0x20
| 0x24 & 0x20
| Pair Ability Ribbon
| Pair Ability Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x25 & 0x40
| 0x24 & 0x40
| World Ability Ribbon
| World Ability Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x25 & 0x80
| 0x24 & 0x80
| Alert Ribbon
| Alert Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x24 & 0x01
| 0x25 & 0x01
| Shock Ribbon
| Shock Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x24 & 0x02
| 0x25 & 0x02
| Downcast Ribbon
| Downcast Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x24 & 0x04
| 0x25 & 0x04
| Careless Ribbon
| Careless Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x24 & 0x08
| 0x25 & 0x08
| Relax Ribbon
| Relax Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x24 & 0x10
| 0x25 & 0x10
| Snooze Ribbon
| Snooze Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x24 & 0x20
| 0x25 & 0x20
| Smile Ribbon
| Smile Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x24 & 0x40
| 0x25 & 0x40
| Gorgeous Ribbon
| Gorgeous Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x24 & 0x80
| 0x25 & 0x80
| Royal Ribbon
| Royal Ribbon
|}
|- style="background: #eee;"
 
| 0x26 & 0x01
 
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
! Bit
! Ribbon
|- style="background: #eee;" align="center"
| 0x27 & 0x01
| Gorgeous Royal Ribbon
| Gorgeous Royal Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x27 & 0x02
| 0x26 & 0x02
| Footprint Ribbon
| Footprint Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x27 & 0x04
| 0x26 & 0x04
| Record Ribbon
| Record Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x27 & 0x08
| 0x26 & 0x08
| History Ribbon
| History Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x27 & 0x10
| 0x26 & 0x10
| Legend Ribbon
| Legend Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x27 & 0x20
| 0x26 & 0x20
| Red Ribbon
| Red Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x27 & 0x40
| 0x26 & 0x40
| Green Ribbon
| Green Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x27 & 0x80
| 0x26 & 0x80
| Blue Ribbon
| Blue Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x26 & 0x01
| 0x27 & 0x01
| Festival Ribbon
| Festival Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x26 & 0x02
| 0x27 & 0x02
| Carnival Ribbon
| Carnival Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x26 & 0x04
| 0x27 & 0x04
| Classic Ribbon
| Classic Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x26 & 0x08
| 0x27 & 0x08
| Premier Ribbon
| Premier Ribbon
|}
|}


===Sinnoh Ribbon Set 2===
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Bit
! Ribbon
|- style="background: #eee;"
| 0x60 & 0x01
| Cool Ribbon
|- style="background: #ddd;"
| 0x60 & 0x02
| Cool Ribbon Great
|- style="background: #eee;"
| 0x60 & 0x04
| Cool Ribbon Ultra
|- style="background: #ddd;"
| 0x60 & 0x08
| Cool Ribbon Master
|- style="background: #eee;"
| 0x60 & 0x10
| Beauty Ribbon
|- style="background: #ddd;"
| 0x60 & 0x20
| Beauty Ribbon Great
|- style="background: #eee;"
| 0x60 & 0x40
| Beauty Ribbon Ultra
|- style="background: #ddd;"
| 0x60 & 0x80
| Beauty Ribbon Master
|- style="background: #eee;"
| 0x61 & 0x01
| Cute Ribbon
|- style="background: #ddd;"
| 0x61 & 0x02
| Cute Ribbon Great
|- style="background: #eee;"
| 0x61 & 0x04
| Cute Ribbon Ultra
|- style="background: #ddd;"
| 0x61 & 0x08
| Cute Ribbon Master
|- style="background: #eee;"
| 0x61 & 0x10
| Smart Ribbon
|- style="background: #ddd;"
| 0x61 & 0x20
| Smart Ribbon Great
|- style="background: #eee;"
| 0x61 & 0x40
| Smart Ribbon Ultra
|- style="background: #ddd;"
| 0x61 & 0x80
| Smart Ribbon Master
|- style="background: #eee;"
| 0x62 & 0x01
| Tough Ribbon
|- style="background: #ddd;"
| 0x62 & 0x02
| Tough Ribbon Great
|- style="background: #eee;"
| 0x62 & 0x04
| Tough Ribbon Ultra
|- style="background: #ddd;"
| 0x62 & 0x08
| Tough Ribbon Master
|}
===Hoenn Ribbon Set===


{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Bit
! Bit
! Ribbon
! Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3D & 0x01
| 0x3C & 0x01
| Cool Ribbon
| Cool Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3D & 0x02
| 0x3C & 0x02
| Cool Ribbon Super
| Cool Ribbon Super
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3D & 0x04
| 0x3C & 0x04
| Cool Ribbon Hyper
| Cool Ribbon Hyper
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3D & 0x08
| 0x3C & 0x08
| Cool Ribbon Master
| Cool Ribbon Master
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3D & 0x10
| 0x3C & 0x10
| Beauty Ribbon
| Beauty Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3D & 0x20
| 0x3C & 0x20
| Beauty Ribbon Super
| Beauty Ribbon Super
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3D & 0x40
| 0x3C & 0x40
| Beauty Ribbon Hyper
| Beauty Ribbon Hyper
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3D & 0x80
| 0x3C & 0x80
| Beauty Ribbon Master
| Beauty Ribbon Master
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3C & 0x01
| 0x3D & 0x01
| Cute Ribbon
| Cute Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3C & 0x02
| 0x3D & 0x02
| Cute Ribbon Super
| Cute Ribbon Super
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3C & 0x04
| 0x3D & 0x04
| Cute Ribbon Hyper
| Cute Ribbon Hyper
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3C & 0x08
| 0x3D & 0x08
| Cute Ribbon Master
| Cute Ribbon Master
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3C & 0x10
| 0x3D & 0x10
| Smart Ribbon
| Smart Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3C & 0x20
| 0x3D & 0x20
| Smart Ribbon Super
| Smart Ribbon Super
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3C & 0x40
| 0x3D & 0x40
| Smart Ribbon Hyper
| Smart Ribbon Hyper
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3C & 0x80
| 0x3D & 0x80
| Smart Ribbon Master
| Smart Ribbon Master
|}
|- style="background: #eee;"
 
| 0x3E & 0x01
 
{| border="1" style="border: 1px solid #999; border-collapse: collapse;"
! Bit
! Ribbon
|- style="background: #eee;" align="center"
| 0x3F & 0x01
| Tough Ribbon
| Tough Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3F & 0x02
| 0x3E & 0x02
| Tough Ribbon Super
| Tough Ribbon Super
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3F & 0x04
| 0x3E & 0x04
| Tough Ribbon Hyper
| Tough Ribbon Hyper
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3F & 0x08
| 0x3E & 0x08
| Tough Ribbon Master
| Tough Ribbon Master
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3F & 0x10
| 0x3E & 0x10
| Champion Ribbon
| Champion Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3F & 0x20
| 0x3E & 0x20
| Winning Ribbon
| Winning Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3F & 0x40
| 0x3E & 0x40
| Victory Ribbon
| Victory Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3F & 0x80
| 0x3E & 0x80
| Artist Ribbon
| Artist Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3E & 0x01
| 0x3F & 0x01
| Effort Ribbon
| Effort Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3E & 0x02
| 0x3F & 0x02
| Marine Ribbon
| Marine Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3E & 0x04
| 0x3F & 0x04
| Land Ribbon
| Land Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3E & 0x08
| 0x3F & 0x08
| Sky Ribbon
| Sky Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3E & 0x10
| 0x3F & 0x10
| Country Ribbon
| Country Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3E & 0x20
| 0x3F & 0x20
| National Ribbon
| National Ribbon
|- style="background: #eee;" align="center"
|- style="background: #eee;"
| 0x3E & 0x40
| 0x3F & 0x40
| Earth Ribbon
| Earth Ribbon
|- style="background: #ddd;" align="center"
|- style="background: #ddd;"
| 0x3E & 0x80
| 0x3F & 0x80
| World Ribbon
| World Ribbon
|}
|}


== Location ==
==Technical Details==
The party Pokémon are stored in the [[Save data structure in the DS|save file]] beginning at offset 0x00098 for the first block pair, and 0x40098 for the second block pair. Each party Pokémon is 236 bytes in size.
In Memory, the Player and Enemy Party Pokémon can be accessed using different pointers depending on the game.  These pointers are stored as 32-bit addresses in little endian format.
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Game
! Pointer
|- style="background: #eee;"
| Diamond & Pearl
| 0x02106FAC
|- style="background: #ddd;"
| Platinum
| 0x02101D2C
|- style="background: #eee;"
| Heartgold & Soulsilver
| 0x0211186C
|}
In addition to this pointer, the order in which they store the Pokémon changes slightly.  The following addresses when added to the pointer result in their respective locations
{| border="1" style="border: 1px solid #999; border-collapse: collapse; text-align:center"
! Game
! Player Party
! Enemy Party
|- style="background: #eee;"
| Diamond & Pearl
| 0xD2AC
| 0x364C8
|- style="background: #ddd;"
| Platinum
| 0xD088
| 0x37970
|- style="background: #eee;"
| Heartgold & Soulsilver
| 0xD094
| 0x352F4
|}
 
==Location==
The party Pokémon are stored in the {{OBP|Save data structure|Generation IV|save file}} beginning at offset 0x00098 for the first block pair, and 0x40098 for the second block pair. Each party Pokémon is 236 bytes in size.


The PC storage Pokémon are stored in the save file from Box 1 to Box 18. They start at 0x0C104 in the first block pair, and at 0x4C104 in the second block pair. Each PC stored Pokémon is 136 bytes in size.
The PC storage Pokémon are stored in the save file from Box 1 to Box 18. They start at 0x0C104 in the first block pair, and at 0x4C104 in the second block pair. Each PC stored Pokémon is 136 bytes in size.


For a csv file of every box and box slot offset, [http://www.filefactory.com/file/a00a32g/n/BOXES_csv click here].
{{data structure}}
{{data structure}}
{{Project Games notice|data structure}}

Latest revision as of 17:32, 16 September 2024

Boxed Pokémon in the games Diamond and Pearl are stored in a 136-byte structure. All unencrypted values are stored in little-endian format. The game encrypts the data when it is stored into the save data. In-party Pokémon have additional values appended to them to hold calculated stats. The information below describes the boxed Pokémon data format.

Checksum

The checksum serves two purposes:

  1. It validates the data after decryption, and
  2. It serves as the encryption key for the data.

The checksum is calculated in three steps:

  1. Split the unencrypted data from offsets 0x08 to 0x87 into two-byte words,
  2. Take the sum of the words, and
  3. Truncate the sum to sixteen bits.

Block shuffling

The 128 bytes of Pokémon data are split into four 32-byte blocks for shuffling. The blocks are shuffled according to a shift value derived from the personality value. Given the personality value pv, the expression yielding the shift value is:

((pv & 0x3E000) >> 0xD) % 24

The right shifting (>> 0xD) is equivalent to a division of 8192.

To shuffle the blocks, take the four blocks of unencrypted data, A, B, C, and D. The blocks shall be rearranged in the encrypted data according to the Block Order column of the following table. (To unshuffle, use the Inverse column.)

Shift Value (decimal) Block Order Inverse
00 ABCD ABCD
01 ABDC ABDC
02 ACBD ACBD
03 ACDB ADBC
04 ADBC ACDB
05 ADCB ADCB
06 BACD BACD
07 BADC BADC
08 BCAD CABD
09 BCDA DABC
10 BDAC CADB
11 BDCA DACB
12 CABD BCAD
13 CADB BDAC
14 CBAD CBAD
15 CBDA DBAC
16 CDAB CDAB
17 CDBA DCAB
18 DABC BCDA
19 DACB BDCA
20 DBAC CBDA
21 DBCA DBCA
22 DCAB CDBA
23 DCBA DCBA

Encryption

The encryption uses a pseudorandom number generator (PRNG), a 32-bit linear congruential generator to be exact.

The order of the ABCD blocks is irrelevant when encrypting or decrypting, because the data is treated as a bit stream, so the algorithm is the same in both cases.

First, the PRNG is seeded with the checksum of the Pokémon:

X[0] = checksum

Then, we loop over the 64 2-byte words of ABCD block data by advancing the PRNG and XORing the top 16 bits of each new state with each 16 bits of data:

X[n+1] = 0x41C64E6D * X[n] + 0x6073

D[n] = D[n] XOR (X[n+1] >> 16)

To read from or write to an encrypted Pokémon's ABCD block data, the game first decrypts the data as a whole, then determines what the block order is from the personality value and figures out the offset it needs to use to read from or write to either block.

Unencrypted bytes

Offset Contents
0x00-0x03 Personality value
0x04-0x05 Bit 0-1: If set, skip checksum checks
Bit 2: Bad egg flag
Bit 3-7: Unused
0x06-0x07 Checksum

Encrypted bytes

Block A

Offset Contents
0x08-0x09 Species ID
0x0A-0x0B Held Item
0x0C-0x0D OT ID
0x0E-0x0F OT Secret ID
0x10-0x13 Experience points
0x14 Friendship/Egg Steps to Hatch
0x15 Ability
0x16 Markings
0x17 Language of origin
0x18 HP EVs
0x19 Attack EVs
0x1A Defense EVs
0x1B Speed EVs
0x1C Sp. Atk EVs
0x1D Sp. Def. EVs
0x1E Cool Contest stat
0x1F Beauty Contest stat
0x20 Cute Contest stat
0x21 Smart Contest stat
0x22 Tough Contest stat
0x23 Sheen
0x24-0x27 Sinnoh Ribbons Set 1

Block B

Offset Contents
0x28-0x2F Moveset
0x30-0x33 Move PP
0x34-0x37 Move PP Ups
0x38-0x3B Bits 0-29 - Individual values
HP ( [0-31] << 0 )
Attack ( [0-31] << 5 )
Defense ( [0-31] << 10 )
Speed ( [0-31] << 15 )
Sp. Atk. ( [0-31] << 20 )
Sp. Def. ( [0-31] << 25 )
Bit 30 - IsEgg Flag
Bit 31 - IsNicknamed Flag
0x3C-0x3F Hoenn Ribbon Set
0x40 Bit 0 - Fateful encounter Flag
Bit 1 - Female
Bit 2 - Gender unknown
Bit 3-7 - Alternate Forms (Form Index << 3)
0x41 Shiny Leaves (HGSS)
Bit 5 - Leaf Crown
Bits 0–4 - Leaves A–E (bit 0 is leftmost)
0x42-0x43 Unused
0x44-0x45 Platinum Egg Location
0x46-0x47 Platinum Met at Location

Block C

Offset Contents
0x48-0x5D Nickname
0x5E Unused
0x5F Game of origin
0x60-0x63 Sinnoh Ribbons Set 2
0x64-0x67 Unused

Block D

Offset Contents
0x68-0x77 OT Name
0x78-0x7A Date Egg Received
0x7B-0x7D Date Met
0x7E-0x7F Diamond/Pearl Egg Location
0x80-0x81 Diamond/Pearl Met At Location
0x82 Pokérus
0x83 Poké Ball
0x84 Bit 0-6 - Met At Level
Bit 7 - Female OT Gender
0x85 Encounter Type
0x86 HG/SS Poké Ball
0x87 Walking Pokémon Mood (unused in DPPt)

Battle stats

The battle stats are encrypted in the same manner, however the seed is not the checksum, it is the personality value, and the bytes are not shuffled.

Encrypted bytes

Offset Contents
0x88 Bits 0-2 - Asleep (0-7 rounds)
Bit 3 - Poisoned
Bit 4 - Burned
Bit 5 - Frozen
Bit 6 - Paralyzed
Bit 7 - Toxic
0x89 Unknown - Flags - Max Value 0xF0
0x8A-0x8B Unknown
0x8C Level
0x8D Capsule Index (Seals)
0x8E-0x8F Current HP
0x90-0x91 Max HP
0x92-0x93 Attack
0x94-0x95 Defense
0x96-0x97 Speed
0x98-0x99 Special Attack
0x9A-0x9B Special Defense
0x9C-0xD3 Mail data
0xD4-0xEB Seal Coordinates

Language of origin

Main article: Language of origin
Value Language
0x1 日本語 (Japanese)
0x2 English
0x3 Français (French)
0x4 Italiano (Italian)
0x5 Deutsch (German)
0x7 Español (Spanish)
0x8 한국어 (Korean)

Markings

Bit Marking
0x01 Circle
0x02 Triangle
0x04 Square
0x08 Heart
0x10 Star
0x20 Diamond

Alternate forms

Alternate forms are stored at offset 0x40 of the Pokémon structure. Each form follows the pattern of index << 3 where index starts at zero for the main form.

Rotom's alternate forms, Giratina's Origin Forme, and Shaymin's Sky Forme will only be displayed in Pokémon Platinum, HeartGold and SoulSilver. Rotom may be traded among Pokémon Diamond, Pearl, and Platinum without losing its alternate form.

Byte Unown Deoxys Burmy/Wormadam Shellos/Gastrodon Rotom Giratina Shaymin Arceus Pichu (HGSS only)
0x00 A Normal Plant West Normal Altered Land Normal Normal
0x08 B Attack Sandy East Heat Origin Sky Fighting Spiky-eared
0x10 C Defense Trash Wash Flying
0x18 D Speed Frost Poison
0x20 E Fan Ground
0x28 F Mow Rock
0x30 G Bug
0x38 H Ghost
0x40 I Steel
0x48 J ???
0x50 K Fire
0x58 L Water
0x60 M Grass
0x68 N Electric
0x70 O Psychic
0x78 P Ice
0x80 Q Dragon
0x88 R Dark
0x90 S
0x98 T
0xA0 U
0xA8 V
0xB0 W
0xB8 X
0xC0 Y
0xC8 Z
0xD0 !
0xD8 ?

Encounter types

Value Encounter
0x0 Pal Park, Egg, Hatched, Special Event
0x2 Tall Grass
0x4 Dialga/Palkia In-Game Event
0x5 Cave, Hall of Origin
0x7 Surfing, Fishing
0x9 Building
0xA Great Marsh (Safari Zone)
0xC Starter, Fossil, Gift (Eevee) (D/P)
0x18 Starter, Fossil, Gift (Eevee) (HGSS/Pt)

Ribbons

Pokémon Diamond, Pearl, and Platinum store the Ribbon data as bitfields in 16-bit words. Given below are the bytewise representations of the ribbon bitfields:

Sinnoh Ribbon Set 1

Bit Ribbon
0x24 & 0x01 Sinnoh Champ Ribbon
0x24 & 0x02 Ability Ribbon
0x24 & 0x04 Great Ability Ribbon
0x24 & 0x08 Double Ability Ribbon
0x24 & 0x10 Multi Ability Ribbon
0x24 & 0x20 Pair Ability Ribbon
0x24 & 0x40 World Ability Ribbon
0x24 & 0x80 Alert Ribbon
0x25 & 0x01 Shock Ribbon
0x25 & 0x02 Downcast Ribbon
0x25 & 0x04 Careless Ribbon
0x25 & 0x08 Relax Ribbon
0x25 & 0x10 Snooze Ribbon
0x25 & 0x20 Smile Ribbon
0x25 & 0x40 Gorgeous Ribbon
0x25 & 0x80 Royal Ribbon
0x26 & 0x01 Gorgeous Royal Ribbon
0x26 & 0x02 Footprint Ribbon
0x26 & 0x04 Record Ribbon
0x26 & 0x08 History Ribbon
0x26 & 0x10 Legend Ribbon
0x26 & 0x20 Red Ribbon
0x26 & 0x40 Green Ribbon
0x26 & 0x80 Blue Ribbon
0x27 & 0x01 Festival Ribbon
0x27 & 0x02 Carnival Ribbon
0x27 & 0x04 Classic Ribbon
0x27 & 0x08 Premier Ribbon

Sinnoh Ribbon Set 2

Bit Ribbon
0x60 & 0x01 Cool Ribbon
0x60 & 0x02 Cool Ribbon Great
0x60 & 0x04 Cool Ribbon Ultra
0x60 & 0x08 Cool Ribbon Master
0x60 & 0x10 Beauty Ribbon
0x60 & 0x20 Beauty Ribbon Great
0x60 & 0x40 Beauty Ribbon Ultra
0x60 & 0x80 Beauty Ribbon Master
0x61 & 0x01 Cute Ribbon
0x61 & 0x02 Cute Ribbon Great
0x61 & 0x04 Cute Ribbon Ultra
0x61 & 0x08 Cute Ribbon Master
0x61 & 0x10 Smart Ribbon
0x61 & 0x20 Smart Ribbon Great
0x61 & 0x40 Smart Ribbon Ultra
0x61 & 0x80 Smart Ribbon Master
0x62 & 0x01 Tough Ribbon
0x62 & 0x02 Tough Ribbon Great
0x62 & 0x04 Tough Ribbon Ultra
0x62 & 0x08 Tough Ribbon Master

Hoenn Ribbon Set

Bit Ribbon
0x3C & 0x01 Cool Ribbon
0x3C & 0x02 Cool Ribbon Super
0x3C & 0x04 Cool Ribbon Hyper
0x3C & 0x08 Cool Ribbon Master
0x3C & 0x10 Beauty Ribbon
0x3C & 0x20 Beauty Ribbon Super
0x3C & 0x40 Beauty Ribbon Hyper
0x3C & 0x80 Beauty Ribbon Master
0x3D & 0x01 Cute Ribbon
0x3D & 0x02 Cute Ribbon Super
0x3D & 0x04 Cute Ribbon Hyper
0x3D & 0x08 Cute Ribbon Master
0x3D & 0x10 Smart Ribbon
0x3D & 0x20 Smart Ribbon Super
0x3D & 0x40 Smart Ribbon Hyper
0x3D & 0x80 Smart Ribbon Master
0x3E & 0x01 Tough Ribbon
0x3E & 0x02 Tough Ribbon Super
0x3E & 0x04 Tough Ribbon Hyper
0x3E & 0x08 Tough Ribbon Master
0x3E & 0x10 Champion Ribbon
0x3E & 0x20 Winning Ribbon
0x3E & 0x40 Victory Ribbon
0x3E & 0x80 Artist Ribbon
0x3F & 0x01 Effort Ribbon
0x3F & 0x02 Marine Ribbon
0x3F & 0x04 Land Ribbon
0x3F & 0x08 Sky Ribbon
0x3F & 0x10 Country Ribbon
0x3F & 0x20 National Ribbon
0x3F & 0x40 Earth Ribbon
0x3F & 0x80 World Ribbon

Technical Details

In Memory, the Player and Enemy Party Pokémon can be accessed using different pointers depending on the game. These pointers are stored as 32-bit addresses in little endian format.

Game Pointer
Diamond & Pearl 0x02106FAC
Platinum 0x02101D2C
Heartgold & Soulsilver 0x0211186C

In addition to this pointer, the order in which they store the Pokémon changes slightly. The following addresses when added to the pointer result in their respective locations

Game Player Party Enemy Party
Diamond & Pearl 0xD2AC 0x364C8
Platinum 0xD088 0x37970
Heartgold & Soulsilver 0xD094 0x352F4

Location

The party Pokémon are stored in the save file beginning at offset 0x00098 for the first block pair, and 0x40098 for the second block pair. Each party Pokémon is 236 bytes in size.

The PC storage Pokémon are stored in the save file from Box 1 to Box 18. They start at 0x0C104 in the first block pair, and at 0x4C104 in the second block pair. Each PC stored Pokémon is 136 bytes in size.


Data structure in the Pokémon games
General Character encoding
Generation I Pokémon speciesPokémonPoké MartCharacter encoding (Stadium) • Save
Generation II Pokémon speciesPokémonTrainerCharacter encoding (StadiumKorean) • Save
Generation III Pokémon species (EvolutionPokédexType chart)
Pokémon (substructures) • MoveContestContest moveItem
Trainer TowerBattle FrontierCharacter encoding (GameCube) • Save
Generation IV Pokémon species (EvolutionLearnsets)
PokémonSaveCharacter encoding (Wii)
Generation V–present Character encoding
Generation VIII Save
TCG GB and GB2 Character encoding
Project Games logo.png This data structure article is part of Project Games, a Bulbapedia project that aims to write comprehensive articles on the Pokémon games.