Overworld Tile32 save improvements

This commit is contained in:
scawful
2024-01-29 16:12:15 -05:00
parent 0a388e60b4
commit 752215be03
4 changed files with 247 additions and 154 deletions

View File

@@ -372,7 +372,7 @@ void Canvas::DrawOutline(int x, int y, int w, int h) {
canvas_p0_.y + scrolling_.y + y); canvas_p0_.y + scrolling_.y + y);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w, ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
canvas_p0_.y + scrolling_.y + y + h); canvas_p0_.y + scrolling_.y + y + h);
draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255)); draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 200), 0, 0, 1.5f);
} }
void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color) { void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color) {
@@ -384,6 +384,15 @@ void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color) {
IM_COL32(color.x, color.y, color.z, color.w)); IM_COL32(color.x, color.y, color.z, color.w));
} }
void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color) {
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
canvas_p0_.y + scrolling_.y + y);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
canvas_p0_.y + scrolling_.y + y + h);
draw_list_->AddRect(origin, size, color);
}
namespace { namespace {
std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width, std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width,
int height, int tile_size) { int height, int tile_size) {
@@ -404,14 +413,6 @@ std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width,
} }
} // namespace } // namespace
void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color) {
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
canvas_p0_.y + scrolling_.y + y);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
canvas_p0_.y + scrolling_.y + y + h);
draw_list_->AddRect(origin, size, color);
}
void Canvas::DrawSelectRect(int tile_size, float scale) { void Canvas::DrawSelectRect(int tile_size, float scale) {
const ImGuiIO &io = ImGui::GetIO(); const ImGuiIO &io = ImGui::GetIO();
static ImVec2 drag_start_pos; static ImVec2 drag_start_pos;

View File

@@ -25,20 +25,6 @@ namespace zelda3 {
namespace { namespace {
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, 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)]);
return core::SnesToPc(p2);
}
absl::flat_hash_map<int, MapData> parseFile(const std::string &filename) { absl::flat_hash_map<int, MapData> parseFile(const std::string &filename) {
absl::flat_hash_map<int, MapData> resultMap; absl::flat_hash_map<int, MapData> resultMap;
@@ -79,9 +65,9 @@ absl::flat_hash_map<int, MapData> parseFile(const std::string &filename) {
while (getline(ss, valueStr, ',')) { while (getline(ss, valueStr, ',')) {
uint8_t value = std::stoi(valueStr, nullptr, 16); uint8_t value = std::stoi(valueStr, nullptr, 16);
if (isHigh) { if (isHigh) {
resultMap[currentKey].highData.push_back(value); resultMap[currentKey].highData.emplace_back(value);
} else { } else {
resultMap[currentKey].lowData.push_back(value); resultMap[currentKey].lowData.emplace_back(value);
} }
} }
} }
@@ -135,8 +121,8 @@ absl::Status Overworld::LoadOverworldMaps() {
} else if (i >= 0x80) { } else if (i >= 0x80) {
world_type = 2; world_type = 2;
} }
futures.push_back(std::async(std::launch::async, [this, i, size, futures.emplace_back(std::async(std::launch::async, [this, i, size,
world_type]() { world_type]() {
return overworld_maps_[i].BuildMap(size, game_state_, world_type, return overworld_maps_[i].BuildMap(size, game_state_, world_type,
map_parent_, GetMapTiles(world_type)); map_parent_, GetMapTiles(world_type));
})); }));
@@ -255,11 +241,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers1 for map " + std::to_string(i) + core::Logger::log("Saving map pointers1 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos)); " at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + 3 * i, b1)); rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + (3 * i), b1));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + 3 * i, b2)); rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + (3 * i), b2));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + 3 * i, b3)); rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + (3 * i), b3));
for (const uint8_t byte : a) { for (const uint8_t byte : a) {
RETURN_IF_ERROR(rom()->WriteByte(pos, byte)); RETURN_IF_ERROR(rom()->WriteByte(pos, byte));
pos++; pos++;
@@ -273,11 +259,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers1 for map " + std::to_string(i) + core::Logger::log("Saving map pointers1 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos)); " at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + 3 * i, b1)); rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + (3 * i), b1));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + 3 * i, b2)); rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + (3 * i), b2));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + 3 * i, b3)); rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + (3 * i), b3));
} }
if ((pos + b.size()) >= 0x5FE70 && (pos + b.size()) <= 0x60000) { if ((pos + b.size()) >= 0x5FE70 && (pos + b.size()) <= 0x60000) {
@@ -302,11 +288,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers2 for map " + std::to_string(i) + core::Logger::log("Saving map pointers2 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos)); " at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + 3 * i, b1)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + (3 * i), b1));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + 3 * i, b2)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + (3 * i), b2));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + 3 * i, b3)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + (3 * i), b3));
for (const uint8_t byte : b) { for (const uint8_t byte : b) {
RETURN_IF_ERROR(rom()->WriteByte(pos, byte)); RETURN_IF_ERROR(rom()->WriteByte(pos, byte));
pos++; pos++;
@@ -320,11 +306,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers2 for map " + std::to_string(i) + core::Logger::log("Saving map pointers2 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos)); " at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + 3 * i, b1)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + (3 * i), b1));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + 3 * i, b2)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + (3 * i), b2));
RETURN_IF_ERROR( RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + 3 * i, b3)); rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + (3 * i), b3));
} }
} }
@@ -444,7 +430,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area to the left is a large area. // If the area to the left is a large area.
if (overworld_maps_[i - 1].IsLargeMap()) { if (overworld_maps_[i - 1].IsLargeMap()) {
// If the area to the left is the bottom right of a large area. // If the area to the left is the bottom right of a large area.
if (overworld_maps_[i - 1].Parent() == 1) { if (overworld_maps_[i - 1].ParentIndex() == 1) {
RETURN_IF_ERROR(rom()->WriteShort( RETURN_IF_ERROR(rom()->WriteShort(
OverworldScreenTileMapChangeByScreen1 + (i * 2) + 16, OverworldScreenTileMapChangeByScreen1 + (i * 2) + 16,
0x0060)); 0x0060));
@@ -471,7 +457,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area to the right is a large area. // If the area to the right is a large area.
if (overworld_maps_[i + 2].IsLargeMap()) { if (overworld_maps_[i + 2].IsLargeMap()) {
// If the area to the right is the top left of a large area. // If the area to the right is the top left of a large area.
if (overworld_maps_[i + 2].Parent() == 0) { if (overworld_maps_[i + 2].ParentIndex() == 0) {
RETURN_IF_ERROR(rom()->WriteShort( RETURN_IF_ERROR(rom()->WriteShort(
OverworldScreenTileMapChangeByScreen2 + (i * 2) + 18, OverworldScreenTileMapChangeByScreen2 + (i * 2) + 18,
0x0080)); // Always 0x1080. 0x0080)); // Always 0x1080.
@@ -497,7 +483,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just above us is a large area. // If the area just above us is a large area.
if (overworld_maps_[i - 8].IsLargeMap()) { if (overworld_maps_[i - 8].IsLargeMap()) {
// If the area just above us is the bottom left of a large area. // If the area just above us is the bottom left of a large area.
if (overworld_maps_[i - 8].Parent() == 2) { if (overworld_maps_[i - 8].ParentIndex() == 2) {
RETURN_IF_ERROR(rom()->WriteShort( RETURN_IF_ERROR(rom()->WriteShort(
OverworldScreenTileMapChangeByScreen3 + (i * 2) + 02, 0x1800)); OverworldScreenTileMapChangeByScreen3 + (i * 2) + 02, 0x1800));
} }
@@ -522,7 +508,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just below us is a large area. // If the area just below us is a large area.
if (overworld_maps_[i + 16].IsLargeMap()) { if (overworld_maps_[i + 16].IsLargeMap()) {
// If the area just below us is the top left of a large area. // If the area just below us is the top left of a large area.
if (overworld_maps_[i + 16].Parent() == 0) { if (overworld_maps_[i + 16].ParentIndex() == 0) {
RETURN_IF_ERROR(rom()->WriteShort( RETURN_IF_ERROR(rom()->WriteShort(
OverworldScreenTileMapChangeByScreen4 + (i * 2) + 18, 0x2000)); OverworldScreenTileMapChangeByScreen4 + (i * 2) + 18, 0x2000));
} }
@@ -556,7 +542,7 @@ absl::Status Overworld::SaveLargeMaps() {
// Just to make sure where don't try to read outside of the array. // Just to make sure where don't try to read outside of the array.
if (i - 1 >= 0 && parentxPos != 0) { if (i - 1 >= 0 && parentxPos != 0) {
if (overworld_maps_[i - 1].IsLargeMap()) { if (overworld_maps_[i - 1].IsLargeMap()) {
if (overworld_maps_[i - 1].Parent() == 3) { if (overworld_maps_[i - 1].ParentIndex() == 3) {
rom()->WriteShort(OverworldScreenTileMapChangeByScreen1 + (i * 2), rom()->WriteShort(OverworldScreenTileMapChangeByScreen1 + (i * 2),
0xF060); 0xF060);
} }
@@ -567,7 +553,7 @@ absl::Status Overworld::SaveLargeMaps() {
0x0040); 0x0040);
if (i + 1 < 64 && parentxPos != 7) { if (i + 1 < 64 && parentxPos != 7) {
if (overworld_maps_[i + 1].IsLargeMap()) { if (overworld_maps_[i + 1].IsLargeMap()) {
if (overworld_maps_[i + 1].Parent() == 1) { if (overworld_maps_[i + 1].ParentIndex() == 1) {
rom()->WriteShort(OverworldScreenTileMapChangeByScreen2 + (i * 2), rom()->WriteShort(OverworldScreenTileMapChangeByScreen2 + (i * 2),
0x1060); 0x1060);
} }
@@ -582,7 +568,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just above us is a large area. // If the area just above us is a large area.
if (overworld_maps_[i - 8].IsLargeMap()) { if (overworld_maps_[i - 8].IsLargeMap()) {
// If we are under the bottom right of the large area. // If we are under the bottom right of the large area.
if (overworld_maps_[i - 8].Parent() == 3) { if (overworld_maps_[i - 8].ParentIndex() == 3) {
rom()->WriteShort(OverworldScreenTileMapChangeByScreen3 + (i * 2), rom()->WriteShort(OverworldScreenTileMapChangeByScreen3 + (i * 2),
0x17C0); 0x17C0);
} }
@@ -597,7 +583,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just below us is a large area. // If the area just below us is a large area.
if (overworld_maps_[i + 8].IsLargeMap()) { if (overworld_maps_[i + 8].IsLargeMap()) {
// If we are on top of the top right of the large area. // If we are on top of the top right of the large area.
if (overworld_maps_[i + 8].Parent() == 1) { if (overworld_maps_[i + 8].ParentIndex() == 1) {
rom()->WriteShort(OverworldScreenTileMapChangeByScreen4 + (i * 2), rom()->WriteShort(OverworldScreenTileMapChangeByScreen4 + (i * 2),
0x0FC0); 0x0FC0);
} }
@@ -645,7 +631,7 @@ std::vector<uint64_t> GetAllTile16(OWMapTiles &map_tiles_) {
tiles_used[x + (sx * 32)][y + 1 + (sy * 32)], tiles_used[x + (sx * 32)][y + 1 + (sy * 32)],
tiles_used[x + 1 + (sx * 32)][y + 1 + (sy * 32)]); tiles_used[x + 1 + (sx * 32)][y + 1 + (sy * 32)]);
all_tile_16.push_back(current_tile.GetPackedValue()); all_tile_16.emplace_back(current_tile.GetPackedValue());
} }
} }
@@ -669,8 +655,11 @@ std::vector<uint64_t> GetAllTile16(OWMapTiles &map_tiles_) {
bool Overworld::CreateTile32Tilemap(bool only_show) { bool Overworld::CreateTile32Tilemap(bool only_show) {
tiles32_unique_.clear(); tiles32_unique_.clear();
tiles32_.clear(); tiles32_list_.clear();
// Get all tiles16 and packs them into tiles32
std::vector<uint64_t> all_tile_16 = GetAllTile16(map_tiles_); std::vector<uint64_t> all_tile_16 = GetAllTile16(map_tiles_);
// Convert to set then back to vector // Convert to set then back to vector
std::set<uint64_t> unique_tiles_set(all_tile_16.begin(), all_tile_16.end()); std::set<uint64_t> unique_tiles_set(all_tile_16.begin(), all_tile_16.end());
@@ -678,33 +667,35 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
unique_tiles.assign(unique_tiles_set.begin(), unique_tiles_set.end()); unique_tiles.assign(unique_tiles_set.begin(), unique_tiles_set.end());
std::cout << "Number of unique Tiles16: " << unique_tiles.size() << std::endl; std::cout << "Number of unique Tiles16: " << unique_tiles.size() << std::endl;
// Ensure it's 64 bits // Create the indexed tiles list
std::unordered_map<uint64_t, ushort> all_tiles_indexed; std::unordered_map<uint64_t, ushort> all_tiles_indexed;
for (size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) { for (size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) {
all_tiles_indexed.insert( all_tiles_indexed.insert(
{unique_tiles[tile32_id], static_cast<ushort>(tile32_id)}); {unique_tiles[tile32_id], static_cast<ushort>(tile32_id)});
} }
// Add all tiles32 from all maps.
// Convert all tiles32 non-unique IDs into unique array of IDs.
for (int j = 0; j < NumberOfMap32; j++) { for (int j = 0; j < NumberOfMap32; j++) {
tiles32_list_.push_back(all_tiles_indexed[all_tile_16[j]]); tiles32_list_.emplace_back(all_tiles_indexed[all_tile_16[j]]);
} }
// Create the unique tiles list // Create the unique tiles list
for (const auto &tile : unique_tiles) { for (int i = 0; i < unique_tiles.size(); ++i) {
// static_cast<ushort>(tile) // static_cast<ushort>(tile)
tiles32_unique_.push_back(gfx::Tile32(tile)); tiles32_unique_.emplace_back(gfx::Tile32(unique_tiles[i]));
} }
while (tiles32_unique_.size() % 4 != 0) { while (tiles32_unique_.size() % 4 != 0) {
gfx::Tile32 padding_tile(420, 420, 420, 420); gfx::Tile32 padding_tile(420, 420, 420, 420);
tiles32_unique_.push_back(padding_tile.GetPackedValue()); tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
} }
if (only_show) { if (only_show) {
std::cout << "Number of unique Tiles32: " << tiles32_unique_.size() std::cout << "Number of unique Tiles32: " << unique_tiles.size()
<< " Out of: " << LimitOfMap32 << std::endl; << " Out of: " << LimitOfMap32 << std::endl;
} else if (tiles32_unique_.size() > LimitOfMap32) { } else if (tiles32_unique_.size() > LimitOfMap32) {
std::cerr << "Number of unique Tiles32: " << tiles32_unique_.size() std::cerr << "Number of unique Tiles32: " << unique_tiles.size()
<< " Out of: " << LimitOfMap32 << " Out of: " << LimitOfMap32
<< "\nUnique Tile32 count exceed the limit" << "\nUnique Tile32 count exceed the limit"
<< "\nThe ROM Has not been saved" << "\nThe ROM Has not been saved"
@@ -721,12 +712,137 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
int v = tiles32_unique_.size(); int v = tiles32_unique_.size();
for (int i = v; i < LimitOfMap32; i++) { for (int i = v; i < LimitOfMap32; i++) {
gfx::Tile32 padding_tile(420, 420, 420, 420); gfx::Tile32 padding_tile(420, 420, 420, 420);
tiles32_unique_.push_back(padding_tile.GetPackedValue()); tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
} }
return false; return false;
} }
absl::Status Overworld::SaveMap32Tiles() {
core::Logger::log("Saving Map32 Tiles");
constexpr int kMaxUniqueTiles = 0x4540;
constexpr int kTilesPer32x32Tile = 6;
constexpr int kQuadrantsPer32x32Tile = 4;
int unique_tile_index = 0;
int num_unique_tiles = tiles32_unique_.size();
for (int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
if (unique_tile_index >= kMaxUniqueTiles) {
return absl::AbortedError("Too many unique tile32 definitions.");
}
// Top Left.
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + i,
(uint8_t)(tiles32_unique_[unique_tile_index].tile0_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + (i + 1),
(uint8_t)(tiles32_unique_[unique_tile_index + 1].tile0_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + (i + 2),
(uint8_t)(tiles32_unique_[unique_tile_index + 2].tile0_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + (i + 3),
(uint8_t)(tiles32_unique_[unique_tile_index + 3].tile0_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + (i + 4),
(uint8_t)(((tiles32_unique_[unique_tile_index].tile0_ >> 4) & 0xF0) +
((tiles32_unique_[unique_tile_index + 1].tile0_ >> 8) &
0x0F)));
rom()->WriteByte(
rom()->version_constants().kMap32TileTL + (i + 5),
(uint8_t)(((tiles32_unique_[unique_tile_index + 2].tile0_ >> 4) &
0xF0) +
((tiles32_unique_[unique_tile_index + 3].tile0_ >> 8) &
0x0F)));
// Top Right.
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + i,
(uint8_t)(tiles32_unique_[unique_tile_index].tile1_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + (i + 1),
(uint8_t)(tiles32_unique_[unique_tile_index + 1].tile1_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + (i + 2),
(uint8_t)(tiles32_unique_[unique_tile_index + 2].tile1_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + (i + 3),
(uint8_t)(tiles32_unique_[unique_tile_index + 3].tile1_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + (i + 4),
(uint8_t)(((tiles32_unique_[unique_tile_index].tile1_ >> 4) & 0xF0) |
((tiles32_unique_[unique_tile_index + 1].tile1_ >> 8) &
0x0F)));
rom()->WriteByte(
rom()->version_constants().kMap32TileTR + (i + 5),
(uint8_t)(((tiles32_unique_[unique_tile_index + 2].tile1_ >> 4) &
0xF0) |
((tiles32_unique_[unique_tile_index + 3].tile1_ >> 8) &
0x0F)));
// Bottom Left.
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + i,
(uint8_t)(tiles32_unique_[unique_tile_index].tile2_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + (i + 1),
(uint8_t)(tiles32_unique_[unique_tile_index + 1].tile2_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + (i + 2),
(uint8_t)(tiles32_unique_[unique_tile_index + 2].tile2_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + (i + 3),
(uint8_t)(tiles32_unique_[unique_tile_index + 3].tile2_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + (i + 4),
(uint8_t)(((tiles32_unique_[unique_tile_index].tile2_ >> 4) & 0xF0) |
((tiles32_unique_[unique_tile_index + 1].tile2_ >> 8) &
0x0F)));
rom()->WriteByte(
rom()->version_constants().kMap32TileBL + (i + 5),
(uint8_t)(((tiles32_unique_[unique_tile_index + 2].tile2_ >> 4) &
0xF0) |
((tiles32_unique_[unique_tile_index + 3].tile2_ >> 8) &
0x0F)));
// Bottom Right.
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + i,
(uint8_t)(tiles32_unique_[unique_tile_index].tile3_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + (i + 1),
(uint8_t)(tiles32_unique_[unique_tile_index + 1].tile3_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + (i + 2),
(uint8_t)(tiles32_unique_[unique_tile_index + 2].tile3_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + (i + 3),
(uint8_t)(tiles32_unique_[unique_tile_index + 3].tile3_ & 0xFF));
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + (i + 4),
(uint8_t)(((tiles32_unique_[unique_tile_index].tile3_ >> 4) & 0xF0) |
((tiles32_unique_[unique_tile_index + 1].tile3_ >> 8) &
0x0F)));
rom()->WriteByte(
rom()->version_constants().kMap32TileBR + (i + 5),
(uint8_t)(((tiles32_unique_[unique_tile_index + 2].tile3_ >> 4) &
0xF0) |
((tiles32_unique_[unique_tile_index + 3].tile3_ >> 8) &
0x0F)));
unique_tile_index += 4;
num_unique_tiles += 2;
}
return absl::OkStatus();
}
absl::Status Overworld::SaveMap16Tiles() { absl::Status Overworld::SaveMap16Tiles() {
core::Logger::log("Saving Map16 Tiles"); core::Logger::log("Saving Map16 Tiles");
int tpos = kMap16Tiles; int tpos = kMap16Tiles;
@@ -748,84 +864,6 @@ absl::Status Overworld::SaveMap16Tiles() {
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status Overworld::SaveMap32Tiles() {
core::Logger::log("Saving Map32 Tiles");
constexpr int kMaxUniqueTiles = 0x4540;
constexpr int kTilesPer32x32Tile = 6;
constexpr int kQuadrantsPer32x32Tile = 4;
int unique_tile_index = 0;
int num_unique_tiles = tiles32_unique_.size();
for (int i = 0; i < num_unique_tiles; i += kTilesPer32x32Tile) {
if (unique_tile_index >= kMaxUniqueTiles) {
return absl::AbortedError("Too many unique tile32 definitions.");
}
// Compute base addresses for each quadrant
int base_addr_TL =
rom()->version_constants().kMap32TileTL + unique_tile_index;
int base_addr_TR =
rom()->version_constants().kMap32TileTR + unique_tile_index;
int base_addr_BL =
rom()->version_constants().kMap32TileBL + unique_tile_index;
int base_addr_BR =
rom()->version_constants().kMap32TileBR + unique_tile_index;
for (int j = 0; j < 4; j++) {
RETURN_IF_ERROR(rom()->WriteByte(base_addr_TL + i + j,
tiles32_unique_[i + j].tile0_));
RETURN_IF_ERROR(rom()->WriteByte(base_addr_TR + i + j,
tiles32_unique_[i + j].tile1_));
RETURN_IF_ERROR(rom()->WriteByte(base_addr_BL + i + j,
tiles32_unique_[i + j].tile2_));
RETURN_IF_ERROR(rom()->WriteByte(base_addr_BR + i + j,
tiles32_unique_[i + j].tile3_));
}
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_TL + i + 4,
((tiles32_unique_[i].tile0_ >> 4) & 0xF0) |
((tiles32_unique_[i + 1].tile0_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_TL + i + 5,
((tiles32_unique_[i + 2].tile0_ >> 4) & 0xF0) |
((tiles32_unique_[i + 3].tile0_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_TR + i + 4,
((tiles32_unique_[i].tile1_ >> 4) & 0xF0) |
((tiles32_unique_[i + 1].tile1_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_TR + i + 5,
((tiles32_unique_[i + 2].tile1_ >> 4) & 0xF0) |
((tiles32_unique_[i + 3].tile1_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_BL + i + 4,
((tiles32_unique_[i].tile2_ >> 4) & 0xF0) |
((tiles32_unique_[i + 1].tile2_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_BL + i + 5,
((tiles32_unique_[i + 2].tile2_ >> 4) & 0xF0) |
((tiles32_unique_[i + 3].tile2_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_BR + i + 4,
((tiles32_unique_[i].tile3_ >> 4) & 0xF0) |
((tiles32_unique_[i + 1].tile3_ >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->WriteByte(base_addr_BR + i + 5,
((tiles32_unique_[i + 2].tile3_ >> 4) & 0xF0) |
((tiles32_unique_[i + 3].tile3_ >> 8) & 0x0F)));
unique_tile_index += 4;
num_unique_tiles += 2;
}
return absl::OkStatus();
}
uint16_t Overworld::GenerateTile32(int index, int quadrant, int dimension) { uint16_t Overworld::GenerateTile32(int index, int quadrant, int dimension) {
// The addresses of the four 32x32 pixel tiles in the rom()-> // The addresses of the four 32x32 pixel tiles in the rom()->
const uint32_t map32address[4] = {rom()->version_constants().kMap32TileTL, const uint32_t map32address[4] = {rom()->version_constants().kMap32TileTL,
@@ -854,19 +892,19 @@ void Overworld::AssembleMap32Tiles() {
uint16_t br = GenerateTile32(i, k, (int)Dimension::map32TilesBR); uint16_t br = GenerateTile32(i, k, (int)Dimension::map32TilesBR);
// Add the generated 16-bit tiles to the tiles32 vector. // Add the generated 16-bit tiles to the tiles32 vector.
tiles32_.push_back(gfx::Tile32(tl, tr, bl, br)); tiles32_unique_.emplace_back(gfx::Tile32(tl, tr, bl, br));
} }
} }
// Initialize the light_world, dark_world, and special_world vectors with // Initialize the light_world, dark_world, and special_world vectors with
// the appropriate number of tiles. // the appropriate number of tiles.
map_tiles_.light_world.resize(kTile32Num); map_tiles_.light_world.resize(0x200);
map_tiles_.dark_world.resize(kTile32Num); map_tiles_.dark_world.resize(0x200);
map_tiles_.special_world.resize(kTile32Num); map_tiles_.special_world.resize(0x200);
for (int i = 0; i < kTile32Num; i++) { for (int i = 0; i < 0x200; i++) {
map_tiles_.light_world[i].resize(kTile32Num); map_tiles_.light_world[i].resize(0x200);
map_tiles_.dark_world[i].resize(kTile32Num); map_tiles_.dark_world[i].resize(0x200);
map_tiles_.special_world[i].resize(kTile32Num); map_tiles_.special_world[i].resize(0x200);
} }
} }
@@ -891,10 +929,10 @@ void Overworld::AssignWorldTiles(int x, int y, int sx, int sy, int tpos,
int position_y1 = (y * 2) + (sy * 32); int position_y1 = (y * 2) + (sy * 32);
int position_x2 = (x * 2) + 1 + (sx * 32); int position_x2 = (x * 2) + 1 + (sx * 32);
int position_y2 = (y * 2) + 1 + (sy * 32); int position_y2 = (y * 2) + 1 + (sy * 32);
world[position_x1][position_y1] = tiles32_[tpos].tile0_; world[position_x1][position_y1] = tiles32_unique_[tpos].tile0_;
world[position_x2][position_y1] = tiles32_[tpos].tile1_; world[position_x2][position_y1] = tiles32_unique_[tpos].tile1_;
world[position_x1][position_y2] = tiles32_[tpos].tile2_; world[position_x1][position_y2] = tiles32_unique_[tpos].tile2_;
world[position_x2][position_y2] = tiles32_[tpos].tile3_; world[position_x2][position_y2] = tiles32_unique_[tpos].tile3_;
} }
void Overworld::OrganizeMapTiles(Bytes &bytes, Bytes &bytes2, int i, int sx, void Overworld::OrganizeMapTiles(Bytes &bytes, Bytes &bytes2, int i, int sx,
@@ -902,7 +940,7 @@ void Overworld::OrganizeMapTiles(Bytes &bytes, Bytes &bytes2, int i, int sx,
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
auto tidD = (ushort)((bytes2[ttpos] << 8) + bytes[ttpos]); auto tidD = (ushort)((bytes2[ttpos] << 8) + bytes[ttpos]);
if (int tpos = tidD; tpos < tiles32_.size()) { if (int tpos = tidD; tpos < tiles32_unique_.size()) {
if (i < 64) { if (i < 64) {
AssignWorldTiles(x, y, sx, sy, tpos, map_tiles_.light_world); AssignWorldTiles(x, y, sx, sy, tpos, map_tiles_.light_world);
} else if (i < 128 && i >= 64) { } else if (i < 128 && i >= 64) {
@@ -916,6 +954,22 @@ void Overworld::OrganizeMapTiles(Bytes &bytes, Bytes &bytes2, int i, int sx,
} }
} }
namespace {
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, 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)]);
return core::SnesToPc(p2);
}
} // namespace
absl::Status Overworld::DecompressAllMapTiles() { absl::Status Overworld::DecompressAllMapTiles() {
int lowest = 0x0FFFFF; int lowest = 0x0FFFFF;
int highest = 0x0F8000; int highest = 0x0F8000;
@@ -970,6 +1024,7 @@ absl::Status Overworld::DecompressAllMapTiles() {
void Overworld::FetchLargeMaps() { void Overworld::FetchLargeMaps() {
for (int i = 128; i < 145; i++) { for (int i = 128; i < 145; i++) {
map_parent_[i] = 0; map_parent_[i] = 0;
overworld_maps_[i].SetAsSmallMap(0);
} }
map_parent_[128] = 128; map_parent_[128] = 128;
@@ -977,6 +1032,11 @@ void Overworld::FetchLargeMaps() {
map_parent_[130] = 129; map_parent_[130] = 129;
map_parent_[137] = 129; map_parent_[137] = 129;
map_parent_[138] = 129; map_parent_[138] = 129;
overworld_maps_[129].SetAsLargeMap(129, 0);
overworld_maps_[129].SetAsLargeMap(130, 1);
overworld_maps_[129].SetAsLargeMap(137, 2);
overworld_maps_[129].SetAsLargeMap(138, 3);
map_parent_[136] = 136; map_parent_[136] = 136;
overworld_maps_[136].SetLargeMap(false); overworld_maps_[136].SetLargeMap(false);
@@ -993,22 +1053,32 @@ void Overworld::FetchLargeMaps() {
mapChecked[i] = true; mapChecked[i] = true;
map_parent_[i] = (uchar)i; map_parent_[i] = (uchar)i;
map_parent_[i + 64] = (uchar)(i + 64); map_parent_[i + 64] = (uchar)(i + 64);
overworld_maps_[i].SetAsLargeMap(i, 0);
overworld_maps_[i + 64].SetAsLargeMap(i + 64, 0);
mapChecked[i + 1] = true; mapChecked[i + 1] = true;
map_parent_[i + 1] = (uchar)i; map_parent_[i + 1] = (uchar)i;
map_parent_[i + 65] = (uchar)(i + 64); map_parent_[i + 65] = (uchar)(i + 64);
overworld_maps_[i + 1].SetAsLargeMap(i, 1);
overworld_maps_[i + 65].SetAsLargeMap(i + 64, 1);
mapChecked[i + 8] = true; mapChecked[i + 8] = true;
map_parent_[i + 8] = (uchar)i; map_parent_[i + 8] = (uchar)i;
map_parent_[i + 72] = (uchar)(i + 64); map_parent_[i + 72] = (uchar)(i + 64);
overworld_maps_[i + 8].SetAsLargeMap(i, 2);
overworld_maps_[i + 64].SetAsLargeMap(i + 64, 2);
mapChecked[i + 9] = true; mapChecked[i + 9] = true;
map_parent_[i + 9] = (uchar)i; map_parent_[i + 9] = (uchar)i;
map_parent_[i + 73] = (uchar)(i + 64); map_parent_[i + 73] = (uchar)(i + 64);
overworld_maps_[i + 9].SetAsLargeMap(i, 3);
overworld_maps_[i + 73].SetAsLargeMap(i + 64, 3);
xx++; xx++;
} else { } else {
map_parent_[i] = (uchar)i; map_parent_[i] = (uchar)i;
map_parent_[i + 64] = (uchar)(i + 64); map_parent_[i + 64] = (uchar)(i + 64);
overworld_maps_[i].SetAsSmallMap(0);
overworld_maps_[i + 64].SetAsSmallMap(0);
mapChecked[i] = true; mapChecked[i] = true;
} }
} }
@@ -1313,7 +1383,7 @@ absl::Status Overworld::SaveItems() {
roomItems[i] = std::vector<OverworldItem>(); roomItems[i] = std::vector<OverworldItem>();
for (const OverworldItem &item : all_items_) { for (const OverworldItem &item : all_items_) {
if (item.room_map_id == i) { if (item.room_map_id == i) {
roomItems[i].push_back(item); roomItems[i].emplace_back(item);
if (item.id == 0x86) { if (item.id == 0x86) {
RETURN_IF_ERROR(rom()->WriteWord( RETURN_IF_ERROR(rom()->WriteWord(
0x16DC5 + (i * 2), (item.game_x_ + (item.game_y_ * 64)) * 2)); 0x16DC5 + (i * 2), (item.game_x_ + (item.game_y_ * 64)) * 2));
@@ -1485,7 +1555,7 @@ absl::Status Overworld::LoadPrototype(ROM &rom,
auto size = tiles16_.size(); auto size = tiles16_.size();
std::vector<std::future<absl::Status>> futures; std::vector<std::future<absl::Status>> futures;
for (int i = 0; i < kNumOverworldMaps; ++i) { for (int i = 0; i < kNumOverworldMaps; ++i) {
futures.push_back(std::async(std::launch::async, [this, i, size]() { futures.emplace_back(std::async(std::launch::async, [this, i, size]() {
if (i < 64) { if (i < 64) {
return overworld_maps_[i].BuildMap(size, game_state_, 0, map_parent_, return overworld_maps_[i].BuildMap(size, game_state_, 0, map_parent_,
map_tiles_.light_world); map_tiles_.light_world);

View File

@@ -58,10 +58,15 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
} }
void OverworldMap::LoadAreaInfo() { void OverworldMap::LoadAreaInfo() {
if (index_ != 0x80 && index_ <= 150 && if (index_ != 0x80) {
rom_[overworldMapSize + (index_ & 0x3F)] != 0) { if (index_ <= 150)
large_map_ = true; large_map_ = rom_[overworldMapSize + (index_ & 0x3F)] != 0;
else {
large_map_ =
index_ == 129 || index_ == 130 || index_ == 137 || index_ == 138;
}
} }
if (index_ < 64) { if (index_ < 64) {
area_graphics_ = rom_[mapGfx + parent_]; area_graphics_ = rom_[mapGfx + parent_];
area_palette_ = rom_[overworldMapPalette + parent_]; area_palette_ = rom_[overworldMapPalette + parent_];
@@ -109,6 +114,9 @@ void OverworldMap::LoadAreaInfo() {
parent_ = 0x2C; parent_ = 0x2C;
} else if (index_ == 0x88) { } else if (index_ == 0x88) {
parent_ = 0x88; parent_ = 0x88;
} else if (index_ == 129 || index_ == 130 || index_ == 137 ||
index_ == 138) {
parent_ = 129;
} }
area_palette_ = rom_[overworldSpecialPALGroup + parent_ - 0x80]; area_palette_ = rom_[overworldSpecialPALGroup + parent_ - 0x80];

View File

@@ -41,7 +41,6 @@ class OverworldMap : public GfxContext {
void DrawAnimatedTiles(); void DrawAnimatedTiles();
auto Tile16Blockset() const { return current_blockset_; } auto Tile16Blockset() const { return current_blockset_; }
auto AreaGraphics() const { return current_gfx_; } auto AreaGraphics() const { return current_gfx_; }
auto AreaPalette() const { return current_palette_; } auto AreaPalette() const { return current_palette_; }
@@ -77,6 +76,20 @@ class OverworldMap : public GfxContext {
auto set_sprite_palette(int i, uint8_t value) { sprite_palette_[i] = value; } auto set_sprite_palette(int i, uint8_t value) { sprite_palette_[i] = value; }
auto set_message_id(uint16_t value) { message_id_ = value; } auto set_message_id(uint16_t value) { message_id_ = value; }
auto ParentIndex() const { return parent_index_; }
void SetAsLargeMap(int parent_index, int quadrant) {
parent_ = parent_index;
parent_index_ = quadrant;
large_map_ = true;
}
void SetAsSmallMap(int quadrant) {
parent_ = index_;
parent_index_ = quadrant;
large_map_ = false;
}
private: private:
void LoadAreaInfo(); void LoadAreaInfo();
@@ -96,6 +109,7 @@ class OverworldMap : public GfxContext {
int parent_ = 0; int parent_ = 0;
int index_ = 0; int index_ = 0;
int parent_index_ = 0;
int world_ = 0; int world_ = 0;
int game_state_ = 0; int game_state_ = 0;
int world_index_ = 0; int world_index_ = 0;