Phase 1: Extraction & Analysis
:::info Status In Progress — ROM structure fully analyzed. Custom compression format identified. Next step: RAM dump via emulator to access decompressed model data. :::
Goals
Determine if model data is compressedYES - ERZ format (Huffman+LZ)Locate model data offsets in the ROM binaryCharacter cluster at 0x621E2- Rip Tony Hawk's existing 3D model from the ROM
- Extract and catalog all character textures
- Document the skeleton hierarchy and segment count
Step 0: RAM Dump (Primary Approach)
Since the ROM uses custom compression, the fastest path is to dump decompressed data directly from N64 RAM while the game is running.
Quick Start
# Install emulator
brew install mupen64plus
# Run the game (select Tony Hawk, enter a level)
mupen64plus "Tony Hawk's Pro Skater (USA) (Rev 1).z64"
# Save state: press F5 in-game
# State saved to: ~/.local/share/mupen64plus/save/
# Extract and analyze
cd n64-mods
python3 scripts/extract_savestate.py ~/.local/share/mupen64plus/save/THPS*.st
python3 scripts/dump_ram.py *_rdram.bin
What This Gets Us
The RAM dump contains the fully decompressed character model currently in use:
- F3DEX2 display lists (ready to parse)
- Vertex data (positions, UVs, normals)
- Loaded textures (in N64 format, ready to view with Texture64)
- Bone/animation state
The dump_ram.py script scans for display list patterns and exports OBJ models
that can be imported into Blender.
Alternative: RetroArch
If mupen64plus doesn't work, RetroArch with the mupen64plus-next core also produces save states we can extract RDRAM from.
Step 1: Rip Model via Emulator (Alternative)
Use Project64 with the LemD3D9 graphics plugin to capture the rendered geometry.
Setup
- Install Project64
- Download LemD3D9 r22 plugin
- Copy
LemD3D9.dllto Project64'sPlugin/GFX/folder - In Project64 Settings → Plugins → Video, select LemD3D9
Ripping Process
- Load THPS ROM in Project64
- Navigate to character select screen (select Tony Hawk)
- In LemD3D9 graphics settings, enable geometry export
- The plugin captures F3DEX2 display lists as they render → exports OBJ files
- Import the OBJ into Blender to study proportions and triangle count
What to Document
- Total triangle count
- Number of mesh segments (body parts)
- Approximate vertex positions (will be used to locate data in ROM)
Step 2: Locate Model Data in ROM
Hex Editor Analysis
Open the .z64 in HxD or ImHex.
Strategy: Use known vertex positions from the ripped model to search the ROM binary.
Example: If a vertex is at position (120, -45, 30)
In big-endian 16-bit: 0x0078 0xFFD3 0x001E
Search for this byte sequence in the ROM
What to Look For
- File table: Usually near the start of ROM, contains offset/size pairs pointing to assets
- Vertex data clusters: Groups of 16-byte entries with signed-16-bit coordinate patterns
- Display list commands: 8-byte entries starting with known F3DEX2 opcodes:
0x01— G_VTX (load vertices)0x05or0x06— G_TRI1/G_TRI2 (draw triangles)0xFD— G_SETTIMG (set texture image)0xF5— G_SETTILE (configure texture tile)
Known F3DEX2 Command Bytes (First byte of 8-byte command)
| Byte | Command | Purpose |
|---|---|---|
01 | G_VTX | Load vertex buffer |
05 | G_TRI1 | Draw 1 triangle |
06 | G_TRI2 | Draw 2 triangles |
D7 | G_TEXTURE | Set texture parameters |
D9 | G_SETOTHERMODE_H | Set render modes |
E7 | G_RDPPIPESYNC | Pipeline sync |
F5 | G_SETTILE | Configure texture tile descriptor |
FD | G_SETTIMG | Set texture image address |
F8 | G_RDPFULLSYNC | Full sync |
Step 3: Extract Textures
Use Texture64 to scan the ROM for textures.
Process
- Open ROM in Texture64
- Scan for CI4/CI8/RGBA16 textures in the character data region
- Identify face, body, clothing textures
- Export as PNG for reference
- Document: format, dimensions, palette, ROM offset for each texture
Expected Texture Formats
- CI4 (4-bit color-indexed): 16 colors per texture, most memory-efficient
- CI8 (8-bit color-indexed): 256 colors, used for more detailed textures like faces
- RGBA16 (5551): 16-bit per pixel, used sparingly due to TMEM constraints
Compression: CONFIRMED - Edge of Reality "ERZ" Format
:::danger Critical Finding The ROM uses a custom Huffman + LZ hybrid compression. No standard tools can decompress it. The emulator-based RAM dump approach bypasses this entirely. :::
ERZ Block Format (discovered via ROM analysis)
Offset Size Description
0x00 3 Magic: "ERZ" (45 52 5A)
0x03 1 Type: 01 (standard) or 02 (alternate)
0x04 4 Buffer size (big-endian u32): 0x4000 for models, 0x10000 for levels
0x08 4 Decompressed data size (big-endian u32)
0x0C ... Compressed bitstream (Huffman + LZ)
ROM Block Statistics
| Buffer Size | Block Count | Avg Decomp Size | Likely Content |
|---|---|---|---|
| 16 KB (0x4000) | 1074 | 8.7 KB | Models, textures, game data |
| 64 KB (0x10000) | 13 | 24.4 KB | Level geometry |
| 8 KB (0x2000) | 22 | 5.7 KB | Audio/small assets |
Character Data Location
Cluster 1 at ROM 0x621E2 - 0xA87CE:
- 51 consecutive ERZ blocks
- Average decompressed size: 5.7 KB each
- Total region: ~285 KB compressed
- This is the strongest candidate for character model + texture data
- 10 characters × ~5 blocks each ≈ 50 blocks (matches!)
Decompressor Function
- ROM offset:
0x1F30 - RAM address:
0x80001330 - Signature: Allocates 384-byte stack buffer for 3 Huffman lookup tables (128 bytes each)
- Algorithm: Reads bitstream byte-by-byte, uses tables to decode Huffman symbols, outputs literal bytes or LZ back-references
Compression NOT Used
| Format | Present? |
|---|---|
| Zlib | No (false positive byte patterns only) |
| MIO0/YAY0/YAZ0 | No |
| Standard LZ77 | No (custom variant) |
Step 5: Document the Skeleton
From the ripped model and ROM analysis, determine:
- Total bone count
- Bone hierarchy (parent-child tree)
- Rest pose bone positions
- Which mesh segments attach to which bones
- Animation data location in ROM (separate from model data)
Expected Skeleton Structure (typical N64 skater)
Root (pelvis)
├── Spine
│ ├── Head
│ ├── Left Upper Arm
│ │ └── Left Forearm
│ │ └── Left Hand
│ └── Right Upper Arm
│ └── Right Forearm
│ └── Right Hand
├── Left Upper Leg
│ └── Left Lower Leg
│ └── Left Foot
└── Right Upper Leg
└── Right Lower Leg
└── Right Foot
Tools Needed
- Project64 — N64 emulator
- LemD3D9 r22 — Model ripping plugin
- Texture64 — Texture extraction
- HxD or ImHex — Hex editor
- Blender — View ripped models
Deliverables
After completing this phase, we should have:
- Tony Hawk's model as OBJ files (per-segment)
- All character textures as PNGs with documented ROM offsets
- Complete skeleton hierarchy map
- ROM offset ranges for model data, texture data, and animation data
- Compression status confirmed