From c66d81082865d2b9e5733cea5dc5c507d601f068 Mon Sep 17 00:00:00 2001 From: scawful Date: Fri, 25 Aug 2023 19:01:52 -0400 Subject: [PATCH] Add support for JP rom and headered ROMs --- src/app/core/constants.h | 54 +---------------- src/app/editor/overworld_editor.cc | 53 +++++++++++++++++ src/app/editor/overworld_editor.h | 20 +++++-- src/app/rom.cc | 34 ++++++----- src/app/rom.h | 93 +++++++++++++++++++++++++++++- src/app/zelda3/overworld.cc | 72 +++++++++++++++++++---- src/app/zelda3/overworld.h | 5 +- src/app/zelda3/overworld_map.cc | 29 ++++++---- 8 files changed, 266 insertions(+), 94 deletions(-) diff --git a/src/app/core/constants.h b/src/app/core/constants.h index 5d10d9ab..b6cff86d 100644 --- a/src/app/core/constants.h +++ b/src/app/core/constants.h @@ -119,53 +119,8 @@ namespace core { // Window Variables // ============================================================================ -constexpr int kScreenWidth = 1440; -constexpr int kScreenHeight = 900; - -// ============================================================================ -// Z3 Version Constants -// ============================================================================ - -enum class Z3_Version { - US = 1, - JP = 2, - SD = 3, -}; - -template -class VersionConstants; - -template <> -class VersionConstants { - public: - static constexpr uint32_t kGgxAnimatedPointer = 0x10275; - static constexpr uint32_t kOverworldGfxGroups1 = 0x5D97; - static constexpr uint32_t kOverworldGfxGroups2 = 0x6073; - - static constexpr uint32_t compressedAllMap32PointersHigh = 0x1794D; - static constexpr uint32_t compressedAllMap32PointersLow = 0x17B2D; -}; - -template <> -class VersionConstants { - public: - static constexpr uint32_t kGgxAnimatedPointer = 0x10624; - static constexpr uint32_t kOverworldGfxGroups1 = 0x5DD7; - static constexpr uint32_t kOverworldGfxGroups2 = 0x60B3; - - // LONGPointers all tiles of maps[High] (mapid* 3) - static constexpr uint32_t compressedAllMap32PointersHigh = 0x176B1; - - // LONGPointers all tiles of maps[Low] (mapid* 3) - static constexpr uint32_t compressedAllMap32PointersLow = 0x17891; - - static constexpr uint32_t overworldMapPalette = 0x7D1C; // JP - static constexpr uint32_t overworldMapPaletteGroup = 0x67E74; - static constexpr uint32_t overworldMapSize = 0x1273B; // JP - static constexpr uint32_t overlayPointers = 0x3FAF4; - static constexpr uint32_t overlayPointersBank = 0x07; - static constexpr uint32_t overworldTilesType = 0x7FD94; -}; +constexpr int kScreenWidth = 1200; +constexpr int kScreenHeight = 800; // ============================================================================ // Magic numbers @@ -209,10 +164,6 @@ constexpr int subtype3_tiles = 0x84F0; // JP = Same constexpr int gfx_animated_pointer = 0x10275; // JP 0x10624 //long pointer constexpr int overworldgfxGroups2 = 0x6073; // 0x60B3 -// 2 byte pointer bank 00 pc -> 0x4320 -constexpr int gfx_1_pointer = 0x6790; // CF80 ; 004F80 -constexpr int gfx_2_pointer = 0x6795; // D05F ; 00505F -constexpr int gfx_3_pointer = 0x679A; // D13E ; 00513E constexpr int hud_palettes = 0xDD660; constexpr int maxGfx = 0xC3FB5; @@ -380,7 +331,6 @@ constexpr int blocks_pointer4 = 0x15B0F; constexpr int torch_data = 0x2736A; // JP 0x2704A constexpr int torches_length_pointer = 0x88C1; -constexpr int kSpriteBlocksetPointer = 0x5B57; constexpr int sprites_data = 0x4D8B0; // It use the unused pointers to have more space //Save purpose constexpr int sprites_data_empty_room = 0x4D8AE; diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index b8eb19e9..c4ef5558 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -16,6 +16,8 @@ #include "app/gfx/snes_tile.h" #include "app/gui/canvas.h" #include "app/gui/icons.h" +#include "app/gui/input.h" +#include "app/gui/style.h" #include "app/rom.h" #include "app/zelda3/overworld.h" @@ -75,9 +77,16 @@ absl::Status OverworldEditor::DrawToolset() { TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator ImGui::TableNextColumn(); // Palette palette_editor_.DisplayPalette(palette_, overworld_.isLoaded()); + TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator + ImGui::TableNextColumn(); // Experimental + ImGui::Checkbox("Experimental", &show_experimental); ImGui::EndTable(); } + + if (show_experimental) { + RETURN_IF_ERROR(DrawExperimentalModal()) + } return absl::OkStatus(); } @@ -364,6 +373,50 @@ absl::Status OverworldEditor::LoadSpriteGraphics() { return absl::OkStatus(); } +absl::Status OverworldEditor::DrawExperimentalModal() { + ImGui::Begin("Experimental", &show_experimental); + + gui::TextWithSeparators("PROTOTYPE OVERWORLD TILEMAP LOADER"); + ImGui::Text("Please provide two files:"); + ImGui::Text("One based on MAPn.DAT, which represents the overworld tilemap"); + ImGui::Text("One based on MAPDATn.DAT, which is the tile32 configurations."); + ImGui::Text("Currently, loading CGX for this component is NOT supported. "); + ImGui::Text("Please load a US ROM of LTTP (JP ROM support coming soon)."); + ImGui::Text( + "Once you've loaded the files, you can click the button below to load " + "the tilemap into the editor"); + + ImGui::InputText("##TilemapFile", &ow_tilemap_filename_); + ImGui::SameLine(); + core::FileDialogPipeline( + "ImportTilemapsKey", ".CGX,.cgx\0", "Tilemap Hex File", [this]() { + ow_tilemap_filename_ = ImGuiFileDialog::Instance()->GetFilePathName(); + }); + + ImGui::InputText("##Tile32ConfigurationFile", + &tile32_configuration_filename_); + ImGui::SameLine(); + core::FileDialogPipeline("ImportTile32Key", ".CGX,.cgx\0", "Tile32 Hex File", + [this]() { + tile32_configuration_filename_ = + ImGuiFileDialog::Instance()->GetFilePathName(); + }); + + ImGui::Button("Load Prototype Overworld with ROM graphics"); + + gui::TextWithSeparators("Configuration"); + + gui::InputHexShort("Tilemap File Offset (High)", &tilemap_file_offset_high_); + gui::InputHexShort("Tilemap File Offset (Low)", &tilemap_file_offset_low_); + + gui::InputHexShort("LW Maps to Load", &light_maps_to_load_); + gui::InputHexShort("DW Maps to Load", &dark_maps_to_load_); + gui::InputHexShort("SP Maps to Load", &sp_maps_to_load_); + + ImGui::End(); + return absl::OkStatus(); +} + } // namespace editor } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index 886905a9..8619b532 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -33,10 +33,10 @@ static constexpr uint kTile8DisplayHeight = 64; static constexpr float kInputFieldSize = 30.f; static constexpr absl::string_view kToolsetColumnNames[] = { - "#undoTool", "#redoTool", "#drawTool", "#separator2", - "#zoomOutTool", "#zoomInTool", "#separator", "#history", - "#entranceTool", "#exitTool", "#itemTool", "#spriteTool", - "#transportTool", "#musicTool"}; + "#undoTool", "#redoTool", "#drawTool", "#separator2", + "#zoomOutTool", "#zoomInTool", "#separator", "#history", + "#entranceTool", "#exitTool", "#itemTool", "#spriteTool", + "#transportTool", "#musicTool", "#separator3", "#tilemapTool"}; static constexpr absl::string_view kOverworldSettingsColumnNames[] = { "##1stCol", "##gfxCol", "##palCol", "##sprgfxCol", @@ -78,6 +78,8 @@ class OverworldEditor : public Editor, public SharedROM { absl::Status LoadGraphics(); absl::Status LoadSpriteGraphics(); + absl::Status DrawExperimentalModal(); + int current_world_ = 0; int current_map_ = 0; int current_tile16_ = 0; @@ -90,12 +92,22 @@ class OverworldEditor : public Editor, public SharedROM { char message_id_[5] = ""; char staticgfx[16]; + uint32_t tilemap_file_offset_high_ = 0; + uint32_t tilemap_file_offset_low_ = 0; + uint32_t light_maps_to_load_ = 0x51; + uint32_t dark_maps_to_load_ = 0x2A; + uint32_t sp_maps_to_load_ = 0x07; + bool opt_enable_grid = true; bool all_gfx_loaded_ = false; bool map_blockset_loaded_ = false; bool selected_tile_loaded_ = false; bool update_selected_tile_ = true; + bool show_experimental = false; + std::string ow_tilemap_filename_ = ""; + std::string tile32_configuration_filename_ = ""; + Bytes selected_tile_data_; std::vector tile16_individual_data_; std::vector tile16_individual_; diff --git a/src/app/rom.cc b/src/app/rom.cc index 89557b08..8a3c399f 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -1,7 +1,7 @@ #include "rom.h" #include -// #include +#include #include #include @@ -27,18 +27,6 @@ namespace yaze { namespace app { -namespace { - -int GetGraphicsAddress(const uchar* data, uint8_t offset) { - auto part_one = data[kOverworldGraphicsPos1 + offset] << 16; - auto part_two = data[kOverworldGraphicsPos2 + offset] << 8; - auto part_three = data[kOverworldGraphicsPos3 + offset]; - auto snes_addr = (part_one | part_two | part_three); - return core::SnesToPc(snes_addr); -} - -} // namespace - absl::StatusOr ROM::Load2bppGraphics() { Bytes sheet; const uint8_t sheets[] = {113, 114, 218, 219, 220, 221}; @@ -120,10 +108,29 @@ absl::Status ROM::LoadFromFile(const absl::string_view& filename, rom_data_[i] = byte_to_read; } + // Check if the sROM has a header + constexpr size_t baseROMSize = 1048576; // 1MB + constexpr size_t headerSize = 0x200; // 512 bytes + + if (size_ % baseROMSize == headerSize) { + has_header_ = true; + } + + if (has_header_) { + // remove header + rom_data_.erase(rom_data_.begin(), rom_data_.begin() + 0x200); + size_ -= 0x200; + } + file.close(); if (z3_load) { // copy ROM title memcpy(title_, rom_data_.data() + kTitleStringOffset, kTitleStringLength); + if (rom_data_[kTitleStringOffset + 0x19] == 0) { + version_ = Z3_Version::JP; + } else { + version_ = Z3_Version::US; + } LoadAllPalettes(); } is_loaded_ = true; @@ -213,6 +220,7 @@ void ROM::LoadAllPalettes() { ReadPalette(core::dungeonMainPalettes + (i * 180), 90)); } + // TODO: Make these grass colors editable color fields palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassLW)); palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassDW)); palette_groups_["grass"].AddColor(ReadColor(core::hardcodedGrassSpecial)); diff --git a/src/app/rom.h b/src/app/rom.h index f407d635..36393c37 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,83 @@ namespace yaze { namespace app { +struct VersionConstants { + uint32_t kGgxAnimatedPointer; + uint32_t kOverworldGfxGroups1; + uint32_t kOverworldGfxGroups2; + // long ptrs all tiles of maps[high/low] (mapid* 3) + uint32_t compressedAllMap32PointersHigh; + uint32_t compressedAllMap32PointersLow; + uint32_t overworldMapPaletteGroup; + uint32_t overlayPointers; + uint32_t overlayPointersBank; + uint32_t overworldTilesType; + uint32_t kOverworldGfxPtr1; + uint32_t kOverworldGfxPtr2; + uint32_t kOverworldGfxPtr3; + uint32_t kMap32TileTL; + uint32_t kMap32TileTR; + uint32_t kMap32TileBL; + uint32_t kMap32TileBR; + uint32_t kSpriteBlocksetPointer; +}; + +enum class Z3_Version { + US = 1, + JP = 2, + SD = 3, + RANDO = 4, +}; + +static constexpr uint32_t overworldMapPaletteGroup = 0x67E74; +static constexpr uint32_t overlayPointers = 0x3FAF4; +static constexpr uint32_t overlayPointersBank = 0x07; +static constexpr uint32_t overworldTilesType = 0x7FD94; + +static const std::map kVersionConstantsMap = { + {Z3_Version::US, + { + 0x10275, // kGgxAnimatedPointer + 0x5D97, // kOverworldGfxGroups1 + 0x6073, // kOverworldGfxGroups2 + 0x1794D, // compressedAllMap32PointersHigh + 0x17B2D, // compressedAllMap32PointersLow + 0x75504, // overworldMapPaletteGroup + 0x77664, // overlayPointers + 0x0E, // overlayPointersBank + 0x71459, // overworldTilesType + 0x4F80, // kOverworldGfxPtr1 + 0x505F, // kOverworldGfxPtr2 + 0x513E, // kOverworldGfxPtr3 + 0x18000, // kMap32TileTL + 0x1B400, // kMap32TileTR + 0x20000, // kMap32TileBL + 0x23400, // kMap32TileBR + 0x5B57, // kSpriteBlocksetPointer + }}, + {Z3_Version::JP, + { + 0x10624, // kGgxAnimatedPointer + 0x5DD7, // kOverworldGfxGroups1 + 0x60B3, // kOverworldGfxGroups2 + 0x176B1, // compressedAllMap32PointersHigh + 0x17891, // compressedAllMap32PointersLow + 0x67E74, // overworldMapPaletteGroup + 0x3FAF4, // overlayPointers + 0x07, // overlayPointersBank + 0x7FD94, // overworldTilesType + 0x4FC0, // kOverworldGfxPtr1 + 0x509F, // kOverworldGfxPtr2 + 0x517E, // kOverworldGfxPtr3 + 0x18000, // kMap32TileTL + 0x1B3C0, // kMap32TileTR + 0x20000, // kMap32TileBL + 0x233C0, // kMap32TileBR + 0x5B97, // kSpriteBlocksetPointer + }} + +}; + constexpr int kOverworldGraphicsPos1 = 0x4F80; constexpr int kOverworldGraphicsPos2 = 0x505F; constexpr int kOverworldGraphicsPos3 = 0x513E; @@ -113,6 +191,16 @@ class ROM { WriteShort(address, bgr); } + VersionConstants GetVersionConstants() const { + return kVersionConstantsMap.at(version_); + } + int GetGraphicsAddress(const uchar* data, uint8_t addr) const { + auto part_one = data[GetVersionConstants().kOverworldGfxPtr1 + addr] << 16; + auto part_two = data[GetVersionConstants().kOverworldGfxPtr2 + addr] << 8; + auto part_three = data[GetVersionConstants().kOverworldGfxPtr3 + addr]; + auto snes_addr = (part_one | part_two | part_three); + return core::SnesToPc(snes_addr); + } uint32_t GetPaletteAddress(const std::string& groupName, size_t paletteIndex, size_t colorIndex) const; gfx::PaletteGroup GetPaletteGroup(const std::string& group) { @@ -182,13 +270,14 @@ class ROM { private: long size_ = 0; bool is_loaded_ = false; + bool has_header_ = false; uchar title_[21] = "ROM Not Loaded"; std::string filename_; Bytes rom_data_; Bytes graphics_buffer_; - core::Z3_Version version_; + Z3_Version version_ = Z3_Version::US; gfx::BitmapTable graphics_bin_; std::shared_ptr renderer_; @@ -211,7 +300,7 @@ class SharedROM { if (!shared_rom_) { shared_rom_ = std::make_shared(); } - ROM *rom = shared_rom_.get(); + ROM* rom = shared_rom_.get(); return rom; } diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index 60e434ac..2b24e359 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -21,16 +21,14 @@ namespace zelda3 { namespace { -uint GetOwMapGfxHighPtr(const uchar *rom, int index) { - int map_high_ptr = core::compressedAllMap32PointersHigh; +uint GetOwMapGfxHighPtr(const uchar *rom, int index, uint32_t map_high_ptr) { int p1 = (rom[map_high_ptr + 2 + (3 * index)] << 16) + (rom[map_high_ptr + 1 + (3 * index)] << 8) + (rom[map_high_ptr + (3 * index)]); return core::SnesToPc(p1); } -uint GetOwMapGfxLowPtr(const uchar *rom, int index) { - int map_low_ptr = core::compressedAllMap32PointersLow; +uint GetOwMapGfxLowPtr(const uchar *rom, int index, uint32_t map_low_ptr) { int p2 = (rom[map_low_ptr + 2 + (3 * index)] << 16) + (rom[map_low_ptr + 1 + (3 * index)] << 8) + (rom[map_low_ptr + (3 * index)]); @@ -321,13 +319,13 @@ void Overworld::SaveMap32Tiles() { } }; - write_tiles(core::map32TilesTL, + write_tiles(rom_.GetVersionConstants().kMap32TileTL, [&](int i) { return tiles32_unique_[i].tile0_; }); - write_tiles(core::map32TilesTR, + write_tiles(rom_.GetVersionConstants().kMap32TileTR, [&](int i) { return tiles32_unique_[i].tile1_; }); - write_tiles(core::map32TilesBL, + write_tiles(rom_.GetVersionConstants().kMap32TileBL, [&](int i) { return tiles32_unique_[i].tile2_; }); - write_tiles(core::map32TilesBR, + write_tiles(rom_.GetVersionConstants().kMap32TileBR, [&](int i) { return tiles32_unique_[i].tile3_; }); if (unique_size > max_tiles) { @@ -338,6 +336,11 @@ void Overworld::SaveMap32Tiles() { // ---------------------------------------------------------------------------- ushort Overworld::GenerateTile32(int i, int k, int dimension) { + const uint32_t map32address[4] = {rom_.GetVersionConstants().kMap32TileTL, + rom_.GetVersionConstants().kMap32TileTR, + rom_.GetVersionConstants().kMap32TileBL, + rom_.GetVersionConstants().kMap32TileBR}; + return (ushort)(rom_[map32address[dimension] + k + (i)] + (((rom_[map32address[dimension] + (i) + (k <= 1 ? 4 : 5)] >> (k % 2 == 0 ? 4 : 0)) & @@ -428,8 +431,12 @@ absl::Status Overworld::DecompressAllMapTiles() { int sy = 0; int c = 0; for (int i = 0; i < 160; i++) { - auto p1 = GetOwMapGfxHighPtr(rom_.data(), i); - auto p2 = GetOwMapGfxLowPtr(rom_.data(), i); + auto p1 = GetOwMapGfxHighPtr( + rom_.data(), i, + rom_.GetVersionConstants().compressedAllMap32PointersHigh); + auto p2 = GetOwMapGfxLowPtr( + rom_.data(), i, + rom_.GetVersionConstants().compressedAllMap32PointersLow); int ttpos = 0; if (p1 >= highest) { @@ -627,6 +634,51 @@ void Overworld::LoadSpritesFromMap(int spriteStart, int spriteCount, } } +absl::Status Overworld::LoadPrototype(ROM &rom, std::vector &tilemap, + std::vector tile32) { + rom_ = rom; + + AssembleMap32Tiles(); + AssembleMap16Tiles(); + RETURN_IF_ERROR(DecompressAllMapTiles()) + + for (int map_index = 0; map_index < core::kNumOverworldMaps; ++map_index) + overworld_maps_.emplace_back(map_index, rom_, tiles16); + + FetchLargeMaps(); + LoadEntrances(); + + auto size = tiles16.size(); + std::vector> futures; + for (int i = 0; i < core::kNumOverworldMaps; ++i) { + futures.push_back(std::async(std::launch::async, [this, i, size]() { + if (i < 64) { + return overworld_maps_[i].BuildMap(size, game_state_, 0, map_parent_, + map_tiles_.light_world); + } else if (i < 0x80 && i >= 0x40) { + return overworld_maps_[i].BuildMap(size, game_state_, 1, map_parent_, + map_tiles_.dark_world); + } else { + return overworld_maps_[i].BuildMap(size, game_state_, 2, map_parent_, + map_tiles_.special_world); + } + })); + } + + // Wait for all tasks to complete and check their results + for (auto &future : futures) { + absl::Status status = future.get(); + if (!status.ok()) { + return status; + } + } + + // LoadSprites(); + + is_loaded_ = true; + return absl::OkStatus(); +} + } // namespace zelda3 } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index 21227b63..8a837c40 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -94,9 +94,10 @@ class Overworld { auto isLoaded() const { return is_loaded_; } void SetCurrentMap(int i) { current_map_ = i; } + absl::Status LoadPrototype(ROM &rom_, std::vector &tilemap, + std::vector tile32); + private: - const int map32address[4] = {core::map32TilesTL, core::map32TilesTR, - core::map32TilesBL, core::map32TilesBR}; enum Dimension { map32TilesTL = 0, map32TilesTR = 1, diff --git a/src/app/zelda3/overworld_map.cc b/src/app/zelda3/overworld_map.cc index 39e4cefd..65354eb9 100644 --- a/src/app/zelda3/overworld_map.cc +++ b/src/app/zelda3/overworld_map.cc @@ -285,22 +285,24 @@ void OverworldMap::LoadSpritesBlocksets() { static_graphics_[11] = static_graphics_base + 0x07; for (int i = 0; i < 4; i++) { - static_graphics_[12 + i] = (rom_[core::kSpriteBlocksetPointer + - (sprite_graphics_[game_state_] * 4) + i] + - static_graphics_base); + static_graphics_[12 + i] = + (rom_[rom_.GetVersionConstants().kSpriteBlocksetPointer + + (sprite_graphics_[game_state_] * 4) + i] + + static_graphics_base); } } void OverworldMap::LoadMainBlocksets() { for (int i = 0; i < 8; i++) { - static_graphics_[i] = - rom_[core::overworldgfxGroups2 + (world_index_ * 8) + i]; + static_graphics_[i] = rom_[rom_.GetVersionConstants().kOverworldGfxGroups2 + + (world_index_ * 8) + i]; } } void OverworldMap::LoadAreaGraphicsBlocksets() { for (int i = 0; i < 4; i++) { - uchar value = rom_[core::overworldgfxGroups + (area_graphics_ * 4) + i]; + uchar value = rom_[rom_.GetVersionConstants().kOverworldGfxGroups1 + + (area_graphics_ * 4) + i]; if (value != 0) { static_graphics_[3 + i] = value; } @@ -328,7 +330,8 @@ void OverworldMap::LoadAreaGraphics() { gfx::SNESPalette OverworldMap::GetPalette(const std::string& group, int index, int previousIndex, int limit) { if (index == 255) { - index = rom_[core::overworldMapPaletteGroup + (previousIndex * 4)]; + index = rom_[rom_.GetVersionConstants().overworldMapPaletteGroup + + (previousIndex * 4)]; } if (index != 255) { if (index >= limit) { @@ -349,9 +352,12 @@ void OverworldMap::LoadPalette() { area_palette_ = std::min(area_palette_, 0xA3); uchar pal0 = 0; - uchar pal1 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4)]; - uchar pal2 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1]; - uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 2]; + uchar pal1 = rom_[rom_.GetVersionConstants().overworldMapPaletteGroup + + (area_palette_ * 4)]; + uchar pal2 = rom_[rom_.GetVersionConstants().overworldMapPaletteGroup + + (area_palette_ * 4) + 1]; + uchar pal3 = rom_[rom_.GetVersionConstants().overworldMapPaletteGroup + + (area_palette_ * 4) + 2]; uchar pal4 = rom_[core::overworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2)]; uchar pal5 = rom_[core::overworldSpritePaletteGroup + @@ -364,7 +370,8 @@ void OverworldMap::LoadPalette() { // Additional handling of `pal3` and `parent_` if (pal3 == 255) { - pal3 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4) + 2]; + pal3 = rom_[rom_.GetVersionConstants().overworldMapPaletteGroup + + (previousPalId * 4) + 2]; } if (parent_ < 0x40) { pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0;