fix(dungeon-map): rewrite save layout

This commit is contained in:
scawful
2025-12-22 14:56:17 -05:00
parent d5e06e943f
commit 326594f3e6
2 changed files with 88 additions and 14 deletions

View File

@@ -3,6 +3,7 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include "absl/strings/str_format.h"
#include "app/gfx/backend/irenderer.h" #include "app/gfx/backend/irenderer.h"
#include "app/gfx/core/bitmap.h" #include "app/gfx/core/bitmap.h"
#include "app/gfx/render/tilemap.h" #include "app/gfx/render/tilemap.h"
@@ -77,22 +78,91 @@ absl::StatusOr<std::vector<DungeonMap>> LoadDungeonMaps(
} }
absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) { absl::Status SaveDungeonMaps(Rom& rom, std::vector<DungeonMap>& dungeon_maps) {
for (int d = 0; d < kNumDungeons; d++) { int pos = kDungeonMapDataStart;
int ptr = kDungeonMapRoomsPtr + (d * 2);
int ptr_gfx = kDungeonMapGfxPtr + (d * 2);
int pc_ptr = SnesToPc(ptr);
int pc_ptr_gfx = SnesToPc(ptr_gfx);
const int nbr_floors = dungeon_maps[d].nbr_of_floor; for (int d = 0; d < kNumDungeons; d++) {
const int nbr_basements = dungeon_maps[d].nbr_of_basement; if (d >= static_cast<int>(dungeon_maps.size())) {
for (int i = 0; i < nbr_floors + nbr_basements; i++) { break;
for (int j = 0; j < kNumRooms; j++) {
RETURN_IF_ERROR(rom.WriteByte(pc_ptr + j + (i * kNumRooms),
dungeon_maps[d].floor_rooms[i][j]));
RETURN_IF_ERROR(rom.WriteByte(pc_ptr_gfx + j + (i * kNumRooms),
dungeon_maps[d].floor_gfx[i][j]));
pc_ptr_gfx++;
} }
auto& map = dungeon_maps[d];
const int total_floors = map.nbr_of_floor + map.nbr_of_basement;
uint16_t floors = (map.nbr_of_floor << 4) | map.nbr_of_basement;
RETURN_IF_ERROR(rom.WriteWord(kDungeonMapFloors + (d * 2), floors));
RETURN_IF_ERROR(rom.WriteWord(kDungeonMapBossRooms + (d * 2),
map.boss_room));
bool search_boss = map.boss_room != 0x000F;
if (!search_boss) {
RETURN_IF_ERROR(
rom.WriteWord(kDungeonMapBossFloors + (d * 2), 0xFFFF));
}
RETURN_IF_ERROR(
rom.WriteWord(kDungeonMapRoomsPtr + (d * 2), PcToSnes(pos)));
bool restart = false;
for (int f = 0; f < total_floors; f++) {
for (int r = 0; r < kNumRooms; r++) {
if (search_boss && map.floor_rooms[f][r] == map.boss_room) {
RETURN_IF_ERROR(
rom.WriteWord(kDungeonMapBossFloors + (d * 2), f));
search_boss = false;
}
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_rooms[f][r]));
pos++;
if (pos >= kDungeonMapDataReservedStart &&
pos <= kDungeonMapDataReservedEnd) {
pos = kDungeonMapDataReservedEnd + 1;
restart = true;
break;
}
}
if (restart) break;
}
if (restart) {
d--;
continue;
}
RETURN_IF_ERROR(
rom.WriteWord(kDungeonMapGfxPtr + (d * 2), PcToSnes(pos)));
for (int f = 0; f < total_floors; f++) {
for (int r = 0; r < kNumRooms; r++) {
if (map.floor_rooms[f][r] != 0x0F) {
RETURN_IF_ERROR(rom.WriteByte(pos, map.floor_gfx[f][r]));
pos++;
if (pos >= kDungeonMapDataReservedStart &&
pos <= kDungeonMapDataReservedEnd) {
pos = kDungeonMapDataReservedEnd + 1;
RETURN_IF_ERROR(rom.WriteWord(kDungeonMapGfxPtr + (d * 2),
PcToSnes(pos)));
restart = true;
break;
}
}
}
if (restart) break;
}
if (pos >= kDungeonMapDataLimit) {
return absl::OutOfRangeError(
"Dungeon map data exceeds reserved space");
}
if (restart) {
d--;
continue;
}
if (search_boss) {
return absl::NotFoundError(
absl::StrFormat("Boss room not found for dungeon %d", d));
} }
} }

View File

@@ -20,6 +20,9 @@ constexpr int kDungeonMapGfxPtr = 0x57BE4; // 14 pointers of gfx data
// data start for floors/gfx MUST skip 575D9 to 57621 (pointers) // data start for floors/gfx MUST skip 575D9 to 57621 (pointers)
constexpr int kDungeonMapDataStart = 0x57039; constexpr int kDungeonMapDataStart = 0x57039;
constexpr int kDungeonMapDataReservedStart = 0x575D9;
constexpr int kDungeonMapDataReservedEnd = 0x57620;
constexpr int kDungeonMapDataLimit = 0x57CE0;
// IF Byte = 0xB9 dungeon maps are not expanded // IF Byte = 0xB9 dungeon maps are not expanded
constexpr int kDungeonMapExpCheck = 0x56652; // $0A:E652 constexpr int kDungeonMapExpCheck = 0x56652; // $0A:E652
@@ -28,6 +31,7 @@ constexpr int kDungeonMapTile16Expanded = 0x109010; // $21:9010
// 14 words values 0x000F = no boss // 14 words values 0x000F = no boss
constexpr int kDungeonMapBossRooms = 0x56807; constexpr int kDungeonMapBossRooms = 0x56807;
constexpr int kDungeonMapBossFloors = 0x56E79;
constexpr int kTriforceVertices = 0x04FFD2; // group of 3, X, Y ,Z constexpr int kTriforceVertices = 0x04FFD2; // group of 3, X, Y ,Z
constexpr int kTriforceFaces = 0x04FFE4; // group of 5 constexpr int kTriforceFaces = 0x04FFE4; // group of 5