backend-infra-engineer: Post v0.3.9-hotfix7 snapshot (build cleanup)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
55
docs/internal/research/emulator-music-subsystem.md
Normal file
55
docs/internal/research/emulator-music-subsystem.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Emulator Music Subsystem Research - Audit & Verification
|
||||
|
||||
## 1. Naming Screen Logic Audit
|
||||
|
||||
**Finding:** The Naming Screen is **Module 0x04** (`Module04_NameFile`), located in `usdasm/bank_0C.asm`.
|
||||
* **Correction:** The initial hypothesis of Module 0x0E was incorrect (0x0E is the Interface module).
|
||||
* **Input Mechanism:** The Naming Screen does **not** read hardware registers (`$4218`) directly. It reads **WRAM variables** updated by the NMI handler:
|
||||
* `$F0` (`JOY1A_ALL`): Current state of controller 1.
|
||||
* `$F4` (`JOY1A_NEW`): New button presses (Edge Detected).
|
||||
* `$F6` (`JOY1B_NEW`): New button presses for controller 2? (Usually filtered input).
|
||||
* **Edge Detection Source:** The NMI handler (`NMI_ReadJoypads` in `bank_00.asm`) performs the edge detection:
|
||||
```asm
|
||||
LDA $4218 ; Read Auto-Joypad register
|
||||
STA $F0 ; Store current state
|
||||
EOR $F2 ; XOR with previous state
|
||||
AND $F0 ; AND with current state -> only bits that went 0->1 remain
|
||||
STA $F4 ; Store as "NEW" buttons
|
||||
LDA $F0
|
||||
STA $F2 ; Update previous state
|
||||
```
|
||||
* **Implication for Emulator Issue:**
|
||||
* If the 'A' button isn't working, it means `$F4` bit 7 (A button) isn't being set.
|
||||
* This happens if `$F0` (current) and `$F2` (previous) are identical when `NMI_ReadJoypads` runs.
|
||||
* If the emulator runs multiple frames in a catch-up loop, and `InputManager::Poll` reports the same "Pressed" state for all of them:
|
||||
* Frame 1: Current=Pressed, Previous=Released -> NEW=Pressed (Correct)
|
||||
* Frame 2: Current=Pressed, Previous=Pressed -> NEW=0 (Correct for "held", but user might expect repeat?)
|
||||
* **The Issue:** If the game expects to see a "Released" frame to register a *subsequent* press (e.g., typing "A" then "A"), and the emulator's input polling misses the physical release (because it's polling at 60Hz but the user released and pressed faster, or due to frame skipping), the game sees continuous "Pressed".
|
||||
* **Critical:** If the Naming Screen relies on `JOY1A_NEW` (`$F4`) for the *initial* selection, and that works, but fails for *subsequent* presses of the same character, it confirms the "Released" state is being missed.
|
||||
|
||||
## 2. Audio/SPC Emulation Audit
|
||||
|
||||
**Finding:**
|
||||
* **kNativeSampleRate:**
|
||||
* `src/app/emu/emulator.cc`: `constexpr int kNativeSampleRate = 32040;`
|
||||
* `src/app/editor/music/music_player.cc`: In `EnsureAudioReady`, it defines `constexpr int kNativeSampleRate = 32000;` locally!
|
||||
* **Discrepancy:** This 40Hz difference (0.125%) is small but indicates inconsistency. If `QueueSamplesNative` is called with 32000 but the backend expects 32040 (or vice versa), it might cause subtle drift or resampling artifacting, though unlikely to cause the massive 1.5x speedup on its own.
|
||||
* **1.5x Speedup Confirmation:**
|
||||
* 48000 Hz (Host) / 32040 Hz (Emulator) = **1.498**
|
||||
* The math confirms that playing 32k samples at 48k results in exactly the reported speedup.
|
||||
* **HMAGIC Reference:**
|
||||
* `assets/hmagic/AudioLogic.c` uses `ws_freq = 22050`. This suggests the C-based tracker (hmagic) was optimized for lower quality/performance or older systems, and is *not* a 1:1 reference for the high-fidelity SNES emulation in `yaze`. It explains why "Music Only Mode" (which seemingly uses the `MusicPlayer` / `Emulator` core) behaves differently than the lightweight hmagic tracker.
|
||||
|
||||
## 3. Recommendations Update
|
||||
|
||||
1. **Fix `kNativeSampleRate` Inconsistency:**
|
||||
* Update `src/app/editor/music/music_player.cc` to use `32040` or include `emulator.h`'s constant to match `src/app/emu/emulator.cc`.
|
||||
|
||||
2. **Fix Input Polling for Naming Screen:**
|
||||
* The Naming Screen depends on `NMI_ReadJoypads` detecting a 0->1 transition.
|
||||
* If the user taps 'A' quickly, or if `turbo_mode` is used, the "Released" state must be visible to `NMI_ReadJoypads` for at least one frame.
|
||||
* **Action:** Verify `InputManager::Poll` logic. If it blindly polls SDL state, ensure it's not "sticky".
|
||||
* **Action:** Ensure `auto_joy_timer_` is emulated correctly. If `NMI_ReadJoypads` reads `$4218` while the transfer is still "happening" (timer > 0), it might get garbage or old values. The emulator currently returns the *new* value immediately.
|
||||
|
||||
3. **Resampling Fix:**
|
||||
* As previously identified, the fallback in `Emulator::RunFrameOnly` that queues 32k samples to a 48k backend must be removed.
|
||||
115
docs/internal/research/gigaleak-integration.md
Normal file
115
docs/internal/research/gigaleak-integration.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# YAZE Gigaleak Integration Plan
|
||||
|
||||
How to leverage `~/Code/alttp-gigaleak/` resources to improve YAZE.
|
||||
|
||||
## Symbol Database Integration
|
||||
|
||||
### Source Files
|
||||
| File | Contents | Priority |
|
||||
|------|----------|----------|
|
||||
| `DISASM/jpdasm/symbols_wram.asm` | Work RAM definitions ($7E0000-$7FFFFF) | HIGH |
|
||||
| `DISASM/jpdasm/symbols_sram.asm` | Save RAM definitions ($700000-$70FFFF) | HIGH |
|
||||
| `DISASM/jpdasm/symbols_apu.asm` | Audio processor definitions | MEDIUM |
|
||||
| `alttp_labels.mlb` | Memory location label database | HIGH |
|
||||
| `DISASM/jpdasm/registers.asm` | SNES hardware register names | MEDIUM |
|
||||
|
||||
### Implementation Ideas
|
||||
1. **Label Database Feature**
|
||||
- Parse symbol ASM files into internal label map
|
||||
- Display official names in hex editor alongside addresses
|
||||
- Add search-by-label functionality
|
||||
- Export/import label sets
|
||||
|
||||
2. **Memory Viewer Enhancement**
|
||||
- Color-code RAM regions by purpose (player, enemies, dungeon, etc.)
|
||||
- Show symbol name tooltips on hover
|
||||
- Add "Go to symbol" command
|
||||
|
||||
3. **Disassembly View**
|
||||
- Use official labels when displaying ASM
|
||||
- Cross-reference jumps/calls with symbol names
|
||||
- Show data structure boundaries
|
||||
|
||||
## Graphics Format Research
|
||||
|
||||
### Source Files
|
||||
| File | Contents | Priority |
|
||||
|------|----------|----------|
|
||||
| `Good_NEWS_v002/` | Categorized CGX/COL assets | HIGH |
|
||||
| `CGXViewer/` | C# CGX viewer (reference impl) | HIGH |
|
||||
| `NEWS_11_hino/NEW-CHR/` | 247 subdirs of original graphics | MEDIUM |
|
||||
| `tools/yychr20210606/` | Reference sprite editor | LOW |
|
||||
|
||||
### Implementation Ideas
|
||||
1. **CGX Format Support**
|
||||
- Study CGXViewer.exe source for format spec
|
||||
- Add CGX import/export to graphics editor
|
||||
- Support COL palette files alongside CGX
|
||||
|
||||
2. **Sprite Sheet Improvements**
|
||||
- Use Good_NEWS_v002 categorization as template
|
||||
- Add sprite preview with correct palettes
|
||||
- Show animation sequences
|
||||
|
||||
## Map Format Research
|
||||
|
||||
### Source Files
|
||||
| File | Contents | Priority |
|
||||
|------|----------|----------|
|
||||
| `Overworld/Reconstructing_zel_munt_Overworld_in_Tiled.zip` | Tiled project | HIGH |
|
||||
| `Overworld/*.png` | Annotated world maps | MEDIUM |
|
||||
| `super donkey/ALTTP_RoomsDate.txt` | Room ID reference | MEDIUM |
|
||||
| `super donkey/ALTTPProto_RomMap.txt` | ROM address map | HIGH |
|
||||
|
||||
### Implementation Ideas
|
||||
1. **Tiled Integration**
|
||||
- Study Tiled project structure for map format
|
||||
- Consider Tiled export/import support
|
||||
- Use map square IDs from annotated PNGs
|
||||
|
||||
2. **Room Editor Enhancement**
|
||||
- Reference RoomsDate.txt for room metadata
|
||||
- Use RomMap.txt for address validation
|
||||
- Add prototype room comparison view
|
||||
|
||||
## Japanese Source Terminology
|
||||
|
||||
### Key Naming Conventions (from source)
|
||||
| Japanese | English | Used For |
|
||||
|----------|---------|----------|
|
||||
| zel_char | character | Player/NPC sprites |
|
||||
| zel_mut0 | mutation | State changes |
|
||||
| zel_ram | RAM | Memory definitions |
|
||||
| zel_munt | mount/map | Overworld |
|
||||
| ongen | sound | Audio data |
|
||||
|
||||
### Implementation Ideas
|
||||
1. **Documentation Enhancement**
|
||||
- Add glossary of Japanese terms to YAZE docs
|
||||
- Show both English and Japanese names where known
|
||||
- Reference original source file names in comments
|
||||
|
||||
## Roadmap
|
||||
|
||||
### Phase 1: Symbol Integration
|
||||
- [ ] Parse symbols_wram.asm format
|
||||
- [ ] Create internal label database structure
|
||||
- [ ] Add label display to hex editor
|
||||
- [ ] Implement label search
|
||||
|
||||
### Phase 2: Graphics Research
|
||||
- [ ] Reverse engineer CGX format from viewer source
|
||||
- [ ] Document format in YAZE wiki/docs
|
||||
- [ ] Prototype CGX import
|
||||
|
||||
### Phase 3: Map Research
|
||||
- [ ] Extract and study Tiled project
|
||||
- [ ] Document room format findings
|
||||
- [ ] Consider Tiled compatibility layer
|
||||
|
||||
## References
|
||||
|
||||
- Gigaleak location: `~/Code/alttp-gigaleak/`
|
||||
- Main disassembly: `~/Code/alttp-gigaleak/DISASM/jpdasm/`
|
||||
- Graphics assets: `~/Code/alttp-gigaleak/Good_NEWS_v002/`
|
||||
- Research notes: `~/Code/alttp-gigaleak/glitter_references.txt`
|
||||
47
docs/internal/research/halext-collab-server.md
Normal file
47
docs/internal/research/halext-collab-server.md
Normal file
@@ -0,0 +1,47 @@
|
||||
## Halext collaboration server hookup (yaze.halext.org)
|
||||
|
||||
Goal: keep the WASM bundle on GitHub Pages but let the page at `https://yaze.halext.org` talk to the collab server running on the box. The client now auto-points to `wss://<host>/ws` for any `*.halext.org` host when no server URL is configured.
|
||||
|
||||
### What changed in code
|
||||
- `src/web/core/config.js` now falls back to `wss://<current-host>/ws` when the page is served from a `halext.org` domain and no explicit `window.YAZE_CONFIG.collaboration.serverUrl` or meta tag is set. This keeps GH Pages (front-end) and the collab server (backend) on the same origin.
|
||||
|
||||
### Nginx work (needs sudo)
|
||||
Edit `/etc/nginx/sites/yaze.halext.org.conf` so GitHub Pages stays the default, but WebSocket/HTTP traffic under `/ws` proxies to the collab server on `127.0.0.1:8765`.
|
||||
|
||||
Add inside the `server { ... }` block that listens on 443:
|
||||
|
||||
```
|
||||
# Collab server (WS + HTTP)
|
||||
location /ws/ {
|
||||
proxy_pass http://127.0.0.1:8765/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 7d;
|
||||
proxy_send_timeout 7d;
|
||||
proxy_buffering off;
|
||||
}
|
||||
```
|
||||
|
||||
Keep the existing `/` proxy to GitHub Pages so the WASM UI still serves from GH.
|
||||
|
||||
Then reload nginx (as root):
|
||||
|
||||
```
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Collab server config check (no sudo required)
|
||||
- Service: user systemd unit `yaze-server.service` already runs `/home/halext/yaze-server/server.js` on port 8765.
|
||||
- Allowed origins in `/home/halext/.config/yaze-server.env` include `https://yaze.halext.org`; leave secrets untouched.
|
||||
- Health: `curl -H "Origin: https://yaze.halext.org" http://127.0.0.1:8765/health` (from the server) should return status 200.
|
||||
|
||||
### Usage once nginx is updated
|
||||
- Load `https://yaze.halext.org` (served from GH Pages). The collab client should auto-connect to `wss://yaze.halext.org/ws`.
|
||||
- Hosting/joining creates distinct room codes; multiple rooms can coexist. Admin API remains on the same origin under `/ws/admin/...` with `x-admin-key` header.
|
||||
|
||||
No secrets were changed; only client fallback logic was added locally.
|
||||
119
docs/internal/research/hmagic-reference.md
Normal file
119
docs/internal/research/hmagic-reference.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# HMagic Reference Documentation
|
||||
|
||||
**Consolidated:** 2025-12-08
|
||||
**Purpose:** Reference notes and regression checklist for porting HMagic data to yaze
|
||||
|
||||
## Overview
|
||||
|
||||
HMagic is a legacy ALTTP ROM editor. This document consolidates extraction notes and regression testing requirements to ensure yaze parsers/editors avoid known HMagic bugs while reusing valuable data knowledge.
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Extraction Notes
|
||||
|
||||
Goal: reuse hmagic's data knowledge (not its unsafe plumbing) to improve yaze parsers/editors.
|
||||
|
||||
### Offsets and Structures to Port
|
||||
|
||||
- `structs.h` contains `offsets_ty` with `dungeon_offsets_ty`, `overworld_offsets_ty`, `text_offsets_ty/text_codes_ty`.
|
||||
- `z3ed.c::LoadOffsets` (currently US-only, hardcoded): torches (`0x2736a`), torch_count (`0x88c1`); text dictionary/regions (`bank=0x0e`, dictionary=0x74703..0x748D9, param_counts=0x7536b, region1=0xe0000..0xe8000, region2=0x75f40..0x77400, codes bounds).
|
||||
- Action: lift into a region table (US/EU/JP) with file-size validation before use.
|
||||
- Status: US offsets added at `src/zelda3/formats/offsets.{h,cc}` with basic bounds validation; EU/JP remain TODO.
|
||||
|
||||
### Text Decode/Encode Logic (TextLogic.c)
|
||||
|
||||
- **Decoder**: walks monologue stream until `abs_terminator`; handles `region_switch`, zchars `< zchar_bound`, dictionary entries (`dict_base`..), `msg_terminator`, and commands with params via `param_counts` table. Appends to `ZTextMessage` buffers.
|
||||
- **Encoder**: rebuilds messages, searches dictionary for matches (linear search), writes params per `param_counts`, respects `max_message_length`.
|
||||
- **Bugs/risks**: heavy global reliance on `offsets`, no ROM bounds checks, dictionary search inline and naive. Port by reimplementing with span/bounds checks and unit tests.
|
||||
|
||||
### Tile/Palette Rendering Math
|
||||
|
||||
Files: `DungeonLogic.c`, `TileMapLogic.c`, `GraphicsLogic.c`
|
||||
|
||||
- Helpers like `fill4x2`, `drawXx3/4`, bitplane copies
|
||||
- Data: tile stride = 64 words per row in buffer; SNES bitplane packing assumed
|
||||
- **Bugs**: `draw3x2` doesn't advance pointers; many helpers assume globals (`dm_rd`, `dm_wr`, `dm_buf`, `dm_l`)
|
||||
- If reusing math, reimplement with explicit buffer sizes and tests
|
||||
|
||||
### Data Tables/Enums Worth Reusing
|
||||
|
||||
- `sprname.dat` (sprite names) - standard format parsed and ported to `src/zelda3/sprite/sprite_names.h` (284 entries, length-prefixed, limit 15 chars)
|
||||
- Enum headers: `DungeonEnum.h`, `OverworldEnum.h`, `HMagicEnum.h`, `TextEnum.h`, `SampleEnum.h`, etc.
|
||||
- UI labels (entrance names, dungeon names) via `HM_TextResource entrance_names`
|
||||
|
||||
### Known Bugs/Behavior to Test Against
|
||||
|
||||
From z3ed.c header:
|
||||
- **Overworld**: editing items/exits/whirlpools can corrupt pointers; "remove all exits" nukes ending white dots and Ganon->Triforce entrance; global grid editing inserts entrances/crashes
|
||||
- **Dungeon**: pointer calc fails with too much data (space issues)
|
||||
- **BG1/BG2**: sprite handling fixed in later epochs; still verify
|
||||
- **Monologue**: storage corruption fixed once; still regression-test text save/load
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Regression Checklist
|
||||
|
||||
Goal: ensure yaze parsers/editors don't reproduce known hmagic bugs.
|
||||
|
||||
### Test Scenarios
|
||||
|
||||
#### 1. Overworld Exits/Items/Whirlpools Pointer Integrity
|
||||
- Edit exits/whirlpools/items, save, reload ROM
|
||||
- Verify ending white dots (credits) and Ganon->Triforce entrance remain intact
|
||||
- Validate pointer tables (no mass repoint to empty room)
|
||||
|
||||
#### 2. "Remove All Overworld Exits" Safety
|
||||
- Invoke bulk-delete; ensure credits dots and special entrances remain
|
||||
- Verify no unintended entrance insertion/crash when editing global grid
|
||||
|
||||
#### 3. Dungeon Room Pointer Overflow
|
||||
- Add room data until near limit
|
||||
- Ensure pointer calc stays valid and refuses to corrupt or overrun
|
||||
- Should emit error instead of silent corruption
|
||||
|
||||
#### 4. BG1/BG2 Sprite Handling
|
||||
- Move BG2 markers (red dots) and confirm BG flag persists across save/reload
|
||||
|
||||
#### 5. Monologue Storage
|
||||
- Round-trip text: decode -> modify -> encode
|
||||
- Ensure no bank overflow, region switch honored, abs terminator respected
|
||||
- Dictionary bounds enforced
|
||||
|
||||
#### 6. Sprite Names
|
||||
- Decode `sprname.dat` standard format (flag=0, LE size, 0x11c length-prefixed entries)
|
||||
- Ensure names load
|
||||
- If alt format (flag!=0) appears, validate 256x9-byte table
|
||||
|
||||
### Implementation Plan
|
||||
|
||||
Add gtest cases using a US ROM fixture (vanilla.sfc):
|
||||
- **Text**: round-trip known messages and synthetic long messages; check max length enforcement
|
||||
- **Sprite names**: decode standard/alt format blobs; compare to reference array
|
||||
- **Pointer safety**: build synthetic overworld/dungeon tables and assert parsers reject OOB offsets
|
||||
|
||||
Add CLI fixtures for bulk operations (remove exits/items) and assert postconditions via serializers.
|
||||
|
||||
---
|
||||
|
||||
## Porting Approach for yaze
|
||||
|
||||
1. Add a `formats/zelda3_offsets.{h,cc}` with a region table (US/EU/JP) + validation (file size, bounds on dictionary/regions/param tables). Expose typed structs matching hmagic but without globals.
|
||||
|
||||
2. **Text**: implement a safe decoder/encoder following hmagic's logic, with tests using a known US ROM fixture; include dictionary search as a reusable function. Add CLI or unit tests to compare round-trip.
|
||||
|
||||
3. **Tile/metatile**: reimplement only the packing math you need; avoid copying `dm_*` globals. Add tests with sample tile data to verify blits.
|
||||
|
||||
4. **Data tables**: convert `sprname.dat` and enums into constexpr arrays/enum classes; include provenance comments.
|
||||
|
||||
5. **Regression checklist**: create a test list based on the "Remaining things Puzzledude claims are borked" to ensure yaze doesn't repeat those bugs.
|
||||
|
||||
---
|
||||
|
||||
## References to Harvest
|
||||
|
||||
- `structs.h` for offsets structs
|
||||
- `z3ed.c::LoadOffsets` for US constants
|
||||
- `TextLogic.c` for monologue decode/encode flow
|
||||
- `DungeonLogic.c` / `TileMapLogic.c` / `GraphicsLogic.c` for tile/bitplane math (reimplement safely)
|
||||
- `sprname.dat` for sprite names
|
||||
- Header comments in `z3ed.c` for bug/regression notes
|
||||
30
docs/internal/research/implot-visualization-ideas.md
Normal file
30
docs/internal/research/implot-visualization-ideas.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# ImPlot Integration and Visualization Ideas
|
||||
|
||||
This repository now ships a thin wrapper for ImPlot under `yaze::gui::plotting`
|
||||
(`src/app/gui/plots/implot_support.*`). The helpers:
|
||||
- Ensure the ImPlot context exists (`EnsureImPlotContext()`).
|
||||
- Apply theme-aware styling (`PlotStyleScope`, `BuildStyleFromTheme`).
|
||||
- Wrap `BeginPlot`/`EndPlot` with RAII (`PlotGuard`).
|
||||
|
||||
Example usage:
|
||||
```c++
|
||||
using namespace yaze::gui::plotting;
|
||||
|
||||
PlotStyleScope plot_style(ThemeManager::Get().GetCurrentTheme());
|
||||
PlotConfig config{.id = "Tile Usage", .flags = ImPlotFlags_NoLegend};
|
||||
PlotGuard plot(config);
|
||||
if (plot) {
|
||||
ImPlot::PlotHistogram("tiles", tile_hist.data(), tile_hist.size());
|
||||
}
|
||||
```
|
||||
|
||||
Candidate ROM-hacking visualizations worth adding:
|
||||
- Tile and palette analytics: histograms of tile IDs per region; stacked bars of palette usage; scatter of tile index vs. frequency to find unused art.
|
||||
- VRAM/CHR timelines: line plots of VRAM writes or DMA burst sizes during playback; overlays comparing two builds to spot regressions.
|
||||
- Memory watch dashboards: line plots of key WRAM variables (health, rupees, mode flags) with markers for room transitions or boss flags.
|
||||
- RNG/logic inspection: scatter of RNG seed vs. outcome (drops, patterns); step plots of RNG state across frames to debug determinism.
|
||||
- Audio/SPC insight: per-channel volume over time; simple spectrum snapshots before/after a music tweak.
|
||||
- Compression/asset diffs: bar charts of bank sizes and free space; plot of LZ chunk sizes to catch anomalies.
|
||||
- Overworld/dungeon tuning: line plots of enemy counts, chest density, or item rarity per region; cumulative difficulty curves across progression.
|
||||
- Performance profiling: stacked bars for frame time breakdowns (render vs. emu vs. scripting); list of slowest frames with hover tooltips describing scene state.
|
||||
- Script/event timelines: Gantt-like plots for cutscene steps or event triggers, with hover showing script IDs and offsets.
|
||||
66
docs/internal/research/zscream_analysis.md
Normal file
66
docs/internal/research/zscream_analysis.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# ZScreamDungeon Codebase Analysis for YAZE Feature Parity
|
||||
|
||||
**Date:** November 22, 2025
|
||||
**Source Codebase:** `ZScreamDungeon` (C#)
|
||||
**Target Project:** `yaze` (C++)
|
||||
|
||||
## 1. Executive Summary
|
||||
The ZScreamDungeon codebase provides a comprehensive roadmap for implementing feature parity in the 'yaze' project. The core architecture revolves around direct manipulation of a byte array containing the game's ROM data. Data is read from the ROM in a structured way, with `Constants.cs` providing the necessary memory addresses.
|
||||
|
||||
The system uses a custom object factory pattern to parse variable-length object streams from the ROM and instantiate specific C# classes for rendering. Graphics are decompressed on startup and cached, then composited into a final image buffer during the room loading process.
|
||||
|
||||
## 2. Core Architecture
|
||||
|
||||
- **ROM Handling:** The entire ROM is loaded into a static `byte[]` array in `ROM.cs`. All reads/writes happen directly on this buffer.
|
||||
- **Address Mapping:** `Constants.cs` serves as the "Rosetta Stone," mapping high-level concepts (headers, sprite pointers, etc.) to physical ROM addresses.
|
||||
- **Room Loading:** Rooms are not contiguous blocks. `Room.cs` orchestrates loading from multiple scattered tables (headers, object data, sprites) based on the room index.
|
||||
|
||||
## 3. Key Data Structures
|
||||
|
||||
### Rooms (`Room.cs`)
|
||||
A room is composed of:
|
||||
- **Header (14 bytes):** Contains palettes, blocksets, effect flags, and collision modes.
|
||||
- **Object Data:** A variable-length stream of bytes. This is **not** a fixed array. It uses a custom packing format where the first byte determines the object type (Type 1, 2, or 3) and subsequent bytes define position and size.
|
||||
- **Sprite Data:** A separate list of sprites, typically 3 bytes per entry (ID, X, Y), loaded via `addSprites()`.
|
||||
|
||||
### Room Objects (`Room_Object.cs`)
|
||||
- Base class for all interactive elements.
|
||||
- **Factory Pattern:** The `loadTilesObjects()` method in `Room.cs` parses the byte stream and calls `addObject()`, which switches on the object ID to instantiate the correct subclass (e.g., `Room_Object_Door`, `Room_Object_Chest`).
|
||||
|
||||
### Graphics (`GFX.cs`)
|
||||
- **Storage:** Graphics are stored compressed in the ROM.
|
||||
- **Decompression:** Uses a custom LZ-style algorithm (`std_nintendo_decompress`).
|
||||
- **Decoding:** Raw bitplanes (2bpp/3bpp) are decoded into a 4bpp format usable by the editor's renderer.
|
||||
|
||||
## 4. Rendering Pipeline
|
||||
|
||||
1. **Initialization:** On startup, all graphics packs are decompressed and decoded into a master `allgfxBitmap`.
|
||||
2. **Room Load:** When entering a room, the specific graphics needed for that room (based on the header) are copied into `currentgfx16Bitmap`.
|
||||
3. **Object Rasterization:**
|
||||
- `Room.cs` iterates through all loaded `Room_Object` instances.
|
||||
- It calls `obj.Draw()`.
|
||||
- Crucially, `Draw()` **does not** render to the screen. It writes tile IDs, palette indices, and flip flags into two 2D arrays: `GFX.tilesBg1Buffer` and `GFX.tilesBg2Buffer` (representing the SNES background layers).
|
||||
4. **Final Composition:**
|
||||
- `GFX.DrawBG1()` and `GFX.DrawBG2()` iterate through the buffers.
|
||||
- They look up the actual pixel data in `currentgfx16Bitmap` based on the tile IDs.
|
||||
- The pixels are written to the final `Bitmap` displayed in the UI.
|
||||
|
||||
## 5. Implementation Recommendations for YAZE
|
||||
|
||||
To achieve feature parity, `yaze` should:
|
||||
|
||||
1. **Replicate the Parsing Logic:** The `loadTilesObjects()` method in `Room.cs` is the critical path. Porting this logic to C++ is essential for correctly interpreting the room object data stream.
|
||||
2. **Port the Decompressor:** The `std_nintendo_decompress` algorithm in `Decompress.cs` must be ported to C++ to read graphics and map data.
|
||||
3. **Adopt the Buffer-Based Rendering:** Instead of trying to render objects directly to a texture, use an intermediate "Tilemap Buffer" (similar to `tilesBg1Buffer`). This accurately simulates the SNES PPU architecture where objects are just collections of tilemap entries.
|
||||
4. **Constants Mirroring:** Create a C++ header that mirrors `Constants.cs`. Do not try to derive these addresses algorithmically; the hardcoded values are necessary for compatibility.
|
||||
|
||||
## 6. Key File References
|
||||
|
||||
| File Path (Relative to ZScreamDungeon) | Key Responsibility | Important Symbols |
|
||||
| :--- | :--- | :--- |
|
||||
| `ZeldaFullEditor/ROM.cs` | Raw ROM access | `ROM.DATA`, `ReadByte`, `WriteByte` |
|
||||
| `ZeldaFullEditor/Constants.cs` | Address definitions | `room_header_pointer`, `room_object_pointer` |
|
||||
| `ZeldaFullEditor/Rooms/Room.cs` | Room parsing & orchestration | `loadTilesObjects()`, `addSprites()`, `addObject()` |
|
||||
| `ZeldaFullEditor/Rooms/Room_Object.cs` | Object base class | `Draw()`, `draw_tile()` |
|
||||
| `ZeldaFullEditor/GFX.cs` | Graphics pipeline | `CreateAllGfxData()`, `DrawBG1()`, `tilesBg1Buffer` |
|
||||
| `ZeldaFullEditor/ZCompressLibrary/Decompress.cs` | Data decompression | `std_nintendo_decompress()` |
|
||||
Reference in New Issue
Block a user