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);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
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) {
@@ -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));
}
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 {
std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width,
int height, int tile_size) {
@@ -404,14 +413,6 @@ std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width,
}
} // 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) {
const ImGuiIO &io = ImGui::GetIO();
static ImVec2 drag_start_pos;

View File

@@ -25,20 +25,6 @@ namespace zelda3 {
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> resultMap;
@@ -79,9 +65,9 @@ absl::flat_hash_map<int, MapData> parseFile(const std::string &filename) {
while (getline(ss, valueStr, ',')) {
uint8_t value = std::stoi(valueStr, nullptr, 16);
if (isHigh) {
resultMap[currentKey].highData.push_back(value);
resultMap[currentKey].highData.emplace_back(value);
} 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) {
world_type = 2;
}
futures.push_back(std::async(std::launch::async, [this, i, size,
world_type]() {
futures.emplace_back(std::async(std::launch::async, [this, i, size,
world_type]() {
return overworld_maps_[i].BuildMap(size, game_state_, 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) +
" at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + 3 * i, b1));
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + (3 * i), b1));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + 3 * i, b2));
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + (3 * i), b2));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + 3 * i, b3));
rom()->WriteByte(kCompressedAllMap32PointersLow + 2 + (3 * i), b3));
for (const uint8_t byte : a) {
RETURN_IF_ERROR(rom()->WriteByte(pos, byte));
pos++;
@@ -273,11 +259,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers1 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + 3 * i, b1));
rom()->WriteByte(kCompressedAllMap32PointersLow + 0 + (3 * i), b1));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + 3 * i, b2));
rom()->WriteByte(kCompressedAllMap32PointersLow + 1 + (3 * i), b2));
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) {
@@ -302,11 +288,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers2 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + 3 * i, b1));
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + (3 * i), b1));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + 3 * i, b2));
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + (3 * i), b2));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + 3 * i, b3));
rom()->WriteByte(kCompressedAllMap32PointersHigh + 2 + (3 * i), b3));
for (const uint8_t byte : b) {
RETURN_IF_ERROR(rom()->WriteByte(pos, byte));
pos++;
@@ -320,11 +306,11 @@ absl::Status Overworld::SaveOverworldMaps() {
core::Logger::log("Saving map pointers2 for map " + std::to_string(i) +
" at " + core::UppercaseHexLong(snes_pos));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + 3 * i, b1));
rom()->WriteByte(kCompressedAllMap32PointersHigh + 0 + (3 * i), b1));
RETURN_IF_ERROR(
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + 3 * i, b2));
rom()->WriteByte(kCompressedAllMap32PointersHigh + 1 + (3 * i), b2));
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 (overworld_maps_[i - 1].IsLargeMap()) {
// 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(
OverworldScreenTileMapChangeByScreen1 + (i * 2) + 16,
0x0060));
@@ -471,7 +457,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area to the right is a large area.
if (overworld_maps_[i + 2].IsLargeMap()) {
// 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(
OverworldScreenTileMapChangeByScreen2 + (i * 2) + 18,
0x0080)); // Always 0x1080.
@@ -497,7 +483,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just above us is a large area.
if (overworld_maps_[i - 8].IsLargeMap()) {
// 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(
OverworldScreenTileMapChangeByScreen3 + (i * 2) + 02, 0x1800));
}
@@ -522,7 +508,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just below us is a large area.
if (overworld_maps_[i + 16].IsLargeMap()) {
// 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(
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.
if (i - 1 >= 0 && parentxPos != 0) {
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),
0xF060);
}
@@ -567,7 +553,7 @@ absl::Status Overworld::SaveLargeMaps() {
0x0040);
if (i + 1 < 64 && parentxPos != 7) {
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),
0x1060);
}
@@ -582,7 +568,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just above us is a large area.
if (overworld_maps_[i - 8].IsLargeMap()) {
// 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),
0x17C0);
}
@@ -597,7 +583,7 @@ absl::Status Overworld::SaveLargeMaps() {
// If the area just below us is a large area.
if (overworld_maps_[i + 8].IsLargeMap()) {
// 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),
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 + 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) {
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_);
// Convert to set then back to vector
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());
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;
for (size_t tile32_id = 0; tile32_id < unique_tiles.size(); tile32_id++) {
all_tiles_indexed.insert(
{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++) {
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
for (const auto &tile : unique_tiles) {
for (int i = 0; i < unique_tiles.size(); ++i) {
// 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) {
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) {
std::cout << "Number of unique Tiles32: " << tiles32_unique_.size()
std::cout << "Number of unique Tiles32: " << unique_tiles.size()
<< " Out of: " << LimitOfMap32 << std::endl;
} 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
<< "\nUnique Tile32 count exceed the limit"
<< "\nThe ROM Has not been saved"
@@ -721,12 +712,137 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
int v = tiles32_unique_.size();
for (int i = v; i < LimitOfMap32; i++) {
gfx::Tile32 padding_tile(420, 420, 420, 420);
tiles32_unique_.push_back(padding_tile.GetPackedValue());
tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
}
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() {
core::Logger::log("Saving Map16 Tiles");
int tpos = kMap16Tiles;
@@ -748,84 +864,6 @@ absl::Status Overworld::SaveMap16Tiles() {
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) {
// The addresses of the four 32x32 pixel tiles in the rom()->
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);
// 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
// the appropriate number of tiles.
map_tiles_.light_world.resize(kTile32Num);
map_tiles_.dark_world.resize(kTile32Num);
map_tiles_.special_world.resize(kTile32Num);
for (int i = 0; i < kTile32Num; i++) {
map_tiles_.light_world[i].resize(kTile32Num);
map_tiles_.dark_world[i].resize(kTile32Num);
map_tiles_.special_world[i].resize(kTile32Num);
map_tiles_.light_world.resize(0x200);
map_tiles_.dark_world.resize(0x200);
map_tiles_.special_world.resize(0x200);
for (int i = 0; i < 0x200; i++) {
map_tiles_.light_world[i].resize(0x200);
map_tiles_.dark_world[i].resize(0x200);
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_x2 = (x * 2) + 1 + (sx * 32);
int position_y2 = (y * 2) + 1 + (sy * 32);
world[position_x1][position_y1] = tiles32_[tpos].tile0_;
world[position_x2][position_y1] = tiles32_[tpos].tile1_;
world[position_x1][position_y2] = tiles32_[tpos].tile2_;
world[position_x2][position_y2] = tiles32_[tpos].tile3_;
world[position_x1][position_y1] = tiles32_unique_[tpos].tile0_;
world[position_x2][position_y1] = tiles32_unique_[tpos].tile1_;
world[position_x1][position_y2] = tiles32_unique_[tpos].tile2_;
world[position_x2][position_y2] = tiles32_unique_[tpos].tile3_;
}
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 x = 0; x < 16; x++) {
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) {
AssignWorldTiles(x, y, sx, sy, tpos, map_tiles_.light_world);
} 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() {
int lowest = 0x0FFFFF;
int highest = 0x0F8000;
@@ -970,6 +1024,7 @@ absl::Status Overworld::DecompressAllMapTiles() {
void Overworld::FetchLargeMaps() {
for (int i = 128; i < 145; i++) {
map_parent_[i] = 0;
overworld_maps_[i].SetAsSmallMap(0);
}
map_parent_[128] = 128;
@@ -977,6 +1032,11 @@ void Overworld::FetchLargeMaps() {
map_parent_[130] = 129;
map_parent_[137] = 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;
overworld_maps_[136].SetLargeMap(false);
@@ -993,22 +1053,32 @@ void Overworld::FetchLargeMaps() {
mapChecked[i] = true;
map_parent_[i] = (uchar)i;
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;
map_parent_[i + 1] = (uchar)i;
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;
map_parent_[i + 8] = (uchar)i;
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;
map_parent_[i + 9] = (uchar)i;
map_parent_[i + 73] = (uchar)(i + 64);
overworld_maps_[i + 9].SetAsLargeMap(i, 3);
overworld_maps_[i + 73].SetAsLargeMap(i + 64, 3);
xx++;
} else {
map_parent_[i] = (uchar)i;
map_parent_[i + 64] = (uchar)(i + 64);
overworld_maps_[i].SetAsSmallMap(0);
overworld_maps_[i + 64].SetAsSmallMap(0);
mapChecked[i] = true;
}
}
@@ -1313,7 +1383,7 @@ absl::Status Overworld::SaveItems() {
roomItems[i] = std::vector<OverworldItem>();
for (const OverworldItem &item : all_items_) {
if (item.room_map_id == i) {
roomItems[i].push_back(item);
roomItems[i].emplace_back(item);
if (item.id == 0x86) {
RETURN_IF_ERROR(rom()->WriteWord(
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();
std::vector<std::future<absl::Status>> futures;
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) {
return overworld_maps_[i].BuildMap(size, game_state_, 0, map_parent_,
map_tiles_.light_world);

View File

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

View File

@@ -41,7 +41,6 @@ class OverworldMap : public GfxContext {
void DrawAnimatedTiles();
auto Tile16Blockset() const { return current_blockset_; }
auto AreaGraphics() const { return current_gfx_; }
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_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:
void LoadAreaInfo();
@@ -96,6 +109,7 @@ class OverworldMap : public GfxContext {
int parent_ = 0;
int index_ = 0;
int parent_index_ = 0;
int world_ = 0;
int game_state_ = 0;
int world_index_ = 0;