Pokémon data structure (Generation IV): Difference between revisions
(Added information on the checksum and encryption algorithms; minor edits to layout and top-matter for clarity.) |
(Prettified layout, corrected style, changed wording.) |
||
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. In-party | 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. 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 == | ||
Line 8: | Line 8: | ||
The checksum is calculated in three steps: | The checksum is calculated in three steps: | ||
# Split the unencrypted data from 0x08 | # Split the unencrypted data from offsets 0x08 to 0x87 into two-byte words, | ||
# Take the sum of the words, and | # Take the sum of the words, and | ||
# Truncate the sum to sixteen bits. | # Truncate the sum to sixteen bits. | ||
Line 14: | Line 14: | ||
== Block Shuffling == | == Block Shuffling == | ||
The 128 bytes of | 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'' | : ''((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: | |||
{| | {| border="1" style="border: 1px solid #999; border-collapse: collapse;" | ||
| 00 = | |- style="background: #ccc;" align="center" | ||
| 01 = | ! Shift Value | ||
| 02 = | ! Block Order | ||
| 03 = | |- style="background: #eee;" align="center" | ||
| 04 = | | 00 | ||
| 05 | | ABCD | ||
|- | |- style="background: #ddd;" align="center" | ||
| 06 = | | 01 | ||
| 07 = | | ABDC | ||
| 08 = | |- style="background: #eee;" align="center" | ||
| 09 = | | 02 | ||
| 10 = | | ACBD | ||
| 11 | |- style="background: #ddd;" align="center" | ||
|- | | 03 | ||
| 12 = | | ACDB | ||
| 13 = | |- style="background: #eee;" align="center" | ||
| 14 = | | 04 | ||
| 15 = | | ADBC | ||
| 16 = | |- style="background: #ddd;" align="center" | ||
| 17 | | 05 | ||
|- | | ADCB | ||
| 18 = | |- style="background: #eee;" align="center" | ||
| 19 = | | 06 | ||
| 20 = | | BACD | ||
| 21 = | |- style="background: #ddd;" align="center" | ||
| 22 = | | 07 | ||
| 23 | | BADC | ||
|- style="background: #eee;" align="center" | |||
| 08 | |||
| BCAD | |||
|- style="background: #ddd;" align="center" | |||
| 09 | |||
| BCDA | |||
|- style="background: #eee;" align="center" | |||
| 10 | |||
| BDAC | |||
|- style="background: #ddd;" align="center" | |||
| 11 | |||
| BDCA | |||
|- style="background: #eee;" align="center" | |||
| 12 | |||
| CABD | |||
|- style="background: #ddd;" align="center" | |||
| 13 | |||
| CADB | |||
|- style="background: #eee;" align="center" | |||
| 14 | |||
| CBAD | |||
|- style="background: #ddd;" align="center" | |||
| 15 | |||
| CBDA | |||
|- style="background: #eee;" align="center" | |||
| 16 | |||
| CDAB | |||
|- style="background: #ddd;" align="center" | |||
| 17 | |||
| CDBA | |||
|- style="background: #eee;" align="center" | |||
| 18 | |||
| DABC | |||
|- style="background: #ddd;" align="center" | |||
| 19 | |||
| DACB | |||
|- style="background: #eee;" align="center" | |||
| 20 | |||
| DBAC | |||
|- style="background: #ddd;" align="center" | |||
| 21 | |||
| DBCA | |||
|- style="background: #eee;" align="center" | |||
| 22 | |||
| DCAB | |||
|- style="background: #ddd;" align="center" | |||
| 23 | |||
| DCBA | |||
|} | |} | ||
== Encryption == | == Encryption == | ||
The 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'' | : ''X[n+1] = (0x41C64E6D * X[n] + 0x6073) % 0xFFFFFFFF'' | ||
To decrypt the data, given a function ''rand()'' which returns the result of the above given function: | To decrypt the data, given a function ''rand()'' which returns the result of the above given function: | ||
# Seed the PRNG with the checksum, | # 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()'' | # 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. | # Un-shuffle the blocks using the block shuffling algorithm above. |
Revision as of 08:43, 12 July 2008
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 | 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 result 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
- 00-03 Personality value
- 04-05 Unknown
- 06-07 Checksum
Block A
- 08-09 Species ID
- 0A-0B Held Item
- 0C-0D OT ID
- 0E-0F OT Secret ID
- 10-13 Experience points
- 14 Friendship/Egg Steps to Hatch
- 15 Ability
- 16 Markings
- 17 Country of Origin
- 18-1D Effort values
- 1E-23 Contest stats
- 24-27 Ribbons
Block B
- 28-2F Moveset
- 30-33 Move PP
- 34-37 Move PP Ups
- 38-3B Individual values
- 3C-3F Ribbons 2
- 40 Gender
- 41-47 Unknown
Block C
- 48-5D Nickname
- 5E Unknown
- 5F Hometown
- 60-62 Contests
- 63-67 Unknown
Block D
- 68-77 OT Name
- 78-7A Date Egg Received
- 7B-7D Date Met
- 7E-7F Egg Location
- 80-81 Met At Location
- 82 Pokérus
- 83 Poké Ball
- 84 Met At Level
- 85 Encounter Type
- 86-87 Unknown