5#include <unordered_map>
8#include "absl/status/status.h"
21 if (
rom.size() == 0) {
22 return absl::InvalidArgumentError(
"ROM file not loaded");
42 return absl::OkStatus();
46 for (
int i = 128; i < 145; i++) {
56 std::array<bool, 0x40> map_checked;
57 std::fill(map_checked.begin(), map_checked.end(),
false);
62 if (
int i = xx + (yy * 8); map_checked[i] ==
false) {
64 map_checked[i] =
true;
68 map_checked[i + 1] =
true;
72 map_checked[i + 8] =
true;
76 map_checked[i + 9] =
true;
83 map_checked[i] =
true;
99 int index,
int quadrant,
int dimension,
const uint32_t *map32address) {
101 rom_.ReadByte(map32address[dimension] + quadrant + (index)));
103 (quadrant <= 1 ? 4 : 5)));
104 return (uint16_t)(arg1 +
105 (((arg2 >> (quadrant % 2 == 0 ? 4 : 0)) & 0x0F) * 256));
112 uint32_t map32address[4] = {
rom_.version_constants().kMap32TileTL,
113 rom_.version_constants().kMap32TileTR,
114 rom_.version_constants().kMap32TileBL,
115 rom_.version_constants().kMap32TileBR};
118 map32address[0] =
rom_.version_constants().kMap32TileTL;
127 for (
int i = 0; i < num_tile32; i += 6) {
129 for (
int k = 0; k < 4; k++) {
153 for (
int i = 0; i < 0x200; i++) {
159 return absl::OkStatus();
172 for (
int i = 0; i < num_tile16; i += 1) {
185 tiles16_.emplace_back(t0, t1, t2, t3);
187 return absl::OkStatus();
192 int position_x1 = (x * 2) + (sx * 32);
193 int position_y1 = (y * 2) + (sy * 32);
194 int position_x2 = (x * 2) + 1 + (sx * 32);
195 int position_y2 = (y * 2) + 1 + (sy * 32);
203 std::vector<uint8_t> &bytes2,
int i,
int sx,
204 int sy,
int &ttpos) {
205 for (
int y = 0; y < 16; y++) {
206 for (
int x = 0; x < 16; x++) {
207 auto tidD = (uint16_t)((bytes2[ttpos] << 8) + bytes[ttpos]);
223 const auto get_ow_map_gfx_ptr = [
this](
int index, uint32_t map_ptr) {
224 int p = (
rom()->data()[map_ptr + 2 + (3 * index)] << 16) +
225 (
rom()->data()[map_ptr + 1 + (3 * index)] << 8) +
226 (
rom()->data()[map_ptr + (3 * index)]);
230 constexpr uint32_t kBaseLowest = 0x0FFFFF;
231 constexpr uint32_t kBaseHighest = 0x0F8000;
233 uint32_t lowest = kBaseLowest;
234 uint32_t highest = kBaseHighest;
239 auto p1 = get_ow_map_gfx_ptr(
240 i,
rom()->version_constants().kCompressedAllMap32PointersHigh);
241 auto p2 = get_ow_map_gfx_ptr(
242 i,
rom()->version_constants().kCompressedAllMap32PointersLow);
246 if (p1 >= highest) highest = p1;
247 if (p2 >= highest) highest = p2;
249 if (p1 <= lowest && p1 > kBaseHighest) lowest = p1;
250 if (p2 <= lowest && p2 > kBaseHighest) lowest = p2;
274 std::vector<std::future<absl::Status>> futures;
282 auto task_function = [
this, i, size, world_type]() {
286 futures.emplace_back(std::async(std::launch::async, task_function));
290 for (
auto &future : futures) {
294 return absl::OkStatus();
300 rom()->data()[
rom()->version_constants().kOverworldTilesType + i];
308 int num_entrances = 129;
317 for (
int i = 0; i < num_entrances; i++) {
319 rom()->ReadWord(ow_entrance_map_ptr + (i * 2)));
321 rom()->ReadWord(ow_entrance_pos_ptr + (i * 2)));
323 int p = map_pos >> 1;
326 bool deleted =
false;
327 if (map_pos == 0xFFFF) {
331 (x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
332 (y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id, map_pos,
336 return absl::OkStatus();
340 constexpr int kNumHoles = 0x13;
341 for (
int i = 0; i < kNumHoles; i++) {
348 int p = (map_pos + 0x400) >> 1;
352 (x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
353 (y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id,
354 (uint16_t)(map_pos + 0x400),
true);
356 return absl::OkStatus();
360 const int NumberOfOverworldExits = 0x4F;
361 std::vector<OverworldExit>
exits;
362 for (
int i = 0; i < NumberOfOverworldExits; i++) {
363 auto rom_data =
rom()->data();
365 uint16_t exit_room_id;
366 uint16_t exit_map_id;
368 uint16_t exit_y_scroll;
369 uint16_t exit_x_scroll;
370 uint16_t exit_y_player;
371 uint16_t exit_x_player;
372 uint16_t exit_y_camera;
373 uint16_t exit_x_camera;
374 uint16_t exit_scroll_mod_y;
375 uint16_t exit_scroll_mod_x;
376 uint16_t exit_door_type_1;
377 uint16_t exit_door_type_2;
385 exit_scroll_mod_x,
OWExitUnk2 + i, exit_door_type_1,
389 uint16_t py = (uint16_t)((rom_data[
OWExitYPlayer + (i * 2) + 1] << 8) +
391 uint16_t px = (uint16_t)((rom_data[
OWExitXPlayer + (i * 2) + 1] << 8) +
395 std::cout <<
"Exit: " << i <<
" RoomID: " << exit_room_id
396 <<
" MapID: " << exit_map_id <<
" VRAM: " << exit_vram
397 <<
" YScroll: " << exit_y_scroll
398 <<
" XScroll: " << exit_x_scroll <<
" YPlayer: " << py
399 <<
" XPlayer: " << px <<
" YCamera: " << exit_y_camera
400 <<
" XCamera: " << exit_x_camera
401 <<
" ScrollModY: " << exit_scroll_mod_y
402 <<
" ScrollModX: " << exit_scroll_mod_x
403 <<
" DoorType1: " << exit_door_type_1
404 <<
" DoorType2: " << exit_door_type_2 << std::endl;
407 exits.emplace_back(exit_room_id, exit_map_id, exit_vram, exit_y_scroll,
408 exit_x_scroll, py, px, exit_y_camera, exit_x_camera,
409 exit_scroll_mod_y, exit_scroll_mod_x, exit_door_type_1,
410 exit_door_type_2, (px & py) == 0xFFFF);
413 return absl::OkStatus();
419 uint32_t pointer_pc =
SnesToPc(pointer);
420 for (
int i = 0; i < 128; i++) {
422 rom()->ReadWord(pointer_pc + i * 2));
423 uint32_t addr = (pointer & 0xFF0000) | word_address;
437 if (b1 == 0xFF && b2 == 0xFF) {
441 int p = (((b2 & 0x1F) << 8) + b1) >> 1;
452 int sx = fakeID - (sy * 8);
454 all_items_.emplace_back(b3, (uint16_t)i, (x * 16) + (sx * 512),
455 (y * 16) + (sy * 512),
false);
463 return absl::OkStatus();
467 std::vector<std::future<absl::Status>> futures;
468 futures.emplace_back(std::async(std::launch::async, [
this]() {
471 futures.emplace_back(std::async(std::launch::async, [
this]() {
474 futures.emplace_back(std::async(std::launch::async, [
this]() {
478 for (
auto &future : futures) {
482 return absl::OkStatus();
486 int num_maps_per_gamestate,
488 for (
int i = 0; i < num_maps_per_gamestate; i++) {
491 int current_spr_ptr = sprites_per_gamestate_ptr + (i * 2);
493 int sprite_address =
SnesToPc((0x09 << 0x10) | word_addr);
498 if (b1 == 0xFF)
break;
500 int editor_map_index = i;
501 if (game_state != 0) {
502 if (editor_map_index >= 128)
503 editor_map_index -= 128;
504 else if (editor_map_index >= 64)
505 editor_map_index -= 64;
507 int mapY = (editor_map_index / 8);
508 int mapX = (editor_map_index % 8);
510 int realX = ((b2 & 0x3F) * 16) + mapX * 512;
511 int realY = ((b1 & 0x3F) * 16) + mapY * 512;
514 (uint8_t)(b2 & 0x3F), (uint8_t)(b1 & 0x3F), realX, realY);
521 return absl::OkStatus();
533 return absl::OkStatus();
537 util::logf(
"Saving Overworld Maps");
546 std::vector<uint8_t> single_map_1(512);
547 std::vector<uint8_t> single_map_2(512);
551 for (
int y = 0; y < 16; y++) {
552 for (
int x = 0; x < 16; x++) {
554 single_map_1[npos] = packed & 0xFF;
555 single_map_2[npos] = (packed >> 8) & 0xFF;
564 if (a.empty() || b.empty()) {
565 return absl::AbortedError(
"Error compressing map gfx.");
572 if ((pos + size_a) >= 0x5FE70 && (pos + size_a) <= 0x60000) {
576 if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) {
577 util::logf(
"Pos set to overflow region for map %s at %s",
582 const auto compare_array = [](
const std::vector<uint8_t> &array1,
583 const std::vector<uint8_t> &array2) ->
bool {
584 if (array1.size() != array2.size()) {
588 for (
size_t i = 0; i < array1.size(); i++) {
589 if (array1[i] != array2[i]) {
597 for (
int j = 0; j < i; j++) {
611 std::copy(a.begin(), a.end(),
map_data_p1[i].begin());
614 util::logf(
"Saving map pointers1 and compressed data for map %s at %s",
617 rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i),
624 util::logf(
"Saving map pointers1 for map %s at %s",
util::HexByte(i),
627 rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i),
631 if ((pos + b.size()) >= 0x5FE70 && (pos + b.size()) <= 0x60000) {
635 if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) {
636 util::logf(
"Pos set to overflow region for map %s at %s",
643 std::copy(b.begin(), b.end(),
map_data_p2[i].begin());
646 util::logf(
"Saving map pointers2 and compressed data for map %s at %s",
649 rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i),
656 util::logf(
"Saving map pointers2 for map %s at %s",
util::HexByte(i),
659 rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i),
667 return absl::AbortedError(
"Too many maps data " + std::to_string(pos));
671 return absl::OkStatus();
675 util::logf(
"Saving Large Maps");
676 std::vector<uint8_t> checked_map;
678 for (
int i = 0; i < 0x40; i++) {
688 if (std::find(checked_map.begin(), checked_map.end(), i) !=
696 const uint8_t large_map_offsets[] = {0, 1, 8, 9};
697 for (
const auto &offset : large_map_offsets) {
722 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
725 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
729 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
732 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
736 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
739 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
743 (uint16_t)((parent_y_pos * 0x200) - 0xE0)));
746 (uint16_t)((parent_x_pos * 0x200) - 0x100)));
750 (parent_x_pos * 0x200)));
752 (parent_y_pos * 0x200)));
756 (parent_x_pos * 0x200)));
759 (parent_y_pos * 0x200)));
764 (parent_x_pos * 0x200)));
767 (parent_y_pos * 0x200)));
771 (parent_x_pos * 0x200)));
774 (parent_y_pos * 0x200)));
783 if (parent_x_pos == 0) {
886 checked_map.emplace_back(i);
887 checked_map.emplace_back((i + 1));
888 checked_map.emplace_back((i + 8));
889 checked_map.emplace_back((i + 9));
911 if (i - 1 >= 0 && parent_x_pos != 0) {
923 if (i + 1 < 64 && parent_x_pos != 7) {
967 (uint16_t)((y_pos * 0x200) - 0xE0)));
969 (uint16_t)((x_pos * 0x200) - 0x100)));
976 checked_map.emplace_back(i);
980 constexpr int OverworldScreenTileMapChangeMask = 0x1262C;
983 rom()->WriteShort(OverworldScreenTileMapChangeMask + 0, 0x1F80));
985 rom()->WriteShort(OverworldScreenTileMapChangeMask + 2, 0x1F80));
987 rom()->WriteShort(OverworldScreenTileMapChangeMask + 4, 0x007F));
989 rom()->WriteShort(OverworldScreenTileMapChangeMask + 6, 0x007F));
991 return absl::OkStatus();
996 std::vector<uint64_t> all_tile_16;
1011 for (
int y = 0; y < 32; y += 2) {
1012 for (
int x = 0; x < 32; x += 2) {
1014 tiles_used[x + (sx * 32)][y + (sy * 32)],
1015 tiles_used[x + 1 + (sx * 32)][y + (sy * 32)],
1016 tiles_used[x + (sx * 32)][y + 1 + (sy * 32)],
1017 tiles_used[x + 1 + (sx * 32)][y + 1 + (sy * 32)]);
1046 std::vector<uint64_t> all_tile_16 = GetAllTile16(
map_tiles_);
1049 std::set<uint64_t> unique_tiles_set(all_tile_16.begin(), all_tile_16.end());
1051 std::vector<uint64_t> unique_tiles(all_tile_16);
1052 unique_tiles.assign(unique_tiles_set.begin(), unique_tiles_set.end());
1055 std::unordered_map<uint64_t, uint16_t> all_tiles_indexed;
1056 for (
size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) {
1057 all_tiles_indexed.insert(
1058 {unique_tiles[tile32_id],
static_cast<uint16_t
>(tile32_id)});
1064 tiles32_list_.emplace_back(all_tiles_indexed[all_tile_16[j]]);
1068 for (
size_t i = 0; i < unique_tiles.size(); ++i) {
1078 return absl::InternalError(absl::StrFormat(
1079 "Number of unique Tiles32: %d Out of: %d\nUnique Tile32 count exceed "
1080 "the limit\nThe ROM Has not been saved\nYou can fill maps with grass "
1081 "tiles to free some space\nOr use the option Clear DW Tiles in the "
1098 return absl::OkStatus();
1149 return absl::OkStatus();
1153 util::logf(
"Saving Map32 Tiles");
1154 constexpr int kMaxUniqueTiles = 0x4540;
1155 constexpr int kTilesPer32x32Tile = 6;
1157 int unique_tile_index = 0;
1160 for (
int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
1161 if (unique_tile_index >= kMaxUniqueTiles) {
1162 return absl::AbortedError(
"Too many unique tile32 definitions.");
1166 auto top_left =
rom()->version_constants().kMap32TileTL;
1194 auto top_right =
rom()->version_constants().kMap32TileTR;
1199 top_right + (i + 1),
1202 top_right + (i + 2),
1205 top_right + (i + 3),
1209 top_right + (i + 4),
1214 top_right + (i + 5),
1274 unique_tile_index += 4;
1275 num_unique_tiles += 2;
1278 return absl::OkStatus();
1356 return absl::OkStatus();
1360 util::logf(
"Saving Map16 Tiles");
1365 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile0_)))
1368 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile1_)))
1371 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile2_)))
1374 rom()->WriteShort(tpos, TileInfoToShort(
tiles16_[i].tile3_)))
1377 return absl::OkStatus();
1381 util::logf(
"Saving Entrances");
1411 return absl::OkStatus();
1415 util::logf(
"Saving Exits");
1444 return absl::OkStatus();
1449 std::vector<OverworldItem> item_array2) {
1450 if (item_array1.size() != item_array2.size()) {
1455 for (
size_t i = 0; i < item_array1.size(); i++) {
1457 for (
size_t j = 0; j < item_array2.size(); j++) {
1459 if (item_array1[i].x_ == item_array2[j].x_ &&
1460 item_array1[i].y_ == item_array2[j].y_ &&
1461 item_array1[i].id_ == item_array2[j].id_) {
1477 std::vector<std::vector<OverworldItem>> room_items(
1481 room_items[i] = std::vector<OverworldItem>();
1483 if (item.room_map_id_ == i) {
1484 room_items[i].emplace_back(item);
1485 if (item.id_ == 0x86) {
1487 0x16DC5 + (i * 2), (item.game_x_ + (item.game_y_ * 64)) * 2));
1496 int empty_pointer = 0;
1498 item_pointers_reuse[i] = -1;
1499 for (
int ci = 0; ci < i; ci++) {
1500 if (room_items[i].empty()) {
1501 item_pointers_reuse[i] = -2;
1506 if (CompareItemsArrays(
1507 std::vector<OverworldItem>(room_items[i].begin(),
1508 room_items[i].end()),
1509 std::vector<OverworldItem>(room_items[ci].begin(),
1510 room_items[ci].end()))) {
1511 item_pointers_reuse[i] = ci;
1518 if (item_pointers_reuse[i] == -1) {
1519 item_pointers[i] = data_pos;
1522 static_cast<short>(((item.game_y_ << 6) + item.game_x_) << 1);
1524 uint32_t data =
static_cast<uint8_t
>(map_pos & 0xFF) |
1525 static_cast<uint8_t
>(map_pos >> 8) |
1526 static_cast<uint8_t
>(item.id_);
1531 empty_pointer = data_pos;
1534 }
else if (item_pointers_reuse[i] == -2) {
1535 item_pointers[i] = empty_pointer;
1537 item_pointers[i] = item_pointers[item_pointers_reuse[i]];
1540 int snesaddr =
PcToSnes(item_pointers[i]);
1546 return absl::AbortedError(
"Too many items");
1550 std::cout <<
"End of Items : " << data_pos << std::endl;
1553 return absl::OkStatus();
1557 util::logf(
"Saving Map Properties");
1604 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data.
Tile composition of four 16x16 tiles.
uint64_t GetPackedValue() const
SNES 16-bit tile metadata container.
absl::Status SaveMap32Expanded()
std::vector< uint16_t > tiles32_list_
absl::Status Load(Rom &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)
std::array< int, kNumOverworldMaps > map_pointers1
std::vector< gfx::Tile32 > tiles32_unique_
void DecompressAllMapTiles()
absl::Status SaveMapProperties()
absl::Status SaveMap32Tiles()
std::vector< OverworldEntrance > all_entrances_
OverworldMapTiles map_tiles_
absl::Status SaveMap16Tiles()
absl::Status SaveLargeMaps()
std::array< uint8_t, kNumOverworldMaps > map_parent_
void AssignWorldTiles(int x, int y, int sx, int sy, int tpos, OverworldBlockset &world)
std::array< uint8_t, kNumTileTypes > all_tiles_types_
absl::Status CreateTile32Tilemap()
std::array< int, kNumOverworldMaps > map_pointers1_id
absl::Status Save(Rom &rom)
absl::Status SaveEntrances()
absl::Status LoadSprites()
std::vector< OverworldMap > overworld_maps_
absl::Status LoadEntrances()
absl::Status SaveOverworldMaps()
std::array< std::vector< Sprite >, 3 > all_sprites_
std::array< int, kNumOverworldMaps > map_pointers2_id
absl::Status LoadOverworldMaps()
std::vector< gfx::Tile16 > tiles16_
absl::Status AssembleMap16Tiles()
absl::Status LoadSpritesFromMap(int sprite_start, int sprite_count, int sprite_index)
std::array< std::vector< uint8_t >, kNumOverworldMaps > map_data_p1
absl::Status SaveMap16Expanded()
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 AssembleMap32Tiles()
OverworldBlockset & GetMapTiles(int world_type)
std::vector< OverworldEntrance > all_holes_
#define RETURN_IF_ERROR(expression)
#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)
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)
std::string HexLong(uint32_t dword, HexStringParams params)
bool CompareItemsArrays(std::vector< OverworldItem > item_array1, std::vector< OverworldItem > item_array2)
std::vector< uint64_t > GetAllTile16(OverworldMapTiles &map_tiles_)
Zelda 3 specific classes and functions.
constexpr int OWExitYScroll
constexpr int kAreaGfxIdPtr
constexpr int kOverworldHoleArea
constexpr int kOverworldTransitionPositionY
constexpr int kOverworldEntrancePos
constexpr int kOverworldHoleEntrance
constexpr int kOverworldSpriteset
constexpr int kMap16ExpandedFlagPos
constexpr int LimitOfMap32
constexpr int NumberOfMap16Ex
constexpr int kOverworldScreenTileMapChangeByScreen1
constexpr int kOverworldMapDataOverflow
constexpr int kOverworldMapSizeHighByte
constexpr int kOverworldEntranceEntranceIdExpanded
constexpr int kNumTileTypes
constexpr int NumberOfMap32
constexpr int kNumOverworldMapItemPointers
constexpr int kOverworldScreenSize
constexpr int kOverworldScreenTileMapChangeByScreen4
constexpr int kNumTile16Individual
constexpr int kNumOverworldHoles
constexpr int kSpecialWorldMapIdStart
constexpr int OWExitDoorType2
constexpr int kOverworldEntranceEntranceId
constexpr int kOverworldItemsAddress
constexpr int kMap16Tiles
constexpr int kOverworldHolePos
constexpr int kNumOverworldMaps
constexpr int kOverworldEntranceMap
constexpr int kOverworldItemsEndData
constexpr int OWExitYCamera
std::vector< std::vector< uint16_t > > OverworldBlockset
Represents tile32 data for the overworld.
constexpr int kMap32TileBLExpanded
constexpr int kOverworldTransitionPositionX
constexpr int OWExitXScroll
constexpr int OWExitRoomId
constexpr int OWExitXCamera
constexpr int OWExitYPlayer
constexpr int kOverworldScreenSizeForLoading
constexpr int kOverworldSpritePaletteIds
constexpr int kMap32TileBRExpanded
constexpr int kMap32TileCountExpanded
constexpr int OWExitMapId
constexpr int kTransitionTargetWest
constexpr int kOverworldSpritesZelda
constexpr int kOverworldMapParentId
constexpr int kMap32ExpandedFlagPos
constexpr int kOverworldEntrancePosExpanded
constexpr int OWExitDoorType1
constexpr int kOverworldItemsPointers
constexpr int kNumOverworldExits
constexpr int NumberOfMap16
constexpr int kMap32TilesLength
constexpr int kOverworldMapSize
constexpr int kOverworldScreenTileMapChangeByScreen2
constexpr int kOverworldEntranceMapExpanded
constexpr int kDarkWorldMapIdStart
constexpr int kOverworldCompressedMapPos
constexpr int kOverworldSpritesBeginning
constexpr int kOverworldScreenTileMapChangeByScreen3
constexpr int kMap16TilesExpanded
constexpr int kOverworldEntranceExpandedFlagPos
constexpr int kNumOverworldEntrances
constexpr int kOverworldSpritesAgahnim
constexpr int kTransitionTargetNorth
constexpr int kOverworldCompressedOverflowPos
constexpr int kMap32TileTRExpanded
constexpr int OWExitXPlayer
constexpr int kOverworldMapPaletteIds
Main namespace for the application.
uint32_t PcToSnes(uint32_t addr)
uint32_t SnesToPc(uint32_t addr) noexcept
Overworld map tile32 data.
OverworldBlockset dark_world
OverworldBlockset special_world
OverworldBlockset light_world