Overworld updates, Tile16 and large map fixes
This commit is contained in:
@@ -571,18 +571,14 @@ void MasterEditor::SaveRom() {
|
|||||||
RETURN_VOID_IF_ERROR(status_);
|
RETURN_VOID_IF_ERROR(status_);
|
||||||
}
|
}
|
||||||
if (flags()->overworld.kSaveOverworldMaps) {
|
if (flags()->overworld.kSaveOverworldMaps) {
|
||||||
if (!overworld_editor_.overworld()->CreateTile32Tilemap()) {
|
RETURN_VOID_IF_ERROR(
|
||||||
|
status_ = overworld_editor_.overworld()->CreateTile32Tilemap());
|
||||||
status_ = overworld_editor_.overworld()->SaveMap32Tiles();
|
status_ = overworld_editor_.overworld()->SaveMap32Tiles();
|
||||||
RETURN_VOID_IF_ERROR(status_);
|
RETURN_VOID_IF_ERROR(status_);
|
||||||
status_ = overworld_editor_.overworld()->SaveMap16Tiles();
|
status_ = overworld_editor_.overworld()->SaveMap16Tiles();
|
||||||
RETURN_VOID_IF_ERROR(status_);
|
RETURN_VOID_IF_ERROR(status_);
|
||||||
status_ = overworld_editor_.overworld()->SaveOverworldMaps();
|
status_ = overworld_editor_.overworld()->SaveOverworldMaps();
|
||||||
RETURN_VOID_IF_ERROR(status_);
|
RETURN_VOID_IF_ERROR(status_);
|
||||||
} else {
|
|
||||||
status_ = absl::InternalError(
|
|
||||||
"Failed to save Overworld maps, aborting ROM save.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (flags()->overworld.kSaveOverworldEntrances) {
|
if (flags()->overworld.kSaveOverworldEntrances) {
|
||||||
status_ = overworld_editor_.overworld()->SaveEntrances();
|
status_ = overworld_editor_.overworld()->SaveEntrances();
|
||||||
|
|||||||
@@ -485,9 +485,8 @@ void OverworldEditor::DrawOverworldMaps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::DrawOverworldEdits() {
|
void OverworldEditor::DrawOverworldEdits() {
|
||||||
auto mouse_position = ow_map_canvas_.drawn_tile_position();
|
|
||||||
|
|
||||||
// Determine which overworld map the user is currently editing.
|
// Determine which overworld map the user is currently editing.
|
||||||
|
auto mouse_position = ow_map_canvas_.drawn_tile_position();
|
||||||
constexpr int small_map_size = 512;
|
constexpr int small_map_size = 512;
|
||||||
int map_x = mouse_position.x / small_map_size;
|
int map_x = mouse_position.x / small_map_size;
|
||||||
int map_y = mouse_position.y / small_map_size;
|
int map_y = mouse_position.y / small_map_size;
|
||||||
@@ -511,12 +510,7 @@ void OverworldEditor::DrawOverworldEdits() {
|
|||||||
int tile16_x = (mouse_x % small_map_size) / (small_map_size / 32);
|
int tile16_x = (mouse_x % small_map_size) / (small_map_size / 32);
|
||||||
int tile16_y = (mouse_y % small_map_size) / (small_map_size / 32);
|
int tile16_y = (mouse_y % small_map_size) / (small_map_size / 32);
|
||||||
|
|
||||||
// Update the overworld_.map_tiles() data (word) based on tile16 ID and
|
// Update the overworld_.map_tiles() based on tile16 ID and current world
|
||||||
// current world
|
|
||||||
uint16_t tile_value = current_tile16_;
|
|
||||||
uint8_t low_byte = tile_value & 0xFF;
|
|
||||||
uint8_t high_byte = (tile_value >> 8) & 0xFF;
|
|
||||||
|
|
||||||
auto &selected_world =
|
auto &selected_world =
|
||||||
(current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
|
(current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
|
||||||
: (current_world_ == 1) ? overworld_.mutable_map_tiles()->dark_world
|
: (current_world_ == 1) ? overworld_.mutable_map_tiles()->dark_world
|
||||||
@@ -525,7 +519,7 @@ void OverworldEditor::DrawOverworldEdits() {
|
|||||||
int index_x = superX * 32 + tile16_x;
|
int index_x = superX * 32 + tile16_x;
|
||||||
int index_y = superY * 32 + tile16_y;
|
int index_y = superY * 32 + tile16_y;
|
||||||
|
|
||||||
selected_world[index_x][index_y] = tile_value;
|
selected_world[index_x][index_y] = current_tile16_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
||||||
@@ -557,12 +551,14 @@ void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::CheckForOverworldEdits() {
|
void OverworldEditor::CheckForOverworldEdits() {
|
||||||
|
// User has selected a tile they want to draw from the blockset.
|
||||||
if (!blockset_canvas_.points().empty() &&
|
if (!blockset_canvas_.points().empty() &&
|
||||||
current_mode == EditingMode::DRAW_TILE) {
|
current_mode == EditingMode::DRAW_TILE) {
|
||||||
// User has selected a tile they want to draw from the blockset.
|
// int x = blockset_canvas_.points().front().x / 32;
|
||||||
int x = blockset_canvas_.points().front().x / 32;
|
// int y = blockset_canvas_.points().front().y / 32;
|
||||||
int y = blockset_canvas_.points().front().y / 32;
|
// current_tile16_ = x + (y * 8);
|
||||||
current_tile16_ = x + (y * 8);
|
CheckForSelectRectangle();
|
||||||
|
|
||||||
if (ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_],
|
if (ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_],
|
||||||
16)) {
|
16)) {
|
||||||
// Update the overworld map.
|
// Update the overworld map.
|
||||||
@@ -571,6 +567,28 @@ void OverworldEditor::CheckForOverworldEdits() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverworldEditor::CheckForSelectRectangle() {
|
||||||
|
ow_map_canvas_.DrawSelectRectTile16(current_map_);
|
||||||
|
|
||||||
|
static std::vector<int> tile16_ids;
|
||||||
|
if (ow_map_canvas_.selected_tiles().size() != 0) {
|
||||||
|
// Get the tile16 IDs from the selected tile ID positions
|
||||||
|
// if (tile16_ids.size() != 0) {
|
||||||
|
// tile16_ids.clear();
|
||||||
|
// }
|
||||||
|
// for (auto &each : ow_map_canvas_.selected_tiles()) {
|
||||||
|
// tile16_ids.push_back(overworld_.GetTile16Id(each));
|
||||||
|
// }
|
||||||
|
if (ow_map_canvas_.selected_tiles().size() == 1) {
|
||||||
|
current_tile16_ =
|
||||||
|
overworld_.GetTile16Id(ow_map_canvas_.selected_tiles().at(0));
|
||||||
|
}
|
||||||
|
ow_map_canvas_.mutable_selected_tiles()->clear();
|
||||||
|
}
|
||||||
|
// Create a composite image of all the tile16s selected
|
||||||
|
// ow_map_canvas_.DrawBitmapGroup(tile16_ids, tile16_individual_, 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
void OverworldEditor::CheckForCurrentMap() {
|
void OverworldEditor::CheckForCurrentMap() {
|
||||||
// 4096x4096, 512x512 maps and some are larges maps 1024x1024
|
// 4096x4096, 512x512 maps and some are larges maps 1024x1024
|
||||||
auto mouse_position = ImGui::GetIO().MousePos;
|
auto mouse_position = ImGui::GetIO().MousePos;
|
||||||
@@ -618,26 +636,6 @@ void OverworldEditor::CheckForCurrentMap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::CheckForSelectRectangle() {
|
|
||||||
if (current_mode == EditingMode::DRAW_TILE) {
|
|
||||||
ow_map_canvas_.DrawSelectRect(0x10);
|
|
||||||
static std::vector<int> tile16_ids;
|
|
||||||
if (ow_map_canvas_.selected_tiles().size() != 0) {
|
|
||||||
// Get the tile16 IDs from the selected tile ID positions
|
|
||||||
if (tile16_ids.size() != 0) {
|
|
||||||
tile16_ids.clear();
|
|
||||||
}
|
|
||||||
for (auto &each : ow_map_canvas_.selected_tiles()) {
|
|
||||||
int tile16_id = overworld_.GetTile16Id(each);
|
|
||||||
tile16_ids.push_back(tile16_id);
|
|
||||||
}
|
|
||||||
ow_map_canvas_.mutable_selected_tiles()->clear();
|
|
||||||
}
|
|
||||||
// Create a composite image of all the tile16s selected
|
|
||||||
ow_map_canvas_.DrawBitmapGroup(tile16_ids, tile16_individual_, 0x10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() {
|
||||||
@@ -686,6 +684,11 @@ void OverworldEditor::DrawTile16Selector() {
|
|||||||
tile16_editor_.set_tile16(id);
|
tile16_editor_.set_tile16(id);
|
||||||
show_tile16_editor_ = true;
|
show_tile16_editor_ = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemClicked() && !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);
|
||||||
|
}
|
||||||
blockset_canvas_.DrawGrid();
|
blockset_canvas_.DrawGrid();
|
||||||
blockset_canvas_.DrawOverlay();
|
blockset_canvas_.DrawOverlay();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|||||||
@@ -384,7 +384,6 @@ 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) {
|
void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color) {
|
||||||
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
||||||
canvas_p0_.y + scrolling_.y + y);
|
canvas_p0_.y + scrolling_.y + y);
|
||||||
@@ -420,20 +419,18 @@ void Canvas::DrawSelectRect(int tile_size, float scale) {
|
|||||||
|
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||||
// Start dragging and snap the start position to the nearest grid point
|
// Start dragging and snap the start position to the nearest grid point
|
||||||
drag_start_pos.x =
|
drag_start_pos = {
|
||||||
std::floor(io.MousePos.x / (tile_size * scale)) * tile_size * scale;
|
std::floor(io.MousePos.x / (tile_size * scale)) * tile_size * scale,
|
||||||
drag_start_pos.y =
|
std::floor(io.MousePos.y / (tile_size * scale)) * tile_size * scale};
|
||||||
std::floor(io.MousePos.y / (tile_size * scale)) * tile_size * scale;
|
|
||||||
dragging = true;
|
dragging = true;
|
||||||
}
|
}
|
||||||
|
if (dragging) {
|
||||||
ImVec2 current_pos = io.MousePos;
|
ImVec2 current_pos = io.MousePos;
|
||||||
// Snap current position to the nearest grid point
|
// Snap current position to the nearest grid point
|
||||||
ImVec2 snapped_current_pos;
|
ImVec2 snapped_current_pos{
|
||||||
snapped_current_pos.x =
|
std::floor(current_pos.x / (tile_size * scale)) * tile_size * scale,
|
||||||
std::floor(current_pos.x / (tile_size * scale)) * tile_size * scale;
|
std::floor(current_pos.y / (tile_size * scale)) * tile_size * scale};
|
||||||
snapped_current_pos.y =
|
|
||||||
std::floor(current_pos.y / (tile_size * scale)) * tile_size * scale;
|
|
||||||
// Calculate rect_min and rect_max considering the drag direction
|
// Calculate rect_min and rect_max considering the drag direction
|
||||||
ImVec2 rect_min = ImVec2(std::min(drag_start_pos.x, snapped_current_pos.x),
|
ImVec2 rect_min = ImVec2(std::min(drag_start_pos.x, snapped_current_pos.x),
|
||||||
std::min(drag_start_pos.y, snapped_current_pos.y));
|
std::min(drag_start_pos.y, snapped_current_pos.y));
|
||||||
@@ -441,21 +438,30 @@ void Canvas::DrawSelectRect(int tile_size, float scale) {
|
|||||||
std::max(drag_start_pos.x, snapped_current_pos.x) + tile_size * scale,
|
std::max(drag_start_pos.x, snapped_current_pos.x) + tile_size * scale,
|
||||||
std::max(drag_start_pos.y, snapped_current_pos.y) + tile_size * scale);
|
std::max(drag_start_pos.y, snapped_current_pos.y) + tile_size * scale);
|
||||||
|
|
||||||
if (dragging && ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
|
if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
|
||||||
draw_list_->AddRect(rect_min, rect_max, kRectangleBorder);
|
draw_list_->AddRect(rect_min, rect_max, kRectangleBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
if (!ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
||||||
dragging = false;
|
dragging = false;
|
||||||
ImVec2 scaled_rect_min =
|
ImVec2 scaled_rect_min =
|
||||||
ImVec2(drag_start_pos.x / scale, drag_start_pos.y / scale);
|
ImVec2(drag_start_pos.x / scale, drag_start_pos.y / scale);
|
||||||
ImVec2 scaled_rect_max = ImVec2(rect_max.x / scale, rect_max.y / scale);
|
ImVec2 scaled_rect_max = ImVec2(rect_max.x / scale, rect_max.y / scale);
|
||||||
|
|
||||||
// Here, calculate and store the tile16 IDs within the rectangle
|
// Calculate the bounds of the rectangle in terms of 16x16 tile indices
|
||||||
selected_tiles_ =
|
constexpr int tile16_size = 16;
|
||||||
GetTileIDsInGrid(scaled_rect_min.x, scaled_rect_min.y,
|
int start_x = scaled_rect_min.x / tile16_size;
|
||||||
scaled_rect_max.x - scaled_rect_min.x,
|
int start_y = scaled_rect_min.y / tile16_size;
|
||||||
scaled_rect_max.y - scaled_rect_min.y, tile_size);
|
int end_x = scaled_rect_max.x / tile16_size;
|
||||||
|
int end_y = scaled_rect_max.y / tile16_size;
|
||||||
|
|
||||||
|
// Loop through the tiles in the rectangle and store their positions
|
||||||
|
selected_tiles_.clear();
|
||||||
|
for (int y = start_y; y < end_y; ++y) {
|
||||||
|
for (int x = start_x; x < end_x; ++x) {
|
||||||
|
selected_tiles_.push_back(ImVec2(x * tile16_size, y * tile16_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clear and add the calculated rectangle points
|
// Clear and add the calculated rectangle points
|
||||||
points_.clear();
|
points_.clear();
|
||||||
@@ -463,6 +469,33 @@ void Canvas::DrawSelectRect(int tile_size, float scale) {
|
|||||||
points_.push_back(scaled_rect_max);
|
points_.push_back(scaled_rect_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawSelectRectTile16(int current_map) {
|
||||||
|
const ImGuiIO &io = ImGui::GetIO();
|
||||||
|
const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y);
|
||||||
|
const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
|
||||||
|
|
||||||
|
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||||
|
// Calculate the coordinates of the mouse
|
||||||
|
ImVec2 painter_pos;
|
||||||
|
painter_pos.x = std::floor((double)mouse_pos.x / 16) * 16;
|
||||||
|
painter_pos.y = std::floor((double)mouse_pos.y / 16) * 16;
|
||||||
|
int painter_x = painter_pos.x;
|
||||||
|
int painter_y = painter_pos.y;
|
||||||
|
constexpr int small_map_size = 0x200;
|
||||||
|
|
||||||
|
auto tile16_x = (painter_x % small_map_size) / (small_map_size / 0x20);
|
||||||
|
auto tile16_y = (painter_y % small_map_size) / (small_map_size / 0x20);
|
||||||
|
|
||||||
|
int superY = current_map / 8;
|
||||||
|
int superX = current_map % 8;
|
||||||
|
|
||||||
|
int index_x = superX * 0x20 + tile16_x;
|
||||||
|
int index_y = superY * 0x20 + tile16_y;
|
||||||
|
selected_tiles_.push_back(ImVec2(index_x, index_y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::DrawBitmapGroup(std::vector<int> &group,
|
void Canvas::DrawBitmapGroup(std::vector<int> &group,
|
||||||
std::vector<gfx::Bitmap> &tile16_individual_,
|
std::vector<gfx::Bitmap> &tile16_individual_,
|
||||||
|
|||||||
@@ -98,8 +98,12 @@ class Canvas {
|
|||||||
void DrawOutline(int x, int y, int w, int h);
|
void DrawOutline(int x, int y, int w, int h);
|
||||||
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color);
|
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color);
|
||||||
void DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color);
|
void DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color);
|
||||||
|
|
||||||
void DrawSelectRect(int tile_size, float scale = 1.0f);
|
void DrawSelectRect(int tile_size, float scale = 1.0f);
|
||||||
|
void DrawSelectRectTile16(int current_map);
|
||||||
|
|
||||||
void DrawRect(int x, int y, int w, int h, ImVec4 color);
|
void DrawRect(int x, int y, int w, int h, ImVec4 color);
|
||||||
|
|
||||||
void DrawText(std::string text, int x, int y);
|
void DrawText(std::string text, int x, int y);
|
||||||
void DrawGridLines(float grid_step);
|
void DrawGridLines(float grid_step);
|
||||||
void DrawGrid(float grid_step = 64.0f, int tile_id_offset = 8);
|
void DrawGrid(float grid_step = 64.0f, int tile_id_offset = 8);
|
||||||
@@ -184,7 +188,7 @@ class Canvas {
|
|||||||
ImVec2 mouse_pos_in_canvas_;
|
ImVec2 mouse_pos_in_canvas_;
|
||||||
ImVec2 drawn_tile_pos_;
|
ImVec2 drawn_tile_pos_;
|
||||||
|
|
||||||
std::vector<int> selected_tiles_;
|
std::vector<ImVec2> selected_tiles_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
|
|||||||
@@ -99,33 +99,6 @@ absl::Status Overworld::Load(ROM &rom) {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Overworld::LoadOverworldMaps() {
|
|
||||||
auto size = tiles16_.size();
|
|
||||||
std::vector<std::future<absl::Status>> futures;
|
|
||||||
for (int i = 0; i < kNumOverworldMaps; ++i) {
|
|
||||||
int world_type = 0;
|
|
||||||
if (i >= 64 && i < 0x80) {
|
|
||||||
world_type = 1;
|
|
||||||
} else if (i >= 0x80) {
|
|
||||||
world_type = 2;
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all tasks to complete and check their results
|
|
||||||
for (auto &future : futures) {
|
|
||||||
absl::Status status = future.get();
|
|
||||||
if (!status.ok()) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -171,7 +144,7 @@ void Overworld::FetchLargeMaps() {
|
|||||||
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 + 8].SetAsLargeMap(i, 2);
|
||||||
overworld_maps_[i + 64].SetAsLargeMap(i + 64, 2);
|
overworld_maps_[i + 72].SetAsLargeMap(i + 64, 2);
|
||||||
|
|
||||||
mapChecked[i + 9] = true;
|
mapChecked[i + 9] = true;
|
||||||
map_parent_[i + 9] = (uchar)i;
|
map_parent_[i + 9] = (uchar)i;
|
||||||
@@ -199,40 +172,36 @@ void Overworld::FetchLargeMaps() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Overworld::GenerateTile32(int index, int quadrant, int dimension) {
|
void Overworld::AssembleMap32Tiles() {
|
||||||
// The addresses of the four 32x32 pixel tiles in the rom()->
|
auto get_tile16_for_tile32 = [this](int index, int quadrant, int dimension) {
|
||||||
const uint32_t map32address[4] = {rom()->version_constants().kMap32TileTL,
|
const uint32_t map32address[4] = {rom()->version_constants().kMap32TileTL,
|
||||||
rom()->version_constants().kMap32TileTR,
|
rom()->version_constants().kMap32TileTR,
|
||||||
rom()->version_constants().kMap32TileBL,
|
rom()->version_constants().kMap32TileBL,
|
||||||
rom()->version_constants().kMap32TileBR};
|
rom()->version_constants().kMap32TileBR};
|
||||||
|
return (uint16_t)(rom_[map32address[dimension] + quadrant + (index)] +
|
||||||
return (ushort)(rom_[map32address[dimension] + quadrant + (index)] +
|
|
||||||
(((rom_[map32address[dimension] + (index) +
|
(((rom_[map32address[dimension] + (index) +
|
||||||
(quadrant <= 1 ? 4 : 5)] >>
|
(quadrant <= 1 ? 4 : 5)] >>
|
||||||
(quadrant % 2 == 0 ? 4 : 0)) &
|
(quadrant % 2 == 0 ? 4 : 0)) &
|
||||||
0x0F) *
|
0x0F) *
|
||||||
256));
|
256));
|
||||||
}
|
};
|
||||||
|
|
||||||
void Overworld::AssembleMap32Tiles() {
|
|
||||||
// Loop through each 32x32 pixel tile in the rom()->
|
// Loop through each 32x32 pixel tile in the rom()->
|
||||||
for (int i = 0; i < 0x33F0; i += 6) {
|
for (int i = 0; i < 0x33F0; i += 6) {
|
||||||
// Loop through each quadrant of the 32x32 pixel tile.
|
// Loop through each quadrant of the 32x32 pixel tile.
|
||||||
for (int k = 0; k < 4; k++) {
|
for (int k = 0; k < 4; k++) {
|
||||||
// Generate the 16-bit tile for the current quadrant of the current
|
// Generate the 16-bit tile for the current quadrant of the current
|
||||||
// 32x32 pixel tile.
|
// 32x32 pixel tile.
|
||||||
uint16_t tl = GenerateTile32(i, k, (int)Dimension::map32TilesTL);
|
uint16_t tl = get_tile16_for_tile32(i, k, (int)Dimension::map32TilesTL);
|
||||||
uint16_t tr = GenerateTile32(i, k, (int)Dimension::map32TilesTR);
|
uint16_t tr = get_tile16_for_tile32(i, k, (int)Dimension::map32TilesTR);
|
||||||
uint16_t bl = GenerateTile32(i, k, (int)Dimension::map32TilesBL);
|
uint16_t bl = get_tile16_for_tile32(i, k, (int)Dimension::map32TilesBL);
|
||||||
uint16_t br = GenerateTile32(i, k, (int)Dimension::map32TilesBR);
|
uint16_t br = get_tile16_for_tile32(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_unique_.emplace_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(0x200);
|
map_tiles_.light_world.resize(0x200);
|
||||||
map_tiles_.dark_world.resize(0x200);
|
map_tiles_.dark_world.resize(0x200);
|
||||||
map_tiles_.special_world.resize(0x200);
|
map_tiles_.special_world.resize(0x200);
|
||||||
@@ -289,55 +258,46 @@ 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() {
|
||||||
|
const auto get_ow_map_gfx_ptr = [this](int index, uint32_t map_ptr) {
|
||||||
|
int p = (rom()->data()[map_ptr + 2 + (3 * index)] << 16) +
|
||||||
|
(rom()->data()[map_ptr + 1 + (3 * index)] << 8) +
|
||||||
|
(rom()->data()[map_ptr + (3 * index)]);
|
||||||
|
return core::SnesToPc(p);
|
||||||
|
};
|
||||||
|
|
||||||
int lowest = 0x0FFFFF;
|
int lowest = 0x0FFFFF;
|
||||||
int highest = 0x0F8000;
|
int highest = 0x0F8000;
|
||||||
int sx = 0;
|
int sx = 0;
|
||||||
int sy = 0;
|
int sy = 0;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (int i = 0; i < 160; i++) {
|
for (int i = 0; i < 160; i++) {
|
||||||
auto p1 = GetOwMapGfxHighPtr(
|
auto p1 = get_ow_map_gfx_ptr(
|
||||||
rom()->data(), i,
|
i, rom()->version_constants().kCompressedAllMap32PointersHigh);
|
||||||
rom()->version_constants().kCompressedAllMap32PointersHigh);
|
auto p2 = get_ow_map_gfx_ptr(
|
||||||
auto p2 = GetOwMapGfxLowPtr(
|
i, rom()->version_constants().kCompressedAllMap32PointersLow);
|
||||||
rom()->data(), i,
|
|
||||||
rom()->version_constants().kCompressedAllMap32PointersLow);
|
|
||||||
int ttpos = 0;
|
int ttpos = 0;
|
||||||
|
|
||||||
if (p1 >= highest) {
|
if (p1 >= highest) highest = p1;
|
||||||
highest = p1;
|
if (p2 >= highest) highest = p2;
|
||||||
|
|
||||||
|
if (p1 <= lowest && p1 > 0x0F8000) lowest = p1;
|
||||||
|
if (p2 <= lowest && p2 > 0x0F8000) lowest = p2;
|
||||||
|
|
||||||
|
std::vector<uint8_t> bytes, bytes2;
|
||||||
|
int size1, size2;
|
||||||
|
auto decomp = gfx::lc_lz2::Uncompress(rom()->data() + p2, &size1, 1);
|
||||||
|
bytes.resize(size1);
|
||||||
|
for (int i = 0; i < size1; i++) {
|
||||||
|
bytes[i] = decomp[i];
|
||||||
}
|
}
|
||||||
if (p2 >= highest) {
|
decomp = gfx::lc_lz2::Uncompress(rom()->data() + p1, &size2, 1);
|
||||||
highest = p2;
|
bytes2.resize(size2);
|
||||||
|
for (int i = 0; i < size2; i++) {
|
||||||
|
bytes2[i] = decomp[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p1 <= lowest && p1 > 0x0F8000) {
|
|
||||||
lowest = p1;
|
|
||||||
}
|
|
||||||
if (p2 <= lowest && p2 > 0x0F8000) {
|
|
||||||
lowest = p2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSIGN_OR_RETURN(
|
|
||||||
auto bytes, gfx::lc_lz2::DecompressOverworld(rom()->data(), p2, 0x1000))
|
|
||||||
ASSIGN_OR_RETURN(auto bytes2, gfx::lc_lz2::DecompressOverworld(
|
|
||||||
rom()->data(), p1, 0x1000))
|
|
||||||
OrganizeMapTiles(bytes, bytes2, i, sx, sy, ttpos);
|
OrganizeMapTiles(bytes, bytes2, i, sx, sy, ttpos);
|
||||||
|
|
||||||
sx++;
|
sx++;
|
||||||
@@ -356,6 +316,33 @@ absl::Status Overworld::DecompressAllMapTiles() {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status Overworld::LoadOverworldMaps() {
|
||||||
|
auto size = tiles16_.size();
|
||||||
|
std::vector<std::future<absl::Status>> futures;
|
||||||
|
for (int i = 0; i < kNumOverworldMaps; ++i) {
|
||||||
|
int world_type = 0;
|
||||||
|
if (i >= 64 && i < 0x80) {
|
||||||
|
world_type = 1;
|
||||||
|
} else if (i >= 0x80) {
|
||||||
|
world_type = 2;
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all tasks to complete and check their results
|
||||||
|
for (auto &future : futures) {
|
||||||
|
absl::Status status = future.get();
|
||||||
|
if (!status.ok()) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
void Overworld::LoadTileTypes() {
|
void Overworld::LoadTileTypes() {
|
||||||
for (int i = 0; i < 0x200; i++) {
|
for (int i = 0; i < 0x200; i++) {
|
||||||
all_tiles_types_[i] = rom()->data()[overworldTilesType + i];
|
all_tiles_types_[i] = rom()->data()[overworldTilesType + i];
|
||||||
@@ -454,12 +441,13 @@ absl::Status Overworld::LoadExits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Overworld::LoadItems() {
|
absl::Status Overworld::LoadItems() {
|
||||||
ASSIGN_OR_RETURN(int pointer, rom()->ReadLong(zelda3::overworldItemsAddress));
|
ASSIGN_OR_RETURN(uint32_t pointer,
|
||||||
int pointer_pc = core::SnesToPc(pointer); // 1BC2F9 -> 0DC2F9
|
rom()->ReadLong(zelda3::overworldItemsAddress));
|
||||||
|
uint32_t pointer_pc = core::SnesToPc(pointer); // 1BC2F9 -> 0DC2F9
|
||||||
for (int i = 0; i < 128; i++) {
|
for (int i = 0; i < 128; i++) {
|
||||||
ASSIGN_OR_RETURN(uint16_t word_address,
|
ASSIGN_OR_RETURN(uint16_t word_address,
|
||||||
rom()->ReadWord(pointer_pc + i * 2));
|
rom()->ReadWord(pointer_pc + i * 2));
|
||||||
int addr = (pointer & 0xFF0000) | word_address; // 1B F9 3C
|
uint32_t addr = (pointer & 0xFF0000) | word_address; // 1B F9 3C
|
||||||
addr = core::SnesToPc(addr);
|
addr = core::SnesToPc(addr);
|
||||||
|
|
||||||
if (overworld_maps_[i].IsLargeMap()) {
|
if (overworld_maps_[i].IsLargeMap()) {
|
||||||
@@ -551,6 +539,8 @@ absl::Status Overworld::LoadSpritesFromMap(int sprite_start, int sprite_count,
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
absl::Status Overworld::Save(ROM &rom) {
|
absl::Status Overworld::Save(ROM &rom) {
|
||||||
rom_ = rom;
|
rom_ = rom;
|
||||||
|
|
||||||
@@ -590,7 +580,6 @@ absl::Status Overworld::SaveOverworldMaps() {
|
|||||||
std::vector<uint8_t> a, b;
|
std::vector<uint8_t> a, b;
|
||||||
int size_a, size_b;
|
int size_a, size_b;
|
||||||
// Compress single_map_1 and single_map_2
|
// Compress single_map_1 and single_map_2
|
||||||
if (flags()->kUseClassicCompression) {
|
|
||||||
auto a_char = gfx::lc_lz2::Compress(single_map_1.data(), 256, &size_a, 1);
|
auto a_char = gfx::lc_lz2::Compress(single_map_1.data(), 256, &size_a, 1);
|
||||||
auto b_char = gfx::lc_lz2::Compress(single_map_2.data(), 256, &size_b, 1);
|
auto b_char = gfx::lc_lz2::Compress(single_map_2.data(), 256, &size_b, 1);
|
||||||
// Copy the compressed data to a and b
|
// Copy the compressed data to a and b
|
||||||
@@ -603,12 +592,6 @@ absl::Status Overworld::SaveOverworldMaps() {
|
|||||||
for (int k = 0; k < size_b; k++) {
|
for (int k = 0; k < size_b; k++) {
|
||||||
b[k] = b_char[k];
|
b[k] = b_char[k];
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ASSIGN_OR_RETURN(
|
|
||||||
a, gfx::lc_lz2::CompressOverworld(single_map_1.data(), 0, 256))
|
|
||||||
ASSIGN_OR_RETURN(
|
|
||||||
b, gfx::lc_lz2::CompressOverworld(single_map_2.data(), 0, 256))
|
|
||||||
}
|
|
||||||
if (a.empty() || b.empty()) {
|
if (a.empty() || b.empty()) {
|
||||||
return absl::AbortedError("Error compressing map gfx.");
|
return absl::AbortedError("Error compressing map gfx.");
|
||||||
}
|
}
|
||||||
@@ -775,38 +758,42 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
const int large_map_offsets[] = {0, 1, 8, 9};
|
const int large_map_offsets[] = {0, 1, 8, 9};
|
||||||
for (const auto &offset : large_map_offsets) {
|
for (const auto &offset : large_map_offsets) {
|
||||||
// Check 1
|
// Check 1
|
||||||
RETURN_IF_ERROR(rom()->Write(overworldMapSize + i + offset, 0x20));
|
RETURN_IF_ERROR(rom()->WriteByte(overworldMapSize + i + offset, 0x20));
|
||||||
// Check 2
|
// Check 2
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->Write(overworldMapSizeHighByte + i + offset, 0x03));
|
rom()->WriteByte(overworldMapSizeHighByte + i + offset, 0x03));
|
||||||
// Check 3
|
// Check 3
|
||||||
RETURN_IF_ERROR(rom()->Write(overworldScreenSize + i + offset, 0x00));
|
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->Write(overworldScreenSize + i + offset + 64, 0x00));
|
rom()->WriteByte(overworldScreenSize + i + offset, 0x00));
|
||||||
|
RETURN_IF_ERROR(
|
||||||
|
rom()->WriteByte(overworldScreenSize + i + offset + 64, 0x00));
|
||||||
// Check 4
|
// Check 4
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->Write(OverworldScreenSizeForLoading + i + offset, 0x04));
|
rom()->WriteByte(OverworldScreenSizeForLoading + i + offset, 0x04));
|
||||||
RETURN_IF_ERROR(rom()->Write(
|
RETURN_IF_ERROR(rom()->WriteByte(
|
||||||
OverworldScreenSizeForLoading + i + offset + 64, 0x04));
|
OverworldScreenSizeForLoading + i + offset + 64, 0x04));
|
||||||
RETURN_IF_ERROR(rom()->Write(
|
RETURN_IF_ERROR(rom()->WriteByte(
|
||||||
OverworldScreenSizeForLoading + i + offset + 128, 0x04));
|
OverworldScreenSizeForLoading + i + offset + 128, 0x04));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check 5 and 6
|
// Check 5 and 6
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 2,
|
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 2,
|
||||||
(short)((parentyPos * 0x200) - 0xE0)));
|
(ushort)((parentyPos * 0x200) - 0xE0)));
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + 2,
|
RETURN_IF_ERROR(
|
||||||
(short)((parentxPos * 0x200) - 0x100)));
|
rom()->WriteShort(transition_target_west + (i * 2) + 2,
|
||||||
|
(ushort)((parentxPos * 0x200) - 0x100)));
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 16,
|
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 16,
|
||||||
(short)((parentyPos * 0x200) - 0xE0)));
|
(ushort)((parentyPos * 0x200) - 0xE0)));
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + 16,
|
RETURN_IF_ERROR(
|
||||||
(short)((parentxPos * 0x200) - 0x100)));
|
rom()->WriteShort(transition_target_west + (i * 2) + 16,
|
||||||
|
(ushort)((parentxPos * 0x200) - 0x100)));
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 18,
|
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + 18,
|
||||||
(short)((parentyPos * 0x200) - 0xE0)));
|
(ushort)((parentyPos * 0x200) - 0xE0)));
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + 18,
|
RETURN_IF_ERROR(
|
||||||
(short)((parentxPos * 0x200) - 0x100)));
|
rom()->WriteShort(transition_target_west + (i * 2) + 18,
|
||||||
|
(ushort)((parentxPos * 0x200) - 0x100)));
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(overworldTransitionPositionX + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(overworldTransitionPositionX + (i * 2),
|
||||||
(parentxPos * 0x200)));
|
(parentxPos * 0x200)));
|
||||||
@@ -884,8 +871,7 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
// 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].ParentIndex() == 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));
|
||||||
0x0080)); // Always 0x1080.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -968,24 +954,26 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
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].ParentIndex() == 3) {
|
if (overworld_maps_[i - 1].ParentIndex() == 3) {
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen1 + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
0xF060);
|
OverworldScreenTileMapChangeByScreen1 + (i * 2), 0xF060));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen2 + (i * 2) + 128,
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
0x0040);
|
OverworldScreenTileMapChangeByScreen2 + (i * 2) + 128, 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].ParentIndex() == 1) {
|
if (overworld_maps_[i + 1].ParentIndex() == 1) {
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen2 + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
0x1060);
|
OverworldScreenTileMapChangeByScreen2 + (i * 2), 0xF040));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen3 + (i * 2) + 256,
|
|
||||||
0x1800);
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
|
OverworldScreenTileMapChangeByScreen3 + (i * 2) + 256, 0x1800));
|
||||||
|
|
||||||
// If the area above is a large map, we don't need to add an offset to it.
|
// If the area above is a large map, we don't need to add an offset to it.
|
||||||
// otherwise leave it the same.
|
// otherwise leave it the same.
|
||||||
// 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.
|
||||||
@@ -994,13 +982,15 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
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].ParentIndex() == 3) {
|
if (overworld_maps_[i - 8].ParentIndex() == 3) {
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen3 + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
0x17C0);
|
OverworldScreenTileMapChangeByScreen3 + (i * 2), 0x17C0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen4 + (i * 2) + 384,
|
|
||||||
0x1000);
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
|
OverworldScreenTileMapChangeByScreen4 + (i * 2) + 384, 0x1000));
|
||||||
|
|
||||||
// If the area below is a large map, we don't need to add an offset to it.
|
// If the area below is a large map, we don't need to add an offset to it.
|
||||||
// otherwise leave it the same.
|
// otherwise leave it the same.
|
||||||
// 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.
|
||||||
@@ -1009,16 +999,16 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
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].ParentIndex() == 1) {
|
if (overworld_maps_[i + 8].ParentIndex() == 1) {
|
||||||
rom()->WriteShort(OverworldScreenTileMapChangeByScreen4 + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(
|
||||||
0x0FC0);
|
OverworldScreenTileMapChangeByScreen4 + (i * 2), 0x0FC0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2),
|
||||||
(short)((yPos * 0x200) - 0xE0)));
|
(ushort)((yPos * 0x200) - 0xE0)));
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2),
|
||||||
(short)((xPos * 0x200) - 0x100)));
|
(ushort)((xPos * 0x200) - 0x100)));
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->WriteShort(overworldTransitionPositionX + (i * 2),
|
RETURN_IF_ERROR(rom()->WriteShort(overworldTransitionPositionX + (i * 2),
|
||||||
(xPos * 0x200)));
|
(xPos * 0x200)));
|
||||||
@@ -1078,7 +1068,7 @@ std::vector<uint64_t> GetAllTile16(OWMapTiles &map_tiles_) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool Overworld::CreateTile32Tilemap(bool only_show) {
|
absl::Status Overworld::CreateTile32Tilemap() {
|
||||||
tiles32_unique_.clear();
|
tiles32_unique_.clear();
|
||||||
tiles32_list_.clear();
|
tiles32_list_.clear();
|
||||||
|
|
||||||
@@ -1090,7 +1080,6 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
|
|||||||
|
|
||||||
std::vector<uint64_t> unique_tiles(all_tile_16);
|
std::vector<uint64_t> unique_tiles(all_tile_16);
|
||||||
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;
|
|
||||||
|
|
||||||
// Create the indexed tiles list
|
// Create the indexed tiles list
|
||||||
std::unordered_map<uint64_t, ushort> all_tiles_indexed;
|
std::unordered_map<uint64_t, ushort> all_tiles_indexed;
|
||||||
@@ -1116,23 +1105,20 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
|
|||||||
tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
|
tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (only_show) {
|
if (tiles32_unique_.size() > LimitOfMap32) {
|
||||||
std::cout << "Number of unique Tiles32: " << unique_tiles.size()
|
return absl::InternalError(absl::StrFormat(
|
||||||
<< " Out of: " << LimitOfMap32 << std::endl;
|
"Number of unique Tiles32: %d Out of: %d\nUnique Tile32 count exceed "
|
||||||
} else if (tiles32_unique_.size() > LimitOfMap32) {
|
"the limit\nThe ROM Has not been saved\nYou can fill maps with grass "
|
||||||
std::cerr << "Number of unique Tiles32: " << unique_tiles.size()
|
"tiles to free some space\nOr use the option Clear DW Tiles in the "
|
||||||
<< " Out of: " << LimitOfMap32
|
"Overworld Menu",
|
||||||
<< "\nUnique Tile32 count exceed the limit"
|
unique_tiles.size(), LimitOfMap32));
|
||||||
<< "\nThe ROM Has not been saved"
|
|
||||||
<< "\nYou can fill maps with grass tiles to free some space"
|
|
||||||
<< "\nOr use the option Clear DW Tiles in the Overworld Menu"
|
|
||||||
<< std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags()->kLogToConsole) {
|
||||||
std::cout << "Number of unique Tiles32: " << tiles32_unique_.size()
|
std::cout << "Number of unique Tiles32: " << tiles32_unique_.size()
|
||||||
<< " Saved:" << tiles32_unique_.size()
|
<< " Saved:" << tiles32_unique_.size()
|
||||||
<< " Out of: " << LimitOfMap32 << std::endl;
|
<< " Out of: " << LimitOfMap32 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
int v = tiles32_unique_.size();
|
int v = tiles32_unique_.size();
|
||||||
for (int i = v; i < LimitOfMap32; i++) {
|
for (int i = v; i < LimitOfMap32; i++) {
|
||||||
@@ -1140,7 +1126,7 @@ bool Overworld::CreateTile32Tilemap(bool only_show) {
|
|||||||
tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
|
tiles32_unique_.emplace_back(padding_tile.GetPackedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Overworld::SaveMap32Tiles() {
|
absl::Status Overworld::SaveMap32Tiles() {
|
||||||
|
|||||||
@@ -462,15 +462,22 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
|||||||
absl::Status SaveExits();
|
absl::Status SaveExits();
|
||||||
absl::Status SaveItems();
|
absl::Status SaveItems();
|
||||||
|
|
||||||
bool CreateTile32Tilemap(bool onlyShow = false);
|
absl::Status CreateTile32Tilemap();
|
||||||
absl::Status SaveMap16Tiles();
|
absl::Status SaveMap16Tiles();
|
||||||
absl::Status SaveMap32Tiles();
|
absl::Status SaveMap32Tiles();
|
||||||
|
|
||||||
absl::Status SaveMapProperties();
|
absl::Status SaveMapProperties();
|
||||||
absl::Status LoadPrototype(ROM &rom_, const std::string &tilemap_filename);
|
absl::Status LoadPrototype(ROM &rom_, const std::string &tilemap_filename);
|
||||||
|
|
||||||
int GetTile16Id(int grid_id) const {
|
int current_world_ = 0;
|
||||||
return map_tiles_.light_world[game_state_][grid_id];
|
int GetTile16Id(ImVec2 position) const {
|
||||||
|
if (current_world_ == 0) {
|
||||||
|
return map_tiles_.light_world[position.x][position.y];
|
||||||
|
} else if (current_world_ == 1) {
|
||||||
|
return map_tiles_.dark_world[position.x][position.y];
|
||||||
|
} else {
|
||||||
|
return map_tiles_.special_world[position.x][position.y];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto overworld_maps() const { return overworld_maps_; }
|
auto overworld_maps() const { return overworld_maps_; }
|
||||||
@@ -519,7 +526,6 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void FetchLargeMaps();
|
void FetchLargeMaps();
|
||||||
uint16_t GenerateTile32(int index, int quadrant, int dimension);
|
|
||||||
void AssembleMap32Tiles();
|
void AssembleMap32Tiles();
|
||||||
void AssembleMap16Tiles();
|
void AssembleMap16Tiles();
|
||||||
void AssignWorldTiles(int x, int y, int sx, int sy, int tpos,
|
void AssignWorldTiles(int x, int y, int sx, int sy, int tpos,
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
|||||||
OWBlockset& world_blockset) {
|
OWBlockset& world_blockset) {
|
||||||
game_state_ = game_state;
|
game_state_ = game_state;
|
||||||
world_ = world;
|
world_ = world;
|
||||||
if (large_map_) {
|
|
||||||
parent_ = map_parent[index_];
|
parent_ = map_parent[index_];
|
||||||
|
if (large_map_) {
|
||||||
if (parent_ != index_ && !initialized_) {
|
if (parent_ != index_ && !initialized_) {
|
||||||
if (index_ >= 0x80 && index_ <= 0x8A && index_ != 0x88) {
|
if (index_ >= 0x80 && index_ <= 0x8A && index_ != 0x88) {
|
||||||
area_graphics_ = rom_[overworldSpecialGFXGroup + (parent_ - 0x80)];
|
area_graphics_ = rom_[overworldSpecialGFXGroup + (parent_ - 0x80)];
|
||||||
@@ -60,7 +60,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
|||||||
void OverworldMap::LoadAreaInfo() {
|
void OverworldMap::LoadAreaInfo() {
|
||||||
if (index_ != 0x80) {
|
if (index_ != 0x80) {
|
||||||
if (index_ <= 150)
|
if (index_ <= 150)
|
||||||
large_map_ = rom_[overworldMapSize + (index_ & 0x3F)] != 0;
|
large_map_ = (rom_[overworldMapSize + (index_ & 0x3F)] != 0);
|
||||||
else {
|
else {
|
||||||
large_map_ =
|
large_map_ =
|
||||||
index_ == 129 || index_ == 130 || index_ == 137 || index_ == 138;
|
index_ == 129 || index_ == 130 || index_ == 137 || index_ == 138;
|
||||||
@@ -119,8 +119,10 @@ void OverworldMap::LoadAreaInfo() {
|
|||||||
parent_ = 129;
|
parent_ = 129;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message_id_ = rom_[overworldMessages + parent_];
|
||||||
|
|
||||||
area_palette_ = rom_[overworldSpecialPALGroup + parent_ - 0x80];
|
area_palette_ = rom_[overworldSpecialPALGroup + parent_ - 0x80];
|
||||||
if (index_ >= 0x80 && index_ <= 0x8A && index_ != 0x88) {
|
if ((index_ >= 0x80 && index_ <= 0x8A && index_ != 0x88) || index_ == 0x94) {
|
||||||
area_graphics_ = rom_[overworldSpecialGFXGroup + (parent_ - 0x80)];
|
area_graphics_ = rom_[overworldSpecialGFXGroup + (parent_ - 0x80)];
|
||||||
area_palette_ = rom_[overworldSpecialPALGroup + 1];
|
area_palette_ = rom_[overworldSpecialPALGroup + 1];
|
||||||
} else if (index_ == 0x88) {
|
} else if (index_ == 0x88) {
|
||||||
@@ -132,8 +134,6 @@ void OverworldMap::LoadAreaInfo() {
|
|||||||
area_palette_ = rom_[overworldMapPalette + parent_];
|
area_palette_ = rom_[overworldMapPalette + parent_];
|
||||||
}
|
}
|
||||||
|
|
||||||
message_id_ = rom_[overworldMessages + parent_];
|
|
||||||
|
|
||||||
sprite_graphics_[0] = rom_[overworldSpriteset + parent_ + 0x80];
|
sprite_graphics_[0] = rom_[overworldSpriteset + parent_ + 0x80];
|
||||||
sprite_graphics_[1] = rom_[overworldSpriteset + parent_ + 0x80];
|
sprite_graphics_[1] = rom_[overworldSpriteset + parent_ + 0x80];
|
||||||
sprite_graphics_[2] = rom_[overworldSpriteset + parent_ + 0x80];
|
sprite_graphics_[2] = rom_[overworldSpriteset + parent_ + 0x80];
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ class OverworldMap : public GfxContext {
|
|||||||
bool large_map_ = false;
|
bool large_map_ = false;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
||||||
int parent_ = 0;
|
int index_ = 0; // Map index
|
||||||
int index_ = 0;
|
int parent_ = 0; // Parent map index
|
||||||
int parent_index_ = 0;
|
int parent_index_ = 0; // Quadrant ID [0-3]
|
||||||
int world_ = 0;
|
int world_ = 0; // World ID [0-2]
|
||||||
int game_state_ = 0;
|
int game_state_ = 0; // Game state [0-2]
|
||||||
int world_index_ = 0;
|
int world_index_ = 0; // Spr Pal Modifier
|
||||||
|
|
||||||
uint16_t message_id_ = 0;
|
uint16_t message_id_ = 0;
|
||||||
uint8_t area_graphics_ = 0;
|
uint8_t area_graphics_ = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user