Pokémon data structure (Generation IV)

From Bulbapedia, the community-driven Pokémon encyclopedia.
Revision as of 08:43, 12 July 2008 by Tsanth (talk | contribs) (Prettified layout, corrected style, changed wording.)
Jump to navigationJump to search

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:

  1. It validates the data after decryption, and
  2. It serves as the encryption key for the data.

The checksum is calculated in three steps:

  1. Split the unencrypted data from offsets 0x08 to 0x87 into two-byte words,
  2. Take the sum of the words, and
  3. 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:

  1. Seed the PRNG with the checksum (let X[n] be the checksum),
  2. Sequentially, for each 2-byte word Y from 0x08 to 0x87, apply the transformation: unencryptedByte = Y xor rand()
  3. Un-shuffle the blocks using the block shuffling algorithm above.

Unencrypted bytes

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