Files
yaze/docs/internal/agents/archive/gemini-sessions/gemini-v040-session.md

385 lines
13 KiB
Markdown

# Gemini 3 Pro - v0.4.0 Development Session
## Context
You are working on **YAZE** (Yet Another Zelda3 Editor), a C++23 cross-platform ROM editor for The Legend of Zelda: A Link to the Past.
**Current Situation:**
- **v0.3.9**: CI/CD hotfix running (another agent handling - DO NOT TOUCH)
- **v0.4.0**: Your focus - "Editor Stability & OOS Support"
- **Goal**: Unblock Oracle of Secrets (OOS) ROM hack development
---
## Quick Start
```bash
# Use dedicated build directory (DO NOT use build/ or build_agent/)
cmake --preset mac-dbg -B build_gemini
cmake --build build_gemini -j8 --target yaze
# Run stable tests
ctest --test-dir build_gemini -L stable -j4 --output-on-failure
```
---
## Completed Work
### Priority 2: Message Editor - Expanded BIN Export [COMPLETE]
**Completed by Gemini 3 Pro:**
1. **JSON Export Implementation** (`message_data.h/cc`):
- Added `SerializeMessagesToJson()` - Converts `MessageData` vector to JSON array
- Added `ExportMessagesToJson()` - Writes JSON file with error handling
- Uses nlohmann/json library with 2-space pretty printing
2. **File Dialog Integration** (`message_editor.cc:317-376`):
- "Load Expanded Message" - Opens file dialog to load BIN
- "Save Expanded Messages" - Saves to remembered path
- "Save As..." - Prompts for new path
- "Export to JSON" - JSON export with file dialog
3. **Path Persistence**:
- `expanded_message_path_` member stores last used path
- Reuses path for subsequent saves
4. **SaveExpandedMessages() Implementation** (`message_editor.cc:521-571`):
- Uses `expanded_message_bin_` member for ROM-like storage
- Handles buffer expansion for new messages
- Writes terminator byte (0xFF) after data
### Priority 1: Dungeon Editor - SaveDungeon() [IN PROGRESS]
**Completed by Gemini 3 Pro:**
1. **SaveDungeon() Implementation** (`dungeon_editor_system.cc:44-59`):
- No longer a stub! Loops through all 296 rooms
- Calls `SaveRoomData()` for each room
- Tracks dirty state and last save time
2. **SaveObjects() Implementation** (`room.cc:873-925`):
- Properly calculates available space via `CalculateRoomSize()`
- Validates encoded size fits before writing
- Returns `OutOfRangeError` if data too large
3. **SaveSprites() Implementation** (`room.cc:927-999`):
- Calculates sprite space from pointer table
- Handles sortsprites byte
- Returns `OutOfRangeError` if data too large
4. **New Tests** (`test/unit/zelda3/dungeon/dungeon_save_test.cc`):
- `SaveObjects_FitsInSpace` - verifies normal save works
- `SaveObjects_TooLarge` - verifies overflow detection
- `SaveSprites_FitsInSpace` - verifies normal save works
- `SaveSprites_TooLarge` - verifies overflow detection
**Tests Pass:**
```bash
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="*DungeonSave*"
# [ PASSED ] 4 tests.
```
---
## Testing Instructions
### Build and Run Tests
```bash
# Build test target (uses existing build_gemini)
cmake --build build_gemini --target yaze_test_stable -j8
# Run ALL stable tests
./build_gemini/bin/Debug/yaze_test_stable
# Run specific test pattern
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="*DungeonSave*"
# Run dungeon-related tests
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="*Dungeon*"
# Run with verbose output
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="*YourTest*" --gtest_print_time=1
```
### Known Test Issues (Pre-existing)
**FAILING:** `RoomObjectEncodingTest.DetermineObjectTypeType2`
- Location: `test/unit/zelda3/dungeon/room_object_encoding_test.cc:29-31`
- Issue: `DetermineObjectType()` returns 1 instead of 2 for bytes 0xFC, 0xFD, 0xFF
- Status: Pre-existing failure, NOT caused by your changes
- Action: Ignore unless you're specifically working on object type detection
### Test File Locations
| Test Type | Location | Filter Pattern |
|-----------|----------|----------------|
| Dungeon Save | `test/unit/zelda3/dungeon/dungeon_save_test.cc` | `*DungeonSave*` |
| Room Encoding | `test/unit/zelda3/dungeon/room_object_encoding_test.cc` | `*RoomObjectEncoding*` |
| Room Manipulation | `test/unit/zelda3/dungeon/room_manipulation_test.cc` | `*RoomManipulation*` |
| Dungeon Integration | `test/integration/dungeon_editor_test.cc` | `*DungeonEditorIntegration*` |
| Overworld | `test/unit/zelda3/overworld_test.cc` | `*Overworld*` |
---
## Your Priorities (Pick One)
### Priority 1: Dungeon Editor - Save Infrastructure [COMPLETE] ✅
**Completed by Gemini 3 Pro:**
1. **SaveRoomData() Implementation** (`dungeon_editor_system.cc:914-973`):
- ✅ Detects if room is currently being edited in UI
- ✅ Uses editor's in-memory `Room` object (contains unsaved changes)
- ✅ Syncs sprites from `DungeonEditorSystem` to `Room` before saving
- ✅ Selectively saves objects only for current room (optimization)
2. **UI Integration** (`dungeon_editor_v2.cc:244-291`):
-`Save()` method calls `SaveDungeon()` correctly
- ✅ Palette saving via `PaletteManager`
- ✅ Room objects saved via `Room::SaveObjects()`
- ✅ Sprites saved via `DungeonEditorSystem::SaveRoom()`
3. **Edge Cases Verified:**
- ✅ Current room with unsaved changes
- ✅ Non-current rooms (sprite-only save)
- ✅ Multiple rooms open in tabs
- ✅ Empty sprite lists
**Audit Report:** `zscow_audit_report.md` (artifact)
**Minor Improvements Recommended:**
- Add integration tests for `DungeonEditorSystem` save flow
- Remove redundant `SaveObjects()` call in `DungeonEditorV2::Save()`
- Document stub methods
**Test your changes:**
```bash
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="*DungeonSave*:*RoomManipulation*"
```
---
### Priority 3: ZSCOW Audit [COMPLETE] ✅
**Completed by Gemini 3 Pro:**
#### 1. Version Detection - VERIFIED ✅
**Implementation:** `overworld_version_helper.h:51-71`
| ASM Byte | Version | Status |
|----------|---------|--------|
| `0xFF` | Vanilla | ✅ Correct |
| `0x00` | Vanilla | ✅ **CORRECT** - Expanded ROMs are zero-filled |
| `0x01` | v1 | ✅ Verified |
| `0x02` | v2 | ⚠️ Not tested (no v2 ROM available) |
| `0x03+` | v3 | ✅ Verified |
**Task 1: Version 0x00 Edge Case - RESOLVED ✅**
- **Answer:** Treating `0x00` as vanilla is **CORRECT**
- **Rationale:** When vanilla ROM is expanded to 2MB, new space is zero-filled
- **Address:** `0x140145` is in expanded space (beyond 1MB)
- **Tests Added:** 5 comprehensive tests in `overworld_version_helper_test.cc`
- **Bounds Check Added:** Prevents crashes on small ROMs
**Task 2: Death Mountain GFX TODO - DOCUMENTED ⚠️**
**Location:** `overworld_map.cc:595-602`
- **Current logic:** Checks parent ranges `0x03-0x07`, `0x0B-0x0E` (LW), `0x43-0x47`, `0x4B-0x4E` (DW)
- **Recommended:** Only check `0x03`, `0x05`, `0x07` (LW) and `0x43`, `0x45`, `0x47` (DW)
- **Rationale:** Matches ZScream 3.0.4+ behavior, handles non-large DM areas correctly
- **Impact:** Low risk improvement
- **Status:** Documented in audit report, not implemented yet
**Task 3: ConfigureMultiAreaMap - FULLY VERIFIED ✅**
**Location:** `overworld.cc:267-422`
- ✅ Vanilla ROM: Correctly rejects Wide/Tall areas
- ✅ v1/v2 ROM: Same as vanilla (no area enum support)
- ✅ v3 ROM: All 4 sizes work (Small, Large, Wide, Tall)
- ✅ Sibling cleanup: Properly resets all quadrants when shrinking Large→Small
- ✅ Edge maps: Boundary conditions handled safely
**Task 4: Special World Hardcoded Cases - VERIFIED ✅**
**Location:** `overworld_map.cc:202-293`
- ✅ Triforce room (`0x88`, `0x93`): Special graphics `0x51`, palette `0x00`
- ✅ Master Sword area (`0x80`): Special GFX group
- ✅ Zora's Domain (`0x81`, `0x82`, `0x89`, `0x8A`): Sprite GFX `0x0E`
- ✅ Version-aware logic for v3 vs vanilla/v2
**Audit Report:** `zscow_audit_report.md` (artifact)
**Test Results:**
```bash
./build_gemini/bin/Debug/yaze_test_stable --gtest_filter="OverworldVersionHelperTest*"
# [ PASSED ] 5 tests.
```
**Overall Assessment:** ZSCOW implementation is production-ready with one low-priority enhancement (Death Mountain GFX logic).
---
### Priority 4: Agent Inspection - Wire Real Data [MEDIUM] - DETAILED
**Problem:** CLI inspection commands return stub output. Helper functions exist but aren't connected.
#### Overworld Command Handlers (`src/cli/handlers/game/overworld.cc`)
| Line | Handler | Status | Helper to Use |
|------|---------|--------|---------------|
| 33 | `OverworldGetTileCommandHandler` | TODO | Manual ROM read |
| 84 | `OverworldSetTileCommandHandler` | TODO | Manual ROM write |
| 162 | `OverworldFindTileCommandHandler` | TODO | `FindTileMatches()` |
| 325 | `OverworldDescribeMapCommandHandler` | TODO | `BuildMapSummary()` |
| 508 | `OverworldListWarpsCommandHandler` | TODO | `CollectWarpEntries()` |
| 721 | `OverworldSelectRectCommandHandler` | TODO | N/A (GUI) |
| 759 | `OverworldScrollToCommandHandler` | TODO | N/A (GUI) |
| 794 | `OverworldSetZoomCommandHandler` | TODO | N/A (GUI) |
| 822 | `OverworldGetVisibleRegionCommandHandler` | TODO | N/A (GUI) |
#### Dungeon Command Handlers (`src/cli/handlers/game/dungeon_commands.cc`)
| Line | Handler | Status |
|------|---------|--------|
| 36 | Sprite listing | TODO - need `Room::sprites()` |
| 158 | Object listing | TODO - need `Room::objects()` |
| 195 | Tile data | TODO - need `Room::floor1()`/`floor2()` |
| 237 | Property setting | TODO - need `Room::set_*()` methods |
#### Available Helper Functions (`overworld_inspect.h`)
These are fully implemented and ready to use:
```cpp
// Build complete map metadata summary
absl::StatusOr<MapSummary> BuildMapSummary(zelda3::Overworld& overworld, int map_id);
// Find all warps matching query (entrances, exits, holes)
absl::StatusOr<std::vector<WarpEntry>> CollectWarpEntries(
const zelda3::Overworld& overworld, const WarpQuery& query);
// Find all occurrences of a tile16 ID
absl::StatusOr<std::vector<TileMatch>> FindTileMatches(
zelda3::Overworld& overworld, uint16_t tile_id, const TileSearchOptions& options);
// Get sprites on overworld maps
absl::StatusOr<std::vector<OverworldSprite>> CollectOverworldSprites(
const zelda3::Overworld& overworld, const SpriteQuery& query);
// Get entrance details by ID
absl::StatusOr<EntranceDetails> GetEntranceDetails(
const zelda3::Overworld& overworld, uint8_t entrance_id);
// Analyze how often a tile is used
absl::StatusOr<TileStatistics> AnalyzeTileUsage(
zelda3::Overworld& overworld, uint16_t tile_id, const TileSearchOptions& options);
```
#### Example Fix Pattern
```cpp
// BEFORE (broken):
absl::Status OverworldFindTileCommandHandler::Execute(
CommandContext& context, std::ostream& output) {
output << "Placeholder: would find tile..."; // STUB!
return absl::OkStatus();
}
// AFTER (working):
absl::Status OverworldFindTileCommandHandler::Execute(
CommandContext& context, std::ostream& output) {
auto tile_id_str = context.GetArgument("tile_id");
ASSIGN_OR_RETURN(auto tile_id, ParseHexOrDecimal(tile_id_str));
TileSearchOptions options;
if (auto world = context.GetOptionalArgument("world")) {
ASSIGN_OR_RETURN(options.world, ParseWorldSpecifier(*world));
}
ASSIGN_OR_RETURN(auto matches,
overworld::FindTileMatches(context.overworld(), tile_id, options));
output << "Found " << matches.size() << " occurrences:\n";
for (const auto& match : matches) {
output << absl::StrFormat(" Map %d (%s): (%d, %d)\n",
match.map_id, WorldName(match.world), match.local_x, match.local_y);
}
return absl::OkStatus();
}
```
#### Priority Order
1. `OverworldDescribeMapCommandHandler` - Most useful for agents
2. `OverworldFindTileCommandHandler` - Common query
3. `OverworldListWarpsCommandHandler` - Needed for navigation
4. Dungeon sprite/object listing - For dungeon editing support
---
## DO NOT TOUCH
- `.github/workflows/` - CI/CD hotfix in progress
- `build/`, `build_agent/`, `build_test/` - User's build directories
- `src/util/crash_handler.cc` - Being patched for Windows
---
## Code Style
- Use `absl::Status` and `absl::StatusOr<T>` for error handling
- Macros: `RETURN_IF_ERROR()`, `ASSIGN_OR_RETURN()`
- Format: `cmake --build build_gemini --target format`
- Follow Google C++ Style Guide
---
## Reference Documentation
- **CLAUDE.md** - Project conventions and patterns
- **Roadmap:** `docs/internal/roadmaps/2025-11-23-refined-roadmap.md`
- **Message Editor Plans:** `docs/internal/plans/message_editor_implementation_roadmap.md`
- **Test Guide:** `docs/public/build/quick-reference.md`
---
## Recommended Approach
1. **Pick ONE priority** to focus on
2. **Read the relevant files** before making changes
3. **Run tests frequently** (`ctest --test-dir build_gemini -L stable`)
4. **Commit with clear messages** following conventional commits (`fix:`, `feat:`)
5. **Don't touch CI/CD** - that's being handled separately
---
## Current State of Uncommitted Work
The working tree has changes you should be aware of:
- `tile16_editor.cc` - Texture queueing improvements
- `entity.cc/h` - Sprite movement fixes
- `overworld_editor.cc` - Entity rendering
- `overworld_map.cc` - Map rendering
- `object_drawer.cc/h` - Dungeon objects
Review these before making overlapping changes.
---
## Success Criteria
When you're done, one of these should be true:
- [x] ~~Dungeon save actually persists changes to ROM~~ **COMPLETE**
- [x] ~~Message editor can export expanded BIN files~~ **COMPLETE**
- [x] ~~ZSCOW loads correctly for vanilla + v1/v2/v3 ROMs~~ **COMPLETE**
- [ ] Agent inspection returns real data
Good luck!