Pokémon data structure (Generation IV): Difference between revisions
(Prettified layout, corrected style, changed wording.) |
(Fixed error in encryption algorithm; denoted decimal versus hexadecimal numbers.) |
||
Line 21: | Line 21: | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | {| border="1" style="border: 1px solid #999; border-collapse: collapse;" | ||
|- style="background: #ccc;" align="center" | |- style="background: #ccc;" align="center" | ||
! Shift Value | ! Shift Value (decimal) | ||
! Block Order | ! Block Order | ||
|- style="background: #eee;" align="center" | |- style="background: #eee;" align="center" | ||
Line 102: | Line 102: | ||
: ''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 | 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), | # 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()'' | ||
Line 108: | Line 108: | ||
== Unencrypted bytes == | == Unencrypted bytes == | ||
* | * 0x00-0x03 [[Personality value]] | ||
* | * 0x04-0x05 ''Unknown'' | ||
* | * 0x06-0x07 [[Checksum]] | ||
=== Block A === | === Block A === | ||
* | * 0x08-0x09 Species ID | ||
* | * 0x0A-0x0B Held Item | ||
* | * 0x0C-0x0D OT ID | ||
* | * 0x0E-0x0F OT Secret ID | ||
* | * 0x10-0x13 [[Experience|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 === | === 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 === | === Block C === | ||
* | * 0x48-0x5D Nickname | ||
* | * 0x5E ''Unknown'' | ||
* | * 0x5F Hometown | ||
* | * 0x60-0x62 Contests | ||
* | * 0x63-0x67 ''Unknown'' | ||
=== Block D === | === 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'' | ||
[[Category:Structures]] | [[Category:Structures]] | ||
[[Category:Game mechanics]] | [[Category:Game mechanics]] |
Revision as of 08:52, 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 (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