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");
125 return absl::OkStatus();
145 }
else if (i == parent + 1) {
147 }
else if (i == parent + 8) {
149 }
else if (i == parent + 9) {
160 std::array<bool, kNumOverworldMaps> map_checked{};
161 std::ranges::fill(map_checked,
false);
164 for (
int world_offset = 0; world_offset < 128; world_offset += 64) {
165 for (
int local = 0; local < 64; local++) {
166 int i = world_offset + local;
181 }
else if (i == parent + 1) {
183 }
else if (i == parent + 8) {
185 }
else if (i == parent + 9) {
190 map_checked[i] =
true;
195 std::array<int, 4> siblings = {parent, parent + 1, parent + 8,
197 int world_start = world_offset;
198 int world_end = world_offset + 64;
199 for (
int q = 0; q < 4; q++) {
200 int sibling = siblings[q];
202 if (sibling >= world_start && sibling < world_end &&
203 !map_checked[sibling]) {
205 map_checked[sibling] =
true;
211 map_checked[i] =
true;
229 int i = world + xx + (yy * 8);
231 if (i >=
static_cast<int>(map_checked.size())) {
235 if (!map_checked[i]) {
236 switch (maps[i].area_size()) {
238 map_checked[i] =
true;
243 map_checked[i] =
true;
244 maps[i].SetAsLargeMap(i, 0);
246 if (i + 1 <
static_cast<int>(maps.size())) {
247 map_checked[i + 1] =
true;
248 maps[i + 1].SetAsLargeMap(i, 1);
251 if (i + 8 <
static_cast<int>(maps.size())) {
252 map_checked[i + 8] =
true;
253 maps[i + 8].SetAsLargeMap(i, 2);
256 if (i + 9 <
static_cast<int>(maps.size())) {
257 map_checked[i + 9] =
true;
258 maps[i + 9].SetAsLargeMap(i, 3);
265 map_checked[i] =
true;
268 maps[i].SetParent(i);
271 if (i + 1 <
static_cast<int>(maps.size())) {
272 map_checked[i + 1] =
true;
273 maps[i + 1].SetParent(i);
281 map_checked[i] =
true;
284 maps[i].SetParent(i);
287 if (i + 8 <
static_cast<int>(maps.size())) {
288 map_checked[i + 8] =
true;
289 maps[i + 8].SetParent(i);
312 return absl::InvalidArgumentError(
313 absl::StrFormat(
"Invalid parent index: %d", parent_index));
322 return absl::FailedPreconditionError(
323 "Wide and Tall areas require ZSCustomOverworld v3+");
327 "ConfigureMultiAreaMap: parent=%d, current_size=%d, new_size=%d, "
331 static_cast<int>(size),
335 std::vector<int> old_siblings;
341 old_siblings = {old_parent, old_parent + 1, old_parent + 8,
345 old_siblings = {old_parent, old_parent + 1};
348 old_siblings = {old_parent, old_parent + 8};
351 old_siblings = {parent_index};
356 for (
int old_sibling : old_siblings) {
363 std::vector<int> new_siblings;
370 new_siblings = {parent_index};
374 new_siblings = {parent_index, parent_index + 1, parent_index + 8,
376 for (
size_t i = 0; i < new_siblings.size(); ++i) {
377 int sibling = new_siblings[i];
385 new_siblings = {parent_index, parent_index + 1};
386 for (
int sibling : new_siblings) {
395 new_siblings = {parent_index, parent_index + 8};
396 for (
int sibling : new_siblings) {
406 std::set<int> all_affected;
407 for (
int sibling : old_siblings) {
408 all_affected.insert(sibling);
410 for (
int sibling : new_siblings) {
411 all_affected.insert(sibling);
416 for (
int sibling : all_affected) {
428 for (
int sibling : all_affected) {
440 for (
int sibling : all_affected) {
455 "Configured %s area: parent=%d, old_siblings=%zu, new_siblings=%zu",
460 parent_index, old_siblings.size(), new_siblings.size());
462 return absl::OkStatus();
466 int index,
int quadrant,
int dimension,
const uint32_t* map32address) {
468 auto arg1,
rom()->ReadByte(map32address[dimension] + quadrant + (index)));
470 rom()->ReadWord(map32address[dimension] + (index) +
471 (quadrant <= 1 ? 4 : 5)));
472 return (uint16_t)(arg1 +
473 (((arg2 >> (quadrant % 2 == 0 ? 4 : 0)) & 0x0F) * 256));
477 constexpr int kMap32TilesLength = 0x33F0;
478 int num_tile32 = kMap32TilesLength;
479 uint32_t map32address[4] = {
487 util::logf(
"Expanded tile32 flag: %d", expanded_flag);
488 if (expanded_flag != 0x04 ||
501 for (
int i = 0; i < num_tile32; i += 6) {
503 for (
int k = 0; k < 4; k++) {
527 for (
int i = 0; i < 0x200; i++) {
533 return absl::OkStatus();
544 util::logf(
"Expanded tile16 flag: %d", expanded_flag);
554 for (
int i = 0; i < num_tile16; i += 1) {
567 tiles16_.emplace_back(t0, t1, t2, t3);
569 return absl::OkStatus();
574 int position_x1 = (x * 2) + (sx * 32);
575 int position_y1 = (y * 2) + (sy * 32);
576 int position_x2 = (x * 2) + 1 + (sx * 32);
577 int position_y2 = (y * 2) + 1 + (sy * 32);
585 switch (world_type) {
604 int local_index = map_index % 64;
605 int sx = local_index % 8;
606 int sy = local_index / 8;
610 for (
int y = 0; y < 32; ++y) {
611 for (
int x = 0; x < 32; ++x) {
612 world[(sx * 32) + x][(sy * 32) + y] = 0;
618 std::vector<uint8_t>& bytes2,
int i,
int sx,
619 int sy,
int& ttpos) {
620 for (
int y = 0; y < 16; y++) {
621 for (
int x = 0; x < 16; x++) {
622 auto tidD = (uint16_t)((bytes2[ttpos] << 8) + bytes[ttpos]);
638 const auto get_ow_map_gfx_ptr = [
this](
int index, uint32_t map_ptr) {
639 int p = (
rom()->data()[map_ptr + 2 + (3 * index)] << 16) +
640 (
rom()->data()[map_ptr + 1 + (3 * index)] << 8) +
641 (
rom()->data()[map_ptr + (3 * index)]);
645 constexpr uint32_t kBaseLowest = 0x0FFFFF;
646 constexpr uint32_t kBaseHighest = 0x0F8000;
648 uint32_t lowest = kBaseLowest;
649 uint32_t highest = kBaseHighest;
656 const bool allow_special_tail =
662 if (!allow_special_tail &&
679 auto p1 = get_ow_map_gfx_ptr(
681 auto p2 = get_ow_map_gfx_ptr(
686 bool pointers_valid =
687 (p1 > 0 && p2 > 0 && p1 <
rom()->size() && p2 <
rom()->size());
688 if (!pointers_valid) {
710 if (p1 <= lowest && p1 > kBaseHighest)
712 if (p2 <= lowest && p2 > kBaseHighest)
716 size_t max_size_p2 =
rom()->size() - p2;
719 size_t max_size_p1 =
rom()->size() - p1;
724 if (bytes.empty() || bytes2.empty()) {
744 return absl::OkStatus();
755 constexpr int kEssentialMapsPerWorld = 4;
757 constexpr int kEssentialMapsPerWorld = 16;
759 constexpr int kLightWorldEssential = kEssentialMapsPerWorld;
760 constexpr int kDarkWorldEssential =
762 constexpr int kSpecialWorldEssential =
766 "Building essential maps only (first %d maps per world) for faster "
768 kEssentialMapsPerWorld);
776 bool is_essential =
false;
778 if (i < kLightWorldEssential) {
801 if (map->is_large_map() &&
803 if (map->parent() != i && !map->is_initialized()) {
806 map->set_sprite_graphics(0, 0x0E);
807 map->set_sprite_graphics(1, 0x0E);
808 map->set_sprite_graphics(2, 0x0E);
809 map->set_area_graphics(
813 }
else if (i == 0x88) {
814 map->set_area_graphics(0x51);
815 map->set_area_palette(0x00);
819 map->set_area_palette(
829 const std::vector<uint8_t>* cached_tileset =
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();
917 return absl::OkStatus();
949 if (map->parent() != map_index && !map->is_initialized()) {
955 map->set_sprite_graphics(0, 0x0E);
956 map->set_sprite_graphics(1, 0x0E);
957 map->set_sprite_graphics(2, 0x0E);
958 map->set_area_graphics(
962 }
else if (map_index == 0x88) {
963 map->set_area_graphics(0x51);
964 map->set_area_palette(0x00);
987 if (!cached_tileset) {
1018 hash ^=
static_cast<uint64_t
>(world_type) << 62;
1019 hash *= 0x517cc1b727220a95ULL;
1024 for (
int i = 0; i < 12; ++i) {
1025 hash ^=
static_cast<uint64_t
>(map->static_graphics(i)) << ((i % 8) * 8);
1026 hash *= 0x517cc1b727220a95ULL;
1033 hash *= 0x517cc1b727220a95ULL;
1037 for (
int i = 0; i < 3; ++i) {
1038 hash ^=
static_cast<uint64_t
>(map->sprite_graphics(i)) << (52 + i * 4);
1039 hash *= 0x517cc1b727220a95ULL;
1043 hash ^=
static_cast<uint64_t
>(map->area_graphics()) << 48;
1044 hash *= 0x517cc1b727220a95ULL;
1048 hash ^=
static_cast<uint64_t
>(map->main_gfx_id()) << 56;
1049 hash *= 0x517cc1b727220a95ULL;
1052 hash ^=
static_cast<uint64_t
>(map->parent()) << 40;
1053 hash *= 0x517cc1b727220a95ULL;
1059 hash ^=
static_cast<uint64_t
>(map_index) << 8;
1060 hash *= 0x517cc1b727220a95ULL;
1063 hash ^=
static_cast<uint64_t
>(map->main_palette()) << 24;
1064 hash *= 0x517cc1b727220a95ULL;
1067 hash ^=
static_cast<uint64_t
>(map->animated_gfx()) << 16;
1068 hash *= 0x517cc1b727220a95ULL;
1071 hash ^=
static_cast<uint64_t
>(map->area_palette()) << 32;
1072 hash *= 0x517cc1b727220a95ULL;
1076 hash ^=
static_cast<uint64_t
>(map->subscreen_overlay());
1077 hash *= 0x517cc1b727220a95ULL;
1085 it->second.reference_count++;
1086 return &it->second.current_gfx;
1092 const std::vector<uint8_t>& tileset) {
1099 if (it->second.reference_count < min_it->second.reference_count) {
1135 int parent_id = map->parent();
1136 std::vector<int> siblings;
1142 switch (map->area_size()) {
1144 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1147 siblings = {parent_id, parent_id + 1};
1150 siblings = {parent_id, parent_id + 8};
1153 siblings = {map_index};
1158 if (map->is_large_map()) {
1159 siblings = {parent_id, parent_id + 1, parent_id + 8, parent_id + 9};
1161 siblings = {map_index};
1166 for (
int sibling : siblings) {
1176#ifdef __EMSCRIPTEN__
1191 std::vector<std::future<absl::Status>> futures;
1195 futures.emplace_back(std::async(std::launch::async, [
this]() {
1198 futures.emplace_back(std::async(std::launch::async, [
this]() {
1201 futures.emplace_back(std::async(std::launch::async, [
this]() {
1206 futures.emplace_back(std::async(std::launch::async, [
this]() {
1209 futures.emplace_back(std::async(std::launch::async, [
this]() {
1212 futures.emplace_back(std::async(std::launch::async, [
this]() {
1217 for (
auto& future : futures) {
1222 return absl::OkStatus();
1226 int num_maps_per_gamestate,
1228 for (
int i = 0; i < num_maps_per_gamestate; i++) {
1232 int current_spr_ptr = sprites_per_gamestate_ptr + (i * 2);
1234 int sprite_address =
SnesToPc((0x09 << 0x10) | word_addr);
1242 int editor_map_index = i;
1243 if (game_state != 0) {
1244 if (editor_map_index >= 128)
1245 editor_map_index -= 128;
1246 else if (editor_map_index >= 64)
1247 editor_map_index -= 64;
1249 int mapY = (editor_map_index / 8);
1250 int mapX = (editor_map_index % 8);
1252 int realX = ((b2 & 0x3F) * 16) + mapX * 512;
1253 int realY = ((b1 & 0x3F) * 16) + mapY * 512;
1256 (uint8_t)(b2 & 0x3F), (uint8_t)(b1 & 0x3F), realX, realY);
1259 sprite_address += 3;
1263 return absl::OkStatus();
1289 return absl::OkStatus();
1306 std::vector<uint8_t> single_map_1(512);
1307 std::vector<uint8_t> single_map_2(512);
1311 for (
int y = 0; y < 16; y++) {
1312 for (
int x = 0; x < 16; x++) {
1314 single_map_1[npos] = packed & 0xFF;
1315 single_map_2[npos] = (packed >> 8) & 0xFF;
1324 if (a.empty() || b.empty()) {
1325 return absl::AbortedError(
"Error compressing map gfx.");
1332 if ((pos + size_a) >= 0x5FE70 && (pos + size_a) <= 0x60000) {
1336 if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) {
1337 util::logf(
"Pos set to overflow region for map %s at %s",
1342 const auto compare_array = [](
const std::vector<uint8_t>& array1,
1343 const std::vector<uint8_t>& array2) ->
bool {
1344 if (array1.size() != array2.size()) {
1348 for (
size_t i = 0; i < array1.size(); i++) {
1349 if (array1[i] != array2[i]) {
1357 for (
int j = 0; j < i; j++) {
1371 std::copy(a.begin(), a.end(),
map_data_p1[i].begin());
1374 util::logf(
"Saving map pointers1 and compressed data for map %s at %s",
1391 if ((pos + b.size()) >= 0x5FE70 && (pos + b.size()) <= 0x60000) {
1395 if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) {
1396 util::logf(
"Pos set to overflow region for map %s at %s",
1403 std::copy(b.begin(), b.end(),
map_data_p2[i].begin());
1406 util::logf(
"Saving map pointers2 and compressed data for map %s at %s",
1427 return absl::AbortedError(
"Too many maps data " + std::to_string(pos));
1431 return absl::OkStatus();
1438 bool use_expanded_transitions =
1441 if (use_expanded_transitions) {
1447 std::vector<uint8_t> checked_map;
1459 if (std::find(checked_map.begin(), checked_map.end(), i) !=
1460 checked_map.end()) {
1467 const uint8_t large_map_offsets[] = {0, 1, 8, 9};
1468 for (
const auto& offset : large_map_offsets) {
1493 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1496 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1500 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1503 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1507 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1510 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1514 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
1517 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
1521 (parent_x_pos * 0x200)));
1523 (parent_y_pos * 0x200)));
1527 (parent_x_pos * 0x200)));
1530 (parent_y_pos * 0x200)));
1534 (parent_x_pos * 0x200)));
1537 (parent_y_pos * 0x200)));
1541 (parent_x_pos * 0x200)));
1544 (parent_y_pos * 0x200)));
1553 if (parent_x_pos == 0) {
1656 checked_map.emplace_back(i);
1657 checked_map.emplace_back((i + 1));
1658 checked_map.emplace_back((i + 8));
1659 checked_map.emplace_back((i + 9));
1681 if (i - 1 >= 0 && parent_x_pos != 0) {
1693 if (i + 1 < 64 && parent_x_pos != 7) {
1737 (uint16_t)((y_pos * 0x200) - 0xE0)));
1739 (uint16_t)((x_pos * 0x200) - 0x100)));
1746 checked_map.emplace_back(i);
1750 constexpr int OverworldScreenTileMapChangeMask = 0x1262C;
1753 rom()->WriteShort(OverworldScreenTileMapChangeMask + 0, 0x1F80));
1755 rom()->WriteShort(OverworldScreenTileMapChangeMask + 2, 0x1F80));
1757 rom()->WriteShort(OverworldScreenTileMapChangeMask + 4, 0x007F));
1759 rom()->WriteShort(OverworldScreenTileMapChangeMask + 6, 0x007F));
1761 return absl::OkStatus();
1765 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
1766 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
1767 int screen_change_1,
int screen_change_2,
int screen_change_3,
1768 int screen_change_4) {
1771 rom()->WriteShort(transition_target_north + (i * 2),
1772 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
1774 rom()->WriteShort(transition_target_west + (i * 2),
1775 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
1778 rom()->WriteShort(transition_pos_x + (i * 2), parent_x_pos * 0x0200));
1780 rom()->WriteShort(transition_pos_y + (i * 2), parent_y_pos * 0x0200));
1783 uint16_t by_screen1_small = 0x0060;
1786 if ((i % 0x40) - 1 >= 0) {
1791 west_neighbor.large_index() == 3) {
1792 by_screen1_small = 0xF060;
1796 west_neighbor.large_index() == 2) {
1797 by_screen1_small = 0xF060;
1802 rom()->WriteShort(screen_change_1 + (i * 2), by_screen1_small));
1805 uint16_t by_screen2_small = 0x0040;
1813 east_neighbor.large_index() == 2) {
1814 by_screen2_small = 0xF040;
1818 east_neighbor.large_index() == 2) {
1819 by_screen2_small = 0xF040;
1824 rom()->WriteShort(screen_change_2 + (i * 2), by_screen2_small));
1827 uint16_t by_screen3_small = 0x1800;
1830 if ((i % 0x40) - 8 >= 0) {
1835 north_neighbor.large_index() == 3) {
1836 by_screen3_small = 0x17C0;
1840 north_neighbor.large_index() == 1) {
1841 by_screen3_small = 0x17C0;
1846 rom()->WriteShort(screen_change_3 + (i * 2), by_screen3_small));
1849 uint16_t by_screen4_small = 0x1000;
1857 south_neighbor.large_index() == 1) {
1858 by_screen4_small = 0x0FC0;
1862 south_neighbor.large_index() == 1) {
1863 by_screen4_small = 0x0FC0;
1868 rom()->WriteShort(screen_change_4 + (i * 2), by_screen4_small));
1870 return absl::OkStatus();
1874 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
1875 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
1876 int screen_change_1,
int screen_change_2,
int screen_change_3,
1877 int screen_change_4) {
1879 const uint16_t offsets[] = {0, 2, 16, 18};
1880 for (
auto offset : offsets) {
1882 rom()->WriteShort(transition_target_north + (i * 2) + offset,
1883 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
1885 rom()->WriteShort(transition_target_west + (i * 2) + offset,
1886 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
1888 parent_x_pos * 0x0200));
1890 parent_y_pos * 0x0200));
1895 std::array<uint16_t, 4> by_screen1_large = {0x0060, 0x0060, 0x1060, 0x1060};
1898 if ((i % 0x40) - 1 >= 0) {
1902 switch (west_neighbor.large_index()) {
1904 by_screen1_large[2] = 0x0060;
1907 by_screen1_large[0] = 0xF060;
1911 switch (west_neighbor.large_index()) {
1913 by_screen1_large[2] = 0x0060;
1916 by_screen1_large[0] = 0xF060;
1922 for (
int j = 0; j < 4; j++) {
1924 by_screen1_large[j]));
1928 std::array<uint16_t, 4> by_screen2_large = {0x0080, 0x0080, 0x1080, 0x1080};
1935 switch (east_neighbor.large_index()) {
1937 by_screen2_large[3] = 0x0080;
1940 by_screen2_large[1] = 0xF080;
1944 switch (east_neighbor.large_index()) {
1946 by_screen2_large[3] = 0x0080;
1949 by_screen2_large[1] = 0xF080;
1955 for (
int j = 0; j < 4; j++) {
1957 by_screen2_large[j]));
1961 std::array<uint16_t, 4> by_screen3_large = {0x1800, 0x1840, 0x1800, 0x1840};
1964 if ((i % 0x40) - 8 >= 0) {
1968 switch (north_neighbor.large_index()) {
1970 by_screen3_large[1] = 0x1800;
1973 by_screen3_large[0] = 0x17C0;
1977 switch (north_neighbor.large_index()) {
1979 by_screen3_large[1] = 0x1800;
1982 by_screen3_large[0] = 0x17C0;
1988 for (
int j = 0; j < 4; j++) {
1990 by_screen3_large[j]));
1994 std::array<uint16_t, 4> by_screen4_large = {0x2000, 0x2040, 0x2000, 0x2040};
2001 switch (south_neighbor.large_index()) {
2003 by_screen4_large[3] = 0x2000;
2006 by_screen4_large[2] = 0x1FC0;
2010 switch (south_neighbor.large_index()) {
2012 by_screen4_large[3] = 0x2000;
2015 by_screen4_large[2] = 0x1FC0;
2021 for (
int j = 0; j < 4; j++) {
2023 by_screen4_large[j]));
2026 return absl::OkStatus();
2030 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
2031 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
2032 int screen_change_1,
int screen_change_2,
int screen_change_3,
2033 int screen_change_4) {
2035 const uint16_t offsets[] = {0, 2};
2036 for (
auto offset : offsets) {
2038 rom()->WriteShort(transition_target_north + (i * 2) + offset,
2039 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
2041 rom()->WriteShort(transition_target_west + (i * 2) + offset,
2042 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
2044 parent_x_pos * 0x0200));
2046 parent_y_pos * 0x0200));
2050 std::array<uint16_t, 2> by_screen1_wide = {0x0060, 0x0060};
2053 if ((i % 0x40) - 1 >= 0) {
2058 west_neighbor.large_index() == 3) {
2059 by_screen1_wide[0] = 0xF060;
2063 west_neighbor.large_index() == 2) {
2064 by_screen1_wide[0] = 0xF060;
2068 for (
int j = 0; j < 2; j++) {
2070 by_screen1_wide[j]));
2074 std::array<uint16_t, 2> by_screen2_wide = {0x0080, 0x0080};
2082 east_neighbor.large_index() == 2) {
2083 by_screen2_wide[1] = 0xF080;
2087 east_neighbor.large_index() == 2) {
2088 by_screen2_wide[1] = 0xF080;
2092 for (
int j = 0; j < 2; j++) {
2094 by_screen2_wide[j]));
2098 std::array<uint16_t, 2> by_screen3_wide = {0x1800, 0x1840};
2101 if ((i % 0x40) - 8 >= 0) {
2105 switch (north_neighbor.large_index()) {
2107 by_screen3_wide[1] = 0x1800;
2110 by_screen3_wide[0] = 0x17C0;
2114 switch (north_neighbor.large_index()) {
2116 by_screen3_wide[1] = 0x1800;
2119 by_screen3_wide[0] = 0x07C0;
2125 for (
int j = 0; j < 2; j++) {
2127 by_screen3_wide[j]));
2131 std::array<uint16_t, 2> by_screen4_wide = {0x1000, 0x1040};
2138 switch (south_neighbor.large_index()) {
2140 by_screen4_wide[1] = 0x1000;
2143 by_screen4_wide[0] = 0x0FC0;
2147 if (south_neighbor.large_index() == 1) {
2148 by_screen4_wide[0] = 0x0FC0;
2150 switch (south_neighbor.large_index()) {
2152 by_screen4_wide[1] = 0x1000;
2155 by_screen4_wide[0] = 0x0FC0;
2161 for (
int j = 0; j < 2; j++) {
2163 by_screen4_wide[j]));
2166 return absl::OkStatus();
2170 int i,
int parent_x_pos,
int parent_y_pos,
int transition_target_north,
2171 int transition_target_west,
int transition_pos_x,
int transition_pos_y,
2172 int screen_change_1,
int screen_change_2,
int screen_change_3,
2173 int screen_change_4) {
2175 const uint16_t offsets[] = {0, 16};
2176 for (
auto offset : offsets) {
2178 rom()->WriteShort(transition_target_north + (i * 2) + offset,
2179 (uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
2181 rom()->WriteShort(transition_target_west + (i * 2) + offset,
2182 (uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
2184 parent_x_pos * 0x0200));
2186 parent_y_pos * 0x0200));
2190 std::array<uint16_t, 2> by_screen1_tall = {0x0060, 0x1060};
2193 if ((i % 0x40) - 1 >= 0) {
2197 switch (west_neighbor.large_index()) {
2199 by_screen1_tall[1] = 0x0060;
2202 by_screen1_tall[0] = 0xF060;
2206 switch (west_neighbor.large_index()) {
2208 by_screen1_tall[1] = 0x0060;
2211 by_screen1_tall[0] = 0xF060;
2217 for (
int j = 0; j < 2; j++) {
2219 by_screen1_tall[j]));
2223 std::array<uint16_t, 2> by_screen2_tall = {0x0040, 0x1040};
2230 switch (east_neighbor.large_index()) {
2232 by_screen2_tall[1] = 0x0040;
2235 by_screen2_tall[0] = 0xF040;
2239 switch (east_neighbor.large_index()) {
2241 by_screen2_tall[1] = 0x0040;
2244 by_screen2_tall[0] = 0xF040;
2250 for (
int j = 0; j < 2; j++) {
2252 by_screen2_tall[j]));
2256 std::array<uint16_t, 2> by_screen3_tall = {0x1800, 0x1800};
2259 if ((i % 0x40) - 8 >= 0) {
2264 north_neighbor.large_index() == 3) {
2265 by_screen3_tall[0] = 0x17C0;
2269 north_neighbor.large_index() == 1) {
2270 by_screen3_tall[0] = 0x17C0;
2274 for (
int j = 0; j < 2; j++) {
2276 by_screen3_tall[j]));
2280 std::array<uint16_t, 2> by_screen4_tall = {0x2000, 0x2000};
2288 south_neighbor.large_index() == 1) {
2289 by_screen4_tall[1] = 0x1FC0;
2293 south_neighbor.large_index() == 1) {
2294 by_screen4_tall[1] = 0x1FC0;
2298 for (
int j = 0; j < 2; j++) {
2300 by_screen4_tall[j]));
2303 return absl::OkStatus();
2307 util::logf(
"Saving Large Maps (v3+ Expanded)");
2319 std::vector<uint8_t> checked_map;
2324 if (std::find(checked_map.begin(), checked_map.end(), i) !=
2325 checked_map.end()) {
2340 i, parent_x_pos, parent_y_pos, transition_target_north,
2341 transition_target_west, transition_pos_x, transition_pos_y,
2342 screen_change_1, screen_change_2, screen_change_3,
2344 checked_map.emplace_back(i);
2349 i, parent_x_pos, parent_y_pos, transition_target_north,
2350 transition_target_west, transition_pos_x, transition_pos_y,
2351 screen_change_1, screen_change_2, screen_change_3,
2354 checked_map.emplace_back(i);
2355 checked_map.emplace_back(i + 1);
2356 checked_map.emplace_back(i + 8);
2357 checked_map.emplace_back(i + 9);
2362 i, parent_x_pos, parent_y_pos, transition_target_north,
2363 transition_target_west, transition_pos_x, transition_pos_y,
2364 screen_change_1, screen_change_2, screen_change_3,
2367 checked_map.emplace_back(i);
2368 checked_map.emplace_back(i + 1);
2373 i, parent_x_pos, parent_y_pos, transition_target_north,
2374 transition_target_west, transition_pos_x, transition_pos_y,
2375 screen_change_1, screen_change_2, screen_change_3,
2378 checked_map.emplace_back(i);
2379 checked_map.emplace_back(i + 8);
2384 return absl::OkStatus();
2389 std::vector<uint64_t> all_tile_16;
2404 for (
int y = 0; y < 32; y += 2) {
2405 for (
int x = 0; x < 32; x += 2) {
2407 tiles_used[x + (sx * 32)][y + (sy * 32)],
2408 tiles_used[x + 1 + (sx * 32)][y + (sy * 32)],
2409 tiles_used[x + (sx * 32)][y + 1 + (sy * 32)],
2410 tiles_used[x + 1 + (sx * 32)][y + 1 + (sy * 32)]);
2439 std::vector<uint64_t> all_tile_16 = GetAllTile16(
map_tiles_);
2442 std::set<uint64_t> unique_tiles_set(all_tile_16.begin(), all_tile_16.end());
2444 std::vector<uint64_t> unique_tiles(all_tile_16);
2445 unique_tiles.assign(unique_tiles_set.begin(), unique_tiles_set.end());
2448 std::unordered_map<uint64_t, uint16_t> all_tiles_indexed;
2449 for (
size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) {
2450 all_tiles_indexed.insert(
2451 {unique_tiles[tile32_id],
static_cast<uint16_t
>(tile32_id)});
2457 tiles32_list_.emplace_back(all_tiles_indexed[all_tile_16[j]]);
2461 for (
size_t i = 0; i < unique_tiles.size(); ++i) {
2471 return absl::InternalError(absl::StrFormat(
2472 "Number of unique Tiles32: %d Out of: %d\nUnique Tile32 count exceed "
2473 "the limit\nThe ROM Has not been saved\nYou can fill maps with grass "
2474 "tiles to free some space\nOr use the option Clear DW Tiles in the "
2491 return absl::OkStatus();
2540 constexpr int kTilesPer32x32Tile = 6;
2541 int unique_tile_index = 0;
2544 for (
int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
2545 if (unique_tile_index >= limit) {
2546 return absl::AbortedError(
"Too many unique tile32 definitions.");
2577 auto top_right = topRight;
2582 top_right + (i + 1),
2585 top_right + (i + 2),
2588 top_right + (i + 3),
2592 top_right + (i + 4),
2597 top_right + (i + 5),
2604 auto bottom_left = bottomLeft;
2609 bottom_left + (i + 1),
2612 bottom_left + (i + 2),
2615 bottom_left + (i + 3),
2619 bottom_left + (i + 4),
2624 bottom_left + (i + 5),
2631 auto bottom_right = bottomRight;
2636 bottom_right + (i + 1),
2639 bottom_right + (i + 2),
2642 bottom_right + (i + 3),
2646 bottom_right + (i + 4),
2651 bottom_right + (i + 5),
2657 unique_tile_index += 4;
2660 return absl::OkStatus();
2665 constexpr int kMaxUniqueTiles = 0x4540;
2666 constexpr int kTilesPer32x32Tile = 6;
2668 int unique_tile_index = 0;
2671 for (
int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
2672 if (unique_tile_index >= kMaxUniqueTiles) {
2673 return absl::AbortedError(
"Too many unique tile32 definitions.");
2710 top_right + (i + 1),
2713 top_right + (i + 2),
2716 top_right + (i + 3),
2720 top_right + (i + 4),
2725 top_right + (i + 5),
2785 unique_tile_index += 4;
2786 num_unique_tiles += 2;
2789 return absl::OkStatus();
2871 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile0_)));
2874 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile1_)));
2877 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile2_)));
2880 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile3_)));
2884 return absl::OkStatus();
2893 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile0_)))
2896 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile1_)))
2899 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile2_)))
2902 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile3_)))
2905 return absl::OkStatus();
2912 return absl::OkStatus();
2917 return absl::OkStatus();
2922 return absl::OkStatus();
2929 std::vector<uint8_t> new_overlay_code = {
2935 0xBF, 0x00, 0x00, 0x00,
2937 0xBF, 0x00, 0x00, 0x00,
2953 int snes_ptr_start =
PcToSnes(ptr_start);
2963 constexpr int kExpandedOverlaySpace = 0x120000;
2964 int pos = kExpandedOverlaySpace;
2975 for (
size_t t = 0; t < overlay_data.size(); t += 3) {
2976 if (t + 2 < overlay_data.size()) {
2980 pos + 1, overlay_data[t] | (overlay_data[t + 1] << 8)));
2994 return absl::OkStatus();
3005 return absl::OkStatus();
3015 if (enable_flag != 0x00 && enable_flag != 0xFF) {
3017 std::array<uint8_t, kDiggableTilesBitfieldSize> bitfield;
3028 return absl::OkStatus();
3036 return absl::OkStatus();
3051 return absl::OkStatus();
3060 for (uint16_t tile_id = 0; tile_id < static_cast<uint16_t>(
tiles16_.size()) &&
3068 util::logf(
"Auto-detected %d diggable tiles",
3070 return absl::OkStatus();
3074 bool enable_main_palette,
3076 bool enable_gfx_groups,
3077 bool enable_subscreen_overlay,
3078 bool enable_animated) {
3082 return absl::OkStatus();
3089 uint8_t enable_value = enable_bg_color ? 0xFF : 0x00;
3093 enable_value = enable_main_palette ? 0xFF : 0x00;
3106 uint8_t enable_value = enable_mosaic ? 0xFF : 0x00;
3110 enable_value = enable_gfx_groups ? 0xFF : 0x00;
3114 enable_value = enable_animated ? 0xFF : 0x00;
3118 enable_value = enable_subscreen_overlay ? 0xFF : 0x00;
3126 uint8_t mosaic_byte = (mosaic[0] ? 0x08 : 0x00) |
3127 (mosaic[1] ? 0x04 : 0x00) |
3128 (mosaic[2] ? 0x02 : 0x00) |
3129 (mosaic[3] ? 0x01 : 0x00);
3137 for (
int j = 0; j < 8; j++) {
3154 return absl::OkStatus();
3160 return absl::OkStatus();
3163 util::logf(
"Saving Area Specific Background Colors");
3172 return absl::OkStatus();
3223 return absl::OkStatus();
3248 return absl::OkStatus();
3256 if (asm_version < 3 || asm_version == 0xFF) {
3257 return absl::OkStatus();
3262 uint8_t area_size_byte =
3274 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_
OverworldVersion cached_version_
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