Files
yaze/docs/R1-alttp-rom-reference.md
2025-10-17 12:10:25 -04:00

262 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# A Link to the Past ROM Reference
## Graphics System
### Graphics Sheets
The ROM contains 223 graphics sheets, each 128x32 pixels (16 tiles × 4 tiles, 8×8 tile size):
**Sheet Categories**:
- Sheets 0-112: Overworld/Dungeon graphics (compressed 3BPP)
- Sheets 113-114: Uncompressed 2BPP graphics
- Sheets 115-126: Uncompressed 3BPP graphics
- Sheets 127-217: Additional dungeon/sprite graphics
- Sheets 218-222: Menu/HUD graphics (2BPP)
**Graphics Format**:
- 3BPP (3 bits per pixel): 8 colors per tile, commonly used for backgrounds
- 2BPP (2 bits per pixel): 4 colors per tile, used for fonts and simple graphics
### Palette System
#### Color Format
SNES uses 15-bit BGR555 color format:
- 2 bytes per color
- Format: `0BBB BBGG GGGR RRRR`
- Each channel: 0-31 (5 bits)
- Total possible colors: 32,768
**Conversion Formulas:**
```cpp
// From BGR555 to RGB888 (0-255 range)
uint8_t red = (snes_color & 0x1F) * 8;
uint8_t green = ((snes_color >> 5) & 0x1F) * 8;
uint8_t blue = ((snes_color >> 10) & 0x1F) * 8;
// From RGB888 to BGR555
uint16_t snes_color = ((r / 8) & 0x1F) |
(((g / 8) & 0x1F) << 5) |
(((b / 8) & 0x1F) << 10);
```
#### 16-Color Row Structure
The SNES organizes palettes in **rows of 16 colors**:
- Each row starts with a **transparent color** at indices 0, 16, 32, 48, 64, etc.
- Palettes must respect these boundaries for proper display
- Multiple sub-palettes can share a row if they're 8 colors or less
#### Palette Groups
**Dungeon Palettes** (0xDD734):
- 20 palettes × 90 colors each
- Structure: 5 full rows (0-79) + 10 colors (80-89)
- Transparent at: indices 0, 16, 32, 48, 64
- Distributed as: BG1 colors, BG2 colors, sprite colors
- Applied per-room via palette ID
**Overworld Palettes**:
- Main: 35 colors per palette (0xDE6C8)
- Structure: 2 full rows (0-15, 16-31) + 3 colors (32-34)
- Transparent at: 0, 16
- Auxiliary: 21 colors per palette (0xDE86C)
- Structure: 1 full row (0-15) + 5 colors (16-20)
- Transparent at: 0
- Animated: 7 colors per palette (0xDE604)
- Overlay palette (no transparent)
**Sprite Palettes**:
- Global sprites: 2 palettes of 60 colors each
- Light World: 0xDD218
- Dark World: 0xDD290
- Structure: 4 rows per set (0-15, 16-31, 32-47, 48-59)
- Transparent at: 0, 16, 32, 48
- Auxiliary 1: 12 palettes × 7 colors (0xDD39E)
- Auxiliary 2: 11 palettes × 7 colors (0xDD446)
- Auxiliary 3: 24 palettes × 7 colors (0xDD4E0)
- Note: Aux palettes store 7 colors; transparent added at runtime
**Other Palettes**:
- HUD: 2 palettes × 32 colors (0xDD218)
- Structure: 2 full rows (0-15, 16-31)
- Transparent at: 0, 16
- Armors: 5 palettes × 15 colors (0xDD630)
- 15 colors + transparent at runtime = full 16-color row
- Swords: 4 palettes × 3 colors (overlay, no transparent)
- Shields: 3 palettes × 4 colors (overlay, no transparent)
- Grass: 3 individual hardcoded colors (LW, DW, Special)
- 3D Objects: 2 palettes × 8 colors (Triforce, Crystal)
- Overworld Mini Map: 2 palettes × 128 colors
- Structure: 8 full rows (0-127)
- Transparent at: 0, 16, 32, 48, 64, 80, 96, 112
#### Palette Application to Graphics
**8-Color Sub-Palettes:**
- Index 0: Transparent (not rendered)
- Indices 1-7: Visible colors
- Each tile/sprite references a specific 8-color sub-palette
**Graphics Format:**
- 2BPP: 4 colors per tile (uses indices 0-3)
- 3BPP: 8 colors per tile (uses indices 0-7)
- 4BPP: 16 colors per tile (uses indices 0-15)
**Rendering Process:**
1. Load compressed graphics sheet from ROM
2. Decompress and convert to indexed pixels (values 0-7 for 3BPP)
3. Select appropriate palette group for room/area
4. Map pixel indices to actual colors from palette
5. Upload to GPU texture
## Dungeon System
### Room Data Structure
**Room Objects** (3 bytes each):
```
Byte 1: YYYXXXXX
YYY = Y coordinate (0-31)
XXXXX = X coordinate (0-31) + layer flag (bit 5)
Byte 2: SSSSSSSS
Size byte (interpretation varies by object type)
Byte 3: IIIIIIII
Object ID or ID component (0-255)
```
**Object Patterns**:
- 0x34: 1x1 solid block
- 0x00-0x08: Rightward 2x2 expansion
- 0x60-0x68: Downward 2x2 expansion
- 0x09-0x14: Diagonal acute (/)
- 0x15-0x20: Diagonal grave (\)
- 0x33, 0x70-0x71: 4x4 blocks
### Tile16 Format
Each Tile16 is composed of four 8x8 tiles:
```
[Top-Left] [Top-Right]
[Bot-Left] [Bot-Right]
```
Stored as 8 bytes (2 bytes per 8x8 tile):
```cpp
// 16-bit tile info: vhopppcccccccccc
// v = vertical flip
// h = horizontal flip
// o = priority
// ppp = palette index (0-7)
// cccccccccc = tile ID (0-1023)
```
### Blocksets
Each dungeon room uses a blockset defining which graphics sheets are loaded:
- 16 sheets per blockset
- First 8: Background graphics
- Last 8: Sprite graphics
**Blockset Pointer**: 0x0FFC40
## Message System
### Text Data Locations
- Text Block 1: 0xE0000 - 0xE7FFF (32KB)
- Text Block 2: 0x75F40 - 0x773FF (5.3KB)
- Dictionary Pointers: 0x74703
### Character Encoding
- 0x00-0x66: Standard characters (A-Z, a-z, 0-9, punctuation)
- 0x67-0x80: Text commands (line breaks, colors, window controls)
- 0x88-0xE8: Dictionary references (compressed common words)
- 0x7F: Message terminator
### Text Commands
- 0x6A: Player name insertion
- 0x6B: Window border (+ 1 argument byte)
- 0x73: Scroll text vertically
- 0x74-0x76: Line 1, 2, 3 markers
- 0x77: Text color (+ 1 argument byte)
- 0x7E: Wait for key press
### Font Graphics
- Location: 0x70000
- Format: 2BPP
- Size: 8KB (0x2000 bytes)
- Organized as 8x8 tiles for characters
## Overworld System
### Map Structure
- 3 worlds: Light, Dark, Special
- Each world: 8×8 grid of 512×512 pixel maps
- Total maps: 192 (64 per world)
### Area Sizes (ZSCustomOverworld v3+)
- Small: 512×512 (1 map)
- Wide: 1024×512 (2 maps horizontal)
- Tall: 512×1024 (2 maps vertical)
- Large: 1024×1024 (4 maps in 2×2 grid)
### Tile Format
- Map uses Tile16 (16×16 pixel tiles)
- Each Tile16 composed of four 8x8 tiles
- 32×32 Tile16s per 512×512 map
## Compression
### LC-LZ2 Algorithm
Both graphics and map data use a variant of LZ compression:
**Commands**:
- 0x00-0x1F: Direct copy (copy N bytes verbatim)
- 0x20-0x3F: Byte fill (repeat 1 byte N times)
- 0x40-0x5F: Word fill (repeat 2 bytes N times)
- 0x60-0x7F: Incremental fill (0x05, 0x06, 0x07...)
- 0x80-0xFF: LZ copy (copy from earlier in buffer)
**Extended Headers** (for lengths > 31):
- 0xE0-0xFF: Extended command headers
- Allows compression of up to 1024 bytes
**Modes**:
- Mode 1 (Nintendo): Graphics decompression (byte order variation)
- Mode 2 (Nintendo): Overworld decompression (byte order variation)
## Memory Map
### ROM Banks (LoROM)
- Bank 0x00-0x7F: ROM data
- Bank 0x80-0xFF: Mirror of 0x00-0x7F
### Important ROM Locations
```
Graphics:
0x080000+ Link graphics (uncompressed)
0x0F8000+ Dungeon object subtype tables
0x0FB373 Object subtype 1 table
0x0FFC40 Blockset pointers
Palettes:
0x0DD218 HUD palettes
0x0DD308 Global sprite palettes
0x0DD734 Dungeon main palettes
0x0DE6C8 Overworld main palettes
0x0DE604 Animated palettes
Text:
0x070000 Font graphics
0x0E0000 Main text data
0x075F40 Extended text data
Tile Data:
0x0F8000 Tile16 data (4032 tiles)
```
---
**Last Updated**: October 13, 2025