12#include <unordered_map>
15#include "absl/status/status.h"
16#include "absl/status/statusor.h"
17#include "absl/strings/str_format.h"
39 if (
rom->size() == 0) {
40 return absl::InvalidArgumentError(
"ROM file not loaded");
124 return absl::OkStatus();
144 }
else if (i == parent + 1) {
146 }
else if (i == parent + 8) {
148 }
else if (i == parent + 9) {
159 std::array<bool, kNumOverworldMaps> map_checked{};
160 std::ranges::fill(map_checked,
false);
163 for (
int world_offset = 0; world_offset < 128; world_offset += 64) {
164 for (
int local = 0; local < 64; local++) {
165 int i = world_offset + local;
167 if (map_checked[i])
continue;
179 }
else if (i == parent + 1) {
181 }
else if (i == parent + 8) {
183 }
else if (i == parent + 9) {
188 map_checked[i] =
true;
193 std::array<int, 4> siblings = {parent, parent + 1, parent + 8, parent + 9};
194 int world_start = world_offset;
195 int world_end = world_offset + 64;
196 for (
int q = 0; q < 4; q++) {
197 int sibling = siblings[q];
199 if (sibling >= world_start && sibling < world_end &&
200 !map_checked[sibling]) {
202 map_checked[sibling] =
true;
208 map_checked[i] =
true;
226 int i = world + xx + (yy * 8);
228 if (i >=
static_cast<int>(map_checked.size())) {
232 if (!map_checked[i]) {
233 switch (maps[i].area_size()) {
235 map_checked[i] =
true;
240 map_checked[i] =
true;
241 maps[i].SetAsLargeMap(i, 0);
243 if (i + 1 <
static_cast<int>(maps.size())) {
244 map_checked[i + 1] =
true;
245 maps[i + 1].SetAsLargeMap(i, 1);
248 if (i + 8 <
static_cast<int>(maps.size())) {
249 map_checked[i + 8] =
true;
250 maps[i + 8].SetAsLargeMap(i, 2);
253 if (i + 9 <
static_cast<int>(maps.size())) {
254 map_checked[i + 9] =
true;
255 maps[i + 9].SetAsLargeMap(i, 3);
262 map_checked[i] =
true;
265 maps[i].SetParent(i);
268 if (i + 1 <
static_cast<int>(maps.size())) {
269 map_checked[i + 1] =
true;
270 maps[i + 1].SetParent(i);
278 map_checked[i] =
true;
281 maps[i].SetParent(i);
284 if (i + 8 <
static_cast<int>(maps.size())) {
285 map_checked[i + 8] =
true;
286 maps[i + 8].SetParent(i);
309 return absl::InvalidArgumentError(
310 absl::StrFormat(
"Invalid parent index: %d", parent_index));
320 return absl::FailedPreconditionError(
321 "Wide and Tall areas require ZSCustomOverworld v3+");
325 "ConfigureMultiAreaMap: parent=%d, current_size=%d, new_size=%d, "
329 static_cast<int>(size),
333 std::vector<int> old_siblings;
339 old_siblings = {old_parent, old_parent + 1, old_parent + 8,
343 old_siblings = {old_parent, old_parent + 1};
346 old_siblings = {old_parent, old_parent + 8};
349 old_siblings = {parent_index};
354 for (
int old_sibling : old_siblings) {
361 std::vector<int> new_siblings;
368 new_siblings = {parent_index};
372 new_siblings = {parent_index, parent_index + 1, parent_index + 8,
374 for (
size_t i = 0; i < new_siblings.size(); ++i) {
375 int sibling = new_siblings[i];
383 new_siblings = {parent_index, parent_index + 1};
384 for (
int sibling : new_siblings) {
393 new_siblings = {parent_index, parent_index + 8};
394 for (
int sibling : new_siblings) {
404 std::set<int> all_affected;
405 for (
int sibling : old_siblings) {
406 all_affected.insert(sibling);
408 for (
int sibling : new_siblings) {
409 all_affected.insert(sibling);
414 for (
int sibling : all_affected) {
426 for (
int sibling : all_affected) {
438 for (
int sibling : all_affected) {
453 "Configured %s area: parent=%d, old_siblings=%zu, new_siblings=%zu",
458 parent_index, old_siblings.size(), new_siblings.size());
460 return absl::OkStatus();
464 int index,
int quadrant,
int dimension,
const uint32_t* map32address) {
466 auto arg1,
rom()->ReadByte(map32address[dimension] + quadrant + (index)));
468 rom()->ReadWord(map32address[dimension] + (index) +
469 (quadrant <= 1 ? 4 : 5)));
470 return (uint16_t)(arg1 +
471 (((arg2 >> (quadrant % 2 == 0 ? 4 : 0)) & 0x0F) * 256));
475 constexpr int kMap32TilesLength = 0x33F0;
476 int num_tile32 = kMap32TilesLength;
490 util::logf(
"Expanded tile32 flag: %d", expanded_flag);
491 if (expanded_flag != 0x04 ||
504 for (
int i = 0; i < num_tile32; i += 6) {
506 for (
int k = 0; k < 4; k++) {
530 for (
int i = 0; i < 0x200; i++) {
536 return absl::OkStatus();
551 util::logf(
"Expanded tile16 flag: %d", expanded_flag);
561 for (
int i = 0; i < num_tile16; i += 1) {
574 tiles16_.emplace_back(t0, t1, t2, t3);
576 return absl::OkStatus();
581 int position_x1 = (x * 2) + (sx * 32);
582 int position_y1 = (y * 2) + (sy * 32);
583 int position_x2 = (x * 2) + 1 + (sx * 32);
584 int position_y2 = (y * 2) + 1 + (sy * 32);
592 switch (world_type) {
610 int local_index = map_index % 64;
611 int sx = local_index % 8;
612 int sy = local_index / 8;
616 for (
int y = 0; y < 32; ++y) {
617 for (
int x = 0; x < 32; ++x) {
618 world[(sx * 32) + x][(sy * 32) + y] = 0;
624 std::vector<uint8_t>& bytes2,
int i,
int sx,
625 int sy,
int& ttpos) {
626 for (
int y = 0; y < 16; y++) {
627 for (
int x = 0; x < 16; x++) {
628 auto tidD = (uint16_t)((bytes2[ttpos] << 8) + bytes[ttpos]);
644 const auto get_ow_map_gfx_ptr = [
this](
int index, uint32_t map_ptr) {
645 int p = (
rom()->data()[map_ptr + 2 + (3 * index)] << 16) +
646 (
rom()->data()[map_ptr + 1 + (3 * index)] << 8) +
647 (
rom()->data()[map_ptr + (3 * index)]);
651 constexpr uint32_t kBaseLowest = 0x0FFFFF;
652 constexpr uint32_t kBaseHighest = 0x0F8000;
654 uint32_t lowest = kBaseLowest;
655 uint32_t highest = kBaseHighest;
662 const bool allow_special_tail =
668 if (!allow_special_tail &&
685 auto p1 = get_ow_map_gfx_ptr(
687 auto p2 = get_ow_map_gfx_ptr(
692 bool pointers_valid = (p1 > 0 && p2 > 0 && p1 <
rom()->size() &&
694 if (!pointers_valid) {
716 if (p1 <= lowest && p1 > kBaseHighest)
718 if (p2 <= lowest && p2 > kBaseHighest)
722 size_t max_size_p2 =
rom()->size() - p2;
724 size_t max_size_p1 =
rom()->size() - p1;
728 if (bytes.empty() || bytes2.empty()) {
748 return absl::OkStatus();
759 constexpr int kEssentialMapsPerWorld = 4;
761 constexpr int kEssentialMapsPerWorld = 16;
763 constexpr int kLightWorldEssential = kEssentialMapsPerWorld;
764 constexpr int kDarkWorldEssential =
766 constexpr int kSpecialWorldEssential =
770 "Building essential maps only (first %d maps per world) for faster "
772 kEssentialMapsPerWorld);
780 bool is_essential =
false;
782 if (i < kLightWorldEssential) {
806 if (map->parent() != i && !map->is_initialized()) {
809 map->set_sprite_graphics(0, 0x0E);
810 map->set_sprite_graphics(1, 0x0E);
811 map->set_sprite_graphics(2, 0x0E);
812 map->set_area_graphics(
815 }
else if (i == 0x88) {
816 map->set_area_graphics(0x51);
817 map->set_area_palette(0x00);
834 if (!cached_tileset) {
843 std::vector<std::future<absl::Status>> futures;
847 bool is_essential =
false;
850 if (i < kLightWorldEssential) {
866 auto task_function = [
this, i, size, world_type]() {
870 futures.emplace_back(std::async(std::launch::async, task_function));
878 for (
auto& future : futures) {
884 util::logf(
"Essential maps built. Remaining maps will be built on-demand.");
885 return absl::OkStatus();
890 return absl::InvalidArgumentError(
"Invalid map index");
896 const bool allow_special_tail =
899 if (!allow_special_tail &&
905 return absl::OkStatus();
916 return absl::OkStatus();
947 if (map->parent() != map_index && !map->is_initialized()) {
953 map->set_sprite_graphics(0, 0x0E);
954 map->set_sprite_graphics(1, 0x0E);
955 map->set_sprite_graphics(2, 0x0E);
956 map->set_area_graphics(
959 }
else if (map_index == 0x88) {
960 map->set_area_graphics(0x51);
961 map->set_area_palette(0x00);
984 if (!cached_tileset) {
1014 hash ^=
static_cast<uint64_t
>(world_type) << 62;
1015 hash *= 0x517cc1b727220a95ULL;
1020 for (
int i = 0; i < 12; ++i) {
1021 hash ^=
static_cast<uint64_t
>(map->static_graphics(i)) << ((i % 8) * 8);
1022 hash *= 0x517cc1b727220a95ULL;
1029 hash *= 0x517cc1b727220a95ULL;
1033 for (
int i = 0; i < 3; ++i) {
1034 hash ^=
static_cast<uint64_t
>(map->sprite_graphics(i)) << (52 + i * 4);
1035 hash *= 0x517cc1b727220a95ULL;
1039 hash ^=
static_cast<uint64_t
>(map->area_graphics()) << 48;
1040 hash *= 0x517cc1b727220a95ULL;
1044 hash ^=
static_cast<uint64_t
>(map->main_gfx_id()) << 56;
1045 hash *= 0x517cc1b727220a95ULL;
1048 hash ^=
static_cast<uint64_t
>(map->parent()) << 40;
1049 hash *= 0x517cc1b727220a95ULL;
1055 hash ^=
static_cast<uint64_t
>(map_index) << 8;
1056 hash *= 0x517cc1b727220a95ULL;
1059 hash ^=
static_cast<uint64_t
>(map->main_palette()) << 24;
1060 hash *= 0x517cc1b727220a95ULL;
1063 hash ^=
static_cast<uint64_t
>(map->animated_gfx()) << 16;
1064 hash *= 0x517cc1b727220a95ULL;
1067 hash ^=
static_cast<uint64_t
>(map->area_palette()) << 32;
1068 hash *= 0x517cc1b727220a95ULL;
1072 hash ^=
static_cast<uint64_t
>(map->subscreen_overlay());
1073 hash *= 0x517cc1b727220a95ULL;
1081 it->second.reference_count++;
1082 return &it->second.current_gfx;
1088 const std::vector<uint8_t>& tileset) {
1095 if (it->second.reference_count < min_it->second.reference_count) {
1130 int parent_id = map->parent();
1131 std::vector<int> siblings;
1138 switch (map->area_size()) {
1140 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1143 siblings = {parent_id, parent_id + 1};
1146 siblings = {parent_id, parent_id + 8};
1149 siblings = {map_index};
1154 if (map->is_large_map()) {
1155 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1157 siblings = {map_index};
1162 for (
int sibling : siblings) {
1173#ifdef __EMSCRIPTEN__
1186 std::vector<std::future<absl::Status>> futures;
1190 futures.emplace_back(std::async(std::launch::async, [
this]() {
1193 futures.emplace_back(std::async(std::launch::async, [
this]() {
1196 futures.emplace_back(std::async(std::launch::async, [
this]() {
1201 futures.emplace_back(std::async(std::launch::async, [
this]() {
1204 futures.emplace_back(std::async(std::launch::async, [
this]() {
1207 futures.emplace_back(std::async(std::launch::async, [
this]() {
1212 for (
auto& future : futures) {
1217 return absl::OkStatus();
1221 int num_maps_per_gamestate,
1223 for (
int i = 0; i < num_maps_per_gamestate; i++) {
1227 int current_spr_ptr = sprites_per_gamestate_ptr + (i * 2);
1229 int sprite_address =
SnesToPc((0x09 << 0x10) | word_addr);
1237 int editor_map_index = i;
1238 if (game_state != 0) {
1239 if (editor_map_index >= 128)
1240 editor_map_index -= 128;
1241 else if (editor_map_index >= 64)
1242 editor_map_index -= 64;
1244 int mapY = (editor_map_index / 8);
1245 int mapX = (editor_map_index % 8);
1247 int realX = ((b2 & 0x3F) * 16) + mapX * 512;
1248 int realY = ((b1 & 0x3F) * 16) + mapY * 512;
1251 (uint8_t)(b2 & 0x3F), (uint8_t)(b1 & 0x3F), realX, realY);
1254 sprite_address += 3;
1258 return absl::OkStatus();
1283 return absl::OkStatus();
1296 std::vector<uint8_t> single_map_1(512);
1297 std::vector<uint8_t> single_map_2(512);
1301 for (
int y = 0; y < 16; y++) {
1302 for (
int x = 0; x < 16; x++) {
1304 single_map_1[npos] = packed & 0xFF;
1305 single_map_2[npos] = (packed >> 8) & 0xFF;
1314 if (a.empty() || b.empty()) {
1315 return absl::AbortedError(
"Error compressing map gfx.");
1322 if ((pos + size_a) >= 0x5FE70 && (pos + size_a) <= 0x60000) {
1326 if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) {
1327 util::logf(
"Pos set to overflow region for map %s at %s",
1332 const auto compare_array = [](
const std::vector<uint8_t>& array1,
1333 const std::vector<uint8_t>& array2) ->
bool {
1334 if (array1.size() != array2.size()) {
1338 for (
size_t i = 0; i < array1.size(); i++) {
1339 if (array1[i] != array2[i]) {
1347 for (
int j = 0; j < i; j++) {
1361 std::copy(a.begin(), a.end(),
map_data_p1[i].begin());
1364 util::logf(
"Saving map pointers1 and compressed data for map %s at %s",
1381 if ((pos + b.size()) >= 0x5FE70 && (pos + b.size()) <= 0x60000) {
1385 if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) {
1386 util::logf(
"Pos set to overflow region for map %s at %s",
1393 std::copy(b.begin(), b.end(),
map_data_p2[i].begin());
1396 util::logf(
"Saving map pointers2 and compressed data for map %s at %s",
1417 return absl::AbortedError(
"Too many maps data " + std::to_string(pos));
1421 return absl::OkStatus();
1430 bool use_expanded_transitions =
1433 if (use_expanded_transitions) {
1439 std::vector<uint8_t> checked_map;
1451 if (std::find(checked_map.begin(), checked_map.end(), i) !=
1452 checked_map.end()) {
1459 const uint8_t large_map_offsets[] = {0, 1, 8, 9};
1460 for (
const auto& offset : large_map_offsets) {
1485 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1488 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1492 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1495 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1499 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1502 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1506 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1509 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1513 (parent_x_pos * 0x200)));
1515 (parent_y_pos * 0x200)));
1519 (parent_x_pos * 0x200)));
1522 (parent_y_pos * 0x200)));
1526 (parent_x_pos * 0x200)));
1529 (parent_y_pos * 0x200)));
1533 (parent_x_pos * 0x200)));
1536 (parent_y_pos * 0x200)));
1545 if (parent_x_pos == 0) {
1648 checked_map.emplace_back(i);
1649 checked_map.emplace_back((i + 1));
1650 checked_map.emplace_back((i + 8));
1651 checked_map.emplace_back((i + 9));
1673 if (i - 1 >= 0 && parent_x_pos != 0) {
1685 if (i + 1 < 64 && parent_x_pos != 7) {
1729 (uint16_t)((y_pos * 0x200) - 0xE0)));
1731 (uint16_t)((x_pos * 0x200) - 0x100)));
1738 checked_map.emplace_back(i);
1742 constexpr int OverworldScreenTileMapChangeMask = 0x1262C;
1745 rom()->WriteShort(OverworldScreenTileMapChangeMask + 0, 0x1F80));
1747 rom()->WriteShort(OverworldScreenTileMapChangeMask + 2, 0x1F80));
1749 rom()->WriteShort(OverworldScreenTileMapChangeMask + 4, 0x007F));
1751 rom()->WriteShort(OverworldScreenTileMapChangeMask + 6, 0x007F));
1753 return absl::OkStatus();
1757 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
1758 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
1759 int screen_change_1,
int screen_change_2,
int screen_change_3,
1760 int screen_change_4) {
1763 rom()->WriteShort(transition_target_north + (i * 2),
1764 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
1766 rom()->WriteShort(transition_target_west + (i * 2),
1767 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
1770 rom()->WriteShort(transition_pos_x + (i * 2), parent_x_pos * 0x0200));
1772 rom()->WriteShort(transition_pos_y + (i * 2), parent_y_pos * 0x0200));
1775 uint16_t by_screen1_small = 0x0060;
1778 if ((i % 0x40) - 1 >= 0) {
1783 west_neighbor.large_index() == 3) {
1784 by_screen1_small = 0xF060;
1788 west_neighbor.large_index() == 2) {
1789 by_screen1_small = 0xF060;
1794 rom()->WriteShort(screen_change_1 + (i * 2), by_screen1_small));
1797 uint16_t by_screen2_small = 0x0040;
1805 east_neighbor.large_index() == 2) {
1806 by_screen2_small = 0xF040;
1810 east_neighbor.large_index() == 2) {
1811 by_screen2_small = 0xF040;
1816 rom()->WriteShort(screen_change_2 + (i * 2), by_screen2_small));
1819 uint16_t by_screen3_small = 0x1800;
1822 if ((i % 0x40) - 8 >= 0) {
1827 north_neighbor.large_index() == 3) {
1828 by_screen3_small = 0x17C0;
1832 north_neighbor.large_index() == 1) {
1833 by_screen3_small = 0x17C0;
1838 rom()->WriteShort(screen_change_3 + (i * 2), by_screen3_small));
1841 uint16_t by_screen4_small = 0x1000;
1849 south_neighbor.large_index() == 1) {
1850 by_screen4_small = 0x0FC0;
1854 south_neighbor.large_index() == 1) {
1855 by_screen4_small = 0x0FC0;
1860 rom()->WriteShort(screen_change_4 + (i * 2), by_screen4_small));
1862 return absl::OkStatus();
1866 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
1867 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
1868 int screen_change_1,
int screen_change_2,
int screen_change_3,
1869 int screen_change_4) {
1871 const uint16_t offsets[] = {0, 2, 16, 18};
1872 for (
auto offset : offsets) {
1874 rom()->WriteShort(transition_target_north + (i * 2) + offset,
1875 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
1877 rom()->WriteShort(transition_target_west + (i * 2) + offset,
1878 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
1880 parent_x_pos * 0x0200));
1882 parent_y_pos * 0x0200));
1887 std::array<uint16_t, 4> by_screen1_large = {0x0060, 0x0060, 0x1060, 0x1060};
1890 if ((i % 0x40) - 1 >= 0) {
1894 switch (west_neighbor.large_index()) {
1896 by_screen1_large[2] = 0x0060;
1899 by_screen1_large[0] = 0xF060;
1903 switch (west_neighbor.large_index()) {
1905 by_screen1_large[2] = 0x0060;
1908 by_screen1_large[0] = 0xF060;
1914 for (
int j = 0; j < 4; j++) {
1916 by_screen1_large[j]));
1920 std::array<uint16_t, 4> by_screen2_large = {0x0080, 0x0080, 0x1080, 0x1080};
1927 switch (east_neighbor.large_index()) {
1929 by_screen2_large[3] = 0x0080;
1932 by_screen2_large[1] = 0xF080;
1936 switch (east_neighbor.large_index()) {
1938 by_screen2_large[3] = 0x0080;
1941 by_screen2_large[1] = 0xF080;
1947 for (
int j = 0; j < 4; j++) {
1949 by_screen2_large[j]));
1953 std::array<uint16_t, 4> by_screen3_large = {0x1800, 0x1840, 0x1800, 0x1840};
1956 if ((i % 0x40) - 8 >= 0) {
1960 switch (north_neighbor.large_index()) {
1962 by_screen3_large[1] = 0x1800;
1965 by_screen3_large[0] = 0x17C0;
1969 switch (north_neighbor.large_index()) {
1971 by_screen3_large[1] = 0x1800;
1974 by_screen3_large[0] = 0x17C0;
1980 for (
int j = 0; j < 4; j++) {
1982 by_screen3_large[j]));
1986 std::array<uint16_t, 4> by_screen4_large = {0x2000, 0x2040, 0x2000, 0x2040};
1993 switch (south_neighbor.large_index()) {
1995 by_screen4_large[3] = 0x2000;
1998 by_screen4_large[2] = 0x1FC0;
2002 switch (south_neighbor.large_index()) {
2004 by_screen4_large[3] = 0x2000;
2007 by_screen4_large[2] = 0x1FC0;
2013 for (
int j = 0; j < 4; j++) {
2015 by_screen4_large[j]));
2018 return absl::OkStatus();
2022 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
2023 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
2024 int screen_change_1,
int screen_change_2,
int screen_change_3,
2025 int screen_change_4) {
2027 const uint16_t offsets[] = {0, 2};
2028 for (
auto offset : offsets) {
2030 rom()->WriteShort(transition_target_north + (i * 2) + offset,
2031 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
2033 rom()->WriteShort(transition_target_west + (i * 2) + offset,
2034 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
2036 parent_x_pos * 0x0200));
2038 parent_y_pos * 0x0200));
2042 std::array<uint16_t, 2> by_screen1_wide = {0x0060, 0x0060};
2045 if ((i % 0x40) - 1 >= 0) {
2050 west_neighbor.large_index() == 3) {
2051 by_screen1_wide[0] = 0xF060;
2055 west_neighbor.large_index() == 2) {
2056 by_screen1_wide[0] = 0xF060;
2060 for (
int j = 0; j < 2; j++) {
2062 by_screen1_wide[j]));
2066 std::array<uint16_t, 2> by_screen2_wide = {0x0080, 0x0080};
2074 east_neighbor.large_index() == 2) {
2075 by_screen2_wide[1] = 0xF080;
2079 east_neighbor.large_index() == 2) {
2080 by_screen2_wide[1] = 0xF080;
2084 for (
int j = 0; j < 2; j++) {
2086 by_screen2_wide[j]));
2090 std::array<uint16_t, 2> by_screen3_wide = {0x1800, 0x1840};
2093 if ((i % 0x40) - 8 >= 0) {
2097 switch (north_neighbor.large_index()) {
2099 by_screen3_wide[1] = 0x1800;
2102 by_screen3_wide[0] = 0x17C0;
2106 switch (north_neighbor.large_index()) {
2108 by_screen3_wide[1] = 0x1800;
2111 by_screen3_wide[0] = 0x07C0;
2117 for (
int j = 0; j < 2; j++) {
2119 by_screen3_wide[j]));
2123 std::array<uint16_t, 2> by_screen4_wide = {0x1000, 0x1040};
2130 switch (south_neighbor.large_index()) {
2132 by_screen4_wide[1] = 0x1000;
2135 by_screen4_wide[0] = 0x0FC0;
2139 if (south_neighbor.large_index() == 1) {
2140 by_screen4_wide[0] = 0x0FC0;
2142 switch (south_neighbor.large_index()) {
2144 by_screen4_wide[1] = 0x1000;
2147 by_screen4_wide[0] = 0x0FC0;
2153 for (
int j = 0; j < 2; j++) {
2155 by_screen4_wide[j]));
2158 return absl::OkStatus();
2162 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
2163 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
2164 int screen_change_1,
int screen_change_2,
int screen_change_3,
2165 int screen_change_4) {
2167 const uint16_t offsets[] = {0, 16};
2168 for (
auto offset : offsets) {
2170 rom()->WriteShort(transition_target_north + (i * 2) + offset,
2171 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
2173 rom()->WriteShort(transition_target_west + (i * 2) + offset,
2174 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
2176 parent_x_pos * 0x0200));
2178 parent_y_pos * 0x0200));
2182 std::array<uint16_t, 2> by_screen1_tall = {0x0060, 0x1060};
2185 if ((i % 0x40) - 1 >= 0) {
2189 switch (west_neighbor.large_index()) {
2191 by_screen1_tall[1] = 0x0060;
2194 by_screen1_tall[0] = 0xF060;
2198 switch (west_neighbor.large_index()) {
2200 by_screen1_tall[1] = 0x0060;
2203 by_screen1_tall[0] = 0xF060;
2209 for (
int j = 0; j < 2; j++) {
2211 by_screen1_tall[j]));
2215 std::array<uint16_t, 2> by_screen2_tall = {0x0040, 0x1040};
2222 switch (east_neighbor.large_index()) {
2224 by_screen2_tall[1] = 0x0040;
2227 by_screen2_tall[0] = 0xF040;
2231 switch (east_neighbor.large_index()) {
2233 by_screen2_tall[1] = 0x0040;
2236 by_screen2_tall[0] = 0xF040;
2242 for (
int j = 0; j < 2; j++) {
2244 by_screen2_tall[j]));
2248 std::array<uint16_t, 2> by_screen3_tall = {0x1800, 0x1800};
2251 if ((i % 0x40) - 8 >= 0) {
2256 north_neighbor.large_index() == 3) {
2257 by_screen3_tall[0] = 0x17C0;
2261 north_neighbor.large_index() == 1) {
2262 by_screen3_tall[0] = 0x17C0;
2266 for (
int j = 0; j < 2; j++) {
2268 by_screen3_tall[j]));
2272 std::array<uint16_t, 2> by_screen4_tall = {0x2000, 0x2000};
2280 south_neighbor.large_index() == 1) {
2281 by_screen4_tall[1] = 0x1FC0;
2285 south_neighbor.large_index() == 1) {
2286 by_screen4_tall[1] = 0x1FC0;
2290 for (
int j = 0; j < 2; j++) {
2292 by_screen4_tall[j]));
2295 return absl::OkStatus();
2299 util::logf(
"Saving Large Maps (v3+ Expanded)");
2311 std::vector<uint8_t> checked_map;
2316 if (std::find(checked_map.begin(), checked_map.end(), i) !=
2317 checked_map.end()) {
2332 i, parent_x_pos, parent_y_pos, transition_target_north,
2333 transition_target_west, transition_pos_x, transition_pos_y,
2334 screen_change_1, screen_change_2, screen_change_3,
2336 checked_map.emplace_back(i);
2341 i, parent_x_pos, parent_y_pos, transition_target_north,
2342 transition_target_west, transition_pos_x, transition_pos_y,
2343 screen_change_1, screen_change_2, screen_change_3,
2346 checked_map.emplace_back(i);
2347 checked_map.emplace_back(i + 1);
2348 checked_map.emplace_back(i + 8);
2349 checked_map.emplace_back(i + 9);
2354 i, parent_x_pos, parent_y_pos, transition_target_north,
2355 transition_target_west, transition_pos_x, transition_pos_y,
2356 screen_change_1, screen_change_2, screen_change_3,
2359 checked_map.emplace_back(i);
2360 checked_map.emplace_back(i + 1);
2365 i, parent_x_pos, parent_y_pos, transition_target_north,
2366 transition_target_west, transition_pos_x, transition_pos_y,
2367 screen_change_1, screen_change_2, screen_change_3,
2370 checked_map.emplace_back(i);
2371 checked_map.emplace_back(i + 8);
2376 return absl::OkStatus();
2381 std::vector<uint64_t> all_tile_16;
2396 for (
int y = 0; y < 32; y += 2) {
2397 for (
int x = 0; x < 32; x += 2) {
2399 tiles_used[x + (sx * 32)][y + (sy * 32)],
2400 tiles_used[x + 1 + (sx * 32)][y + (sy * 32)],
2401 tiles_used[x + (sx * 32)][y + 1 + (sy * 32)],
2402 tiles_used[x + 1 + (sx * 32)][y + 1 + (sy * 32)]);
2431 std::vector<uint64_t> all_tile_16 = GetAllTile16(
map_tiles_);
2434 std::set<uint64_t> unique_tiles_set(all_tile_16.begin(), all_tile_16.end());
2436 std::vector<uint64_t> unique_tiles(all_tile_16);
2437 unique_tiles.assign(unique_tiles_set.begin(), unique_tiles_set.end());
2440 std::unordered_map<uint64_t, uint16_t> all_tiles_indexed;
2441 for (
size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) {
2442 all_tiles_indexed.insert(
2443 {unique_tiles[tile32_id],
static_cast<uint16_t
>(tile32_id)});
2449 tiles32_list_.emplace_back(all_tiles_indexed[all_tile_16[j]]);
2453 for (
size_t i = 0; i < unique_tiles.size(); ++i) {
2463 return absl::InternalError(absl::StrFormat(
2464 "Number of unique Tiles32: %d Out of: %d\nUnique Tile32 count exceed "
2465 "the limit\nThe ROM Has not been saved\nYou can fill maps with grass "
2466 "tiles to free some space\nOr use the option Clear DW Tiles in the "
2483 return absl::OkStatus();
2532 constexpr int kTilesPer32x32Tile = 6;
2533 int unique_tile_index = 0;
2536 for (
int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
2537 if (unique_tile_index >= limit) {
2538 return absl::AbortedError(
"Too many unique tile32 definitions.");
2569 auto top_right = topRight;
2574 top_right + (i + 1),
2577 top_right + (i + 2),
2580 top_right + (i + 3),
2584 top_right + (i + 4),
2589 top_right + (i + 5),
2596 auto bottom_left = bottomLeft;
2601 bottom_left + (i + 1),
2604 bottom_left + (i + 2),
2607 bottom_left + (i + 3),
2611 bottom_left + (i + 4),
2616 bottom_left + (i + 5),
2623 auto bottom_right = bottomRight;
2628 bottom_right + (i + 1),
2631 bottom_right + (i + 2),
2634 bottom_right + (i + 3),
2638 bottom_right + (i + 4),
2643 bottom_right + (i + 5),
2649 unique_tile_index += 4;
2652 return absl::OkStatus();
2657 constexpr int kMaxUniqueTiles = 0x4540;
2658 constexpr int kTilesPer32x32Tile = 6;
2660 int unique_tile_index = 0;
2663 for (
int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
2664 if (unique_tile_index >= kMaxUniqueTiles) {
2665 return absl::AbortedError(
"Too many unique tile32 definitions.");
2702 top_right + (i + 1),
2705 top_right + (i + 2),
2708 top_right + (i + 3),
2712 top_right + (i + 4),
2717 top_right + (i + 5),
2777 unique_tile_index += 4;
2778 num_unique_tiles += 2;
2781 return absl::OkStatus();
2863 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile0_)));
2866 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile1_)));
2869 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile2_)));
2872 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile3_)));
2876 return absl::OkStatus();
2885 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile0_)))
2888 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile1_)))
2891 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile2_)))
2894 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile3_)))
2897 return absl::OkStatus();
2904 return absl::OkStatus();
2909 return absl::OkStatus();
2914 return absl::OkStatus();
2921 std::vector<uint8_t> new_overlay_code = {
2927 0xBF, 0x00, 0x00, 0x00,
2929 0xBF, 0x00, 0x00, 0x00,
2945 int snes_ptr_start =
PcToSnes(ptr_start);
2955 constexpr int kExpandedOverlaySpace = 0x120000;
2956 int pos = kExpandedOverlaySpace;
2967 for (
size_t t = 0; t < overlay_data.size(); t += 3) {
2968 if (t + 2 < overlay_data.size()) {
2972 pos + 1, overlay_data[t] | (overlay_data[t + 1] << 8)));
2986 return absl::OkStatus();
2997 return absl::OkStatus();
3007 if (enable_flag != 0x00 && enable_flag != 0xFF) {
3009 std::array<uint8_t, kDiggableTilesBitfieldSize> bitfield;
3020 return absl::OkStatus();
3027 return absl::OkStatus();
3043 return absl::OkStatus();
3052 for (uint16_t tile_id = 0;
3053 tile_id < static_cast<uint16_t>(
tiles16_.size()) &&
3061 util::logf(
"Auto-detected %d diggable tiles",
3063 return absl::OkStatus();
3067 bool enable_main_palette,
3069 bool enable_gfx_groups,
3070 bool enable_subscreen_overlay,
3071 bool enable_animated) {
3076 return absl::OkStatus();
3083 uint8_t enable_value = enable_bg_color ? 0xFF : 0x00;
3087 enable_value = enable_main_palette ? 0xFF : 0x00;
3100 uint8_t enable_value = enable_mosaic ? 0xFF : 0x00;
3104 enable_value = enable_gfx_groups ? 0xFF : 0x00;
3108 enable_value = enable_animated ? 0xFF : 0x00;
3112 enable_value = enable_subscreen_overlay ? 0xFF : 0x00;
3120 uint8_t mosaic_byte = (mosaic[0] ? 0x08 : 0x00) |
3121 (mosaic[1] ? 0x04 : 0x00) |
3122 (mosaic[2] ? 0x02 : 0x00) |
3123 (mosaic[3] ? 0x01 : 0x00);
3131 for (
int j = 0; j < 8; j++) {
3148 return absl::OkStatus();
3155 return absl::OkStatus();
3158 util::logf(
"Saving Area Specific Background Colors");
3167 return absl::OkStatus();
3218 return absl::OkStatus();
3243 return absl::OkStatus();
3251 if (asm_version < 3 || asm_version == 0xFF) {
3252 return absl::OkStatus();
3257 uint8_t area_size_byte =
3269 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
RAII timer for automatic timing management.
Tile composition of four 16x16 tiles.
uint64_t GetPackedValue() const
SNES 16-bit tile metadata container.
int GetDiggableCount() const
Get the count of tiles marked as diggable.
void SetVanillaDefaults()
Reset to vanilla diggable tiles.
void FromBytes(const uint8_t *data)
Load bitfield from raw bytes (64 bytes).
void SetDiggable(uint16_t tile_id, bool diggable)
Set or clear the diggable bit for a Map16 tile ID.
static bool IsTile16Diggable(const gfx::Tile16 &tile16, const std::array< uint8_t, 0x200 > &all_tiles_types)
Check if a Tile16 should be diggable based on its component tiles.
const std::array< uint8_t, kDiggableTilesBitfieldSize > & GetRawData() const
Get raw bitfield data for direct ROM writing.
void Clear()
Clear all diggable bits.
static bool SupportsCustomBGColors(OverworldVersion version)
Check if ROM supports custom background colors per area (v2+)
static OverworldVersion GetVersion(const Rom &rom)
Detect ROM version from ASM marker byte.
static bool SupportsAreaEnum(OverworldVersion version)
Check if ROM supports area enum system (v3+ only)
static bool SupportsExpandedSpace(OverworldVersion version)
Check if ROM uses expanded ROM space for overworld data.
static const char * GetVersionName(OverworldVersion version)
Get human-readable version name for display/logging.
absl::Status SaveMap32Expanded()
Save expanded tile32 definitions (v1+ ROMs)
absl::Status DecompressAllMapTilesParallel()
std::vector< uint16_t > tiles32_list_
absl::Status Load(Rom *rom)
Load all overworld data from ROM.
std::vector< OverworldItem > all_items_
void OrganizeMapTiles(std::vector< uint8_t > &bytes, std::vector< uint8_t > &bytes2, int i, int sx, int sy, int &ttpos)
zelda3_version_pointers version_constants() const
Get version-specific ROM addresses.
std::array< int, kNumOverworldMaps > map_pointers1
std::vector< gfx::Tile32 > tiles32_unique_
absl::Status SaveMapProperties()
Save per-area graphics, palettes, and messages.
absl::Status SaveMap32Tiles()
Save tile32 definitions to ROM.
std::vector< OverworldEntrance > all_entrances_
absl::Status SaveTallAreaTransitions(int i, int parent_x_pos, int parent_y_pos, int transition_target_north, int transition_target_west, int transition_pos_x, int transition_pos_y, int screen_change_1, int screen_change_2, int screen_change_3, int screen_change_4)
Save screen transition data for tall (1x2) areas (v3+ only)
OverworldMapTiles map_tiles_
absl::Status SaveMap16Tiles()
Save tile16 definitions to ROM.
absl::Status SaveAreaSizes()
Save area size enum data (v3+ only)
void InvalidateSiblingMapCaches(int map_index)
Invalidate cached tilesets for a map and all its siblings.
absl::Status SaveLargeMaps()
Save large map parent/sibling relationships.
std::array< uint8_t, kNumOverworldMaps > map_parent_
void AssignWorldTiles(int x, int y, int sx, int sy, int tpos, OverworldBlockset &world)
absl::Status SaveDiggableTiles()
void InvalidateMapCache(int map_index)
Invalidate cached tileset for a specific map.
std::array< uint8_t, kNumTileTypes > all_tiles_types_
auto current_graphics() const
std::unordered_map< uint64_t, GraphicsConfigCache > gfx_config_cache_
void LoadTileTypes()
Load tile type collision data.
absl::Status CreateTile32Tilemap()
Build tile32 tilemap from current tile16 data.
std::array< int, kNumOverworldMaps > map_pointers1_id
const std::vector< uint8_t > * GetCachedTileset(uint64_t config_hash)
Try to get cached tileset data for a graphics configuration.
absl::Status SaveLargeAreaTransitions(int i, int parent_x_pos, int parent_y_pos, int transition_target_north, int transition_target_west, int transition_pos_x, int transition_pos_y, int screen_change_1, int screen_change_2, int screen_change_3, int screen_change_4)
Save screen transition data for large (2x2) areas.
OverworldBlockset & SelectWorldBlockset(int world_type)
bool HasExpandedPointerTables() const
Check if the ROM has expanded pointer tables for tail maps.
static constexpr int kMaxCachedConfigs
absl::Status SaveCustomOverworldASM(bool enable_bg_color, bool enable_main_palette, bool enable_mosaic, bool enable_gfx_groups, bool enable_subscreen_overlay, bool enable_animated)
Save custom ASM feature enable flags.
void FillBlankMapTiles(int map_index)
auto mutable_overworld_map(int i)
absl::Status SaveEntrances()
Save entrance warp points to ROM.
absl::Status SaveExits()
Save exit return points to ROM.
absl::Status LoadSprites()
Load sprite data for all game states.
absl::Status EnsureMapBuilt(int map_index)
Build a map on-demand if it hasn't been built yet.
uint64_t ComputeGraphicsConfigHash(int map_index)
Compute hash of graphics configuration for cache lookup.
std::vector< OverworldMap > overworld_maps_
void CacheTileset(uint64_t config_hash, const std::vector< uint8_t > &tileset)
Cache tileset data for future reuse.
absl::Status SaveItems()
Save hidden overworld items to ROM.
absl::Status SaveAreaSpecificBGColors()
Save per-area background colors (v2+)
absl::Status LoadDiggableTiles()
absl::Status Save(Rom *rom)
Master save method (calls sub-methods in correct order)
absl::Status SaveWideAreaTransitions(int i, int parent_x_pos, int parent_y_pos, int transition_target_north, int transition_target_west, int transition_pos_x, int transition_pos_y, int screen_change_1, int screen_change_2, int screen_change_3, int screen_change_4)
Save screen transition data for wide (2x1) areas (v3+ only)
absl::Status SaveOverworldMaps()
Save compressed map tile data to ROM.
std::array< std::vector< Sprite >, 3 > all_sprites_
std::array< int, kNumOverworldMaps > map_pointers2_id
absl::Status LoadOverworldMaps()
Load overworld map tile data.
std::vector< gfx::Tile16 > tiles16_
absl::Status AutoDetectDiggableTiles()
absl::Status AssembleMap16Tiles()
absl::Status LoadSpritesFromMap(int sprite_start, int sprite_count, int sprite_index)
Load sprites from a specific map range.
std::array< std::vector< uint8_t >, kNumOverworldMaps > map_data_p1
absl::Status SaveLargeMapsExpanded()
Save expanded large map data (v1+ ROMs)
void AssignMapSizes(std::vector< OverworldMap > &maps)
Assign map sizes based on area size enum (v3+)
absl::Status SaveMap16Expanded()
Save expanded tile16 definitions (v1+ ROMs)
std::vector< OverworldExit > all_exits_
std::array< int, kNumOverworldMaps > map_pointers2
absl::StatusOr< uint16_t > GetTile16ForTile32(int index, int quadrant, int dimension, const uint32_t *map32address)
std::array< std::vector< uint8_t >, kNumOverworldMaps > map_data_p2
absl::Status SaveSmallAreaTransitions(int i, int parent_x_pos, int parent_y_pos, int transition_target_north, int transition_target_west, int transition_pos_x, int transition_pos_y, int screen_change_1, int screen_change_2, int screen_change_3, int screen_change_4)
Save screen transition data for small (1x1) areas.
std::deque< int > built_map_lru_
absl::Status SaveMapOverlays()
Save interactive overlay data to ROM.
absl::Status AssembleMap32Tiles()
DiggableTiles diggable_tiles_
static constexpr int kMaxBuiltMaps
OverworldBlockset & GetMapTiles(int world_type)
absl::Status SaveOverworldTilesType()
Save tile type collision data to ROM.
absl::Status SaveMusic()
Save per-area music IDs.
absl::Status ConfigureMultiAreaMap(int parent_index, AreaSizeEnum size)
Configure a multi-area map structure (Large/Wide/Tall)
std::vector< OverworldEntrance > all_holes_
#define LOG_DEBUG(category, format,...)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::vector< uint8_t > HyruleMagicDecompress(uint8_t const *src, int *const size, int const p_big_endian, size_t max_src_size)
TileInfo GetTilesInfo(uint16_t tile)
std::vector< uint8_t > HyruleMagicCompress(uint8_t const *const src, int const oldsize, int *const size, int const flag)
std::string HexByte(uint8_t byte, HexStringParams params)
void logf(const absl::FormatSpec< Args... > &format, Args &&... args)
std::string HexLong(uint32_t dword, HexStringParams params)
std::vector< uint64_t > GetAllTile16(OverworldMapTiles &map_tiles_)
Zelda 3 specific classes and functions.
constexpr int kDiggableTilesBitfieldSize
constexpr int kAreaGfxIdPtr
absl::Status SaveEntrances(Rom *rom, const std::vector< OverworldEntrance > &entrances, bool expanded_entrances)
constexpr int OverworldCustomTileGFXGroupEnabled
constexpr int OverworldCustomAreaSpecificBGEnabled
constexpr int kOverworldTransitionPositionY
constexpr int kNumMapsPerWorld
constexpr int kOverworldSpriteset
constexpr int kMap16ExpandedFlagPos
constexpr int LimitOfMap32
constexpr int NumberOfMap16Ex
absl::StatusOr< std::vector< OverworldEntrance > > LoadEntrances(Rom *rom)
absl::Status SaveItems(Rom *rom, const std::vector< OverworldItem > &items)
constexpr int kOverworldScreenTileMapChangeByScreen1
constexpr int kOverworldScreenTileMapChangeByScreen2Expanded
constexpr int kOverworldMapDataOverflow
constexpr int kOverworldMapSizeHighByte
absl::StatusOr< std::vector< OverworldItem > > LoadItems(Rom *rom, std::vector< OverworldMap > &overworld_maps)
constexpr int overworldSpritesBeginingExpanded
constexpr int kNumTileTypes
constexpr int NumberOfMap32
constexpr int kOverworldScreenSize
constexpr int kOverworldScreenTileMapChangeByScreen4
constexpr int kNumTile16Individual
constexpr int kSpecialWorldMapIdStart
constexpr int OverworldCustomMosaicArray
constexpr int kOverworldCustomDiggableTilesEnabled
constexpr int kOverworldTransitionPositionXExpanded
constexpr int kMap16Tiles
constexpr int overworldSpritesAgahnimExpanded
constexpr int OverworldCustomAnimatedGFXEnabled
constexpr int OverworldCustomMainPaletteEnabled
constexpr int kNumOverworldMaps
constexpr int OverworldCustomMainPaletteArray
constexpr int kOverworldTransitionPositionYExpanded
constexpr int kOverworldMapParentIdExpanded
constexpr int kOverworldMusicBeginning
std::vector< std::vector< uint16_t > > OverworldBlockset
Represents tile32 data for the overworld.
constexpr int kMap32TileBLExpanded
AreaSizeEnum
Area size enumeration for v3+ ROMs.
constexpr int kOverworldTransitionPositionX
constexpr int kOverworldMusicDarkWorld
constexpr int kOverworldSpecialPalGroup
constexpr int kOverworldScreenSizeForLoading
constexpr int kOverworldSpritePaletteIds
constexpr int overworldTilesType
constexpr int transition_target_westExpanded
absl::StatusOr< std::vector< OverworldExit > > LoadExits(Rom *rom)
constexpr int kMap32TileBRExpanded
constexpr int kMap32TileCountExpanded
constexpr int kTransitionTargetWest
constexpr int OverworldCustomASMHasBeenApplied
constexpr int kOverworldMusicAgahnim
constexpr int kOverworldSpritesZelda
constexpr int kOverworldMapParentId
constexpr int kOverworldCustomDiggableTilesArray
constexpr int kMap32ExpandedFlagPos
@ kZSCustomV1
Basic features, expanded pointers.
@ kVanilla
0xFF in ROM, no ZScream ASM applied
constexpr int kOverworldMessagesExpanded
constexpr int kOverworldMusicMasterSword
constexpr int kOverworldScreenTileMapChangeByScreen3Expanded
constexpr int kOverworldMusicZelda
constexpr int transition_target_northExpanded
constexpr int NumberOfMap16
constexpr int kOverworldMapSize
constexpr int kOverworldScreenTileMapChangeByScreen2
constexpr int OverworldCustomAnimatedGFXArray
constexpr int kDarkWorldMapIdStart
absl::Status SaveHoles(Rom *rom, const std::vector< OverworldEntrance > &holes)
absl::StatusOr< std::vector< OverworldEntrance > > LoadHoles(Rom *rom)
constexpr int OverworldCustomMosaicEnabled
constexpr int kOverworldCompressedMapPos
constexpr int kMaxDiggableTileId
constexpr int kOverworldScreenTileMapChangeByScreen4Expanded
constexpr int kOverworldSpritesBeginning
constexpr int kOverworldScreenTileMapChangeByScreen3
constexpr int kOverworldScreenTileMapChangeByScreen1Expanded
constexpr int OverworldCustomTileGFXGroupArray
constexpr int kMap16TilesExpanded
constexpr int OverworldCustomSubscreenOverlayEnabled
constexpr int OverworldCustomAreaSpecificBGPalette
constexpr int kOverworldSpritesAgahnim
constexpr int kTransitionTargetNorth
constexpr int overworldSpritesZeldaExpanded
constexpr int kOverworldCompressedOverflowPos
constexpr int kOverlayCodeStart
constexpr int kMap32TileTRExpanded
absl::Status SaveExits(Rom *rom, const std::vector< OverworldExit > &exits)
constexpr int kOverworldMapPaletteIds
constexpr int kOverworldSpecialGfxGroup
constexpr int OverworldCustomSubscreenOverlayArray
uint32_t PcToSnes(uint32_t addr)
uint32_t SnesToPc(uint32_t addr) noexcept
#define RETURN_IF_ERROR(expr)
bool kEnableSpecialWorldExpansion
struct yaze::core::FeatureFlags::Flags::Overworld overworld
Overworld map tile32 data.
OverworldBlockset dark_world
OverworldBlockset special_world
OverworldBlockset light_world
uint32_t kOverworldTilesType