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. Give the personality value pv, the expression yielding the shift value is:
- ((pv >> 0xD) & 0x1F) % 24
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) % 0xFFFFFFFF
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.
Unencrypted bytes
- 0x00-0x03 Personality value
- 0x04-0x05 Unknown
- 0x06-0x07 Checksum
Block A
- 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
- 0x28-0x2F Moveset
- 0x30-0x33 Move PP
- 0x34-0x37 Move PP Ups
- 0x38-0x3B Individual values
- 0x3C-0x3F Ribbons 2
- 0x40 Gender
- 0x41-0x47 Unknown
Block C
- 0x48-0x5D Nickname
- 0x5E Unknown
- 0x5F Hometown
- 0x60-0x62 Contests
- 0x63-0x67 Unknown
Block D
- 0x68-0x77 OT Name
- 0x78-0x7A Date Egg Received
- 0x7B-0x7D Date Met
- 0x7E-0x7F Egg Location
- 0x80-0x81 Met At Location
- 0x82 Pokérus
- 0x83 Poké Ball
- 0x84 Met At Level
- 0x85 Encounter Type
- 0x86-0x87 Unknown