XIP Archive Format
Overview
XIP is the binary archive format used by the Xbox dashboard to package scripts, textures, meshes, and other assets into a single loadable file. The magic number is 0x30504958 – "XIP0" in ASCII. Microsoft’s internal build pipeline compiled XAP scripts, textures, and meshes into XIPs using a packer tool, then optionally signed them with xipsign.
The dashboard loads default.xip at startup, which contains the root scene and all core UI assets. Additional XIPs (settings, music, memory management, Xbox Live, etc.) are loaded on demand when the user navigates to those sections.
Archive Structure
The format has three parts: a header, a file table, and a name table that maps names to file entries. The structure was reverse-engineered from the files themselves and later confirmed against header definitions that circulated in the scene.
+-------------------+
| XIPHEADER | Magic, data start offset, file count, name count, data size
+-------------------+
| FILEDATA[0..N] | One per file: data offset, size, type, timestamp
+-------------------+
| FILENAME[0..M] | One per name: file index + name string offset
+-------------------+
| Name strings | Null-terminated ASCII filenames
+-------------------+
| File data | Raw file contents (scripts, textures, meshes, audio)
+-------------------+
XIPHEADER (16 bytes)
struct XIPHEADER {
DWORD m_dwMagic; // 0x30504958 ("XIP0")
DWORD m_dwDataStart; // Byte offset where file data begins
WORD m_wFileCount; // Number of FILEDATA entries
WORD m_wNameCount; // Number of FILENAME entries
DWORD m_dwDataSize; // Total size of all file data
};
FILEDATA (16 bytes each)
struct FILEDATA {
DWORD m_dwDataOffset; // Offset from data start to this file's content
DWORD m_dwSize; // Size in bytes
DWORD m_dwType; // File type (see below)
DWORD m_dwTimestamp; // Build timestamp
};
FILENAME (4 bytes each)
struct FILENAME {
WORD m_wFileDataIndex; // Index into the FILEDATA array
WORD m_wNameOffset; // Offset into the name string table
};
The name/file split is worth noting: multiple names can point to the same file data entry. This was used for mesh references – a .meta file could alias another mesh without duplicating the vertex data.
File Types
Microsoft defined seven types in xip.h:
| Value | Name | Content |
|---|---|---|
| 0 | XIP_TYPE_GENERIC |
XAP scripts, audio, and anything else |
| 1 | XIP_TYPE_MESH |
XM mesh files (vertex + index buffers) |
| 2 | XIP_TYPE_TEXTURE |
XBX texture files |
| 3 | XIP_TYPE_WAVE |
WAV audio (often IMA ADPCM compressed) |
| 4 | XIP_TYPE_MESH_REFERENCE |
Points to another mesh by name |
| 5 | XIP_TYPE_INDEXBUFFER |
Raw index buffer (part of a mesh) |
| 6 | XIP_TYPE_VERTEXBUFFER |
Raw vertex buffer (part of a mesh) |
Types 5 and 6 are used internally by the packer – during XIP creation, meshes are split into separate vertex buffer and index buffer entries. When the XIP is loaded, the mesh reader reassembles them into a complete mesh object.
There is no compression. Files are stored raw. This made sense on the Xbox where CPU time was more valuable than disk space, and the hard drive was fast enough for sequential reads.
XIP Signatures
Microsoft’s xipsign tool (found at xbox/ui/private/xipsign/) computed HMAC signatures over 64KB chunks of each XIP file. The signing was straightforward: read the XIP in 64KB blocks, compute a signature per block using Xbox crypto APIs (xcrypt.h), write the signatures to a protection file.
Every dashboard version checked these signatures before loading XIPs. When the modding community started patching out the check, Microsoft responded by moving the signature verification code to different locations in the XBE with each dashboard update. The community would find the new location, NOP out the branch, and the cycle would repeat. Once you could run unsigned XBEs (via modchip or softmod), the XIP signatures were just a single branch instruction to patch out – wherever Microsoft hid it.
File Formats Inside a XIP
XAP Scripts (.xap) – Type 0
Plain text files in VRML97 syntax with JavaScript-like inline scripts. The dashboard compiles them at load time (not pre-compiled to bytecode on disk), which is what made script modding so accessible – edit the text, reload, see changes. See XAP Script System for the full format.
XBX Textures (.xbx) – Type 2
Xbox-native texture files using the XPR0 (Xbox Packed Resource) format:
+------------------+
| XPR_HEADER | Magic (0x30525058 "XPR0"), total size, header size
+------------------+
| D3D Resource | Pixel format, dimensions, mipmap info (encoded in GPU register format)
+------------------+
| Pixel Data | DXT-compressed, swizzled (Morton-order) pixel data
+------------------+
Supported pixel formats: DXT1 (4:1 compression, 1-bit alpha), DXT3 (explicit 4-bit alpha), DXT5 (interpolated alpha), plus uncompressed formats like A8R8G8B8, R5G6B5, L8, A8, and palettized P8.
The “swizzling” is a Morton Z-order curve – pixels are laid out in a GPU-friendly pattern rather than linear scanline order. The desktop port deswizzles the data in software before uploading to OpenGL. Microsoft’s format packed the dimensions and format info directly into NV2A GPU register fields, so parsing these textures required understanding the GPU’s register layout. But the format itself was consistent and well-structured – once you understood the register encoding, every XBX file parsed the same way.
Microsoft also reused the .xbx extension for non-texture data. TitleMeta.xbx and SaveMeta.xbx in the UDATA directory were plain UTF-16LE text files with save game metadata. These weren’t in XPR0 format at all – just text with a misleading extension. And none of them were signed.
XM Meshes (.xm) – Type 1
3D geometry files exported from 3ds Max via Microsoft’s wrl2xm converter. The tool read VRML97 .wrl files and compiled them into Xbox-native mesh data:
+--------------------+
| Mesh Header | FVF code, vertex count, index count, primitive type, material name
+--------------------+
| Vertex Buffer | Array of vertices (layout defined by FVF)
+--------------------+
| Index Buffer | 16-bit triangle indices
+--------------------+
The FVF (Flexible Vertex Format) code describes each vertex’s layout:
D3DFVF_XYZ(0x002): 3D position (3 floats, 12 bytes)D3DFVF_NORMAL(0x010): Surface normal (3 floats, 12 bytes)D3DFVF_NORMPACKED3: Xbox-specific packed normal (1 DWORD encoding 3 x 11-bit components)D3DFVF_DIFFUSE(0x040): Vertex color (DWORD, ARGB)D3DFVF_TEX1(0x100): Texture coordinates (2 floats, 8 bytes)
Materials are referenced by name string. When a mesh says its material is "chrome_blue", the material system looks up that name in the loaded MaxMaterial nodes.
XTF Fonts (.xtf)
Xbox bitmap fonts with glyph tables, character maps, and kerning data. The format stores glyph metrics (advance width, bearing, bounding box) and bitmap data for each character. On Xbox, glyphs were rendered directly from the font file. On desktop, the glyph data is rasterized to OpenGL textures.
Audio (.wav) – Type 3
WAV files, often using Xbox IMA ADPCM compression (format tag 0x0069). The desktop port includes a software IMA ADPCM decoder that converts these to PCM at load time for playback through SDL_mixer.
Loading Process
When the dashboard starts:
- Load XIP: Read the XIPHEADER, file table, and name table into memory
- Find default.xap: Search the name table for
"default.xap" - Parse: The lexer/parser/compiler process the XAP text into a scene graph with executable bytecode
- Resolve assets: When the scene graph references a texture or mesh by name,
FindObjectInXIP()locates it in the archive - Skin override: Before checking the XIP, the system checks
Q:\Skins\{active_skin}\for an override file with the same name. If found, the skin’s version is used instead.
Sub-XIPs and Lazy Loading
The dashboard uses ~28 XIP files. Only default.xip is loaded at boot. The rest are loaded on demand when the user navigates to that section – triggered by Inline nodes in the scene graph that reference sub-XAP files in other XIPs.
Q:\Xips\
default.xip Root scene, main menu, core UI
mainmenu5.xip Main menu panels
settings3.xip Settings panels
music2.xip Music player / soundtrack manager
memory2.xip Memory management
dvd.xip DVD player UI
keyboard.xip On-screen keyboard
...
On the desktop, XIPs can be loaded in two modes:
- Compiled mode: Load the
.xipbinary directly (same as Xbox) - Extracted mode: Load from a directory of extracted files (for development – edit
.xapscripts and see changes without rebuilding the XIP)
XIP Tool
The tools/xiptool.c utility extracts and creates XIP archives. It builds on 20 years of community XIP tooling – Voltaic’s pixit, MaTiAz5’s UnXiP, and VulgasProfanum’s contributions, among others:
# Extract a XIP
xiptool -x default.xip output_dir/
# Create a XIP from a directory
xiptool -c output_dir/ new_default.xip
When extracting, the tool reassembles mesh entries (recombining split vertex/index buffer entries into complete .xm files with their original MESHFILEHEADER). When creating, it splits .xm files back into IB+VB entries and auto-generates mesh reference entries so scripts can find meshes by name.
A critical detail: the FILENAME directory must be alphabetically sorted (case-insensitive). The engine uses bsearch() to look up files by name, which requires sorted input. Early versions of community XIP tools didn’t sort the directory, producing XIPs that looked valid but couldn’t be loaded – the binary search would miss entries that were out of order. Microsoft’s original xip.exe build tool (found on a 3729 recovery disc in mkxips.cmd) handled this internally.
The FILEDATA array (which stores offsets, sizes, and types) does NOT need to be sorted – it’s accessed by index, not by name. The FILENAME directory is a sorted index into the unsorted FILEDATA array. This separation means you can pack data in any order (IB first, VB second, generic files last) while maintaining fast name lookups.