imgui-frontend-engineer: fix merge blockers in graphics/dungeon map

This commit is contained in:
scawful
2025-12-28 09:50:46 -06:00
parent 07291a0eac
commit a256b589ac
4 changed files with 44 additions and 9 deletions

View File

@@ -4,6 +4,7 @@
// C++ standard library headers // C++ standard library headers
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
#include <set>
// Third-party library headers // Third-party library headers
#include "absl/status/status.h" #include "absl/status/status.h"
@@ -209,6 +210,8 @@ absl::Status GraphicsEditor::Save() {
state_.modified_sheets.size()); state_.modified_sheets.size());
auto& sheets = gfx::Arena::Get().gfx_sheets(); auto& sheets = gfx::Arena::Get().gfx_sheets();
std::set<uint16_t> saved_sheets;
std::vector<uint16_t> skipped_sheets;
for (uint16_t sheet_id : state_.modified_sheets) { for (uint16_t sheet_id : state_.modified_sheets) {
if (sheet_id >= zelda3::kNumGfxSheets) continue; if (sheet_id >= zelda3::kNumGfxSheets) continue;
@@ -230,6 +233,20 @@ absl::Status GraphicsEditor::Save() {
compressed = false; compressed = false;
} }
if (bpp == 2) {
const size_t expected_size =
gfx::kTilesheetWidth * gfx::kTilesheetHeight * 2;
const size_t actual_size = sheet.vector().size();
if (actual_size < expected_size) {
LOG_WARN(
"GraphicsEditor",
"Skipping 2BPP sheet %02X save (expected %zu bytes, got %zu)",
sheet_id, expected_size, actual_size);
skipped_sheets.push_back(sheet_id);
continue;
}
}
// Calculate ROM offset for this sheet // Calculate ROM offset for this sheet
// Get version constants from game_data // Get version constants from game_data
auto version_constants = zelda3::kVersionConstantsMap.at(game_data()->version); auto version_constants = zelda3::kVersionConstantsMap.at(game_data()->version);
@@ -288,10 +305,16 @@ absl::Status GraphicsEditor::Save() {
LOG_INFO("GraphicsEditor", "Saved sheet %02X (%zu bytes, %s) at offset %06X", LOG_INFO("GraphicsEditor", "Saved sheet %02X (%zu bytes, %s) at offset %06X",
sheet_id, final_data.size(), compressed ? "compressed" : "raw", sheet_id, final_data.size(), compressed ? "compressed" : "raw",
offset); offset);
saved_sheets.insert(sheet_id);
} }
// Clear modified tracking after successful save // Clear modified tracking after successful save
state_.ClearModifiedSheets(); state_.ClearModifiedSheets(saved_sheets);
if (!skipped_sheets.empty()) {
return absl::FailedPreconditionError(
absl::StrCat("Skipped ", skipped_sheets.size(),
" 2BPP sheet(s); full data unavailable."));
}
return absl::OkStatus(); return absl::OkStatus();
} }

View File

@@ -139,6 +139,15 @@ class GraphicsEditorState {
*/ */
void ClearModifiedSheets() { modified_sheets.clear(); } void ClearModifiedSheets() { modified_sheets.clear(); }
/**
* @brief Clear specific sheets from modification tracking
*/
void ClearModifiedSheets(const std::set<uint16_t>& sheet_ids) {
for (auto sheet_id : sheet_ids) {
modified_sheets.erase(sheet_id);
}
}
/** /**
* @brief Check if any sheets have unsaved changes * @brief Check if any sheets have unsaved changes
*/ */

View File

@@ -414,6 +414,7 @@ absl::StatusOr<AsarPatchResult> AsarWrapper::ApplyPatchWithBinary(
FILE* pipe = popen(cmd.str().c_str(), "r"); FILE* pipe = popen(cmd.str().c_str(), "r");
if (!pipe) { if (!pipe) {
fs::remove(temp_rom, ec); fs::remove(temp_rom, ec);
fs::remove(temp_symbols, ec);
if (!patch_dir.empty()) fs::current_path(original_cwd, ec); if (!patch_dir.empty()) fs::current_path(original_cwd, ec);
return absl::InternalError("popen() failed for Asar CLI"); return absl::InternalError("popen() failed for Asar CLI");
} }

View File

@@ -93,8 +93,10 @@ absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) {
RETURN_IF_ERROR(rom.WriteWord(kDungeonMapBossRooms + (d * 2), RETURN_IF_ERROR(rom.WriteWord(kDungeonMapBossRooms + (d * 2),
map.boss_room)); map.boss_room));
bool search_boss = map.boss_room != 0x000F; const bool has_boss =
if (!search_boss) { map.boss_room != 0x000F && map.boss_room != 0xFFFF;
bool search_boss = has_boss;
if (!has_boss) {
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom.WriteWord(kDungeonMapBossFloors + (d * 2), 0xFFFF)); rom.WriteWord(kDungeonMapBossFloors + (d * 2), 0xFFFF));
} }
@@ -111,15 +113,15 @@ absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) {
search_boss = false; search_boss = false;
} }
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_rooms[f][r]));
pos++;
if (pos >= kDungeonMapDataReservedStart && if (pos >= kDungeonMapDataReservedStart &&
pos <= kDungeonMapDataReservedEnd) { pos <= kDungeonMapDataReservedEnd) {
pos = kDungeonMapDataReservedEnd + 1; pos = kDungeonMapDataReservedEnd + 1;
restart = true; restart = true;
break; break;
} }
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_rooms[f][r]));
pos++;
} }
if (restart) break; if (restart) break;
} }
@@ -134,9 +136,6 @@ absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) {
for (int f = 0; f < total_floors; f++) { for (int f = 0; f < total_floors; f++) {
for (int r = 0; r < kNumRooms; r++) { for (int r = 0; r < kNumRooms; r++) {
if (map.floor_rooms[f][r] != 0x0F) { if (map.floor_rooms[f][r] != 0x0F) {
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_gfx[f][r]));
pos++;
if (pos >= kDungeonMapDataReservedStart && if (pos >= kDungeonMapDataReservedStart &&
pos <= kDungeonMapDataReservedEnd) { pos <= kDungeonMapDataReservedEnd) {
pos = kDungeonMapDataReservedEnd + 1; pos = kDungeonMapDataReservedEnd + 1;
@@ -145,6 +144,9 @@ absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) {
restart = true; restart = true;
break; break;
} }
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_gfx[f][r]));
pos++;
} }
} }
if (restart) break; if (restart) break;