fix bug with ow edits outside top row

This commit is contained in:
scawful
2023-10-22 16:17:18 -04:00
parent 6a0dc078c1
commit f5c6899d4d
3 changed files with 237 additions and 209 deletions

View File

@@ -200,7 +200,7 @@ void OverworldEditor::DrawOverworldEdits() {
auto canvas_size = ow_map_canvas_.GetCanvasSize(); auto canvas_size = ow_map_canvas_.GetCanvasSize();
int x = mouse_position.x / canvas_size.x; int x = mouse_position.x / canvas_size.x;
int y = mouse_position.y / canvas_size.y; int y = mouse_position.y / canvas_size.y;
auto index = x + (y * 64); auto index = x + (y * 8);
// Determine which overworld map the user is currently editing. // Determine which overworld map the user is currently editing.
DetermineActiveMap(mouse_position); DetermineActiveMap(mouse_position);
@@ -213,14 +213,26 @@ void OverworldEditor::DrawOverworldEdits() {
QueueROMChanges(index, current_tile16_); QueueROMChanges(index, current_tile16_);
} }
void OverworldEditor::DetermineActiveMap(const ImVec2 &mouse_position) {
// Assuming each small map is 256x256 pixels (adjust as needed)
constexpr int small_map_size = 512;
// Calculate which small map the mouse is currently over
int map_x = mouse_position.x / small_map_size;
int map_y = mouse_position.y / small_map_size;
// Calculate the index of the map in the `maps_bmp_` vector
current_map_ = map_x + map_y * 8;
}
void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position, void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position,
const Bytes &tile_data) { const Bytes &tile_data) {
// Calculate the tile position relative to the current active map // Calculate the tile position relative to the current active map
constexpr int tile_size = 16; // Tile size is 16x16 pixels constexpr int tile_size = 16; // Tile size is 16x16 pixels
// Calculate the tile index for x and y based on the click_position // Calculate the tile index for x and y based on the click_position
int tile_index_x = static_cast<int>(click_position.x) / tile_size; int tile_index_x = (static_cast<int>(click_position.x) % 512) / tile_size;
int tile_index_y = static_cast<int>(click_position.y) / tile_size; int tile_index_y = (static_cast<int>(click_position.y) % 512) / tile_size;
// Calculate the pixel start position based on tile index and tile size // Calculate the pixel start position based on tile index and tile size
ImVec2 start_position; ImVec2 start_position;
@@ -256,20 +268,22 @@ void OverworldEditor::QueueROMChanges(int index, ushort new_tile16) {
}); });
} }
void OverworldEditor::DetermineActiveMap(const ImVec2 &mouse_position) {
// Assuming each small map is 256x256 pixels (adjust as needed)
constexpr int small_map_size = 512;
// Calculate which small map the mouse is currently over
int map_x = mouse_position.x / small_map_size;
int map_y = mouse_position.y / small_map_size;
// Calculate the index of the map in the `maps_bmp_` vector
current_map_ = map_x + map_y * 8;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void OverworldEditor::CheckForOverworldEdits() {
if (!blockset_canvas_.Points().empty()) {
// User has selected a tile they want to draw from the blockset.
int x = blockset_canvas_.Points().front().x / 32;
int y = blockset_canvas_.Points().front().y / 32;
current_tile16_ = x + (y * 8);
if (ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_],
16)) {
// Update the overworld map.
DrawOverworldEdits();
}
}
}
// Overworld Editor canvas // Overworld Editor canvas
// Allows the user to make changes to the overworld map. // Allows the user to make changes to the overworld map.
void OverworldEditor::DrawOverworldCanvas() { void OverworldEditor::DrawOverworldCanvas() {
@@ -285,17 +299,7 @@ void OverworldEditor::DrawOverworldCanvas() {
DrawOverworldMaps(); DrawOverworldMaps();
DrawOverworldEntrances(); DrawOverworldEntrances();
// DrawOverworldSprites(); // DrawOverworldSprites();
// User has selected a tile they want to draw from the blockset. CheckForOverworldEdits();
if (!blockset_canvas_.Points().empty()) {
int x = blockset_canvas_.Points().front().x / 32;
int y = blockset_canvas_.Points().front().y / 32;
current_tile16_ = x + (y * 8);
if (ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_],
16)) {
// Update the overworld map.
DrawOverworldEdits();
}
}
} }
ow_map_canvas_.DrawGrid(64.0f); ow_map_canvas_.DrawGrid(64.0f);
ow_map_canvas_.DrawOverlay(); ow_map_canvas_.DrawOverlay();

View File

@@ -63,6 +63,21 @@ class OverworldEditor : public Editor, public SharedROM {
absl::Status Copy() { return absl::UnimplementedError("Copy"); } absl::Status Copy() { return absl::UnimplementedError("Copy"); }
absl::Status Paste() { return absl::UnimplementedError("Paste"); } absl::Status Paste() { return absl::UnimplementedError("Paste"); }
void Shutdown() {
for (auto &bmp : tile16_individual_) {
bmp.Cleanup();
}
for (auto &[i, bmp] : maps_bmp_) {
bmp.Cleanup();
}
for (auto &[i, bmp] : graphics_bin_) {
bmp.Cleanup();
}
for (auto &[i, bmp] : current_graphics_set_) {
bmp.Cleanup();
}
}
private: private:
absl::Status DrawToolset(); absl::Status DrawToolset();
void DrawOverworldMapSettings(); void DrawOverworldMapSettings();
@@ -77,6 +92,7 @@ class OverworldEditor : public Editor, public SharedROM {
void QueueROMChanges(int index, ushort new_tile16); void QueueROMChanges(int index, ushort new_tile16);
void DetermineActiveMap(const ImVec2 &mouse_position); void DetermineActiveMap(const ImVec2 &mouse_position);
void CheckForOverworldEdits();
void DrawOverworldCanvas(); void DrawOverworldCanvas();
void DrawTile8Selector(); void DrawTile8Selector();

View File

@@ -286,7 +286,8 @@ absl::Status Overworld::SaveLargeMaps() {
std::unordered_map<uint8_t, uint8_t> checkedMap; std::unordered_map<uint8_t, uint8_t> checkedMap;
// Always write the map parent since it should not matter // Always write the map parent since it should not matter
rom()->Write(overworldMapParentId + i, overworld_maps_[i].Parent()); RETURN_IF_ERROR(
rom()->Write(overworldMapParentId + i, overworld_maps_[i].Parent()))
if (checkedMap.count(overworld_maps_[i].Parent()) > 0) { if (checkedMap.count(overworld_maps_[i].Parent()) > 0) {
continue; continue;
@@ -295,149 +296,140 @@ absl::Status Overworld::SaveLargeMaps() {
// If it's large then save parent pos * // If it's large then save parent pos *
// 0x200 otherwise pos * 0x200 // 0x200 otherwise pos * 0x200
if (overworld_maps_[i].IsLargeMap()) { if (overworld_maps_[i].IsLargeMap()) {
// Check 1 RETURN_IF_ERROR(rom()->RunTransaction(
rom()->Write(overworldMapSize + i, 0x20); // Check 1
rom()->Write(overworldMapSize + i + 1, 0x20); WriteAction{overworldMapSize + i, 0x20},
rom()->Write(overworldMapSize + i + 8, 0x20); WriteAction{overworldMapSize + i + 1, 0x20},
rom()->Write(overworldMapSize + i + 9, 0x20); WriteAction{overworldMapSize + i + 8, 0x20},
WriteAction{overworldMapSize + i + 9, 0x20},
// Check 2 // Check 2
rom()->Write(overworldMapSizeHighByte + i, 0x03); WriteAction{overworldMapSizeHighByte + i, 0x03},
rom()->Write(overworldMapSizeHighByte + i + 1, 0x03); WriteAction{overworldMapSizeHighByte + i + 1, 0x03},
rom()->Write(overworldMapSizeHighByte + i + 8, 0x03); WriteAction{overworldMapSizeHighByte + i + 8, 0x03},
rom()->Write(overworldMapSizeHighByte + i + 9, 0x03); WriteAction{overworldMapSizeHighByte + i + 9, 0x03},
// Check 3 // Check 3
rom()->Write(overworldScreenSize + i, 0x00); WriteAction{overworldScreenSize + i, 0x00},
rom()->Write(overworldScreenSize + i + 64, 0x00); WriteAction{overworldScreenSize + i + 64, 0x00},
rom()->Write(overworldScreenSize + i + 1, 0x00); WriteAction{overworldScreenSize + i + 1, 0x00},
rom()->Write(overworldScreenSize + i + 1 + 64, 0x00); WriteAction{overworldScreenSize + i + 1 + 64, 0x00},
rom()->Write(overworldScreenSize + i + 8, 0x00); WriteAction{overworldScreenSize + i + 8, 0x00},
rom()->Write(overworldScreenSize + i + 8 + 64, 0x00); WriteAction{overworldScreenSize + i + 8 + 64, 0x00},
rom()->Write(overworldScreenSize + i + 9, 0x00); WriteAction{overworldScreenSize + i + 9, 0x00},
rom()->Write(overworldScreenSize + i + 9 + 64, 0x00); WriteAction{overworldScreenSize + i + 9 + 64, 0x00},
// Check 4 // Check 4
rom()->Write(OverworldScreenSizeForLoading + i, 0x04); WriteAction{OverworldScreenSizeForLoading + i, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 64, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 64, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 128, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 128, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 1, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 1, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 1 + 64, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 1 + 64, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 1 + 128, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 1 + 128, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 8, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 8, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 8 + 64, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 8 + 64, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 8 + 128, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 8 + 128, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 9, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 9, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 9 + 64, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 9 + 64, 0x04},
rom()->Write(OverworldScreenSizeForLoading + i + 9 + 128, 0x04); WriteAction{OverworldScreenSizeForLoading + i + 9 + 128, 0x04},
// Check 5 and 6 // Check 5 and 6
rom()->WriteShort( WriteAction{transition_target_north + (i * 2) + 2,
transition_target_north + (i * 2) + 2, (short)((parentyPos * 0x200) -
(short)((parentyPos * 0x200) - 0xE0)}, // (short) is placed to reduce the int to
0xE0)); // (short) is placed to reduce the int to 2 bytes. // 2 bytes.
rom()->WriteShort(transition_target_west + (i * 2) + 2, WriteAction{transition_target_west + (i * 2) + 2,
(short)((parentxPos * 0x200) - 0x100)); (short)((parentxPos * 0x200) - 0x100)},
rom()->WriteShort( // (short) is placed to reduce the int to 2 bytes.
transition_target_north + (i * 2) + 16, WriteAction{transition_target_north + (i * 2) + 16,
(short)((parentyPos * 0x200) - (short)((parentyPos * 0x200) - 0xE0)},
0xE0)); // (short) is placed to reduce the int to 2 bytes. WriteAction{transition_target_west + (i * 2) + 16,
rom()->WriteShort(transition_target_west + (i * 2) + 16, (short)((parentxPos * 0x200) - 0x100)},
(short)((parentxPos * 0x200) - 0x100));
rom()->WriteShort( // (short) is placed to reduce the int to 2 bytes.
transition_target_north + (i * 2) + 18, WriteAction{transition_target_north + (i * 2) + 18,
(short)((parentyPos * 0x200) - (short)((parentyPos * 0x200) - 0xE0)},
0xE0)); // (short) is placed to reduce the int to 2 bytes. WriteAction{transition_target_west + (i * 2) + 18,
rom()->WriteShort(transition_target_west + (i * 2) + 18, (short)((parentxPos * 0x200) - 0x100)},
(short)((parentxPos * 0x200) - 0x100));
// Check 7 and 8 // Check 7 and 8
rom()->WriteShort(overworldTransitionPositionX + (i * 2), WriteAction{overworldTransitionPositionX + (i * 2),
(parentxPos * 0x200)); (parentxPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionY + (i * 2), WriteAction{overworldTransitionPositionY + (i * 2),
(parentyPos * 0x200)); (parentyPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionX + (i * 2) + 2, WriteAction{overworldTransitionPositionX + (i * 2) + 2,
(parentxPos * 0x200)); (parentxPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionY + (i * 2) + 2, WriteAction{overworldTransitionPositionY + (i * 2) + 2,
(parentyPos * 0x200)); (parentyPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionX + (i * 2) + 16, WriteAction{overworldTransitionPositionX + (i * 2) + 16,
(parentxPos * 0x200)); (parentxPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionY + (i * 2) + 16, WriteAction{overworldTransitionPositionY + (i * 2) + 16,
(parentyPos * 0x200)); (parentyPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionX + (i * 2) + 18, WriteAction{overworldTransitionPositionX + (i * 2) + 18,
(parentxPos * 0x200)); (parentxPos * 0x200)},
rom()->WriteShort(overworldTransitionPositionY + (i * 2) + 18, WriteAction{overworldTransitionPositionY + (i * 2) + 18,
(parentyPos * 0x200)); (parentyPos * 0x200)},
// Check 9 // Check 9
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2), // Always 0x0060
0x0060); // Always 0x0060 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2), 0x0060},
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 2, // Always 0x0060
0x0060); // Always 0x0060 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2,
0x0060}))
uint16_t lowerSubmaps;
// If parentX == 0 then lower submaps == 0x0060 too // If parentX == 0 then lower submaps == 0x0060 too
if (parentxPos == 0) { if (parentxPos == 0) {
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 16, lowerSubmaps = 0x0060;
0x0060);
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 18,
0x0060);
} else { } else {
// Otherwise lower submaps == 0x1060 // Otherwise lower submaps == 0x1060
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 16, lowerSubmaps = 0x1060;
0x1060);
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 18,
0x1060);
} }
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 128, RETURN_IF_ERROR(rom()->RunTransaction(
0x0080); // Always 0x0080 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 16,
rom()->WriteShort( uint16_t(lowerSubmaps)},
OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 128, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18,
0x0080); // Always 0x0080 uint16_t(lowerSubmaps)},
// Lower are always 8010 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 128,
rom()->WriteShort( uint16_t(0x0080)}, // Always 0x0080
OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 128, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 128,
0x1080); // Always 0x1080 uint16_t(0x0080)}, // Always 0x0080
rom()->WriteShort( // Lower are always 8010
OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 128, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 128,
0x1080); // Always 0x1080 uint16_t(0x1080)}, // Always 0x1080
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 128,
uint16_t(0x1080)}, // Always 0x1080
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 256, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 256,
0x1800); // Always 0x1800 uint16_t(0x1800)}, // Always 0x1800
rom()->WriteShort( WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 256,
OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 256, uint16_t(0x1800)}, // Always 0x1800
0x1800); // Always 0x1800 // Right side is always 1840
// Right side is always 1840 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 256,
rom()->WriteShort( uint16_t(0x1840)}, // Always 0x1840
OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 256, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 256,
0x1840); // Always 0x1840 uint16_t(0x1840)}, // Always 0x1840
rom()->WriteShort(
OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 256,
0x1840); // Always 0x1840
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 384, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 384,
0x2000); // Always 0x2000 uint16_t(0x2000)}, // Always 0x2000
rom()->WriteShort( WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 384,
OverworldScreenTileMapChangeByScreen + (i * 2) + 16 + 384, uint16_t(0x2000)}, // Always 0x2000
0x2000); // Always 0x2000 // Right side is always 0x2040
// Right side is always 0x2040 WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 384,
rom()->WriteShort( uint16_t(0x2040)}, // Always 0x2000
OverworldScreenTileMapChangeByScreen + (i * 2) + 2 + 384, WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 384,
0x2040); // Always 0x2000 uint16_t(0x2040)})) // Always 0x2000
rom()->WriteShort(
OverworldScreenTileMapChangeByScreen + (i * 2) + 18 + 384,
0x2040); // Always 0x2000
checkedMap.emplace(i, 1); checkedMap.emplace(i, 1);
checkedMap.emplace((i + 1), 1); checkedMap.emplace((i + 1), 1);
@@ -445,31 +437,31 @@ absl::Status Overworld::SaveLargeMaps() {
checkedMap.emplace((i + 9), 1); checkedMap.emplace((i + 9), 1);
} else { } else {
rom()->Write(overworldMapSize + i, 0x00); RETURN_IF_ERROR(rom()->RunTransaction(
rom()->Write(overworldMapSizeHighByte + i, 0x01); WriteAction{overworldMapSize + i, 0x00},
WriteAction{overworldMapSizeHighByte + i, 0x01},
WriteAction{overworldScreenSize + i, 0x01},
WriteAction{overworldScreenSize + i + 64, 0x01},
WriteAction{OverworldScreenSizeForLoading + i, 0x02},
WriteAction{OverworldScreenSizeForLoading + i + 64, 0x02},
WriteAction{OverworldScreenSizeForLoading + i + 128, 0x02},
rom()->Write(overworldScreenSize + i, 0x01); WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2),
rom()->Write(overworldScreenSize + i + 64, 0x01); uint16_t(0x0060)},
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 128,
rom()->Write(OverworldScreenSizeForLoading + i, 0x02); uint16_t(0x0040)},
rom()->Write(OverworldScreenSizeForLoading + i + 64, 0x02); WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 256,
rom()->Write(OverworldScreenSizeForLoading + i + 128, 0x02); uint16_t(0x1800)},
WriteAction{OverworldScreenTileMapChangeByScreen + (i * 2) + 384,
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2), 0x0060); (0x1000)},
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 128, WriteAction{transition_target_north + (i * 2),
0x0040); uint16_t((yPos * 0x200) - 0xE0)},
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 256, WriteAction{transition_target_west + (i * 2),
0x1800); uint16_t((xPos * 0x200) - 0x100)},
rom()->WriteShort(OverworldScreenTileMapChangeByScreen + (i * 2) + 384, WriteAction{overworldTransitionPositionX + (i * 2),
0x1000); uint16_t(xPos * 0x200)},
WriteAction{overworldTransitionPositionY + (i * 2),
rom()->WriteShort(transition_target_north + (i * 2), uint16_t(yPos * 0x200)}))
(short)((yPos * 0x200) - 0xE0));
rom()->WriteShort(transition_target_west + (i * 2),
(short)((xPos * 0x200) - 0x100));
rom()->WriteShort(overworldTransitionPositionX + (i * 2), (xPos * 0x200));
rom()->WriteShort(overworldTransitionPositionY + (i * 2), (yPos * 0x200));
checkedMap.emplace(i, 1); checkedMap.emplace(i, 1);
} }
@@ -553,60 +545,76 @@ absl::Status Overworld::SaveMap16Tiles() {
int tpos = kMap16Tiles; int tpos = kMap16Tiles;
// 3760 // 3760
for (int i = 0; i < NumberOfMap16; i += 1) { for (int i = 0; i < NumberOfMap16; i += 1) {
RETURN_IF_ERROR(rom()->RunTransaction( RETURN_IF_ERROR(rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile0_)))
WriteAction{tpos, uint16_t(TileInfoToShort(tiles16[i].tile0_))}, tpos += 2;
WriteAction{tpos += 2, uint16_t(TileInfoToShort(tiles16[i].tile1_))}, RETURN_IF_ERROR(rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile1_)))
WriteAction{tpos += 2, uint16_t(TileInfoToShort(tiles16[i].tile2_))}, tpos += 2;
WriteAction{tpos += 2, uint16_t(TileInfoToShort(tiles16[i].tile3_))})); RETURN_IF_ERROR(rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile2_)))
tpos += 2;
// rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile0_)); RETURN_IF_ERROR(rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile3_)))
// tpos += 2; tpos += 2;
// rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile1_));
// tpos += 2;
// rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile2_));
// tpos += 2;
// rom()->WriteShort(tpos, TileInfoToShort(tiles16[i].tile3_));
// tpos += 2;
} }
return absl::OkStatus();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
absl::Status Overworld::SaveMap32Tiles() { absl::Status Overworld::SaveMap32Tiles() {
int index = 0; constexpr int kMaxUniqueTiles = 0x4540;
int c = tiles32_unique_.size(); constexpr int kTilesPer32x32Tile = 6;
constexpr int kQuadrantsPer32x32Tile = 4;
for (int i = 0; i < c; i += 6) { if (tiles32_unique_.size() % kTilesPer32x32Tile != 0) {
if (index >= 0x4540) { return absl::InvalidArgumentError("Invalid number of unique tiles.");
return absl::AbortedError("Too many unique tile32 definitions."); }
}
// Helper lambda to avoid code repetition int unique_tile_index = 0;
auto writeTilesToRom = [&](int base_addr, auto get_tile) { int num_unique_tiles = tiles32_unique_.size();
for (int j = 0; j < 4; ++j) { int num_32x32_tiles = num_unique_tiles / kTilesPer32x32Tile;
rom()->Write(base_addr + i + j,
get_tile(tiles32_unique_[index + j]) & 0xFF); if (num_32x32_tiles > kMaxUniqueTiles / kQuadrantsPer32x32Tile) {
return absl::AbortedError("Too many unique tile32 definitions.");
}
for (int i = 0; i < num_32x32_tiles; ++i) {
int base_addr =
rom()->GetVersionConstants().kMap32TileTL + i * kQuadrantsPer32x32Tile;
auto write_quadrant_to_rom = [&](int quadrant,
auto get_tile) -> absl::Status {
for (int j = 0; j < kQuadrantsPer32x32Tile; ++j) {
int tile_index = unique_tile_index + j;
const gfx::Tile32 &tile = tiles32_unique_[tile_index];
RETURN_IF_ERROR(
rom()->Write(base_addr + quadrant + j, get_tile(tile) & 0xFF));
} }
rom()->Write(base_addr + i + 4,
((get_tile(tiles32_unique_[index]) >> 4) & 0xF0) | int tile0 = get_tile(tiles32_unique_[unique_tile_index]);
((get_tile(tiles32_unique_[index + 1]) >> 8) & 0x0F)); int tile1 = get_tile(tiles32_unique_[unique_tile_index + 1]);
rom()->Write(base_addr + i + 5, int tile2 = get_tile(tiles32_unique_[unique_tile_index + 2]);
((get_tile(tiles32_unique_[index + 2]) >> 4) & 0xF0) | int tile3 = get_tile(tiles32_unique_[unique_tile_index + 3]);
((get_tile(tiles32_unique_[index + 3]) >> 8) & 0x0F));
RETURN_IF_ERROR(
rom()->Write(base_addr + quadrant + 4,
((tile0 >> 4) & 0xF0) | ((tile1 >> 8) & 0x0F)));
RETURN_IF_ERROR(
rom()->Write(base_addr + quadrant + 5,
((tile2 >> 4) & 0xF0) | ((tile3 >> 8) & 0x0F)));
return absl::OkStatus();
}; };
writeTilesToRom(rom()->GetVersionConstants().kMap32TileTL, RETURN_IF_ERROR(write_quadrant_to_rom(
[](const gfx::Tile32 &t) { return t.tile0_; }); 0, [](const gfx::Tile32 &t) { return t.tile0_; }));
writeTilesToRom(rom()->GetVersionConstants().kMap32TileTR, RETURN_IF_ERROR(write_quadrant_to_rom(
[](const gfx::Tile32 &t) { return t.tile1_; }); 1, [](const gfx::Tile32 &t) { return t.tile1_; }));
writeTilesToRom(rom()->GetVersionConstants().kMap32TileBL, RETURN_IF_ERROR(write_quadrant_to_rom(
[](const gfx::Tile32 &t) { return t.tile2_; }); 2, [](const gfx::Tile32 &t) { return t.tile2_; }));
writeTilesToRom(rom()->GetVersionConstants().kMap32TileBR, RETURN_IF_ERROR(write_quadrant_to_rom(
[](const gfx::Tile32 &t) { return t.tile3_; }); 3, [](const gfx::Tile32 &t) { return t.tile3_; }));
index += 4; unique_tile_index += kTilesPer32x32Tile;
c += 2;
} }
return absl::OkStatus(); return absl::OkStatus();
} }