Pokémon data structure (Generation IV): Difference between revisions
(Fixed error in encryption algorithm; denoted decimal versus hexadecimal numbers.) |
(Prettified unencrypted block contents.) |
||
Line 108: | Line 108: | ||
== Unencrypted bytes == | == Unencrypted bytes == | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | |||
|- style="background: #ccc;" align="center" | |||
! Offset | |||
! Contents | |||
|- style="background: #eee;" align="center" | |||
| 0x00-0x03 | |||
| [[Personality value]] | |||
|- style="background: #ddd;" align="center" | |||
| 0x04-0x05 | |||
| ''Unknown'' | |||
|- style="background: #eee;" align="center" | |||
| 0x06-0x07 | |||
| Checksum | |||
|} | |||
=== Block A === | === Block A === | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | |||
|- style="background: #ccc;" align="center" | |||
! Offset | |||
! Contents | |||
|- style="background: #eee;" align="center" | |||
| 0x08-0x09 | |||
| Species ID | |||
|- style="background: #ddd;" align="center" | |||
| 0x0A-0x0B | |||
| Held Item | |||
|- style="background: #eee;" align="center" | |||
| 0x0C-0x0D | |||
| OT ID | |||
|- style="background: #ddd;" align="center" | |||
| 0x0E-0x0F | |||
| OT Secret ID | |||
|- style="background: #ddd;" align="center" | |||
| 0x10-0x13 | |||
| [[Experience|Experience points]] | |||
|- style="background: #eee;" align="center" | |||
| 0x14 | |||
| Friendship/Egg Steps to Hatch | |||
|- style="background: #ddd;" align="center" | |||
| 0x15 | |||
| [[Ability]] | |||
|- style="background: #eee;" align="center" | |||
| 0x16 | |||
| Markings | |||
|- style="background: #ddd;" align="center" | |||
| 0x17 | |||
| Country of Origin | |||
|- style="background: #eee;" align="center" | |||
| 0x18-0x1D | |||
| [[Effort values]] | |||
|- style="background: #ddd;" align="center" | |||
| 0x1E-0x23 | |||
| Contest stats | |||
|- style="background: #eee;" align="center" | |||
| 0x24-0x27 | |||
| Ribbons | |||
|} | |||
=== Block B === | === Block B === | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | |||
|- style="background: #ccc;" align="center" | |||
! Offset | |||
! Contents | |||
|- style="background: #eee;" align="center" | |||
| 0x28-0x2F | |||
| Moveset | |||
|- style="background: #ddd;" align="center" | |||
| 0x30-0x33 | |||
| Move PP | |||
|- style="background: #eee;" align="center" | |||
| 0x34-0x37 | |||
| Move PP Ups | |||
|- style="background: #ddd;" align="center" | |||
| 0x38-0x3B | |||
| [[Individual values]] | |||
|- style="background: #eee;" align="center" | |||
| 0x3C-0x3F | |||
| Ribbons 2 | |||
|- style="background: #ddd;" align="center" | |||
| 0x40 | |||
| Gender | |||
|- style="background: #eee;" align="center" | |||
| 0x41-0x47 | |||
| ''Unknown'' | |||
|} | |||
=== Block C === | === Block C === | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | |||
|- style="background: #ccc;" align="center" | |||
! Offset | |||
! Contents | |||
|- style="background: #eee;" align="center" | |||
| 0x48-0x5D | |||
| Nickname | |||
|- style="background: #ddd;" align="center" | |||
| 0x5E | |||
| ''Unknown'' | |||
|- style="background: #eee;" align="center" | |||
| 0x5F | |||
| Hometown | |||
|- style="background: #ddd;" align="center" | |||
| 0x60-0x62 | |||
| Contests | |||
|- style="background: #eee;" align="center" | |||
| 0x63-0x67 | |||
| ''Unknown'' | |||
|} | |||
=== Block D === | === Block D === | ||
{| border="1" style="border: 1px solid #999; border-collapse: collapse;" | |||
|- style="background: #ccc;" align="center" | |||
! Offset | |||
! Contents | |||
|- style="background: #eee;" align="center" | |||
| 0x68-0x77 | |||
| OT Name | |||
|- style="background: #ddd;" align="center" | |||
| 0x78-0x7A | |||
| Date Egg Received | |||
|- style="background: #eee;" align="center" | |||
| 0x7B-0x7D | |||
| Date Met | |||
|- style="background: #ddd;" align="center" | |||
| 0x7E-0x7F | |||
| Egg Location | |||
|- style="background: #eee;" align="center" | |||
| 0x80-0x81 | |||
| Met At Location | |||
|- style="background: #ddd;" align="center" | |||
| 0x82 | |||
| [[Pokérus]] | |||
|- style="background: #eee;" align="center" | |||
| 0x83 | |||
| Poké Ball | |||
|- style="background: #ddd;" align="center" | |||
| 0x84 | |||
| Met At Level | |||
|- style="background: #eee;" align="center" | |||
| 0x85 | |||
| Encounter Type | |||
|- style="background: #ddd;" align="center" | |||
| 0x86-0x87 | |||
| ''Unknown'' | |||
|} | |||
[[Category:Structures]] | [[Category:Structures]] | ||
[[Category:Game mechanics]] | [[Category:Game mechanics]] |
Revision as of 09:23, 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
Offset | Contents |
---|---|
0x00-0x03 | Personality value |
0x04-0x05 | Unknown |
0x06-0x07 | Checksum |
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 | Individual values |
0x3C-0x3F | Ribbons 2 |
0x40 | Gender |
0x41-0x47 | Unknown |
Block C
Offset | Contents |
---|---|
0x48-0x5D | Nickname |
0x5E | Unknown |
0x5F | Hometown |
0x60-0x62 | Contests |
0x63-0x67 | Unknown |
Block D
Offset | Contents |
---|---|
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 |