Pokémon data structure (Generation IV)
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 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:
- It validates the data after decryption, and
- It serves as the encryption key for the data.
The checksum is calculated in three steps:
- Split the unencrypted data from offsets 0x08 to 0x87 into two-byte words,
- Take the sum of the words, and
- 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 >> 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:
Shift Value (decimal) | Block Order |
---|---|
00 | ABCD |
01 | ABDC |
02 | ACBD |
03 | ACDB |
04 | ADBC |
05 | ADCB |
06 | BACD |
07 | BADC |
08 | BCAD |
09 | BCDA |
10 | BDAC |
11 | BDCA |
12 | CABD |
13 | CADB |
14 | CBAD |
15 | CBDA |
16 | CDAB |
17 | CDBA |
18 | DABC |
19 | DACB |
20 | DBAC |
21 | DBCA |
22 | DCAB |
23 | DCBA |
Encryption
The encryption uses the pseudorandom number generator (PRNG), a linear congruential generator. Elements of the PRNG can be described with the recursive function:
- 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:
- 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:
- 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
Offset | Contents |
---|---|
0x00-0x03 | Personality value |
0x04-0x05 | Unknown |
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 | Country of Origin |
0x18-0x1D | Effort values |
0x1E-0x23 | Contest stats |
0x24-0x27 | Ribbons |
Block B
Offset | Contents |
---|---|
0x28-0x2F | Moveset |
0x30-0x33 | Move PP |
0x34-0x37 | Move PP Ups |
0x38-0x3B | Bits 0-29 - Individual values Bit 30 - IsNicknamed Flag Bit 31 - IsEgg Flag |
0x3C-0x3F | Ribbons 2 |
0x40-0x41 | Bit 0 - Fateful Encountered Flag Bit 1 - Female Bit 2 - Genderless Bit 3-15 - Alternate Forms (Form Index << 3) |
0x42-0x43 | Unknown |
0x44-0x45 | Platinum Egg Location |
0x46-0x47 | Platinum Met at Location |
Block C
Offset | Contents |
---|---|
0x48-0x5D | Nickname |
0x5E-0x5F | Hometown |
0x60-0x63 | Contests |
0x64-0x67 | Unknown |
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-0x87 | Unknown |
Ribbons
DP stores the ribbon data as bitfields in 16-bit words. Given below are the bytewise representations of the ribbon bitfields:
Bit | Ribbon |
---|---|
0x25 & 0x01 | Sinnoh Champ Ribbon |
0x25 & 0x02 | Ability Ribbon |
0x25 & 0x04 | Great Ability Ribbon |
0x25 & 0x08 | Double Ability Ribbon |
0x25 & 0x10 | Multi Ability Ribbon |
0x25 & 0x20 | Pair Ability Ribbon |
0x25 & 0x40 | World Ability Ribbon |
0x25 & 0x80 | Alert Ribbon |
0x24 & 0x01 | Shock Ribbon |
0x24 & 0x02 | Downcast Ribbon |
0x24 & 0x04 | Careless Ribbon |
0x24 & 0x08 | Relax Ribbon |
0x24 & 0x10 | Snooze Ribbon |
0x24 & 0x20 | Smile Ribbon |
0x24 & 0x40 | Gorgeous Ribbon |
0x24 & 0x80 | Royal Ribbon |
Bit | Ribbon |
---|---|
0x27 & 0x01 | Gorgeous Royal Ribbon |
0x27 & 0x02 | Footprint Ribbon |
0x27 & 0x04 | Record Ribbon |
0x27 & 0x08 | History Ribbon |
0x27 & 0x10 | Legend Ribbon |
0x27 & 0x20 | Red Ribbon |
0x27 & 0x40 | Green Ribbon |
0x27 & 0x80 | Blue Ribbon |
0x26 & 0x01 | Festival Ribbon |
0x26 & 0x02 | Carnival Ribbon |
0x26 & 0x04 | Classic Ribbon |
0x26 & 0x08 | Premier Ribbon |
Bit | Ribbon |
---|---|
0x3D & 0x01 | Cool Ribbon |
0x3D & 0x02 | Cool Ribbon Super |
0x3D & 0x04 | Cool Ribbon Hyper |
0x3D & 0x08 | Cool Ribbon Master |
0x3D & 0x10 | Beauty Ribbon |
0x3D & 0x20 | Beauty Ribbon Super |
0x3D & 0x40 | Beauty Ribbon Hyper |
0x3D & 0x80 | Beauty Ribbon Master |
0x3C & 0x01 | Cute Ribbon |
0x3C & 0x02 | Cute Ribbon Super |
0x3C & 0x04 | Cute Ribbon Hyper |
0x3C & 0x08 | Cute Ribbon Master |
0x3C & 0x10 | Smart Ribbon |
0x3C & 0x20 | Smart Ribbon Super |
0x3C & 0x40 | Smart Ribbon Hyper |
0x3C & 0x80 | Smart Ribbon Master |
Bit | Ribbon |
---|---|
0x3F & 0x01 | Tough Ribbon |
0x3F & 0x02 | Tough Ribbon Super |
0x3F & 0x04 | Tough Ribbon Hyper |
0x3F & 0x08 | Tough Ribbon Master |
0x3F & 0x10 | Champion Ribbon |
0x3F & 0x20 | Winning Ribbon |
0x3F & 0x40 | Victory Ribbon |
0x3F & 0x80 | Artist Ribbon |
0x3E & 0x01 | Effort Ribbon |
0x3E & 0x02 | Marine Ribbon |
0x3E & 0x04 | Land Ribbon |
0x3E & 0x08 | Sky Ribbon |
0x3E & 0x10 | Country Ribbon |
0x3E & 0x20 | National Ribbon |
0x3E & 0x40 | Earth Ribbon |
0x3E & 0x80 | World Ribbon |
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.
For a csv file of every box and box slot offset, click here.
|