Pokémon data structure (Generation IV)

From Bulbapedia, the community-driven Pokémon encyclopedia.
Revision as of 08:52, 12 July 2008 by Tsanth (talk | contribs) (Fixed error in encryption algorithm; denoted decimal versus hexadecimal numbers.)
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 (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:

  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

  • 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