Skip to content

PEX Binary Format

Reference for the .pex compiled Papyrus script format as used in Fallout 4 (version 3.9).

All integers are little-endian. All string references are 2-byte indices into the string table.

File Header

Field Type Value
Magic u32 0xFA57C0DE (DE C0 57 FA on disk)
Major version u8 3
Minor version u8 9
Game ID u16 2 (Fallout 4)
Compile time u64 Unix timestamp
Source file strref e.g. "MyScript.psc"
Username strref compiler username
Machine name strref compiler host

String Table

Immediately after the header:

u16 count
count × {u16 length, length × u8 utf8_bytes}

All subsequent strref fields are u16 indices into this table.

Debug Info Block

Follows the string table. Skip unless decompiling.

Object Table

u16 numObjects
numObjects × PexObject

PexObject (FO4 layout)

Important: FO4 adds a constFlag byte between docString and userFlags that Skyrim does not have.

strref  name
u32     size         ← total object byte size (rarely needed; trust field counts)
strref  parentName   ← base class, empty if none
strref  docString
u8      constFlag    ← FO4 ONLY (bit0 = const)
u32     userFlags
strref  autoStateName

u16     numStructs
numStructs × PexStruct

u16     numVariables
numVariables × PexVariable

u16     numProperties
numProperties × PexProperty

u16     numStates
numStates × PexState

PexStruct

strref  name
u16     numMembers
numMembers × PexStructMember

PexStructMember

strref  name
strref  typeName
u32     userFlags
PexValue initialValue
u8      constFlag    ← FO4 ONLY
strref  docString

PexVariable

strref  name
strref  typeName
u32     userFlags
PexValue initialValue
u8      constFlag    ← FO4 ONLY

PexProperty

strref  name
strref  typeName
strref  docString
u32     flags        ← bit0=readable bit1=writable bit2=autoVar
u32     userFlags

Depending on flags: - If autoVar: strref autoVarName - If readable: PexFunction readHandler - If writable: PexFunction writeHandler

PexState

strref  name         ← "" for the default state
u16     numFunctions
numFunctions × PexFunction

PexFunction

strref  name
strref  returnType
strref  docString
u32     userFlags
u8      flags        ← bit0=global(static) bit1=native
u16     numParams
numParams × PexFunctionParam
u16     numLocals
numLocals × PexFunctionVar
u16     numInstructions
numInstructions × PexInstruction

PexFunctionParam and PexFunctionVar both have the same layout:

strref  name
strref  typeName

PexInstruction

u8      opcode
N × PexValue   ← N determined by opcode arity table

For VarArgs opcodes, the fixed operands include an int count operand followed by count more operands. The reader flattens all operands into a single array.

PexValue

A tagged union:

u8 type
  0 = None      (no extra bytes)
  1 = Bool      (u8: 0=false 1=true)
  2 = Int       (i32)
  3 = Float     (f32)
  4 = String    (strref)
  5 = Identifier (strref)

Type 5 (Identifier) is used for variable references, local names, parameter names. Type 4 (String) is used for literal string values and method/property names in call instructions.

Jump Offset Convention

Jump offsets in FO4 are relative to the current instruction index (not the next):

target_index = current_index + signed_offset

Past-end targets (target >= instruction count) mean "exit function / return nil".