778 lines
22 KiB
Markdown
778 lines
22 KiB
Markdown
# Zelda 3 (Link to the Past) Dungeon System Specification
|
|
|
|
**Purpose:** This document provides a comprehensive specification for the ALTTP dungeon/underworld system based on analysis of:
|
|
- **yaze** - C++ dungeon editor implementation (partial)
|
|
- **ZScream** - C# reference implementation (complete)
|
|
- **usdasm** - Assembly disassembly of bank_01.asm (ground truth)
|
|
|
|
**Goal:** Close the gaps in yaze's dungeon editor to achieve correct room rendering.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Room Data Structure](#1-room-data-structure)
|
|
2. [Room Header Format](#2-room-header-format)
|
|
3. [Object System](#3-object-system)
|
|
4. [Layer System](#4-layer-system)
|
|
5. [Door System](#5-door-system)
|
|
6. [Sprites](#6-sprites)
|
|
7. [Items and Chests](#7-items-and-chests)
|
|
8. [Graphics and Tilesets](#8-graphics-and-tilesets)
|
|
9. [Implementation Gaps in yaze](#9-implementation-gaps-in-yaze)
|
|
10. [ROM Address Reference](#10-rom-address-reference)
|
|
|
|
---
|
|
|
|
## 1. Room Data Structure
|
|
|
|
### 1.1 Overview
|
|
|
|
A dungeon room in ALTTP consists of:
|
|
- **Room Header** (14 bytes) - Metadata, properties, warp destinations
|
|
- **Object Data** - Tile objects for walls, floors, decorations
|
|
- **Sprite Data** - Enemies, NPCs, interactive entities
|
|
- **Item Data** - Chest contents, pot items, key drops
|
|
- **Door Data** - Connections between rooms
|
|
|
|
### 1.2 Total Rooms
|
|
|
|
```
|
|
Total Rooms: 296 (0x00 - 0x127)
|
|
Room Size: 512x512 pixels (64x64 tiles at 8x8 pixels each)
|
|
```
|
|
|
|
### 1.3 Room Memory Layout
|
|
|
|
```
|
|
Room Object Data:
|
|
+0x00: Floor nibbles (floor2 << 4 | floor1)
|
|
+0x01: Layout byte ((value >> 2) & 0x07)
|
|
+0x02+: Object stream (3 bytes per object)
|
|
|
|
Layer Separators:
|
|
- 0xFF 0xFF: Marks transition to next layer
|
|
- 0xF0 0xFF: Begin door list
|
|
- Layer 3 reached or 0xFF 0xFF at boundary: End of data
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Room Header Format
|
|
|
|
### 2.1 Header Structure (14 bytes)
|
|
|
|
| Offset | Bits | Field | Description |
|
|
|--------|------|-------|-------------|
|
|
| 0x00 | 7-5 | bg2 | Background 2 / Layer merge type (0-7) |
|
|
| 0x00 | 4-2 | collision | Collision type (0-4) |
|
|
| 0x00 | 0 | light | Light flag (if set, bg2 = 0x08 Dark Room) |
|
|
| 0x01 | 5-0 | palette | Palette ID (0-63, masked 0x3F) |
|
|
| 0x02 | 7-0 | blockset | Tileset/Blockset ID (0-23) |
|
|
| 0x03 | 7-0 | spriteset | Spriteset ID (0-64) |
|
|
| 0x04 | 7-0 | effect | Room effect (0-7) |
|
|
| 0x05 | 7-0 | tag1 | Tag 1 trigger (0-64) |
|
|
| 0x06 | 7-0 | tag2 | Tag 2 trigger (0-64) |
|
|
| 0x07 | 1-0 | holewarp_plane | Pit warp plane (0-3) |
|
|
| 0x07 | 3-2 | staircase_plane[0] | Staircase 1 plane (0-3) |
|
|
| 0x07 | 5-4 | staircase_plane[1] | Staircase 2 plane (0-3) |
|
|
| 0x07 | 7-6 | staircase_plane[2] | Staircase 3 plane (0-3) |
|
|
| 0x08 | 1-0 | staircase_plane[3] | Staircase 4 plane (0-3) |
|
|
| 0x09 | 7-0 | holewarp | Hole warp destination room (0-255) |
|
|
| 0x0A | 7-0 | staircase_rooms[0] | Staircase 1 destination room |
|
|
| 0x0B | 7-0 | staircase_rooms[1] | Staircase 2 destination room |
|
|
| 0x0C | 7-0 | staircase_rooms[2] | Staircase 3 destination room |
|
|
| 0x0D | 7-0 | staircase_rooms[3] | Staircase 4 destination room |
|
|
|
|
### 2.2 Header Address Calculation
|
|
|
|
```cpp
|
|
// Step 1: Get master pointer
|
|
int header_pointer = ROM[kRoomHeaderPointer, 3]; // 24-bit
|
|
header_pointer = SNEStoPC(header_pointer);
|
|
|
|
// Step 2: Index into pointer table
|
|
int table_offset = header_pointer + (room_id * 2);
|
|
int address = (ROM[kRoomHeaderPointerBank] << 16) | ROM[table_offset, 2];
|
|
|
|
// Step 3: Convert to PC address
|
|
int header_location = SNEStoPC(address);
|
|
```
|
|
|
|
### 2.3 Layer Merge Types (bg2 field)
|
|
|
|
| ID | Name | Layer2OnTop | Layer2Translucent | Layer2Visible |
|
|
|----|------|-------------|-------------------|---------------|
|
|
| 0x00 | Off | true | false | false |
|
|
| 0x01 | Parallax | true | false | false |
|
|
| 0x02 | Dark | true | true | true |
|
|
| 0x03 | On top | true | true | false |
|
|
| 0x04 | Translucent | true | true | true |
|
|
| 0x05 | Addition | true | true | true |
|
|
| 0x06 | Normal | true | false | false |
|
|
| 0x07 | Transparent | true | true | true |
|
|
| 0x08 | Dark room | true | true | true |
|
|
|
|
**Note:** When `light` flag is set, bg2 is overridden to 0x08 (Dark room).
|
|
|
|
### 2.4 Collision Types
|
|
|
|
| ID | Name |
|
|
|----|------|
|
|
| 0 | One_Collision |
|
|
| 1 | Both |
|
|
| 2 | Both_With_Scroll |
|
|
| 3 | Moving_Floor_Collision |
|
|
| 4 | Moving_Water_Collision |
|
|
|
|
### 2.5 Room Effects
|
|
|
|
| ID | Name | Description |
|
|
|----|------|-------------|
|
|
| 0 | Nothing | No effect |
|
|
| 1 | One | Effect 1 |
|
|
| 2 | Moving_Floor | Animated floor tiles |
|
|
| 3 | Moving_Water | Animated water tiles |
|
|
| 4 | Four | Effect 4 |
|
|
| 5 | Red_Flashes | Red screen flashes |
|
|
| 6 | Torch_Show_Floor | Floor revealed by torches |
|
|
| 7 | Ganon_Room | Final boss room effect |
|
|
|
|
### 2.6 Room Tags (65 types)
|
|
|
|
Key tags include:
|
|
- `NW_Kill_Enemy_to_Open` (1) - Kill all enemies in NW quadrant
|
|
- `Clear_Quadrant_to_Open` (various) - Quadrant-based triggers
|
|
- `Push_Block_to_Open` (various) - Block puzzle triggers
|
|
- `Water_Gate` - Water level control
|
|
- `Agahnim_Room` - Boss room setup
|
|
- `Holes_0` through `Holes_2` - Pit configurations
|
|
|
|
---
|
|
|
|
## 3. Object System
|
|
|
|
### 3.1 Object Subtypes
|
|
|
|
ALTTP uses three object subtypes with different encoding and capabilities:
|
|
|
|
| Subtype | ID Range | Count | Scalable | Description |
|
|
|---------|----------|-------|----------|-------------|
|
|
| 1 | 0x00-0xF7 | 248 | Yes | Standard room objects |
|
|
| 2 | 0x100-0x13F | 64 | No | Fixed-size objects |
|
|
| 3 | 0xF80-0xFFF | 128 | No | Special/complex objects |
|
|
|
|
### 3.2 Object Encoding (3 bytes)
|
|
|
|
**Subtype 1 (b3 < 0xF8):**
|
|
```
|
|
Byte 1: xxxxxxss (x = X position bits 7-2, s = size X bits 1-0)
|
|
Byte 2: yyyyyyss (y = Y position bits 7-2, s = size Y bits 1-0)
|
|
Byte 3: iiiiiiii (object ID 0x00-0xF7)
|
|
|
|
Decoding:
|
|
posX = (b1 & 0xFC) >> 2
|
|
posY = (b2 & 0xFC) >> 2
|
|
sizeX = b1 & 0x03
|
|
sizeY = b2 & 0x03
|
|
sizeXY = (sizeX << 2) + sizeY
|
|
object_id = b3
|
|
```
|
|
|
|
**Subtype 2 (b1 >= 0xFC):**
|
|
```
|
|
Byte 1: 111111xx (x = X position bits 5-4)
|
|
Byte 2: xxxxyyyy (x = X position bits 3-0, y = Y position bits 5-2)
|
|
Byte 3: yyiiiiii (y = Y position bits 1-0, i = object ID low 6 bits)
|
|
|
|
Decoding:
|
|
posX = ((b2 & 0xF0) >> 4) + ((b1 & 0x03) << 4)
|
|
posY = ((b2 & 0x0F) << 2) + ((b3 & 0xC0) >> 6)
|
|
object_id = (b3 & 0x3F) | 0x100
|
|
```
|
|
|
|
**Subtype 3 (b3 >= 0xF8):**
|
|
```
|
|
Byte 1: xxxxxxii (x = X position bits 7-2, i = size/ID bits 1-0)
|
|
Byte 2: yyyyyyii (y = Y position bits 7-2, i = size/ID bits 3-2)
|
|
Byte 3: 11111iii (i = ID bits 6-4, marker 0xF8-0xFF)
|
|
|
|
Decoding:
|
|
posX = (b1 & 0xFC) >> 2
|
|
posY = (b2 & 0xFC) >> 2
|
|
object_id = ((b3 << 4) | 0x80 + (((b2 & 0x03) << 2) + (b1 & 0x03))) - 0xD80
|
|
// Results in 0x200-0x27E range
|
|
```
|
|
|
|
### 3.3 Object Data Tables (bank_01.asm)
|
|
|
|
```
|
|
Address | Size | Content
|
|
---------------|-------|------------------------------------------
|
|
$018000-$0181FE| 512B | Subtype 1 data offsets (256 entries x 2)
|
|
$018200-$0183EE| 494B | Subtype 1 routine pointers (256 entries)
|
|
$0183F0-$01846E| 128B | Subtype 2 data offsets (64 entries x 2)
|
|
$018470-$0184EE| 128B | Subtype 2 routine pointers (64 entries)
|
|
$0184F0-$0185EE| 256B | Subtype 3 data offsets (128 entries x 2)
|
|
$0185F0-$0186EE| 256B | Subtype 3 routine pointers (128 entries)
|
|
```
|
|
|
|
### 3.4 Drawing Routines
|
|
|
|
There are 24+ unique drawing patterns used by objects:
|
|
|
|
| Routine | Pattern | Multiplier | Objects Using |
|
|
|---------|---------|------------|---------------|
|
|
| Rightwards2x2_1to15or32 | 2x2 horizontal | s*2 | Walls, floors |
|
|
| Rightwards2x4_1to15or26 | 2x4 horizontal | s*2 | Taller walls |
|
|
| Downwards2x2_1to15or32 | 2x2 vertical | s*2 | Vertical features |
|
|
| Downwards4x2_1to15or26 | 4x2 vertical | s*2 | Wide columns |
|
|
| DiagonalAcute_1to16 | Diagonal / | +1,+1 | Stairs up-right |
|
|
| DiagonalGrave_1to16 | Diagonal \ | +1,-1 | Stairs down-right |
|
|
| 4x4 | Fixed 4x4 | none | Type 2 objects |
|
|
| 3x4 | Fixed 3x4 | none | Doors, decorations |
|
|
| Single2x2 | Single 2x2 | none | Small decorations |
|
|
| Single2x3Pillar | Single 2x3 | none | Pillars |
|
|
|
|
### 3.5 Size Handling
|
|
|
|
```cpp
|
|
// Default size when size byte is 0
|
|
if (size == 0) {
|
|
size = 32; // For most subtype 1 objects
|
|
}
|
|
|
|
// Some objects use size + 1 for iteration count
|
|
for (int s = 0; s < size + 1; s++) { ... }
|
|
|
|
// Size masking for some routines
|
|
int effective_size = size & 0x0F; // Use lower 4 bits only
|
|
```
|
|
|
|
### 3.6 Layer Assignment
|
|
|
|
Objects are assigned to layers via the object stream:
|
|
- Objects before first `0xFF 0xFF` marker: Layer 0 (BG1)
|
|
- Objects after first `0xFF 0xFF` marker: Layer 1 (BG2)
|
|
- Objects after second `0xFF 0xFF` marker: Layer 2 (BG3/Sprites)
|
|
|
|
Some objects have `allBgs = true` flag and draw to both BG1 and BG2.
|
|
|
|
### 3.7 Common Object IDs
|
|
|
|
**Subtype 1 (Scalable):**
|
|
| ID | Name |
|
|
|----|------|
|
|
| 0x00-0x07 | Wall segments (N/S/E/W) |
|
|
| 0x08-0x0B | Pit edges |
|
|
| 0x0C-0x20 | Diagonal walls |
|
|
| 0x21-0x30 | Rails and supports |
|
|
| 0x31-0x40 | Carpets and trim |
|
|
| 0xD0-0xD7 | Floor types (8 patterns) |
|
|
| 0xE0-0xE7 | Ceiling types |
|
|
| 0xF0-0xF3 | Conveyor belts (4 directions) |
|
|
|
|
**Subtype 2 (Fixed):**
|
|
| ID | Name |
|
|
|----|------|
|
|
| 0x100-0x107 | Corners (concave/convex) |
|
|
| 0x108-0x10F | Braziers and statues |
|
|
| 0x110-0x117 | Star tiles |
|
|
| 0x118-0x11F | Torches and furniture |
|
|
| 0x120-0x127 | Stairs (inter/intra room) |
|
|
| 0x128-0x12F | Blocks and platforms |
|
|
|
|
**Subtype 3 (Special):**
|
|
| ID | Name |
|
|
|----|------|
|
|
| 0x200-0x207 | Waterfall faces |
|
|
| 0x208-0x20F | Somaria paths |
|
|
| 0x210-0x217 | Item piles (rupees) |
|
|
| 0x218-0x21F | Chests (various) |
|
|
| 0x220-0x227 | Pipes and conveyors |
|
|
| 0x228-0x22F | Pegs and switches |
|
|
|
|
---
|
|
|
|
## 4. Layer System
|
|
|
|
### 4.1 Layer Architecture
|
|
|
|
ALTTP uses a 3-layer system matching SNES hardware:
|
|
|
|
| Layer | SNES Name | Memory | Purpose |
|
|
|-------|-----------|--------|---------|
|
|
| BG1 | Background 1 | $7E2000 | Main room layout |
|
|
| BG2 | Background 2 | $7E4000 | Overlay layer |
|
|
| BG3 | Background 3 | Sprites | Sprites/effects |
|
|
|
|
### 4.2 Tilemap Memory Layout
|
|
|
|
```
|
|
Upper Layer (BG1/BG2): $7E2000-$7E27FF (2KB per layer)
|
|
Lower Layer (BG3): $7E4000-$7E47FF (2KB per layer)
|
|
|
|
Grid Structure: 4 columns x 3 rows of 32x32 blocks
|
|
Offset: $100 bytes per block horizontally
|
|
$1C0 bytes per block vertically
|
|
|
|
Each tilemap entry: 16-bit word
|
|
Bits [9:0]: Tile index (0-1023)
|
|
Bit [10]: Priority bit
|
|
Bits [13:11]: Palette select (0-7)
|
|
Bit [14]: Horizontal flip
|
|
Bit [15]: Vertical flip
|
|
```
|
|
|
|
### 4.3 Layer Merge Behavior
|
|
|
|
The `bg2` field controls how layers are composited:
|
|
|
|
```cpp
|
|
switch (bg2) {
|
|
case 0x00: // Off - BG2 hidden
|
|
case 0x01: // Parallax - BG2 scrolls differently
|
|
case 0x02: // Dark - Dark room effect
|
|
case 0x03: // On top - BG2 overlays BG1
|
|
case 0x04: // Translucent - BG2 semi-transparent
|
|
case 0x05: // Addition - Additive blending
|
|
case 0x06: // Normal - Standard display
|
|
case 0x07: // Transparent - BG2 transparent
|
|
case 0x08: // Dark room - Special dark room
|
|
}
|
|
```
|
|
|
|
### 4.4 Floor Rendering
|
|
|
|
Floor tiles are specified by the first byte of room object data:
|
|
```cpp
|
|
uint8_t floor_byte = ROM[object_data_ptr];
|
|
uint8_t floor1 = floor_byte & 0x0F; // Low nibble
|
|
uint8_t floor2 = floor_byte >> 4; // High nibble
|
|
```
|
|
|
|
Floor patterns (0-15) reference tile graphics at `tile_address_floor`.
|
|
|
|
---
|
|
|
|
## 5. Door System
|
|
|
|
### 5.1 Door Data Format
|
|
|
|
Doors are encoded as 2-byte entries after the `0xF0 0xFF` marker:
|
|
|
|
```
|
|
Byte 1: Door position (0-255)
|
|
Byte 2: Door type and direction
|
|
Bits [3:0]: Direction (0=North, 1=South, 2=West, 3=East)
|
|
Bits [7:4]: Door type/subtype
|
|
```
|
|
|
|
### 5.2 Door Types
|
|
|
|
| Type | Name | Description |
|
|
|------|------|-------------|
|
|
| 0x00 | Regular | Standard door |
|
|
| 0x02 | Regular2 | Standard door variant |
|
|
| 0x06 | EntranceDoor | Entrance from overworld |
|
|
| 0x08 | WaterfallTunnel | Behind waterfall |
|
|
| 0x0A | EntranceLarge | Large entrance |
|
|
| 0x0C | EntranceLarge2 | Large entrance variant |
|
|
| 0x0E | EntranceCave | Cave entrance |
|
|
| 0x12 | ExitToOW | Exit to overworld |
|
|
| 0x14 | ThroneRoom | Throne room door |
|
|
| 0x16 | PlayerBgChange | Layer toggle door |
|
|
| 0x18 | ShuttersTwoWay | Two-way shutter |
|
|
| 0x1A | InvisibleDoor | Hidden door |
|
|
| 0x1C | SmallKeyDoor | Requires small key |
|
|
| 0x20-0x26 | StairMaskLocked | Locked stair doors |
|
|
| 0x28 | BreakableWall | Bomb-able wall |
|
|
| 0x30 | LgExplosion | Large explosion door |
|
|
| 0x32 | Slashable | Sword-cuttable |
|
|
| 0x40 | RegularDoor33 | Regular variant |
|
|
| 0x44 | Shutter | One-way shutter |
|
|
| 0x46 | WarpRoomDoor | Warp tile door |
|
|
| 0x48-0x4A | ShutterTrap | Trap shutter doors |
|
|
|
|
### 5.3 Door Graphics Addresses
|
|
|
|
```
|
|
Direction | Graphics Pointer
|
|
----------|------------------
|
|
North | $014D9E (kDoorGfxUp)
|
|
South | $014E06 (kDoorGfxDown)
|
|
West | $014E66 (kDoorGfxLeft)
|
|
East | $014EC6 (kDoorGfxRight)
|
|
```
|
|
|
|
### 5.4 Door Rendering Dimensions
|
|
|
|
| Direction | Width | Height |
|
|
|-----------|-------|--------|
|
|
| North/South | 4 tiles | 3 tiles |
|
|
| East/West | 3 tiles | 4 tiles |
|
|
|
|
---
|
|
|
|
## 6. Sprites
|
|
|
|
### 6.1 Sprite Data Structure
|
|
|
|
```cpp
|
|
struct Sprite {
|
|
uint8_t id; // Sprite type (0x00-0xF3)
|
|
uint8_t x; // X position (0-63)
|
|
uint8_t y; // Y position (0-63)
|
|
uint8_t subtype; // Subtype flags
|
|
uint8_t layer; // Layer (0-2)
|
|
uint8_t key_drop; // Key drop (0=none, 1=small, 2=big)
|
|
bool overlord; // Is overlord sprite
|
|
};
|
|
```
|
|
|
|
### 6.2 Sprite Encoding
|
|
|
|
Sprites are stored as 3-byte entries:
|
|
```
|
|
Byte 1: Y position (bits 7-1), Layer flag (bit 0)
|
|
Byte 2: X position (bits 7-1), Subtype high (bit 0)
|
|
Byte 3: Sprite ID (0x00-0xFF)
|
|
|
|
Special handling:
|
|
- Overlord check: (subtype & 0x07) == 0x07
|
|
- Key drop at sprite ID 0xE4:
|
|
- Position (0x00, 0x1E) = small key drop
|
|
- Position (0x00, 0x1D) = big key drop
|
|
```
|
|
|
|
### 6.3 Overlord Sprites
|
|
|
|
When `(subtype & 7) == 7`, the sprite is an "overlord" with special behavior.
|
|
Overlord IDs 0x01-0x1A have separate name tables.
|
|
|
|
### 6.4 Key Drop Mechanics
|
|
|
|
```cpp
|
|
// Detection during sprite loading
|
|
if (sprite_id == 0xE4) {
|
|
if (x == 0x00 && y == 0x1E) {
|
|
key_drop = 1; // Small key
|
|
} else if (x == 0x00 && y == 0x1D) {
|
|
key_drop = 2; // Big key
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Items and Chests
|
|
|
|
### 7.1 Chest Data
|
|
|
|
Chests are stored separately from room objects:
|
|
|
|
```cpp
|
|
struct ChestData {
|
|
uint16_t room_id; // Room containing chest
|
|
uint8_t x; // X position
|
|
uint8_t y; // Y position
|
|
uint8_t item_id; // Item contained
|
|
bool is_big; // Big chest flag
|
|
};
|
|
```
|
|
|
|
### 7.2 Item Types (Pot Items)
|
|
|
|
| ID | Item | ID | Item |
|
|
|----|------|----|------|
|
|
| 0 | Nothing | 14 | Small magic |
|
|
| 1 | Rupee (green) | 15 | Big magic |
|
|
| 2 | Rock crab | 16 | Bomb refill |
|
|
| 3 | Bee | 17 | Arrow refill |
|
|
| 4 | Random | 18 | Fairy |
|
|
| 5 | Bomb | 19 | Key |
|
|
| 6 | Heart | 20 | Fairy*8 |
|
|
| 7 | Blue rupee | 21-22 | Various |
|
|
| 8 | Key*8 | 23 | Hole |
|
|
| 9 | Arrow | 24 | Warp |
|
|
| 10 | 1 bomb | 25 | Staircase |
|
|
| 11 | Heart | 26 | Bombable |
|
|
| 12 | Rupee (blue) | 27 | Switch |
|
|
| 13 | Heart variant | | |
|
|
|
|
### 7.3 Item Encoding
|
|
|
|
Items with ID >= 0x80 use special encoding:
|
|
```cpp
|
|
if (id & 0x80) {
|
|
int actual_id = ((id - 0x80) / 2) + 23;
|
|
}
|
|
```
|
|
|
|
### 7.4 Item ROM Addresses
|
|
|
|
```
|
|
Chest Pointers: $01EBF6 (kChestsLengthPointer)
|
|
Chest Data: $01EBFB (kChestsDataPointer1)
|
|
Room Items: $01DB69 (kRoomItemsPointers)
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Graphics and Tilesets
|
|
|
|
### 8.1 Graphics Organization
|
|
|
|
```
|
|
Sheet Count: 223 sheets
|
|
Uncompressed Size: 2048 bytes (0x800) per sheet
|
|
3BPP Size: 1536 bytes (0x600) per sheet
|
|
```
|
|
|
|
### 8.2 Key Graphics Addresses
|
|
|
|
```
|
|
Tile Address: $009B52 (kTileAddress)
|
|
Tile Address Floor: $009B5A (kTileAddressFloor)
|
|
Subtype 1 Tiles: $018000 (kRoomObjectSubtype1)
|
|
Subtype 2 Tiles: $0183F0 (kRoomObjectSubtype2)
|
|
Subtype 3 Tiles: $0184F0 (kRoomObjectSubtype3)
|
|
GFX Groups: $006237 (kGfxGroupsPointer)
|
|
```
|
|
|
|
### 8.3 Palette Configuration
|
|
|
|
```
|
|
Palettes Per Group: 16
|
|
Colors Per Palette: 16
|
|
Total Palette Size: 256 colors
|
|
Half Palette Size: 8 colors
|
|
|
|
Dungeon Main BG: $0DEC4B (kDungeonsMainBgPalettePointers)
|
|
Dungeon Palettes: $0DD734 (kDungeonsPalettes)
|
|
```
|
|
|
|
### 8.4 Tile Info Format
|
|
|
|
```cpp
|
|
struct TileInfo {
|
|
uint16_t id; // Tile index (10 bits)
|
|
uint8_t palette; // Palette (3 bits)
|
|
bool h_flip; // Horizontal mirror
|
|
bool v_flip; // Vertical mirror
|
|
bool priority; // Priority bit
|
|
};
|
|
|
|
// Decode from 16-bit word
|
|
TileInfo decode(uint16_t word) {
|
|
TileInfo t;
|
|
t.id = word & 0x03FF;
|
|
t.priority = (word >> 10) & 1;
|
|
t.palette = (word >> 11) & 0x07;
|
|
t.h_flip = (word >> 14) & 1;
|
|
t.v_flip = (word >> 15) & 1;
|
|
return t;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Implementation Gaps in yaze
|
|
|
|
### 9.1 Critical Gaps (Must Fix for Correct Rendering)
|
|
|
|
| Gap | Severity | Description | ZScream Reference |
|
|
|-----|----------|-------------|-------------------|
|
|
| **Type 3 Objects** | Critical | Stub implementation, simplified drawing | Subtype3_Draw.cs |
|
|
| **Door Rendering** | Critical | LoadDoors() is stub, no type handling | Doors_Draw.cs |
|
|
| **all_bgs Flag Ignored** | Critical | Uses hardcoded routine IDs (3,9,17,18) instead | Room_Object.cs allBgs |
|
|
| **Floor Rendering** | High | Floor values loaded but not rendered | Room.cs floor1/floor2 |
|
|
| **Type 2 Complex Layouts** | High | Missing column, bed, spiral stair handling | Subtype2_Multiple.cs |
|
|
| **Layer Merge Effects** | High | Flags exist but not applied during render | LayerMergeType.cs |
|
|
|
|
### 9.2 Missing Systems
|
|
|
|
| System | Status in yaze | ZScream Implementation |
|
|
|--------|----------------|----------------------|
|
|
| Pot Items | Not implemented | Items_Draw.cs (28 types) |
|
|
| Key Drop Visualization | Detection only, no draw | Sprite.cs DrawKey() |
|
|
| Door Graphics | Generic object render | Doors_Draw.cs (40+ types) |
|
|
| Item-Sprite Linking | Not implemented | PotItem.cs |
|
|
| Selection State | Not tracked | Room_Object.cs selected |
|
|
| Unique Sprite IDs | Not tracked | ROM.uniqueSpriteID |
|
|
|
|
### 9.3 Architectural Differences
|
|
|
|
| Aspect | yaze Approach | ZScream Approach | Recommendation |
|
|
|--------|---------------|------------------|----------------|
|
|
| Object Classes | Single RoomObject class | Per-ID classes (object_00, etc.) | Keep unified, add type handlers |
|
|
| Draw Routines | 38 shared lambdas | 256+ override methods | Keep yaze approach |
|
|
| Tile Loading | On-demand parser | Pre-loaded static arrays | Keep yaze approach |
|
|
| Layer Selection | Binary choice (BG1/BG2) | Enum with BG3 | Add BG3 support |
|
|
|
|
### 9.4 Fix Priority List
|
|
|
|
**Phase 1: Core Rendering**
|
|
1. Fix `all_bgs_` flag usage instead of hardcoded routine IDs
|
|
2. Implement proper floor rendering from floor1/floor2 values
|
|
3. Complete Type 3 object drawing (Somaria paths, etc.)
|
|
4. Add missing Type 2 object patterns
|
|
|
|
**Phase 2: Doors**
|
|
5. Implement door type classification system
|
|
6. Add special door graphics (caves, holes, hidden walls)
|
|
7. Mirror effect for bidirectional doors
|
|
8. Layer-specific door rendering
|
|
|
|
**Phase 3: Items & Sprites**
|
|
9. Implement PotItem system (28 types)
|
|
10. Add key drop visualization
|
|
11. Link items to sprites for drops
|
|
12. Selection state tracking
|
|
|
|
**Phase 4: Polish**
|
|
13. Layer merge effect application
|
|
14. BG3 layer support
|
|
15. Complete bounds checking
|
|
16. Dimension calculation for complex objects
|
|
|
|
---
|
|
|
|
## 10. ROM Address Reference
|
|
|
|
### 10.1 Room Data
|
|
|
|
```cpp
|
|
constexpr int kRoomObjectLayoutPointer = 0x882D;
|
|
constexpr int kRoomObjectPointer = 0x874C;
|
|
constexpr int kRoomHeaderPointer = 0xB5DD;
|
|
constexpr int kRoomHeaderPointerBank = 0xB5E7;
|
|
constexpr int kNumberOfRooms = 296;
|
|
```
|
|
|
|
### 10.2 Graphics
|
|
|
|
```cpp
|
|
constexpr int kTileAddress = 0x001B52;
|
|
constexpr int kTileAddressFloor = 0x001B5A;
|
|
constexpr int kRoomObjectSubtype1 = 0x8000;
|
|
constexpr int kRoomObjectSubtype2 = 0x83F0;
|
|
constexpr int kRoomObjectSubtype3 = 0x84F0;
|
|
constexpr int kGfxGroupsPointer = 0x6237;
|
|
```
|
|
|
|
### 10.3 Palettes
|
|
|
|
```cpp
|
|
constexpr int kDungeonsMainBgPalettePointers = 0xDEC4B;
|
|
constexpr int kDungeonsPalettes = 0xDD734;
|
|
```
|
|
|
|
### 10.4 Sprites & Items
|
|
|
|
```cpp
|
|
constexpr int kRoomItemsPointers = 0xDB69;
|
|
constexpr int kRoomsSpritePointer = 0x4C298;
|
|
constexpr int kSpriteBlocksetPointer = 0x5B57;
|
|
constexpr int kSpritesData = 0x4D8B0;
|
|
constexpr int kDungeonSpritePointers = 0x090000;
|
|
```
|
|
|
|
### 10.5 Blocks & Features
|
|
|
|
```cpp
|
|
constexpr int kBlocksLength = 0x8896;
|
|
constexpr int kBlocksPointer1 = 0x15AFA;
|
|
constexpr int kBlocksPointer2 = 0x15B01;
|
|
constexpr int kBlocksPointer3 = 0x15B08;
|
|
constexpr int kBlocksPointer4 = 0x15B0F;
|
|
```
|
|
|
|
### 10.6 Chests & Torches
|
|
|
|
```cpp
|
|
constexpr int kChestsLengthPointer = 0xEBF6;
|
|
constexpr int kChestsDataPointer1 = 0xEBFB;
|
|
constexpr int kTorchData = 0x2736A;
|
|
constexpr int kTorchesLengthPointer = 0x88C1;
|
|
```
|
|
|
|
### 10.7 Pits & Doors
|
|
|
|
```cpp
|
|
constexpr int kPitPointer = 0x394AB;
|
|
constexpr int kPitCount = 0x394A6;
|
|
constexpr int kDoorPointers = 0xF83C0;
|
|
constexpr int kDoorGfxUp = 0x4D9E;
|
|
constexpr int kDoorGfxDown = 0x4E06;
|
|
constexpr int kDoorGfxLeft = 0x4E66;
|
|
constexpr int kDoorGfxRight = 0x4EC6;
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix A: Object ID Quick Reference
|
|
|
|
### Subtype 1 (0x00-0xF7) - Scalable
|
|
|
|
| Range | Category |
|
|
|-------|----------|
|
|
| 0x00-0x07 | Wall segments |
|
|
| 0x08-0x0B | Pit edges |
|
|
| 0x0C-0x20 | Diagonal walls (allBgs=true) |
|
|
| 0x21-0x30 | Rails and supports |
|
|
| 0x31-0x40 | Carpets and trim |
|
|
| 0x41-0x50 | Decorations |
|
|
| 0xD0-0xD7 | Floor patterns |
|
|
| 0xE0-0xE7 | Ceiling patterns |
|
|
| 0xF0-0xF3 | Conveyor belts |
|
|
|
|
### Subtype 2 (0x100-0x13F) - Fixed Size
|
|
|
|
| Range | Category |
|
|
|-------|----------|
|
|
| 0x100-0x107 | Corners |
|
|
| 0x108-0x10F | Braziers/statues |
|
|
| 0x110-0x117 | Star tiles |
|
|
| 0x118-0x11F | Torches/furniture |
|
|
| 0x120-0x127 | Stairs |
|
|
| 0x128-0x12F | Blocks/platforms |
|
|
| 0x130-0x13F | Misc decorations |
|
|
|
|
### Subtype 3 (0x200-0x27E) - Special
|
|
|
|
| Range | Category |
|
|
|-------|----------|
|
|
| 0x200-0x207 | Waterfall faces |
|
|
| 0x208-0x20F | Somaria paths |
|
|
| 0x210-0x217 | Item piles |
|
|
| 0x218-0x21F | Chests |
|
|
| 0x220-0x227 | Pipes/conveyors |
|
|
| 0x228-0x22F | Pegs/switches |
|
|
| 0x230-0x23F | Boss objects |
|
|
| 0x240-0x27E | Misc special |
|
|
|
|
---
|
|
|
|
## Appendix B: Drawing Routine Reference
|
|
|
|
| ID | Routine Name | Pattern | Objects |
|
|
|----|--------------|---------|---------|
|
|
| 0 | Rightwards2x2_1to15or32 | 2x2 horizontal | 0x00, walls |
|
|
| 1 | Rightwards2x4_1to15or26 | 2x4 horizontal | 0x01-0x02 |
|
|
| 2 | Downwards2x2_1to15or32 | 2x2 vertical | vertical walls |
|
|
| 3 | Rightwards2x2_BothBG | 2x2 both layers | 0x03-0x04 |
|
|
| 4 | Rightwards2x4spaced4_1to16 | 2x4 spaced | 0x05-0x06 |
|
|
| 5 | DiagonalAcute_1to16 | Diagonal / | stairs |
|
|
| 6 | DiagonalGrave_1to16 | Diagonal \ | stairs |
|
|
| 7 | Downwards4x2_1to15or26 | 4x2 vertical | wide columns |
|
|
| 8 | 4x4 | Fixed 4x4 | Type 2 objects |
|
|
| 9 | Downwards4x2_BothBG | 4x2 both layers | special walls |
|
|
| 17 | DiagonalAcute_BothBG | Diagonal both | diagonal walls |
|
|
| 18 | DiagonalGrave_BothBG | Diagonal both | diagonal walls |
|
|
|
|
---
|
|
|
|
*Document generated from analysis of yaze, ZScream, and usdasm codebases.*
|
|
*Last updated: 2025-12-01*
|