Files
Sylpheed/docs/reference/xbox360-re-technical-reference.md
sim 75b546cf2f
All checks were successful
CI / Native — linux (pull_request) Successful in 2h0m10s
CI / WASM — Web (pull_request) Successful in 28m47s
CI / Formatting (pull_request) Successful in 1m29s
docs(reference): adopt the last reference files from the project root
Three untracked files in the project root had no home in either repository:

- the Xbox 360 technical reference report (a research compilation) becomes
  docs/reference/xbox360-re-technical-reference.md, unchanged;
- XBOX360_ARCHITECTURE.md becomes docs/reference/xbox360-architecture.md,
  trimmed to its platform facts. Its format "status" sections (PAK unknown,
  mesh unknown, audio TODO) and the `just sniff` workflow predate every
  decoder in this repo and were wrong;
- generate_export_docs.py becomes tools/generate_export_docs.py, the path the
  committed xbox360-exports.* already name as their generator. It lived
  inside a Canary checkout, so it now takes --canary and --out and fails
  loudly on a tree that is not Canary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 22:19:54 +02:00

41 KiB
Raw Blame History

Reverse Engineering Xbox 360: A Complete Technical Reference

The Xbox 360's architecture — a custom PowerPC CPU, unified-shader GPU, and proprietary OS stack — presents one of the most complex reverse engineering targets in console history. This document provides a definitive binary-level reference for every major subsystem relevant to game porting, from raw instruction encodings and GPU command packets to file format structs and kernel internals. Every offset, opcode, and constant documented here derives from the Xenia emulator source code, Free60 project research, community reverse engineering, and leaked SDK analysis. All multi-byte fields in Xbox 360 structures are big-endian unless explicitly noted otherwise.


1. IBM Xenon CPU: three in-order PowerPC cores at 3.2 GHz

The Xenon (codenamed "Waternoose") is a custom IBM chip implementing the PowerPC 2.02 ISA in 64-bit mode, though games run predominantly in 32-bit addressing. Three symmetric cores share a single die, each running 2 hardware threads (SMT) for 6 total logical processors. All cores execute in-order with dual-issue superscalar pipelines — no out-of-order speculation. The chip clocks at 3.2 GHz and connects to the Xenos GPU via a 21.6 GB/s front-side bus (10.8 GB/s per direction).

Cache hierarchy

Level Size Associativity Line Size Notes
L1 I-Cache 32 KB / core 2-way 128 bytes Private per core
L1 D-Cache 32 KB / core 4-way 128 bytes Write-through, no write-allocate — writes bypass L1, go to L2
L2 Cache 1 MB unified 8-way 128 bytes Shared across all 3 cores, 1.6 GHz, 256-bit bus (51.2 GB/s)

The L1 D-cache's no-write-allocate policy means streaming writes pass directly to L2, preventing cache thrashing for write-heavy workloads. A custom xDCBT prefetch instruction bypasses L2 entirely, pulling data into L1 directly. The GPU can lock L2 lines for Xbox Procedural Synthesis (XPS), where the CPU generates geometry into locked cache sets that the GPU reads without a main-memory round-trip.

Register file

Each hardware thread maintains its own independent context — critical for understanding disassembly:

Register Set Count × Width SPR Number Purpose
GPR r0r31 32 × 64-bit General purpose
FPR f0f31 32 × 64-bit IEEE 754 double-precision floating point
VR v0v127 128 × 128-bit VMX-128 vector registers (extended from standard 32)
CR 1 × 32-bit (8 × 4-bit fields) Condition register (CR0CR7)
LR 1 × 64-bit SPR 8 Link register (return address)
CTR 1 × 64-bit SPR 9 Count register / branch target
XER 1 × 64-bit SPR 1 Fixed-point exception (carry, overflow)
FPSCR 1 × 32-bit FP status and control
TBL / TBU 1 × 32-bit each SPR 268/269 Time base lower/upper
PURR 1 × 64-bit SPR 309 Per-thread cycle counter

The VMX-128 extension is the most significant Xenon-specific ISA change. Standard AltiVec provides 32 vector registers (v0v31) with 5-bit encoding; Xenon extends this to 128 registers per thread using 7-bit encoding, for 256 × 128-bit registers per core. Xenon adds single-cycle vdot3/vdot4 dot-product instructions and D3D compressed-format handling instructions absent from standard AltiVec.

Key instruction encodings

Atomic operations (load-linked / store-conditional):

lwarx  RT, RA, RB — Load Word And Reserve Indexed
  Encoding: 0x7C000028 | (RT<<21) | (RA<<16) | (RB<<11)
  [31:26]=0b011111  [25:21]=RT  [20:16]=RA  [15:11]=RB  [10:1]=0000010100  [0]=0

stwcx. RS, RA, RB — Store Word Conditional Indexed (always records to CR0)
  Encoding: 0x7C00012D | (RS<<21) | (RA<<16) | (RB<<11)
  [31:26]=0b011111  [25:21]=RS  [20:16]=RA  [15:11]=RB  [10:1]=0010010110  [0]=1

VMX load/store (128-bit aligned):

lvx  VRT, RA, RB — Load Vector Indexed
  Primary=31, XO=103.  Encoding: 0x7C0000CE | (VRT<<21) | (RA<<16) | (RB<<11)

stvx VRS, RA, RB — Store Vector Indexed
  Primary=31, XO=231.  Encoding: 0x7C0001CE | (VRS<<21) | (RA<<16) | (RB<<11)

Floating-point special:

fsel  FRT, FRA, FRC, FRB — Floating Select (FRT = FRA >= 0 ? FRC : FRB)
  Primary=63, XO=23.  Encoding: 0xFC00002E | (FRT<<21) | (FRA<<16) | (FRB<<11) | (FRC<<6)

frsqrte FRT, FRB — Floating Reciprocal Square Root Estimate
  Primary=63, XO=26.  Encoding: 0xFC000034 | (FRT<<21) | (FRB<<11)

Synchronization barriers:

hwsync  (sync L=0): 0x7C0004AC   — Full memory barrier, drains write buffers
lwsync  (sync L=1): 0x7C2004AC   — Lightweight barrier, orders loads/stores
eieio:              0x7C0006AC   — Enforces I/O ordering for MMIO

Thread scheduling and hardware priority

Games pin work to specific hardware threads (05) via XSetThreadProcessor(). Thread 0 on Core 0 is the master thread. The hypervisor controls thread dispatch; hardware thread priority is managed through HID (Hypervisor Implementation-Dependent) registers.

Physical address space memory map

Address Range Size Description
0x000000000x1FFFFFFF 512 MB Main GDDR3 DRAM (unified CPU/GPU)
0x7FEA0000 ~64 KB XMA audio decoder MMIO registers
0xC00000000xC00FFFFF ~1 MB PCI / Southbridge configuration
0xC8000000 Region NAND flash controller
0xE00000000xEFFFFFFF Region GPU interface / bus region
0xEC800000 Large region Xenos GPU register file (MMIO)

Internally, the CPU SoC contains a 32 KB boot ROM, 64 KB secure SRAM, 768 eFuse bits for per-console keys, and a hardware security engine — all accessible only at HV privilege.


2. Xenos GPU: unified shaders, 10 MB eDRAM, and PM4 command packets

The Xenos is a custom ATI design based on the R400/R500 family — the world's first GPU with unified shader architecture, predating even ATI's own R600. It clocks at 500 MHz with 48 unified shader processors in 3 SIMD arrays of 16, each with a 5-wide VLIW ALU (240 ALUs total, 240 GFLOPS peak). It also serves as the system northbridge, hosting both 64-bit dual memory controllers (22.4 GB/s to 512 MB GDDR3) and the CPU FSB interface.

eDRAM: the 10 MB render target cache

A separate daughter die containing 10 MB of embedded DRAM sits in the GPU package, connected at 32 GB/s externally but 256 GB/s between its internal logic and memory cells. This 8:1 bandwidth ratio makes alpha blending, Z/stencil testing, and 4× MSAA essentially free — all handled by dedicated logic on the eDRAM die without touching the main bus.

Tile geometry from Xenia (xenos.h):

kEdramTileWidthSamples  = 80
kEdramTileHeightSamples = 16
kEdramTileCount         = 2048
Total = 2048 tiles × 80 × 16 × 4 bytes/sample = 10,485,760 bytes (10 MB)

Each tile covers 80 × 16 samples at 4 bytes per sample = 5,120 bytes. A full 720p (1280×720) frame with 32-bit color + 32-bit depth requires ~7.2 MB, fitting comfortably in eDRAM without tiling. With 4× MSAA at 720p, games must use predicated tiling — the GPU replays the command buffer per tile, with hardware predication culling off-tile primitives. The PM4_SET_BIN_MASK (0x50) and PM4_SET_BIN_BASE_OFFSET (0x4B) commands configure this.

PM4 command buffer protocol

The GPU consumes commands from a ring buffer in system memory using the PM4 (Packet Manager 4) format inherited from ATI R-series GPUs. Three packet types exist:

Type-0 (Register Write):

Bits [31:30] = 0b00
Bit  [29]    = ONE_REG_WR (0=sequential, 1=repeated)
Bits [28:16] = COUNT - 1
Bits [15:0]  = BASE_INDEX (register DWORD index)
Payload: COUNT DWORDs written to sequential registers starting at BASE_INDEX.

Type-2 (NOP):

Bits [31:30] = 0b10
Bits [29:0]  = don't care (padding/alignment filler)
Constant: 0x80000000

Type-3 (IT Command):

Bits [31:30] = 0b11
Bit  [29]    = PREDICATE (conditional on VIZ query)
Bits [28:16] = COUNT - 1
Bits [15:8]  = IT_OPCODE (8-bit)
Bits [7:0]   = Reserved
Payload: COUNT DWORDs of command-specific data.

PM4 opcode table (from Xenia xenos.h)

Opcode Hex Command
PM4_NOP 0x10 No operation
PM4_REG_RMW 0x21 Register read-modify-write
PM4_DRAW_INDX 0x22 Draw indexed primitives
PM4_IM_LOAD 0x27 Load shader microcode from memory address
PM4_IM_LOAD_IMMEDIATE 0x2B Load shader microcode inline in packet
PM4_IM_STORE 0x2C Store shader microcode to system memory
PM4_SET_CONSTANT 0x2D Set GPU constant registers
PM4_LOAD_CONSTANT_CONTEXT 0x2E Load constants from memory
PM4_DRAW_INDX_2 0x36 Draw with inline index buffer
PM4_INDIRECT_BUFFER_PFD 0x37 Indirect buffer, pipelined
PM4_INVALIDATE_STATE 0x3B Selective state invalidation
PM4_WAIT_REG_MEM 0x3C Wait until register/memory matches value
PM4_MEM_WRITE 0x3D Write value to memory
PM4_REG_TO_MEM 0x3E Copy register to memory
PM4_INDIRECT_BUFFER 0x3F Indirect buffer dispatch
PM4_COND_WRITE 0x45 Conditional write
PM4_EVENT_WRITE 0x46 Generate event + memory write on completion
PM4_ME_INIT 0x48 Microengine initialization
PM4_SET_BIN_BASE_OFFSET 0x4B Tiled rendering bin offset
PM4_SET_BIN_MASK 0x50 64-bit bin mask for tiling
PM4_SET_BIN_SELECT 0x51 64-bit bin select
PM4_WAIT_REG_EQ 0x52 Wait until register == value
PM4_WAIT_REG_GTE 0x53 Wait until register ≥ value
PM4_INTERRUPT 0x54 Generate interrupt from command stream
PM4_SET_CONSTANT2 0x55 Set constants block 2
PM4_EVENT_WRITE_SHD 0x58 VS/PS done event
PM4_EVENT_WRITE_CFL 0x59 Cache flush done event
PM4_EVENT_WRITE_EXT 0x5A Screen extent event
PM4_EVENT_WRITE_ZPD 0x5B Z-pass done event
PM4_CONTEXT_UPDATE 0x5E Update current context
PM4_XE_SWAP 0x64 Frame swap (Xenia-specific trigger)

GPU register file layout

The Xenos register file is MMIO-mapped at physical 0xEC800000. Registers are addressed by DWORD index (multiply by 4 for byte offset). Shader constant loading dispatches by type:

Type Code Register Base Contents
0 0x4000 Float shader constants (256 × float4)
1 0x4800 Fetch constants (texture/vertex descriptors, 24 bytes each)
2 0x4900 Boolean shader constants
3 0x4908 Loop constants
4 0x2000 General GPU configuration registers

Key configuration registers include RBBM_STATUS, COHER_STATUS_HOST (0x0578), RB_COLOR_INFO / RB_DEPTH_INFO (0x0D00 range), PA_SC_WINDOW_OFFSET (0x2000 range), VGT_DRAW_INITIATOR (0x2100 range), and SQ_PROGRAM_CNTL (0x4000 range).

Shader microcode format

Xenos microcode closely follows the AMD R600 ISA (publicly documented). Three instruction types exist:

  • Control Flow (CF): 64 bits. Controls execution flow, initiates fetch/export operations.
  • ALU: 64 bits. 5-slot VLIW (vector + scalar). Grouped into ALU clauses.
  • Fetch: 96 bits (3 DWORDs). Vertex and texture fetch operations.

Shader programs are unified — the same microcode format serves both vertex and pixel shaders. The hardware dynamically assigns processors to VS/PS workloads. Xenia's src/xenia/gpu/ucode.h defines the complete microcode structures; shader_translator.cc translates them to host GPU IR.

Memory export (MEMEXPORT)

MEMEXPORT is Xenos-specific: shaders write arbitrary data to system memory addresses, enabling GPGPU compute before compute shaders existed. Vertex shaders export computed data (particles, physics, procedural geometry) to memory via special export registers. The CPU can read this data after GPU synchronization.

Texture formats

Xenos supports standard D3D9 formats plus Xbox 360 extensions. Textures use tiled (Morton/Z-order swizzled) layout by default for optimal cache performance; linear layout requires explicit specification. Maximum dimensions are 8192×8192 (2D).

Xbox 360only compressed formats include DXT3A (4×4, 64 bits, scalar), DXT5A (4×4, 64 bits, two-endpoint scalar), DXN (128 bits, two-channel DXT5A), and CTX1 (4×4, 64 bits, shared-index). Color render target formats range from k_8_8_8_8 through k_2_10_10_10_FLOAT (7e3 HDR) to k_32_32_FLOAT.


3. XDVDFS: the Xbox DVD file system on game discs

Xbox 360 game discs use a proprietary file system called XDVDFS (also GDFX or XISO) — not ISO 9660 or UDF. The sector size is 2048 bytes (0x800). Directory entries form a binary search tree rather than a linear listing.

Volume descriptor at sector 32

The volume descriptor occupies sectors 3233. On a raw XISO image, it begins at byte offset 0x10000 from the game partition start:

Offset Size Type Content
0x000 0x14 char[20] Magic: MICROSOFT*XBOX*MEDIA
0x014 0x04 uint32_le Root directory table sector
0x018 0x04 uint32_le Root directory table size (bytes)
0x01C 0x08 uint64_le Timestamp (Win32 FILETIME)
0x024 0x7C8 Zero padding
0x7EC 0x14 char[20] Magic (repeated): MICROSOFT*XBOX*MEDIA

Directory entry structure (variable size, minimum 14 bytes)

Offset Size Type Field
0x00 0x02 uint16_le Left subtree offset (in DWORDs from directory table start)
0x02 0x02 uint16_le Right subtree offset (in DWORDs)
0x04 0x04 uint32_le Starting sector of file data
0x08 0x04 uint32_le File size in bytes
0x0C 0x01 uint8 Attributes (0x10=DIRECTORY, 0x20=ARCHIVE, 0x80=NORMAL)
0x0D 0x01 uint8 Filename length
0x0E var char[] Filename (padded to DWORD boundary with 0xFF)

Subtree offsets of 0 indicate no child. Files occupy contiguous sectors. Subdirectories point to nested directory tables.

Game disc geometry (XGD2 / XGD3)

Format Game Partition Offset Capacity
XGD2 (early 360) 0x0FD90000 ~6.8 GiB
XGD3 (2011+) 0x02080000 ~7.8 GiB

All Xbox 360 discs are dual-layer DVD-DL. Security sectors on the outer ring use a challenge/response protocol: 23 entries encrypted with RC4 (key derived by SHA-1 hashing a 44-byte block at security sector offset 1183), verified by RSA signatures.


4. STFS: secure transacted file system for saves and DLC

STFS packages contain downloadable content, save games, profiles, and XBLA titles stored on HDD or memory units. The format uses SHA-1 Merkle trees for integrity and RSA signatures for authentication. Block size is 0x1000 (4096 bytes), with hash tables interleaved every 0xAA (170) data blocks.

Header layout (canonical offsets from Free60)

Magic bytes at offset 0x000 (4 bytes):

Magic ASCII Meaning
0x434F4E20 CON Console-signed (saves, profiles)
0x4C495645 LIVE Xbox Live Marketplace content
0x50495253 PIRS Microsoft-signed read-only content

Metadata section:

Offset Size Field
0x022C 0x100 License entries (16 × 0x10 bytes: int64 licenseID + int32 bits + int32 flags)
0x032C 0x14 Header SHA-1 hash (covers 0x0344 through first hash table)
0x0340 0x04 Header size (uint32)
0x0344 0x04 Content type (uint32, see enum below)
0x0348 0x04 Metadata version
0x034C 0x08 Content size (uint64)
0x0354 0x04 Media ID
0x0358 0x04 Version
0x035C 0x04 Base version
0x0360 0x04 Title ID (e.g., 0x4D5307E6 for Halo 3)
0x0364 0x01 Platform (2=Xbox 360, 4=PC)
0x0365 0x01 Executable type
0x0366 0x01 Disc number
0x0367 0x01 Disc in set
0x0368 0x04 Save game ID
0x036C 0x05 Console ID
0x0371 0x08 Profile ID
0x0379 0x24 STFS Volume Descriptor (36 bytes, see below)
0x039D 0x04 Data file count
0x03A1 0x08 Data file combined size
0x0411 0x900 Display name (UTF-8, 18 locales × 0x80 bytes)
0x0D11 0x900 Display description
0x1691 0x80 Title name
0x171A 0x4000 Thumbnail image (PNG, ≤16384 bytes)
0x571A 0x4000 Title thumbnail image

Total header size (v1): 0x971A bytes.

STFS volume descriptor (36 bytes at offset 0x0379)

Offset Size Field
0x00 0x01 Size (always 0x24)
0x01 0x01 Reserved
0x02 0x01 Block separation (bit 0 determines hash table spacing)
0x03 0x02 File table block count
0x05 0x03 File table block number (int24)
0x08 0x14 Top hash table hash (SHA-1)
0x1C 0x04 Total allocated block count
0x20 0x04 Total unallocated block count

Hash table hierarchy

Each hash entry is 24 bytes (0x18): 20-byte SHA-1 digest + 1-byte status + 3-byte next-block number. Status values: 0x00 (unused), 0x40 (freed), 0x80 (used), 0xC0 (newly allocated).

  • Level 0: 0xAA (170) entries, each covering one data block
  • Level 1: 0xAA entries, each covering one L0 table — spans 170² = 28,900 blocks
  • Level 2: 0xAA entries, each covering one L1 table — spans 170³ = 4,913,000 blocks

CON packages may maintain dual hash tables per level for transactional integrity. Block-to-file-offset conversion must account for interleaved hash table blocks:

FileOffset(block) = ((headerSize + 0xFFF) & 0xF000) + (adjustedBlock << 12)

where adjustedBlock adds 1 hash-table block per 0xAA data blocks, plus L1/L2 table blocks for larger packages.

Content type enum (key values)

Value Type
0x0000001 Saved Game
0x0001000 Xbox 360 Title
0x0004000 Installed Game
0x0007000 Game on Demand
0x0010000 Profile
0x0040000 Cache File
0x0080000 Game Demo
0x00D0000 Arcade Title (XBLA)
0x2000000 Community Game

File listing entry (0x40 = 64 bytes each)

Offset Size Field
0x00 0x28 Filename (null-padded, 40 chars max)
0x28 0x01 Flags: bits 05 = name length, bit 6 = consecutive blocks, bit 7 = is directory
0x29 0x03 Allocated block count (int24 LE)
0x2C 0x03 Allocated block count copy
0x2F 0x03 Starting block number (int24 LE)
0x32 0x02 Path indicator (0xFFFF = root; else parent entry index)
0x34 0x04 File size (uint32 BE)
0x38 0x04 Update timestamp (FAT format)
0x3C 0x04 Access timestamp (FAT format)

5. XEX2: the Xbox executable container format

XEX2 is an encrypted, compressed wrapper around a standard PE32 image. It is the mandatory packaging format for all Xbox 360 executables.

IMAGE_XEX_HEADER (0x18 bytes)

struct IMAGE_XEX_HEADER {
    char     Magic[4];                    // +0x00  "XEX2" = 0x58455832
    uint32_t ModuleFlags;                 // +0x04  See flag bits
    uint32_t SizeOfHeaders;              // +0x08  Offset to PE data
    uint32_t SizeOfDiscardableHeaders;   // +0x0C  Reserved
    uint32_t SecurityInfo;               // +0x10  File offset → XEX_SECURITY_INFO
    uint32_t HeaderDirectoryEntryCount;  // +0x14  Number of optional headers
    // IMAGE_XEX_DIRECTORY_ENTRY[] at +0x18
};

Module flags (bitfield): 0x0001=TITLE_PROCESS, 0x0002=TITLE_IMPORTS, 0x0004=DEBUGGER, 0x0008=DLL, 0x0010=PATCH, 0x0020=PATCH_FULL, 0x0040=PATCH_DELTA, 0x0080=USER_MODE.

XEX format variants:

Magic Hex Minimum Kernel
XEX2 0x58455832 ≥ 1861 (retail)
XEX1 0x58455831 ≥ 1838 (beta)
XEX% 0x58455825 ≥ 1746
XEX- 0x5845582D ≥ 1640
XEX0 0x58455830 ≥ 1332

Optional header directory (at +0x18)

Each entry is 8 bytes: uint32 Key + uint32 Value. The low byte of Key encodes the data format:

  • Key & 0xFF == 0x00: Value is an immediate flag
  • Key & 0xFF == 0x01: Value is an immediate DWORD
  • Key & 0xFF == 0xFF: Value is file offset to size-prefixed struct
  • Other: Value is file offset; low byte × 4 = struct size

Complete optional header key table:

Key ID Name Data Type
0x000002FF Section Table SizedStruct
0x000003FF File Data Descriptor (compression/encryption) SizedStruct
0x00000405 Patch File Base Reference Fixed 0x14
0x000005FF Delta Patch Descriptor SizedStruct
0x000103FF Import Libraries SizedStruct
0x00010001 Original Base Address ULONG
0x00010100 Entry Point (VA) Flag
0x00010201 PE Base Address ULONG
0x000183FF Original PE Module Name String
0x000200FF Static Libraries / Build Versions SizedStruct
0x00020104 TLS Data (16 bytes) Struct
0x00020200 Default Stack Size Flag
0x00020301 Default FS Cache Size ULONG
0x00020401 Default Heap Size ULONG
0x00030000 System Flags / Privileges Flag
0x00040006 Execution ID (Title ID, version — 24 bytes) Struct
0x00040310 Game Ratings (64 bytes) Fixed 0x40
0x00040404 LAN Key (16 bytes) Fixed 0x10
0x000405FF Xbox 360 Logo SizedStruct
0x000406FF Multi-Disc Media IDs SizedStruct
0x00E10402 PE Exports (IMAGE_DATA_DIRECTORY) Struct

XEX_SECURITY_INFO structure

Located at the file offset stored in SecurityInfo (+0x10):

struct XEX_SECURITY_INFO {
    uint32_t    Size;                   // +0x000
    uint32_t    ImageSize;              // +0x004
    HV_IMAGE_INFO ImageInfo;            // +0x008 (0x174 bytes, see below)
    uint32_t    AllowedMediaTypes;      // +0x17C
    uint32_t    PageDescriptorCount;    // +0x180
    HV_PAGE_INFO PageDescriptors[];     // +0x184 (variable, 0x18 bytes each)
};

HV_IMAGE_INFO (0x174 bytes at SecurityInfo+0x08):

Offset Size Field
0x000 0x100 RSA-2048 signature (256 bytes)
0x100 0x04 Info size
0x104 0x04 Image flags
0x108 0x04 Virtual load address
0x10C 0x14 Image SHA-1 hash
0x120 0x04 Import table count
0x124 0x14 Import table SHA-1 digest
0x138 0x10 Media ID (16 bytes)
0x148 0x10 Encrypted AES-128 session key
0x158 0x04 Export table VA
0x15C 0x14 Header SHA-1 hash
0x170 0x04 Game region flags

HV_PAGE_INFO (0x18 bytes each):

struct HV_PAGE_INFO {
    uint32_t PageDescription;   // +0x00  Bits [31:28]=Info(type), [27:0]=Size(page count)
    uint8_t  DataDigest[0x14];  // +0x04  SHA-1 hash of page data
};
// Info values: 1=CODE, 2=DATA, 3=READONLY_DATA

Execution ID (24 bytes at optional header 0x00040006)

struct XEX_EXECUTION_ID {
    uint32_t MediaID;           // +0x00
    uint32_t Version;           // +0x04  Major(4):Minor(4):Build(16):QFE(8)
    uint32_t BaseVersion;       // +0x08
    uint32_t TitleID;           // +0x0C  e.g. 0x4D5307E6 (Halo 3)
    uint8_t  Platform;          // +0x10
    uint8_t  ExecutableType;    // +0x11
    uint8_t  DiscNum;           // +0x12
    uint8_t  DiscsInSet;        // +0x13
    uint32_t SaveGameID;        // +0x14
};

Encryption keys and decryption flow

XEX2 Retail Key (AES-128):
  20 B1 85 A5 9D 28 FD C3  40 58 3F BB 08 96 BF 91

XEX2 Devkit Key (AES-128):
  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  (all zeros)

Decryption procedure:

  1. Read 16-byte encrypted session key from HV_IMAGE_INFO.ImageKey (offset +0x148)
  2. Decrypt with AES-128-ECB using the retail (or devkit) key → per-file session key
  3. Decrypt the PE payload (starting at file offset SizeOfHeaders) using AES-128-CBC with the session key (IV = all zeros initially)
  4. If encrypted flag not set in File Data Descriptor, skip decryption

Compression

The File Data Descriptor (key 0x000003FF) specifies compression:

Format Value Name Method
0x0000 NONE Uncompressed
0x0001 RAW Block-based (DataSize + ZeroSize pairs, 8 bytes each)
0x0002 COMPRESSED LZX-based with SHA-1 per block (window typically 0x8000 or 0x20000)
0x0003 DELTA_COMPRESSED Patch format

Import system

Imports are ordinal-only. The import descriptor (key 0x000103FF) contains:

struct XEX_IMPORT_DESCRIPTOR {
    uint32_t Size;             // +0x00
    uint32_t NameTableSize;    // +0x04
    uint32_t ModuleCount;      // +0x08
    // char NameTable[] (null-separated library names)
    // XEX_IMPORT_TABLE[] (one per module)
};

Each per-library table contains a module index, version info, import count, and an array of thunk virtual addresses. Bit 24 of each import record distinguishes function imports (patched as branch stubs) from variable imports (address written directly).


6. Kernel and operating system internals

The Xbox 360 runs a modified NT kernel (xboxkrnl.exe) under a hypervisor (HV) — roughly 128 KB of code operating in PowerPC real mode with highest privilege. The HV enforces W^X (write XOR execute) across all memory, manages page tables via software TLB, and encrypts all executable pages in RAM. Games run in kernel mode with virtual addressing; there is effectively one "process" at a time.

Kernel exports (by ordinal)

Exports are ordinal-only. Selected confirmed ordinals from Xenia's xboxkrnl_table.inc:

Ordinal Export
0x001 DbgBreakPoint
0x003 DbgPrint
0x00E ExEventObjectType
0x0CF NtClose
0x0D0 NtCreateDirectoryObject
0x0D1 NtCreateEvent
0x0D2 NtCreateFile
0x0D3 NtCreateIoCompletion
0x0D4 NtCreateMutant
0x0D5 NtCreateSemaphore
0x0D7 NtCreateTimer
0x0D8 NtDeleteFile
0x156 XboxHardwareInfo (variable, 16 bytes)
0x157 XboxKrnlBaseVersion
0x158 XboxKrnlVersion
0x159 XeCryptAesKey
0x15A XeCryptAesEcb
0x15B XeCryptAesCbc
0x164 XeCryptBnQwBeSigCreate
0x166 XeCryptBnQwBeSigVerify
0x16D XeCryptBnQwNeRsaPubCrypt

The full table contains ~900+ exports. Additional families include Ex* (executive), Ke* (kernel core), Rtl* (runtime), Mm* (memory manager), Ob* (object manager), Xex* (module loading), and Vd* (video). The authoritative reference is Xenia's xboxkrnl_table.inc.

Hypervisor syscall mechanism

The PowerPC sc instruction triggers a syscall interrupt. The CPU enters real mode and vectors to 0x00000C00. Syscall number is in r0, arguments in r3r12, return value in r3.

The HV dispatcher (from the 4532 kernel vulnerability disclosure):

0x13D8: cmplwi %r0, 0x61       ; max syscall = 0x61 (97)
0x13DC: bge    illegal_syscall
0x13F0: rldicr %r1, %r0, 2, 61 ; offset = r0 * 4
0x13F4: lwz    %r4, 0x1F68(%r1); load handler from table at 0x1F68
0x1414: blrl                    ; call handler

Key HV syscalls:

Number Name
0x00 HvxGetVersions
0x02 HvxMemoryProtect
0x07 HvxGetSpecialPurposeRegister
0x08 HvxSetSpecialPurposeRegister
0x10 HvxDvdAuthBegin
0x16 HvxXexLoadImage
0x17 HvxXexUnloadImage
0x19 HvxXexGetProcAddress
0x1A HvxXexGetModuleHandle
0x25 HvxXexVerifyImage
0x40 HvxKeysInitialize
0x41 HvxKeysExGetKey
0x45 HvxKeysExGetConsoleId
0x46 HvxKeysSetKeyVault

Thread local storage

r13 points to the KPCR (Kernel Processor Control Region) in kernel mode. r2 is the user-mode TLS base pointer. The TEB inherits NT structure with key fields at: +0x02C (ThreadLocalStoragePointer), +0x030 (PEB pointer), +0xE10 (TlsSlots[64]).


7. Xbox 360 Direct3D: a thin layer over GPU command buffers

The Xbox 360 D3D implementation is a bare-bones wrapper that writes PM4 packets directly into a GPU ring buffer — no abstracted driver stack. Key differences from PC D3D9 include direct memory control via XGraphics (XGSetTextureHeader, XGSetVertexBufferHeader), eDRAM-centric rendering requiring explicit resolve operations, and extensions like vfetch, tfetch, and MEMEXPORT.

Ring buffer architecture

The Xenos processes commands from a circular buffer in system memory defined by:

  • Base pointer: Physical start address of ring buffer
  • Write pointer: CPU advances after writing PM4 packets
  • Read pointer: GPU advances as it consumes commands
  • Size: Total buffer capacity

The GPU stalls when read would pass write. Secondary command lists dispatch via PM4_INDIRECT_BUFFER (0x3F), analogous to D3D12 command lists.

Shader constant register mapping

Float constants load into GPU registers at base 0x4000 (256 × float4 = 1024 DWORDs for VS, extending into PS range). Fetch constants (texture/vertex descriptors) occupy base 0x4800 as 24-byte structures encoding buffer address, stride, format, and dimensions. Boolean constants pack at 0x4900 as 32-bit bitmasks. Loop constants sit at 0x4908.

CPU-to-GPU memory translation

In the unified memory architecture, CPU and GPU share the same 512 MB physical address space. Vertex/index buffer allocation simply returns a CPU-accessible virtual address that maps to the same physical memory the GPU reads. Fetch constants store the physical address of the buffer. No upload or copy is needed — the GPU reads directly from where the CPU wrote.

Predicated tiling workflow

When eDRAM cannot hold the full framebuffer (e.g., 4× MSAA at 720p), D3D splits rendering into tiles. For each tile, the GPU replays the entire command buffer with hardware predication culling off-tile primitives. This is configured via PM4_SET_BIN_BASE_OFFSET (0x4B), PM4_SET_BIN_MASK (0x50), and PM4_SET_BIN_SELECT (0x51). After rendering each tile, a resolve operation copies eDRAM contents to main RAM, optionally downsampling MSAA.


8. XMA audio and XACT sound banks

XMA2WAVEFORMATEX (52 bytes)

Offset  Size  Field                Notes
0x00    2     wFormatTag           0x0166 (WAVE_FORMAT_XMA2)
0x02    2     nChannels            Decoded channel count
0x04    4     nSamplesPerSec       Decoded sample rate
0x08    4     nAvgBytesPerSec      Encoder internal
0x0C    2     nBlockAlign          channels × bitsPerSample / 8
0x0E    2     wBitsPerSample       Always 16
0x10    2     cbSize               Always 34
0x12    2     NumStreams            1 or 2 channels per stream
0x14    4     ChannelMask          SPEAKER_xxx flags
0x18    4     SamplesEncoded       Total decoded PCM samples
0x1C    4     BytesPerBlock        XMA block size
0x20    4     PlayBegin            First valid decoded sample
0x24    4     PlayLength           Valid audio length
0x28    4     LoopBegin            Loop start (decoded samples)
0x2C    4     LoopLength           Loop length
0x30    1     LoopCount            255=infinite, 254=max finite
0x31    1     EncoderVersion       ≥3 for XMA2
0x32    2     BlockCount           XMA blocks in file

XMA packet structure (2048 bytes, big-endian)

Bits 0-5:   FrameCount        (6 bits)   Frames beginning in this packet
Bits 6-20:  FrameOffsetInBits (15 bits)  Bit offset to first complete frame
Bits 21-23: PacketMetaData    (3 bits)   Always 1 for XMA2
Bits 24-31: PacketSkipCount   (8 bits)   Other-stream packets to skip
Bytes 4-2047: Encoded XMA data (2044 bytes)

Key constants: XMA_BYTES_PER_PACKET = 2048, XMA_SAMPLES_PER_FRAME = 512, XMA_SAMPLES_PER_SUBFRAME = 128. Supported sample rates: 24000, 32000, 44100, 48000 Hz.

Hardware XMA decoder at 0x7FEA0000

The Southbridge chip provides a hardware XMA decoder accessed via MMIO at virtual address 0x7FEA0000 (64 KB register space). Up to 320 hardware contexts can be active simultaneously. Each XMA_CONTEXT_DATA is 64 bytes (16 DWORDs, big-endian) containing input/output buffer pointers, loop parameters, sample rate, stereo flag, and read/write offsets packed into bitfields.

XACT wave bank (XWB) format

Header magic: "WBND" (LE) = 0x444E4257. The 12-byte header is followed by a segment table (5 entries × 8 bytes: offset + length) pointing to Bank Data, Entry Metadata, Seek Tables, Entry Names, and Wave Data.

Bank Data flags: FLAGS_ENTRYNAMES = 0x00010000, FLAGS_COMPACT = 0x00020000, FLAGS_SEEKTABLES = 0x00080000.

XACT sound bank (XSB) format

Header magic: "SDBK" (LE). The header contains tool/format version, platform byte (0=PC, 2=Xbox), counts of simple/complex cues, wave banks, and sounds, followed by offset tables for cue data, sound entries, variation tables, and wave bank name references. Sound entries are variable-sized: simple sounds (11 bytes: flags + category + volume + track index + wave bank index) vs complex sounds with clip arrays.


9. XInput gamepad state and USB protocol

XINPUT_GAMEPAD (12 bytes at XINPUT_STATE+0x04)

struct XINPUT_GAMEPAD {
    uint16_t wButtons;        // +0x00  Bitmask
    uint8_t  bLeftTrigger;    // +0x02  0255
    uint8_t  bRightTrigger;   // +0x03  0255
    int16_t  sThumbLX;        // +0x04  32768 to 32767
    int16_t  sThumbLY;        // +0x06
    int16_t  sThumbRX;        // +0x08
    int16_t  sThumbRY;        // +0x0A
};

Button flags:

DPAD_UP=0x0001  DPAD_DOWN=0x0002  DPAD_LEFT=0x0004   DPAD_RIGHT=0x0008
START=0x0010    BACK=0x0020       LEFT_THUMB=0x0040   RIGHT_THUMB=0x0080
LB=0x0100       RB=0x0200         A=0x1000            B=0x2000
X=0x4000        Y=0x8000

Dead zones: LEFT_THUMB=7849, RIGHT_THUMB=8689, TRIGGER_THRESHOLD=30.

The Xbox 360 controller (VID 0x045E, PID 0x028E) uses vendor-specific USB class 0xFF — not standard HID. Interface 0 returns 20-byte input reports at 250 Hz (4ms interval). Rumble output is an 8-byte report with large motor speed at byte 3 and small motor speed at byte 4.


10. XNet networking with Winsock-like semantics

Xbox 360 networking uses xam.xex exports wrapping a Winsock-like API with mandatory caller-ID parameters. All NetDll_* functions take a first argument specifying caller type (e.g., XNCALLER_SYSAPP).

Key function ordinals from xam_table.inc: NetDll_XNetStartup (0x33), NetDll_XNetCleanup (0x34), NetDll_XNetRandom (0x35), NetDll_XNetCreateKey (0x36), NetDll_XNetXnAddrToInAddr (0x39).

XNADDR is a 36-byte structure combining IP, MAC, and Xbox Live identity. XNet provides built-in IPsec-like encryption for peer-to-peer sessions via XNetCreateKey/XNetRegisterKey. Xbox Live uses TLS 1.2based security; detailed packet structures remain proprietary.


11. Decompilation and disassembly workflow

Ghidra with XEXLoaderWV

XEXLoaderWV (by Warranty Voider, github.com/zeroKilo/XEXLoaderWV) loads XEX files directly into Ghidra with decryption/decompression, PDB support via MSDIA, and correct base address mapping. Set processor to PowerPC:BE:32:default. The loader handles both retail and devkit encryption. Limitation: Ghidra's PPC module does not fully support VMX-128's 7-bit register encoding — extended vector instructions may disassemble incorrectly.

IDA Pro with idaxex

idaxex (by emoose, github.com/emoose/idaxex) supports XEX1/XEX2, all encryption variants, auto-names kernel/XAM imports, and passes CodeView info for PDB loading. Pair with the PPCAltivec plugin (github.com/hayleyxyz/PPC-Altivec-IDA) for VMX instruction support. The xkelib.til type library provides Xbox 360 SDK type definitions.

Xenia as dynamic analysis platform

Xenia provides GPU trace capture (F4 during gameplay), continuous stream logging (--trace_gpu_stream), and a trace viewer (xe-gpu-trace-viewer) for inspecting draw calls, register state, and shader microcode. Shader dumps (--dump_shaders=path/) output both translated host shaders and original Xenos microcode. Key debug flags:

--debug --log_level=3 --break_on_start=true --trace_gpu_stream=true

PowerPC disassembly patterns

Function prologue (Microsoft Xbox 360 compiler):

mflr    r0              ; Save return address
stw     r30, -8(r1)     ; Save nonvolatile registers into red zone
stw     r31, -4(r1)
stw     r0, -0xC(r1)    ; Save LR on stack
stwu    r1, -0x50(r1)   ; Allocate frame atomically

Function epilogue:

lwz     r0, 0x44(r1)    ; Restore saved LR
lwz     r30, 0x48(r1)   ; Restore nonvolatiles
lwz     r31, 0x4C(r1)
mtlr    r0
addi    r1, r1, 0x50    ; Deallocate frame
blr                     ; Return

Import thunk stub (3+ instructions):

lis     r11, 0x8200     ; Upper 16 bits of IAT entry
ori     r11, r11, 0x1234; Lower 16 bits
lwz     r11, 0(r11)     ; Load resolved function address
mtctr   r11
bctr                    ; Indirect branch to import

Register conventions: r0 = scratch/LR only, r1 = stack pointer, r2 = TOC, r3 = return value / arg1, r4r10 = args 28, r14r31 = nonvolatile (callee-saved). Red zone below SP is 232 bytes.

Recompilation tools

XenonRecomp (github.com/hedge-dev/XenonRecomp) performs static recompilation of Xbox 360 PPC code to native x86-64 C++. XenosRecomp (github.com/hedge-dev/XenosRecomp) translates Xenos GPU shaders to HLSL for D3D12/Vulkan, using function boundary analysis from .pdata exception directory entries.


12. Encryption and security architecture

eFUSE-based per-console keys

Each Xbox 360 CPU contains 768 one-time-programmable eFuse bits encoding a unique 16-byte CPU Key (fusesets 3+5 concatenated with 4+6), update sequence counters (lockdown value preventing downgrade), and devkit/retail flags. The CPU Key encrypts the KeyVault — the master store for all per-console cryptographic material.

Memory encryption

The HV implements per-cache-line (128-byte) AES encryption with four access pathways:

Pathway Protection Use
0 None Raw/unprotected memory
1 AES + CRC integrity HV code and data
2 CPU SoC internal Boot ROM, SRAM, eFuses (HV-only)
3 AES only Game/kernel executable pages

Encryption keys change every boot (hardware RNG), incorporating per-page 10-bit whitening values. This prevents cold-boot replay attacks.

XEX key derivation chain

The HV derives the XEX2 decryption key via HMAC-SHA-1 using an 8-byte gCpuSecurityKey (read from MMIO 0x80000200_000250B8 during init), the 1BL public key (0x110 bytes), 1BL encryption key (0x10 bytes), 1BL salt (10 bytes), and a static 0x590-byte key buffer containing the PIRS verification public key, roamable obfuscation key root, and XeMACS authentication public key.

Content license verification

STFS packages bind licenses to console IDs or Xbox Live accounts (XUIDs). CON packages are signed with the console's private key from the KeyVault; LIVE/PIRS packages use Microsoft's public key. The kernel verifies the RSA signature over the header SHA-1 hash before granting access. The SHA-1 Merkle tree (L0 → L1 → L2 hash tables) ensures data block integrity from individual 4096-byte blocks up to the RSA-signed root hash.


13. Complete virtual address space and MMIO reference

Virtual address map

Range Purpose
0x000000000x0000FFFF Null guard / reserved
0x000100000x3FFFFFFF User/title virtual memory (heap, stacks)
0x400000000x7FE9FFFF Extended title space (physical memory mapping)
0x7FEA00000x7FEAFFFF XMA decoder MMIO
0x7FFF00000x7FFFFFFF Guard pages
0x800000000x8FFFFFFF Kernel virtual address space
0x82000000 Typical game XEX load base
0x900000000x9FFFFFFF Physical memory identity map (uncached)
0xA00000000xBFFFFFFF Physical memory alternate mappings
0xC00000000xDFFFFFFF Additional physical mapping regions
0xE00000000xFFFFFFFF MMIO / device register space

MMIO register blocks

Physical Address Size Device
0x7FEA0000 64 KB XMA audio decoder (context array, control registers)
0xC0000000 ~1 MB PCI / Southbridge configuration
0xC8000000 Region NAND flash controller (SFCX)
0xEA001000 ~4 KB Southbridge I/O (SATA, USB)
0xEA001080 16 B SMC write FIFO (System Management Controller)
0xEA001090 16 B SMC read FIFO
0xEC800000 ~256 KB+ Xenos GPU (command processor, shader regs, display)

Conclusion: a roadmap for re-implementation

Three insights emerge from this comprehensive analysis that directly inform porting strategy. First, the Xenon's in-order, VMX-128-heavy execution model means game code is heavily hand-optimized for specific pipeline timings and the extended 128-register vector file — naïve PPC-to-x64 translation loses these optimizations, making static recompilation tools like XenonRecomp essential starting points. Second, the GPU's PM4 command stream is fully documented through Xenia's source, and the shader ISA's kinship with AMD R600 means public ISA manuals cover ~90% of the microcode format, with XenosRecomp handling the translation to modern HLSL. Third, every container format (XEX, STFS, XDVDFS, XWB/XSB) is byte-level documented by the community, enabling complete asset extraction pipelines. The practical path forward combines Xenia's runtime infrastructure for behavioral validation, static recompilation for CPU code, shader translation for GPU code, and format-level extraction for game assets — all grounded in the binary specifications documented above.