Pokémon data structure (Generation IV)

From Bulbapedia, the community-driven Pokémon encyclopedia.
Revision as of 07:02, 12 July 2008 by Tsanth (talk | contribs) (Added information on the checksum and encryption algorithms; minor edits to layout and top-matter for clarity.)
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 0x08..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. The expression yielding the shift value is:

((pv >> 0xD) & 0x1F) % 24

Take the four blocks of unencrypted data to be A, B, C, and D. The blocks shall be shifted according to this table:

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 is dependent upon the pseudorandom number generator (PRNG), which is in turn 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,
  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