backend-infra-engineer: Post v0.3.9-hotfix7 snapshot (build cleanup)
This commit is contained in:
@@ -0,0 +1,687 @@
|
||||
### WASM Debugging Guide: Dungeon Editor
|
||||
|
||||
**Status:** Current (November 2025)
|
||||
**Last Updated:** 2025-11-25
|
||||
**Version:** 2.3.0
|
||||
|
||||
The WASM build includes a powerful, hidden "Debug Inspector" that bypasses the need for GDB/LLDB by exposing C++ state directly to the browser console.
|
||||
|
||||
**Cross-Reference:** For comprehensive debug API reference, see `wasm-debug-infrastructure.md` and `wasm-yazeDebug-api-reference.md`.
|
||||
|
||||
#### 1. The "God Mode" Console Inspector
|
||||
The file `src/web/yaze_debug_inspector.cc` binds C++ functions to the global `Module` object. You can invoke these directly from Chrome/Firefox DevTools.
|
||||
|
||||
**Status & State:**
|
||||
* `Module.getEmulatorStatus()`: Returns JSON with CPU registers (A, X, Y, PC), Flags, and PPU state.
|
||||
* `Module.getFullDebugState()`: Returns a massive JSON dump suitable for pasting into an AI prompt for analysis.
|
||||
* `Module.getArenaStatus()`: Checks the memory arena used for dungeon rendering (vital for "out of memory" rendering glitches).
|
||||
|
||||
**Memory Inspection:**
|
||||
* `Module.readEmulatorMemory(addr, length)`: Reads WRAM/SRAM.
|
||||
* *Example:* Check Link's X-Coordinate ($20): `Module.readEmulatorMemory(0x7E0020, 2)`
|
||||
* `Module.readRom(addr, length)`: Verifies if your ROM patch actually applied in memory.
|
||||
|
||||
**Graphics & Palette:**
|
||||
* `Module.getDungeonPaletteEvents()`: Returns a log of recent palette uploads. Use this if colors look wrong or "flashy" in the editor.
|
||||
|
||||
#### 2. The Command Line Bridge
|
||||
The terminal you see in the web app isn't just a UI toy; it's a direct bridge to the C++ backend.
|
||||
|
||||
* **Architecture**: `src/web/terminal.js` captures your keystrokes and calls `Module.ccall('Z3edProcessCommand', ...)` which routes to `src/cli/wasm_terminal_bridge.cc`.
|
||||
* **Debug Tip**: If the editor UI freezes, the terminal often remains responsive (running on a separate event cadence). You can use it to:
|
||||
1. Save your work: `save`
|
||||
2. Dump state: (If a custom command exists)
|
||||
3. Reset the emulator.
|
||||
|
||||
#### 3. The Hidden "Debug Controls" Card
|
||||
The code in `src/app/editor/dungeon/dungeon_editor_v2.cc` contains a function `DrawDebugControlsCard()`, controlled by the boolean `show_debug_controls_`.
|
||||
|
||||
* **Current Status**: This is currently **hidden** by default and likely has no UI toggle in the public build.
|
||||
* **Recommended Task**: Create a `z3ed` CLI command to toggle this boolean.
|
||||
* *Implementation*: Add a command `editor debug toggle` in `wasm_terminal_bridge.cc` that finds the active `DungeonEditorV2` instance and flips `show_debug_controls_ = !show_debug_controls_`. This would give you on-screen access to render passes and layer toggles.
|
||||
|
||||
#### 4. Feature Parity
|
||||
There are **NO** `__EMSCRIPTEN__` checks inside the `src/app/editor/dungeon/` logic.
|
||||
* **Implication**: If a logic bug exists in WASM, it likely exists in the Native macOS/Linux build too. Reproduce bugs on Desktop first for easier debugging (breakpoints, etc.), then verify the fix on Web.
|
||||
* **Exception**: Rendering glitches are likely WASM-specific due to the single-threaded `TickFrame` loop vs. the multi-threaded desktop renderer.
|
||||
|
||||
#### 5. Thread Pool Configuration
|
||||
The WASM build uses a fixed thread pool (`PTHREAD_POOL_SIZE=8` in CMakePresets.json).
|
||||
* **Warning Signs**: If you see "Tried to spawn a new thread, but the thread pool is exhausted", heavy parallel operations are exceeding the pool size.
|
||||
* **Fix**: Increase `PTHREAD_POOL_SIZE` in CMakePresets.json and rebuild with `--clean`
|
||||
* **Root Cause**: Often happens during ROM loading when multiple graphics sheets are decompressed in parallel.
|
||||
|
||||
#### 6. Memory Configuration
|
||||
The WASM build uses optimized memory settings to reduce heap resize operations:
|
||||
|
||||
| Setting | Value | Purpose |
|
||||
|---------|-------|---------|
|
||||
| `INITIAL_MEMORY` | 256MB | Reduces heap resizing during ROM load |
|
||||
| `MAXIMUM_MEMORY` | 1GB | Prevents runaway allocations |
|
||||
| `STACK_SIZE` | 8MB | Handles recursive asset decompression |
|
||||
|
||||
* **Warning Signs**: Console shows `_emscripten_resize_heap` calls during loading
|
||||
* **Common Causes**: Overworld map loading (~160MB for 160 maps), sprite preview buffers, dungeon object emulator
|
||||
* **Optimization Applied**: Lazy initialization for SNES emulator instances and sprite preview buffers
|
||||
|
||||
#### 7. ROM Loading Progress
|
||||
The C++ `WasmLoadingManager` controls loading progress display. Monitor loading status:
|
||||
|
||||
```javascript
|
||||
// Check if ROM is loaded
|
||||
window.yaze.control.getRomStatus()
|
||||
// Returns: { loaded: true/false, filename: "...", title: "...", size: ... }
|
||||
|
||||
// Check arena (graphics) status
|
||||
window.yazeDebug.arena.getStatus()
|
||||
|
||||
// Full editor state after loading
|
||||
window.yaze.editor.getSnapshot()
|
||||
```
|
||||
|
||||
**Loading Progress Stages:**
|
||||
| Progress | Stage |
|
||||
|----------|-------|
|
||||
| 10% | Initializing editors... |
|
||||
| 18% | Loading graphics sheets... |
|
||||
| 26% | Loading overworld... |
|
||||
| 34% | Loading dungeons... |
|
||||
| 42%+ | Loading remaining editors... |
|
||||
| 100% | Complete |
|
||||
|
||||
#### 8. Prompting AI Agents (Claude Code / Gemini Antigravity)
|
||||
|
||||
This section provides precise prompts and workflows for AI agents to interact with the YAZE WASM app.
|
||||
|
||||
##### Step 1: Verify the App is Ready
|
||||
|
||||
Before any operations, the AI must confirm the WASM module is initialized:
|
||||
|
||||
```javascript
|
||||
// Check module ready state
|
||||
window.YAZE_MODULE_READY // Should be true
|
||||
|
||||
// Check if APIs are available
|
||||
typeof window.yaze !== 'undefined' &&
|
||||
typeof window.yaze.control !== 'undefined' // Should be true
|
||||
```
|
||||
|
||||
**If not ready**, wait and retry:
|
||||
```javascript
|
||||
// Poll until ready (max 10 seconds)
|
||||
async function waitForYaze() {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
if (window.YAZE_MODULE_READY && window.yaze?.control) return true;
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
await waitForYaze();
|
||||
```
|
||||
|
||||
##### Step 2: Load a ROM File
|
||||
|
||||
**Option A: User Drag-and-Drop (Recommended)**
|
||||
Prompt the user: *"Please drag and drop your Zelda 3 ROM (.sfc or .smc) onto the canvas."*
|
||||
|
||||
Then verify:
|
||||
```javascript
|
||||
// Check if ROM loaded successfully
|
||||
const status = window.yaze.control.getRomStatus();
|
||||
console.log(status);
|
||||
// Expected: { loaded: true, filename: "zelda3.sfc", title: "...", size: 1048576 }
|
||||
```
|
||||
|
||||
**Option B: Check if ROM Already Loaded**
|
||||
```javascript
|
||||
window.yaze.control.getRomStatus().loaded // true if ROM is present
|
||||
```
|
||||
|
||||
**Option C: Load from IndexedDB (if previously saved)**
|
||||
```javascript
|
||||
// List saved ROMs
|
||||
FilesystemManager.listSavedRoms && FilesystemManager.listSavedRoms();
|
||||
```
|
||||
|
||||
##### Step 3: Open the Dungeon Editor
|
||||
|
||||
```javascript
|
||||
// Switch to dungeon editor
|
||||
window.yaze.control.switchEditor('Dungeon');
|
||||
|
||||
// Verify switch was successful
|
||||
const snapshot = window.yaze.editor.getSnapshot();
|
||||
console.log(snapshot.editor_type); // Should be "Dungeon"
|
||||
```
|
||||
|
||||
##### Step 4: Navigate to a Specific Room
|
||||
|
||||
```javascript
|
||||
// Get current room info
|
||||
window.yaze.editor.getCurrentRoom();
|
||||
// Returns: { room_id: 0, active_rooms: [...], visible_cards: [...] }
|
||||
|
||||
// Navigate to room 42 (Hyrule Castle Entrance)
|
||||
window.aiTools.navigateTo('room:42');
|
||||
|
||||
// Or use control API
|
||||
window.yaze.control.openCard('Room 42');
|
||||
```
|
||||
|
||||
##### Step 5: Inspect Room Data
|
||||
|
||||
```javascript
|
||||
// Get room properties
|
||||
const props = window.yaze.data.getRoomProperties(42);
|
||||
console.log(props);
|
||||
// Returns: { music: 5, palette: 2, tileset: 7, ... }
|
||||
|
||||
// Get room objects (chests, torches, blocks, etc.)
|
||||
const objects = window.yaze.data.getRoomObjects(42);
|
||||
console.log(objects);
|
||||
|
||||
// Get room tile data
|
||||
const tiles = window.yaze.data.getRoomTiles(42);
|
||||
console.log(tiles.layer1, tiles.layer2);
|
||||
```
|
||||
|
||||
##### Example AI Prompt Workflow
|
||||
|
||||
**User asks:** "Show me the objects in room 42 of the dungeon editor"
|
||||
|
||||
**AI should execute:**
|
||||
```javascript
|
||||
// 1. Verify ready
|
||||
if (!window.YAZE_MODULE_READY) throw new Error("WASM not ready");
|
||||
|
||||
// 2. Check ROM
|
||||
const rom = window.yaze.control.getRomStatus();
|
||||
if (!rom.loaded) throw new Error("No ROM loaded - please drag a ROM file onto the canvas");
|
||||
|
||||
// 3. Switch to dungeon editor
|
||||
window.yaze.control.switchEditor('Dungeon');
|
||||
|
||||
// 4. Navigate to room
|
||||
window.aiTools.navigateTo('room:42');
|
||||
|
||||
// 5. Get and display data
|
||||
const objects = window.yaze.data.getRoomObjects(42);
|
||||
console.log("Room 42 Objects:", JSON.stringify(objects, null, 2));
|
||||
```
|
||||
|
||||
#### 9. JavaScript Tips for Browser Debugging
|
||||
|
||||
##### Console Shortcuts
|
||||
|
||||
```javascript
|
||||
// Alias for quick access
|
||||
const y = window.yaze;
|
||||
const yd = window.yazeDebug;
|
||||
|
||||
// Quick status check
|
||||
y.control.getRomStatus()
|
||||
y.editor.getSnapshot()
|
||||
yd.arena.getStatus()
|
||||
```
|
||||
|
||||
##### Error Handling Pattern
|
||||
|
||||
Always wrap API calls in try-catch when automating:
|
||||
```javascript
|
||||
function safeCall(fn, fallback = null) {
|
||||
try {
|
||||
return fn();
|
||||
} catch (e) {
|
||||
console.error('[YAZE API Error]', e.message);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
const status = safeCall(() => window.yaze.control.getRomStatus(), { loaded: false });
|
||||
```
|
||||
|
||||
##### Async Operations
|
||||
|
||||
Some operations are async. Use proper await patterns:
|
||||
```javascript
|
||||
// Wait for element to appear in GUI
|
||||
await window.yaze.gui.waitForElement('dungeon-room-canvas', 5000);
|
||||
|
||||
// Then interact
|
||||
window.yaze.gui.click('dungeon-room-canvas');
|
||||
```
|
||||
|
||||
##### Debugging State Issues
|
||||
|
||||
```javascript
|
||||
// Full state dump for debugging
|
||||
const debugState = {
|
||||
moduleReady: window.YAZE_MODULE_READY,
|
||||
romStatus: window.yaze?.control?.getRomStatus?.() || 'API unavailable',
|
||||
editorSnapshot: window.yaze?.editor?.getSnapshot?.() || 'API unavailable',
|
||||
arenaStatus: window.yazeDebug?.arena?.getStatus?.() || 'API unavailable',
|
||||
consoleErrors: window._yazeConsoleLogs?.filter(l => l.includes('[ERROR]')) || []
|
||||
};
|
||||
console.log(JSON.stringify(debugState, null, 2));
|
||||
```
|
||||
|
||||
##### Monitoring Loading Progress
|
||||
|
||||
```javascript
|
||||
// Set up a loading progress monitor
|
||||
let lastProgress = 0;
|
||||
const progressInterval = setInterval(() => {
|
||||
const status = window.yaze?.control?.getRomStatus?.();
|
||||
if (status?.loaded) {
|
||||
console.log('ROM loaded successfully!');
|
||||
clearInterval(progressInterval);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// Clear after 30 seconds timeout
|
||||
setTimeout(() => clearInterval(progressInterval), 30000);
|
||||
```
|
||||
|
||||
##### Inspecting Graphics Issues
|
||||
|
||||
```javascript
|
||||
// Check if graphics sheets are loaded
|
||||
const arenaStatus = window.yazeDebug.arena.getStatus();
|
||||
console.log('Loaded sheets:', arenaStatus.loaded_sheets);
|
||||
console.log('Pending textures:', arenaStatus.pending_textures);
|
||||
|
||||
// Check for palette issues
|
||||
const paletteEvents = Module.getDungeonPaletteEvents?.() || 'Not available';
|
||||
console.log('Recent palette changes:', paletteEvents);
|
||||
```
|
||||
|
||||
##### Memory Usage Check
|
||||
|
||||
```javascript
|
||||
// Check WASM memory usage
|
||||
const memInfo = {
|
||||
heapSize: Module.HEAPU8?.length || 0,
|
||||
heapSizeMB: ((Module.HEAPU8?.length || 0) / 1024 / 1024).toFixed(2) + ' MB'
|
||||
};
|
||||
console.log('Memory:', memInfo);
|
||||
```
|
||||
|
||||
#### 10. Gemini Antigravity AI Tools
|
||||
|
||||
For AI assistants using the Antigravity browser extension, use the high-level `window.aiTools` API:
|
||||
|
||||
##### Complete Workflow Example
|
||||
|
||||
```javascript
|
||||
// Step-by-step for Gemini/Antigravity
|
||||
async function inspectDungeonRoom(roomId) {
|
||||
// 1. Verify environment
|
||||
if (!window.YAZE_MODULE_READY) {
|
||||
return { error: "WASM module not ready. Please wait for initialization." };
|
||||
}
|
||||
|
||||
// 2. Check ROM
|
||||
const romStatus = window.yaze.control.getRomStatus();
|
||||
if (!romStatus.loaded) {
|
||||
return { error: "No ROM loaded. Please drag a Zelda 3 ROM onto the canvas." };
|
||||
}
|
||||
|
||||
// 3. Switch to dungeon editor
|
||||
window.yaze.control.switchEditor('Dungeon');
|
||||
|
||||
// 4. Navigate to room
|
||||
window.aiTools.navigateTo(`room:${roomId}`);
|
||||
|
||||
// 5. Gather all data
|
||||
return {
|
||||
room_id: roomId,
|
||||
properties: window.yaze.data.getRoomProperties(roomId),
|
||||
objects: window.yaze.data.getRoomObjects(roomId),
|
||||
tiles: window.yaze.data.getRoomTiles(roomId),
|
||||
editor_state: window.yaze.editor.getCurrentRoom()
|
||||
};
|
||||
}
|
||||
|
||||
// Usage
|
||||
const data = await inspectDungeonRoom(42);
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
```
|
||||
|
||||
##### Quick Reference Commands
|
||||
|
||||
```javascript
|
||||
// Get full application state with console output
|
||||
window.aiTools.getAppState()
|
||||
|
||||
// Get dungeon room data
|
||||
window.aiTools.getRoomData(0)
|
||||
|
||||
// Navigate directly to a room
|
||||
window.aiTools.navigateTo('room:42')
|
||||
|
||||
// Show/hide editor cards
|
||||
window.aiTools.showCard('Room Selector')
|
||||
window.aiTools.hideCard('Object Editor')
|
||||
|
||||
// Get complete API reference
|
||||
window.aiTools.dumpAPIReference()
|
||||
|
||||
// AI-formatted state (paste-ready for prompts)
|
||||
window.yazeDebug.formatForAI()
|
||||
```
|
||||
|
||||
##### Handling Common Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `window.yaze is undefined` | Module not initialized | Wait for `YAZE_MODULE_READY` |
|
||||
| `getRomStatus().loaded = false` | No ROM file | Prompt user to drag ROM |
|
||||
| `switchEditor returns error` | Invalid editor name | Use: Dungeon, Overworld, Graphics, Palette, Sprite, Music |
|
||||
| `getRoomObjects returns empty` | Room not loaded | Navigate to room first |
|
||||
| `Canvas shows black` | Graphics not loaded | Check `yazeDebug.arena.getStatus()` |
|
||||
|
||||
**Nav Bar Access:**
|
||||
The web UI includes dedicated dropdown menus:
|
||||
- **Editor** - Quick switch to any editor
|
||||
- **Emulator** - Run/Pause/Step/Reset controls
|
||||
- **Layouts** - Preset card configurations
|
||||
- **AI Tools** - All `window.aiTools` functions via UI clicks
|
||||
|
||||
**Command Palette (Ctrl+K):**
|
||||
Search for "AI:" to access all AI helper commands.
|
||||
|
||||
#### 11. Copying Data for External Analysis
|
||||
|
||||
```javascript
|
||||
// Copy room data to clipboard for pasting elsewhere
|
||||
async function copyRoomDataToClipboard(roomId) {
|
||||
const data = {
|
||||
timestamp: new Date().toISOString(),
|
||||
room_id: roomId,
|
||||
properties: window.yaze.data.getRoomProperties(roomId),
|
||||
objects: window.yaze.data.getRoomObjects(roomId)
|
||||
};
|
||||
await navigator.clipboard.writeText(JSON.stringify(data, null, 2));
|
||||
console.log(`Room ${roomId} data copied to clipboard!`);
|
||||
}
|
||||
|
||||
// Usage
|
||||
copyRoomDataToClipboard(42);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 12. Antigravity: Debugging Dungeon Object Rendering Issues
|
||||
|
||||
This section provides Gemini Antigravity with specific workflows for identifying and analyzing dungeon object rendering problems, particularly discrepancies between the **Room Graphics Card** (background tiles) and the **Object Editor Card** (dungeon objects like pots, torches, chests).
|
||||
|
||||
##### Understanding the Rendering Pipeline
|
||||
|
||||
Dungeon rooms have two distinct rendering layers:
|
||||
|
||||
| Card | What It Shows | Render Source |
|
||||
|------|--------------|---------------|
|
||||
| **Room Graphics** | Background tiles (floors, walls, pits) | Layer1/Layer2 tile data |
|
||||
| **Object Editor** | Interactive objects (pots, chests, blocks, torches) | Object list with sprite-based rendering |
|
||||
|
||||
**Common Issue:** Objects appear at wrong positions, wrong sprites, or don't match their expected appearance in the Object Editor compared to how they should look based on the room data.
|
||||
|
||||
##### Step-by-Step Debugging Workflow
|
||||
|
||||
###### 1. Capture the Current Visual State
|
||||
|
||||
Use the browser's screenshot capability to capture what you see:
|
||||
|
||||
```javascript
|
||||
// Capture the entire canvas as a data URL
|
||||
async function captureCanvasScreenshot() {
|
||||
const canvas = document.getElementById('canvas');
|
||||
if (!canvas) return { error: 'Canvas not found' };
|
||||
|
||||
const dataUrl = canvas.toDataURL('image/png');
|
||||
console.log('[Screenshot] Canvas captured, length:', dataUrl.length);
|
||||
|
||||
// For AI analysis, you can copy to clipboard
|
||||
await navigator.clipboard.writeText(dataUrl);
|
||||
return { success: true, message: 'Screenshot copied to clipboard as data URL' };
|
||||
}
|
||||
|
||||
// Usage
|
||||
await captureCanvasScreenshot();
|
||||
```
|
||||
|
||||
**For Antigravity:** Take screenshots when:
|
||||
1. Room Graphics Card is visible (shows background)
|
||||
2. Object Editor Card is visible (shows objects overlaid)
|
||||
3. Both cards side-by-side if possible
|
||||
|
||||
###### 2. Extract Room Object Data Efficiently
|
||||
|
||||
```javascript
|
||||
// Get complete object rendering data for a room
|
||||
function getDungeonObjectDebugData(roomId) {
|
||||
const data = {
|
||||
room_id: roomId,
|
||||
timestamp: Date.now(),
|
||||
|
||||
// Room properties affecting rendering
|
||||
properties: window.yaze.data.getRoomProperties(roomId),
|
||||
|
||||
// All objects in the room with positions
|
||||
objects: window.yaze.data.getRoomObjects(roomId),
|
||||
|
||||
// Current editor state
|
||||
editor_state: window.yaze.editor.getCurrentRoom(),
|
||||
|
||||
// Graphics arena status (textures loaded?)
|
||||
arena_status: window.yazeDebug?.arena?.getStatus() || 'unavailable',
|
||||
|
||||
// Visible cards (what's being rendered)
|
||||
visible_cards: window.yaze.editor.getSnapshot()?.visible_cards || []
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Pretty print for analysis
|
||||
const debugData = getDungeonObjectDebugData(42);
|
||||
console.log(JSON.stringify(debugData, null, 2));
|
||||
```
|
||||
|
||||
###### 3. Compare Object Positions vs Tile Positions
|
||||
|
||||
```javascript
|
||||
// Check if objects are aligned with the tile grid
|
||||
function analyzeObjectPlacement(roomId) {
|
||||
const objects = window.yaze.data.getRoomObjects(roomId);
|
||||
const tiles = window.yaze.data.getRoomTiles(roomId);
|
||||
|
||||
const analysis = objects.map(obj => {
|
||||
// Objects use pixel coordinates, tiles are 8x8 or 16x16
|
||||
const tileX = Math.floor(obj.x / 8);
|
||||
const tileY = Math.floor(obj.y / 8);
|
||||
|
||||
return {
|
||||
object_id: obj.id,
|
||||
type: obj.type,
|
||||
pixel_pos: { x: obj.x, y: obj.y },
|
||||
tile_pos: { x: tileX, y: tileY },
|
||||
// Check if position is on grid boundary
|
||||
aligned_8px: (obj.x % 8 === 0) && (obj.y % 8 === 0),
|
||||
aligned_16px: (obj.x % 16 === 0) && (obj.y % 16 === 0)
|
||||
};
|
||||
});
|
||||
|
||||
return analysis;
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(analyzeObjectPlacement(42), null, 2));
|
||||
```
|
||||
|
||||
###### 4. Identify Visual Discrepancies
|
||||
|
||||
**Symptoms to look for:**
|
||||
|
||||
| Symptom | Likely Cause | Debug Command |
|
||||
|---------|-------------|---------------|
|
||||
| Objects invisible | Texture not loaded | `window.yazeDebug.arena.getStatus()` |
|
||||
| Wrong sprite shown | Object type mismatch | `window.yaze.data.getRoomObjects(roomId)` |
|
||||
| Position offset | Coordinate transform bug | Compare pixel_pos in data vs visual |
|
||||
| Colors wrong | Palette not applied | `Module.getDungeonPaletteEvents()` |
|
||||
| Flickering | Z-order/layer issue | Check `layer` property in object data |
|
||||
|
||||
###### 5. DOM Inspection for Card State
|
||||
|
||||
Efficiently query the DOM to understand what's being rendered:
|
||||
|
||||
```javascript
|
||||
// Get all visible ImGui windows (cards)
|
||||
function getVisibleCards() {
|
||||
// ImGui renders to canvas, but card state is tracked in JS
|
||||
const snapshot = window.yaze.editor.getSnapshot();
|
||||
return {
|
||||
active_cards: snapshot.visible_cards || [],
|
||||
editor_type: snapshot.editor_type,
|
||||
// Check if specific cards are open
|
||||
has_room_selector: snapshot.visible_cards?.includes('Room Selector'),
|
||||
has_object_editor: snapshot.visible_cards?.includes('Object Editor'),
|
||||
has_room_canvas: snapshot.visible_cards?.includes('Room Canvas')
|
||||
};
|
||||
}
|
||||
|
||||
console.log(getVisibleCards());
|
||||
```
|
||||
|
||||
###### 6. Full Diagnostic Dump for AI Analysis
|
||||
|
||||
```javascript
|
||||
// Complete diagnostic for Antigravity to analyze rendering issues
|
||||
async function generateRenderingDiagnostic(roomId) {
|
||||
const diagnostic = {
|
||||
timestamp: new Date().toISOString(),
|
||||
room_id: roomId,
|
||||
|
||||
// Visual state
|
||||
visible_cards: getVisibleCards(),
|
||||
|
||||
// Data state
|
||||
room_properties: window.yaze.data.getRoomProperties(roomId),
|
||||
room_objects: window.yaze.data.getRoomObjects(roomId),
|
||||
object_analysis: analyzeObjectPlacement(roomId),
|
||||
|
||||
// Graphics state
|
||||
arena: window.yazeDebug?.arena?.getStatus(),
|
||||
palette_events: (() => {
|
||||
try { return Module.getDungeonPaletteEvents(); }
|
||||
catch { return 'unavailable'; }
|
||||
})(),
|
||||
|
||||
// Memory state
|
||||
heap_mb: ((Module.HEAPU8?.length || 0) / 1024 / 1024).toFixed(2),
|
||||
|
||||
// Console errors (last 10)
|
||||
recent_errors: window._yazeConsoleLogs?.slice(-10) || []
|
||||
};
|
||||
|
||||
// Copy to clipboard for easy pasting
|
||||
const json = JSON.stringify(diagnostic, null, 2);
|
||||
await navigator.clipboard.writeText(json);
|
||||
console.log('[Diagnostic] Copied to clipboard');
|
||||
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
// Usage: Run this, then paste into your AI prompt
|
||||
await generateRenderingDiagnostic(42);
|
||||
```
|
||||
|
||||
##### Common Object Rendering Bugs
|
||||
|
||||
###### Bug: Objects Render at (0,0)
|
||||
|
||||
**Diagnosis:**
|
||||
```javascript
|
||||
// Check for objects with zero coordinates
|
||||
const objects = window.yaze.data.getRoomObjects(roomId);
|
||||
const atOrigin = objects.filter(o => o.x === 0 && o.y === 0);
|
||||
console.log('Objects at origin:', atOrigin);
|
||||
```
|
||||
|
||||
**Cause:** Object position data not loaded or coordinate transformation failed.
|
||||
|
||||
###### Bug: Sprite Shows as Black Square
|
||||
|
||||
**Diagnosis:**
|
||||
```javascript
|
||||
// Check if graphics sheet is loaded for object type
|
||||
const arena = window.yazeDebug.arena.getStatus();
|
||||
console.log('Loaded sheets:', arena.loaded_sheets);
|
||||
console.log('Pending textures:', arena.pending_textures);
|
||||
```
|
||||
|
||||
**Cause:** Texture not yet loaded from deferred queue. Force process:
|
||||
```javascript
|
||||
// Wait for textures to load
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
```
|
||||
|
||||
###### Bug: Object in Wrong Location vs Room Graphics
|
||||
|
||||
**Diagnosis:**
|
||||
```javascript
|
||||
// Compare layer1 tile at object position
|
||||
const obj = window.yaze.data.getRoomObjects(roomId)[0];
|
||||
const tiles = window.yaze.data.getRoomTiles(roomId);
|
||||
const tileAtPos = tiles.layer1[Math.floor(obj.y / 8) * 64 + Math.floor(obj.x / 8)];
|
||||
console.log('Object at:', obj.x, obj.y);
|
||||
console.log('Tile at that position:', tileAtPos);
|
||||
```
|
||||
|
||||
##### Screenshot Comparison Workflow
|
||||
|
||||
For visual debugging, use this workflow:
|
||||
|
||||
1. **Open Room Graphics Card only:**
|
||||
```javascript
|
||||
window.aiTools.hideCard('Object Editor');
|
||||
window.aiTools.showCard('Room Canvas');
|
||||
// Take screenshot #1
|
||||
```
|
||||
|
||||
2. **Enable Object Editor overlay:**
|
||||
```javascript
|
||||
window.aiTools.showCard('Object Editor');
|
||||
// Take screenshot #2
|
||||
```
|
||||
|
||||
3. **Compare:** Objects should align with the room's floor/wall tiles. Misalignment indicates a coordinate bug.
|
||||
|
||||
##### Reporting Issues
|
||||
|
||||
When reporting dungeon rendering bugs, include:
|
||||
|
||||
```javascript
|
||||
// Generate a complete bug report
|
||||
async function generateBugReport(roomId, description) {
|
||||
const report = {
|
||||
bug_description: description,
|
||||
room_id: roomId,
|
||||
diagnostic: await generateRenderingDiagnostic(roomId),
|
||||
steps_to_reproduce: [
|
||||
'1. Load ROM',
|
||||
'2. Open Dungeon Editor',
|
||||
`3. Navigate to Room ${roomId}`,
|
||||
'4. Observe [specific issue]'
|
||||
],
|
||||
expected_behavior: 'Objects should render at correct positions matching tile grid',
|
||||
actual_behavior: description
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(report, null, 2));
|
||||
return report;
|
||||
}
|
||||
|
||||
// Usage
|
||||
await generateBugReport(42, 'Chest renders 8 pixels too far right');
|
||||
```
|
||||
Reference in New Issue
Block a user