From Bulbapedia, the community-driven Pokémon encyclopedia.

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. Given the personality value pv, the expression yielding the shift value is:

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

The right shifting (>> 0xD) is equivalent to a division of 8192.

To shuffle the blocks, take the four blocks of unencrypted data, A, B, C, and D. The blocks shall be rearranged in the encrypted data according to the Block Order column of the following table. (To unshuffle, use the Inverse column.)

Shift Value (decimal) Block Order Inverse 00 ABCD ABCD 01 ABDC ABDC 02 ACBD ACBD 03 ACDB ADBC 04 ADBC ACDB 05 ADCB ADCB 06 BACD BACD 07 BADC BADC 08 BCAD CABD 09 BCDA DABC 10 BDAC CADB 11 BDCA DACB 12 CABD BCAD 13 CADB BDAC 14 CBAD CBAD 15 CBDA DBAC 16 CDAB CDAB 17 CDBA DCAB 18 DABC BCDA 19 DACB BDCA 20 DBAC CBDA 21 DBCA DBCA 22 DCAB CDBA 23 DCBA 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)

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() Unshuffle the blocks using the block shuffling algorithm above.

To encrypt the data:

Shuffle the blocks using the block shuffling algorithm above. 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()

Unencrypted bytes

Offset Contents 0x00-0x03 Personality value 0x04-0x05 Bit 0-1: If set, skip checksum checks

Bit 2: Bad egg flag

Bit 3-7: Unused 0x06-0x07 Checksum

Encrypted bytes

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 Language of origin 0x18 HP EVs 0x19 Attack EVs 0x1A Defense EVs 0x1B Speed EVs 0x1C Sp. Atk EVs 0x1D Sp. Def. EVs 0x1E Cool Contest stat 0x1F Beauty Contest stat 0x20 Cute Contest stat 0x21 Smart Contest stat 0x22 Tough Contest stat 0x23 Sheen 0x24-0x27 Sinnoh Ribbons Set 1

Block B

Offset Contents 0x28-0x2F Moveset 0x30-0x33 Move PP 0x34-0x37 Move PP Ups 0x38-0x3B Bits 0-29 - Individual values

HP ( [0-31] << 0 )

Attack ( [0-31] << 5 )

Defense ( [0-31] << 10 )

Speed ( [0-31] << 15 )

Sp. Atk. ( [0-31] << 20 )

Sp. Def. ( [0-31] << 25 )

Bit 30 - IsEgg Flag

Bit 31 - IsNicknamed Flag 0x3C-0x3F Hoenn Ribbon Set 0x40 Bit 0 - Fateful encounter Flag

Bit 1 - Female

Bit 2 - Genderless

Bit 3-7 - Alternate Forms (Form Index << 3) 0x41 Shiny Leaves (HGSS)

Bit 5 - Leaf Crown

Bits 0–4 - Leaves A–E (bit 0 is leftmost) 0x42-0x43 Unused 0x44-0x45 Platinum Egg Location 0x46-0x47 Platinum Met at Location

Block C

Offset Contents 0x48-0x5D Nickname 0x5E Unused 0x5F Game of origin 0x60-0x63 Sinnoh Ribbons Set 2 0x64-0x67 Unused

Block D

Offset Contents 0x68-0x77 OT Name 0x78-0x7A Date Egg Received 0x7B-0x7D Date Met 0x7E-0x7F Diamond/Pearl Egg Location 0x80-0x81 Diamond/Pearl Met At Location 0x82 Pokérus 0x83 Poké Ball 0x84 Bit 0-6 - Met At Level

Bit 7 - Female OT Gender 0x85 Encounter Type 0x86 HG/SS Poké Ball 0x87 Performance (unused in DPPt)

Battle stats

The battle stats are encrypted in the same manner, however the seed is not the checksum, it is the personality value, and the bytes are not shuffled.

Encrypted bytes

Offset Contents 0x88 Bits 0-2 - Asleep (0-7 rounds)

Bit 3 - Poisoned

Bit 4 - Burned

Bit 5 - Frozen

Bit 6 - Paralyzed

Bit 7 - Toxic 0x89 Unknown - Flags - Max Value 0xF0 0x8A-0x8B Unknown 0x8C Level 0x8D Capsule Index (Seals) 0x8E-0x8F Current HP 0x90-0x91 Max HP 0x92-0x93 Attack 0x94-0x95 Defense 0x96-0x97 Speed 0x98-0x99 Special Attack 0x9A-0x9B Special Defense 0x9C-0xD3 Unknown - Contains Trash Data 0xD4-0xEB Seal Coordinates

Language of origin

Value Language 0x1 日本語 (Japanese) 0x2 English 0x3 Français (French) 0x4 Italiano (Italian) 0x5 Deutsch (German) 0x7 Español (Spanish) 0x8 한국어 (Korean)

Markings

Bit Marking 0x01 Circle 0x02 Triangle 0x04 Square 0x08 Heart 0x10 Star 0x20 Diamond

Alternate forms

Alternate forms are stored at offset 0x40 of the Pokémon structure. Each form follows the pattern of index << 3 where index starts at zero for the main form.

Rotom's alternate forms, Giratina's Origin Forme, and Shaymin's Sky Forme will only be displayed in Pokémon Platinum, HeartGold and SoulSilver. Rotom may be traded among Pokémon Diamond, Pearl, and Platinum without losing its alternate form.

Byte Unown Deoxys Burmy/Wormadam Shellos/Gastrodon Rotom Giratina Shaymin Arceus Pichu (HGSS only) 0x00 A Normal Plant West Normal Altered Land Normal Normal 0x08 B Attack Sandy East Heat Origin Sky Fist Spiky-eared 0x10 C Defense Trash Wash Sky 0x18 D Speed Frost Toxic 0x20 E Fan Earth 0x28 F Mow Stone 0x30 G Insect 0x38 H Spooky 0x40 I Iron 0x48 J Flame 0x50 K Splash 0x58 L Meadow 0x60 M Zap 0x68 N Mind 0x70 O Icicle 0x78 P Draco 0x80 Q Dread 0x88 R ??? 0x90 S 0x98 T 0xA0 U 0xA8 V 0xB0 W 0xB8 X 0xC0 Y 0xC8 Z 0xD0 ! 0xD8 ?

Encounter types

Value Encounter 0x0 Pal Park, Egg, Hatched, Special Event 0x2 Tall Grass 0x4 Dialga/Palkia In-Game Event 0x5 Cave, Hall of Origin 0x7 Surfing, Fishing 0x9 Building 0xA Great Marsh (Safari Zone) 0xC Starter, Fossil, Gift (Eevee)

Ribbons

Pokémon Diamond, Pearl, and Platinum store the Ribbon data as bitfields in 16-bit words. Given below are the bytewise representations of the ribbon bitfields:

Sinnoh Ribbon Set 1

Bit Ribbon 0x24 & 0x01 Sinnoh Champ Ribbon 0x24 & 0x02 Ability Ribbon 0x24 & 0x04 Great Ability Ribbon 0x24 & 0x08 Double Ability Ribbon 0x24 & 0x10 Multi Ability Ribbon 0x24 & 0x20 Pair Ability Ribbon 0x24 & 0x40 World Ability Ribbon 0x24 & 0x80 Alert Ribbon 0x25 & 0x01 Shock Ribbon 0x25 & 0x02 Downcast Ribbon 0x25 & 0x04 Careless Ribbon 0x25 & 0x08 Relax Ribbon 0x25 & 0x10 Snooze Ribbon 0x25 & 0x20 Smile Ribbon 0x25 & 0x40 Gorgeous Ribbon 0x25 & 0x80 Royal Ribbon 0x26 & 0x01 Gorgeous Royal Ribbon 0x26 & 0x02 Footprint Ribbon 0x26 & 0x04 Record Ribbon 0x26 & 0x08 History Ribbon 0x26 & 0x10 Legend Ribbon 0x26 & 0x20 Red Ribbon 0x26 & 0x40 Green Ribbon 0x26 & 0x80 Blue Ribbon 0x27 & 0x01 Festival Ribbon 0x27 & 0x02 Carnival Ribbon 0x27 & 0x04 Classic Ribbon 0x27 & 0x08 Premier Ribbon

Sinnoh Ribbon Set 2

Bit Ribbon 0x60 & 0x01 Cool Ribbon 0x60 & 0x02 Cool Ribbon Great 0x60 & 0x04 Cool Ribbon Ultra 0x60 & 0x08 Cool Ribbon Master 0x60 & 0x10 Beauty Ribbon 0x60 & 0x20 Beauty Ribbon Great 0x60 & 0x40 Beauty Ribbon Ultra 0x60 & 0x80 Beauty Ribbon Master 0x61 & 0x01 Cute Ribbon 0x61 & 0x02 Cute Ribbon Great 0x61 & 0x04 Cute Ribbon Ultra 0x61 & 0x08 Cute Ribbon Master 0x61 & 0x10 Smart Ribbon 0x61 & 0x20 Smart Ribbon Great 0x61 & 0x40 Smart Ribbon Ultra 0x61 & 0x80 Smart Ribbon Master 0x62 & 0x01 Tough Ribbon 0x62 & 0x02 Tough Ribbon Great 0x62 & 0x04 Tough Ribbon Ultra 0x62 & 0x08 Tough Ribbon Master

Hoenn Ribbon Set

Bit Ribbon 0x3C & 0x01 Cool Ribbon 0x3C & 0x02 Cool Ribbon Super 0x3C & 0x04 Cool Ribbon Hyper 0x3C & 0x08 Cool Ribbon Master 0x3C & 0x10 Beauty Ribbon 0x3C & 0x20 Beauty Ribbon Super 0x3C & 0x40 Beauty Ribbon Hyper 0x3C & 0x80 Beauty Ribbon Master 0x3D & 0x01 Cute Ribbon 0x3D & 0x02 Cute Ribbon Super 0x3D & 0x04 Cute Ribbon Hyper 0x3D & 0x08 Cute Ribbon Master 0x3D & 0x10 Smart Ribbon 0x3D & 0x20 Smart Ribbon Super 0x3D & 0x40 Smart Ribbon Hyper 0x3D & 0x80 Smart Ribbon Master 0x3E & 0x01 Tough Ribbon 0x3E & 0x02 Tough Ribbon Super 0x3E & 0x04 Tough Ribbon Hyper 0x3E & 0x08 Tough Ribbon Master 0x3E & 0x10 Champion Ribbon 0x3E & 0x20 Winning Ribbon 0x3E & 0x40 Victory Ribbon 0x3E & 0x80 Artist Ribbon 0x3F & 0x01 Effort Ribbon 0x3F & 0x02 Marine Ribbon 0x3F & 0x04 Land Ribbon 0x3F & 0x08 Sky Ribbon 0x3F & 0x10 Country Ribbon 0x3F & 0x20 National Ribbon 0x3F & 0x40 Earth Ribbon 0x3F & 0x80 World Ribbon

Location

The party Pokémon are stored in the save file beginning at offset 0x00098 for the first block pair, and 0x40098 for the second block pair. Each party Pokémon is 236 bytes in size.

The PC storage Pokémon are stored in the save file from Box 1 to Box 18. They start at 0x0C104 in the first block pair, and at 0x4C104 in the second block pair. Each PC stored Pokémon is 136 bytes in size.



