Skip to main content

PK3, PK4, and PK5 Classes

PK3, PK4, and PK5 represent the Nintendo DS and GBA era Pokémon formats, introducing modern mechanics like abilities, natures, and encrypted data structures.

PK3 Class

Namespace: PKHeX.Core File: PKHeX.Core/PKM/PK3.cs

Format Specifications

PropertyValue
SIZE_STORED80 bytes
SIZE_PARTY100 bytes
Generation3
ContextEntityContext.Gen3
GamesRuby, Sapphire, Emerald, FireRed, LeafGreen

Key Features

Modern Pokémon Mechanics

Gen 3 introduced:
  • Abilities: First generation with abilities
  • Natures: 25 natures affecting stat growth
  • IVs: 32 possible values (0-31) for each stat
  • EVs: Effort Values with 252 max per stat
  • Personality Value (PID): Determines nature, gender, ability, shininess

Data Encryption

PK3 uses block-based encryption:
public ushort Checksum { get; set; }
public ushort Sanity { get; set; }
  • Data divided into 4 blocks (A, B, C, D)
  • Block order shuffled based on PID
  • Each block encrypted with PID as key

Contest Stats

Gen 3 introduced Pokémon Contests:
public byte ContestCool { get; set; }
public byte ContestBeauty { get; set; }
public byte ContestCute { get; set; }
public byte ContestSmart { get; set; }
public byte ContestTough { get; set; }
public byte ContestSheen { get; set; }

Data Structure

Block A (0x20-0x2B)

  • Species (National Dex conversion)
  • Held Item
  • Experience
  • PP Ups (compressed)
  • Friendship

Block B (0x2C-0x37)

  • Moves 1-4
  • PP for each move

Block C (0x38-0x43)

  • EVs (HP, ATK, DEF, SPE, SPA, SPD)
  • Contest stats

Block D (0x44-0x4F)

  • Pokérus state
  • Met location
  • Origins (level, version, ball, OT gender)
  • IVs (30 bits) + Egg flag + Ability bit
  • Ribbons

IV Storage

public uint IV32 { get; set; }
public int IV_HP  { get; set; } // Bits 0-4
public int IV_ATK { get; set; } // Bits 5-9
public int IV_DEF { get; set; } // Bits 10-14
public int IV_SPE { get; set; } // Bits 15-19
public int IV_SPA { get; set; } // Bits 20-24
public int IV_SPD { get; set; } // Bits 25-29
public bool IsEgg { get; set; } // Bit 30
public bool AbilityBit { get; set; } // Bit 31

Conversion to PK4

public PK4 ConvertToPK4()
Transfer through Pal Park:
  • Removes HM moves
  • Converts ribbons from count to boolean
  • Sets met location to Pal Park
  • Preserves PID, IVs, nature

PK4 Class

Namespace: PKHeX.Core File: PKHeX.Core/PKM/PK4.cs

Format Specifications

PropertyValue
SIZE_STORED136 bytes
SIZE_PARTY236 bytes
Generation4
ContextEntityContext.Gen4
GamesDiamond, Pearl, Platinum, HeartGold, SoulSilver

Key Features

Expanded Data Structure

  • Larger format accommodates new features
  • Gender stored separately from PID
  • Form data for new alternate forms
  • Met date tracking (year, month, day)

Dual Location System

Diamond/Pearl vs Platinum/HGSS locations:
public ushort EggLocationDP { get; set; }
public ushort MetLocationDP { get; set; }
public ushort EggLocationExtended { get; set; }
public ushort MetLocationExtended { get; set; }

Shiny Leaf (HGSS)

public int ShinyLeaf { get; set; }
HeartGold/SoulSilver feature for befriended Pokémon.

Data Structure

Block A (0x08-0x27)

  • Species, Held Item, ID32, EXP
  • Ability, Markings, Language
  • EVs (6 bytes)
  • Contest stats
  • Ribbons (Sinnoh, Hoenn)

Block B (0x28-0x47)

  • Moves 1-4, PP, PP Ups
  • IVs (30 bits) + Egg + Nicknamed flags
  • More ribbons (Hoenn contests)
  • Fateful Encounter, Gender, Form
  • Egg and Met locations (HGSS/Pt)

Block C (0x48-0x67)

  • Nickname (22 bytes, UTF-16)
  • Version
  • Contest ribbons (Sinnoh)

Block D (0x68-0x87)

  • OT Name (16 bytes, UTF-16)
  • Met dates (Egg and Met)
  • Met locations (DP)
  • Pokérus, Ball, Met Level, OT Gender
  • Ground Tile type

HGSS Specific Features

public byte BallHGSS { get; set; }        // Separate ball for HGSS
public sbyte WalkingMood { get; set; }     // Following Pokémon mood

Conversion to PK5

public PK5 ConvertToPK5()
Transfer to Generation 5:
  • Removes HM moves (keeps Defog if learned)
  • Separates Nature from PID
  • Clears Pt/HGSS-specific data
  • Updates met location for transfer

PK5 Class

Namespace: PKHeX.Core File: PKHeX.Core/PKM/PK5.cs

Format Specifications

PropertyValue
SIZE_STORED136 bytes
SIZE_PARTY220 bytes
Generation5
ContextEntityContext.Gen5
GamesBlack, White, Black 2, White 2

Key Features

Hidden Abilities

Gen 5 introduced Hidden Abilities:
public bool HiddenAbility { get; set; }
Stored separately from ability slot, allowing for Dream World abilities.

Independent Nature

public override Nature Nature { get; set; }
Nature is now stored independently, not calculated from PID.

N’s Sparkle

public bool NSparkle { get; set; }
Special flag for N’s Pokémon in BW.

New Features

PokéStar Studios (B2W2)

public byte PokeStarFame { get; set; }
public bool IsPokeStar { get; set; }

Ground Tile

public GroundTileType GroundTile { get; set; }
Tracks environment where Pokémon was encountered.

Data Structure Changes

Mostly similar to PK4 but with:
  • Nature stored at 0x41
  • Hidden Ability flag at 0x42
  • N Sparkle flag at 0x42
  • Removed HGSS-specific data
  • Removed Ball Capsule/Seals data

Conversion to PK6

public PK6 ConvertToPK6()
Transfer to Generation 6:
  • Converts PID if shiny rate changes
  • Caps EVs at 252 (from 255)
  • Generates Encryption Constant from PID
  • Creates Handler memories
  • Sets region/country data
  • Converts markings to Gen 6 format

Comparison Table

FeaturePK3PK4PK5
EncryptionBlock shuffleBlock shuffleBlock shuffle
AbilitiesYesYesYes (+ Hidden)
NaturesFrom PIDFrom PIDStored
IVs30 bits + flags30 bits + flags30 bits + flags
FormsBasicExtendedExtended
RibbonsCount-basedBooleanBoolean
Met DateNoYesYes
MemoriesNoNoNo
String Encoding1-byteUTF-16UTF-16

Code Examples

Creating a PK3 Pokémon

var pk3 = new PK3
{
    Species = 384, // Rayquaza
    CurrentLevel = 70,
    Ability = 2,
    Nature = Nature.Adamant,
    Ball = 5, // Safari Ball
    MetLocation = 173 // Sky Pillar
};
pk3.SetPIDNature(pk3.Nature);
pk3.RefreshChecksum();

Converting Across Generations

// Gen 3 → Gen 4 → Gen 5
var pk3 = new PK3(data);
var pk4 = pk3.ConvertToPK4();
var pk5 = pk4.ConvertToPK5();

Checking Encryption

var pk3 = new PK3(data);
if (pk3.ChecksumValid)
{
    Console.WriteLine("Valid checksum");
}

See Also

Build docs developers (and LLMs) love