Refactor map properties handling in Overworld Editor for improved clarity and performance
- Rearranged include statements for better organization and reduced redundancy. - Enhanced the DrawSimplifiedMapSettings method by improving formatting and readability. - Streamlined the logic for handling world and map changes, ensuring more efficient updates. - Updated the DrawMapPropertiesPanel and related methods to improve layout and user interaction. - Refactored overlay handling logic to enhance maintainability and clarity in the Overworld class.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -444,10 +444,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// World selector (always present)
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
if (ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3)) {
|
||||
// Update current map when world changes
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3);
|
||||
|
||||
// Area Graphics (always present)
|
||||
TableNextColumn();
|
||||
@@ -2170,18 +2167,7 @@ void OverworldEditor::DrawMapPropertiesPanel() {
|
||||
Text("World");
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3)) {
|
||||
// Update current map based on world change
|
||||
if (current_map_ >= 0x40 && current_world_ == 0) {
|
||||
current_map_ -= 0x40;
|
||||
} else if (current_map_ < 0x40 && current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
} else if (current_map_ < 0x80 && current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
} else if (current_map_ >= 0x80 && current_world_ != 2) {
|
||||
current_map_ -= 0x80;
|
||||
}
|
||||
}
|
||||
ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3);
|
||||
|
||||
TableNextColumn();
|
||||
Text("Area Graphics");
|
||||
|
||||
@@ -39,7 +39,12 @@ absl::Status Overworld::Load(Rom* rom) {
|
||||
map_parent_[map_index] = overworld_maps_[map_index].parent();
|
||||
}
|
||||
|
||||
FetchLargeMaps();
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3) {
|
||||
AssignMapSizes(overworld_maps_);
|
||||
} else {
|
||||
FetchLargeMaps();
|
||||
}
|
||||
LoadTileTypes();
|
||||
RETURN_IF_ERROR(LoadEntrances());
|
||||
RETURN_IF_ERROR(LoadHoles());
|
||||
@@ -105,6 +110,90 @@ void Overworld::FetchLargeMaps() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads all maps from ROM to see what size they are.
|
||||
* @param maps The maps to update (passed by reference)
|
||||
*/
|
||||
void Overworld::AssignMapSizes(std::vector<OverworldMap>& maps) {
|
||||
std::vector<bool> map_checked(kNumOverworldMaps, false);
|
||||
|
||||
int xx = 0;
|
||||
int yy = 0;
|
||||
int world = 0;
|
||||
|
||||
while (true) {
|
||||
int i = world + xx + (yy * 8);
|
||||
|
||||
if (i >= static_cast<int>(map_checked.size())) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!map_checked[i]) {
|
||||
switch (maps[i].area_size()) {
|
||||
case AreaSizeEnum::SmallArea:
|
||||
map_checked[i] = true;
|
||||
maps[i].SetAreaSize(AreaSizeEnum::SmallArea);
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::LargeArea:
|
||||
map_checked[i] = true;
|
||||
maps[i].SetAsLargeMap(i, 0);
|
||||
|
||||
if (i + 1 < static_cast<int>(maps.size())) {
|
||||
map_checked[i + 1] = true;
|
||||
maps[i + 1].SetAsLargeMap(i, 1);
|
||||
}
|
||||
|
||||
if (i + 8 < static_cast<int>(maps.size())) {
|
||||
map_checked[i + 8] = true;
|
||||
maps[i + 8].SetAsLargeMap(i, 2);
|
||||
}
|
||||
|
||||
if (i + 9 < static_cast<int>(maps.size())) {
|
||||
map_checked[i + 9] = true;
|
||||
maps[i + 9].SetAsLargeMap(i, 3);
|
||||
}
|
||||
|
||||
xx++;
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::WideArea:
|
||||
map_checked[i] = true;
|
||||
maps[i].SetAreaSize(AreaSizeEnum::WideArea);
|
||||
|
||||
if (i + 1 < static_cast<int>(maps.size())) {
|
||||
map_checked[i + 1] = true;
|
||||
maps[i + 1].SetAreaSize(AreaSizeEnum::WideArea);
|
||||
}
|
||||
|
||||
xx++;
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::TallArea:
|
||||
map_checked[i] = true;
|
||||
maps[i].SetAreaSize(AreaSizeEnum::TallArea);
|
||||
|
||||
if (i + 8 < static_cast<int>(maps.size())) {
|
||||
map_checked[i + 8] = true;
|
||||
maps[i + 8].SetAreaSize(AreaSizeEnum::TallArea);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xx++;
|
||||
if (xx >= 8) {
|
||||
xx = 0;
|
||||
yy += 1;
|
||||
|
||||
if (yy >= 8) {
|
||||
yy = 0;
|
||||
world += 0x40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
absl::StatusOr<uint16_t> Overworld::GetTile16ForTile32(
|
||||
int index, int quadrant, int dimension, const uint32_t* map32address) {
|
||||
ASSIGN_OR_RETURN(
|
||||
@@ -443,7 +532,8 @@ absl::Status Overworld::LoadItems() {
|
||||
|
||||
// Determine max number of overworld maps based on actual ASM version
|
||||
// Only use expanded maps (0xA0) if v3+ ASM is actually applied
|
||||
int max_ow = (asm_version >= 0x03 && asm_version != 0xFF) ? kNumOverworldMaps : 0x80;
|
||||
int max_ow =
|
||||
(asm_version >= 0x03 && asm_version != 0xFF) ? kNumOverworldMaps : 0x80;
|
||||
|
||||
ASSIGN_OR_RETURN(uint32_t pointer_snes,
|
||||
rom()->ReadLong(zelda3::overworldItemsAddress));
|
||||
@@ -745,16 +835,16 @@ absl::Status Overworld::SaveOverworldMaps() {
|
||||
|
||||
absl::Status Overworld::SaveLargeMaps() {
|
||||
util::logf("Saving Large Maps");
|
||||
|
||||
|
||||
// Check if this is a v3+ ROM to use expanded transition system
|
||||
uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
bool use_expanded_transitions = (asm_version >= 3 && asm_version != 0xFF);
|
||||
|
||||
|
||||
if (use_expanded_transitions) {
|
||||
// Use new v3+ complex transition system with neighbor awareness
|
||||
return SaveLargeMapsExpanded();
|
||||
}
|
||||
|
||||
|
||||
// Original vanilla/v2 logic preserved
|
||||
std::vector<uint8_t> checked_map;
|
||||
|
||||
@@ -1073,123 +1163,143 @@ absl::Status Overworld::SaveLargeMaps() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveSmallAreaTransitions(int i, int parent_x_pos, int parent_y_pos,
|
||||
int transition_target_north, int transition_target_west,
|
||||
int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2,
|
||||
int screen_change_3, int screen_change_4) {
|
||||
absl::Status Overworld::SaveSmallAreaTransitions(
|
||||
int i, int parent_x_pos, int parent_y_pos, int transition_target_north,
|
||||
int transition_target_west, int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2, int screen_change_3,
|
||||
int screen_change_4) {
|
||||
// Set basic transition targets
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2),
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2),
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_north + (i * 2),
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_west + (i * 2),
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2), parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2), parent_y_pos * 0x0200));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_pos_x + (i * 2), parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_pos_y + (i * 2), parent_y_pos * 0x0200));
|
||||
|
||||
// byScreen1 = Transitioning right
|
||||
uint16_t by_screen1_small = 0x0060;
|
||||
|
||||
|
||||
// Check west neighbor for transition adjustments
|
||||
if ((i % 0x40) - 1 >= 0) {
|
||||
auto& west_neighbor = overworld_maps_[i - 1];
|
||||
|
||||
|
||||
// Transition from bottom right quadrant of large area to small area
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea && west_neighbor.large_index() == 3) {
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
west_neighbor.large_index() == 3) {
|
||||
by_screen1_small = 0xF060;
|
||||
}
|
||||
// Transition from bottom quadrant of tall area to small area
|
||||
else if (west_neighbor.area_size() == AreaSizeEnum::TallArea && west_neighbor.large_index() == 2) {
|
||||
// Transition from bottom quadrant of tall area to small area
|
||||
else if (west_neighbor.area_size() == AreaSizeEnum::TallArea &&
|
||||
west_neighbor.large_index() == 2) {
|
||||
by_screen1_small = 0xF060;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2), by_screen1_small));
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(screen_change_1 + (i * 2), by_screen1_small));
|
||||
|
||||
// byScreen2 = Transitioning left
|
||||
uint16_t by_screen2_small = 0x0040;
|
||||
|
||||
|
||||
// Check east neighbor for transition adjustments
|
||||
if ((i % 0x40) + 1 < 0x40 && i + 1 < kNumOverworldMaps) {
|
||||
auto& east_neighbor = overworld_maps_[i + 1];
|
||||
|
||||
|
||||
// Transition from bottom left quadrant of large area to small area
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea && east_neighbor.large_index() == 2) {
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
east_neighbor.large_index() == 2) {
|
||||
by_screen2_small = 0xF040;
|
||||
}
|
||||
// Transition from bottom quadrant of tall area to small area
|
||||
else if (east_neighbor.area_size() == AreaSizeEnum::TallArea && east_neighbor.large_index() == 2) {
|
||||
else if (east_neighbor.area_size() == AreaSizeEnum::TallArea &&
|
||||
east_neighbor.large_index() == 2) {
|
||||
by_screen2_small = 0xF040;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2), by_screen2_small));
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(screen_change_2 + (i * 2), by_screen2_small));
|
||||
|
||||
// byScreen3 = Transitioning down
|
||||
uint16_t by_screen3_small = 0x1800;
|
||||
|
||||
|
||||
// Check north neighbor for transition adjustments
|
||||
if ((i % 0x40) - 8 >= 0) {
|
||||
auto& north_neighbor = overworld_maps_[i - 8];
|
||||
|
||||
|
||||
// Transition from bottom right quadrant of large area to small area
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea && north_neighbor.large_index() == 3) {
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
north_neighbor.large_index() == 3) {
|
||||
by_screen3_small = 0x17C0;
|
||||
}
|
||||
// Transition from right quadrant of wide area to small area
|
||||
else if (north_neighbor.area_size() == AreaSizeEnum::WideArea && north_neighbor.large_index() == 1) {
|
||||
else if (north_neighbor.area_size() == AreaSizeEnum::WideArea &&
|
||||
north_neighbor.large_index() == 1) {
|
||||
by_screen3_small = 0x17C0;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2), by_screen3_small));
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(screen_change_3 + (i * 2), by_screen3_small));
|
||||
|
||||
// byScreen4 = Transitioning up
|
||||
uint16_t by_screen4_small = 0x1000;
|
||||
|
||||
|
||||
// Check south neighbor for transition adjustments
|
||||
if ((i % 0x40) + 8 < 0x40 && i + 8 < kNumOverworldMaps) {
|
||||
auto& south_neighbor = overworld_maps_[i + 8];
|
||||
|
||||
|
||||
// Transition from top right quadrant of large area to small area
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea && south_neighbor.large_index() == 1) {
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
south_neighbor.large_index() == 1) {
|
||||
by_screen4_small = 0x0FC0;
|
||||
}
|
||||
// Transition from right quadrant of wide area to small area
|
||||
else if (south_neighbor.area_size() == AreaSizeEnum::WideArea && south_neighbor.large_index() == 1) {
|
||||
else if (south_neighbor.area_size() == AreaSizeEnum::WideArea &&
|
||||
south_neighbor.large_index() == 1) {
|
||||
by_screen4_small = 0x0FC0;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2), by_screen4_small));
|
||||
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(screen_change_4 + (i * 2), by_screen4_small));
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveLargeAreaTransitions(int i, int parent_x_pos, int parent_y_pos,
|
||||
int transition_target_north, int transition_target_west,
|
||||
int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2,
|
||||
int screen_change_3, int screen_change_4) {
|
||||
absl::Status Overworld::SaveLargeAreaTransitions(
|
||||
int i, int parent_x_pos, int parent_y_pos, int transition_target_north,
|
||||
int transition_target_west, int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2, int screen_change_3,
|
||||
int screen_change_4) {
|
||||
// Set transition targets for all 4 quadrants
|
||||
const uint16_t offsets[] = {0, 2, 16, 18};
|
||||
for (auto offset : offsets) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset, parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset, parent_y_pos * 0x0200));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset,
|
||||
parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset,
|
||||
parent_y_pos * 0x0200));
|
||||
}
|
||||
|
||||
// Complex neighbor-aware transition calculations for large areas
|
||||
// byScreen1 = Transitioning right
|
||||
std::array<uint16_t, 4> by_screen1_large = {0x0060, 0x0060, 0x1060, 0x1060};
|
||||
|
||||
|
||||
// Check west neighbor
|
||||
if ((i % 0x40) - 1 >= 0) {
|
||||
auto& west_neighbor = overworld_maps_[i - 1];
|
||||
|
||||
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (west_neighbor.large_index()) {
|
||||
case 1: // From bottom right to bottom left of large area
|
||||
@@ -1210,18 +1320,19 @@ absl::Status Overworld::SaveLargeAreaTransitions(int i, int parent_x_pos, int pa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j], by_screen1_large[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j],
|
||||
by_screen1_large[j]));
|
||||
}
|
||||
|
||||
// byScreen2 = Transitioning left
|
||||
std::array<uint16_t, 4> by_screen2_large = {0x0080, 0x0080, 0x1080, 0x1080};
|
||||
|
||||
|
||||
// Check east neighbor
|
||||
if ((i % 0x40) + 2 < 0x40 && i + 2 < kNumOverworldMaps) {
|
||||
auto& east_neighbor = overworld_maps_[i + 2];
|
||||
|
||||
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (east_neighbor.large_index()) {
|
||||
case 0: // From bottom left to bottom right of large area
|
||||
@@ -1242,18 +1353,19 @@ absl::Status Overworld::SaveLargeAreaTransitions(int i, int parent_x_pos, int pa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j], by_screen2_large[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j],
|
||||
by_screen2_large[j]));
|
||||
}
|
||||
|
||||
// byScreen3 = Transitioning down
|
||||
std::array<uint16_t, 4> by_screen3_large = {0x1800, 0x1840, 0x1800, 0x1840};
|
||||
|
||||
|
||||
// Check north neighbor
|
||||
if ((i % 0x40) - 8 >= 0) {
|
||||
auto& north_neighbor = overworld_maps_[i - 8];
|
||||
|
||||
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (north_neighbor.large_index()) {
|
||||
case 2: // From bottom right to top right of large area
|
||||
@@ -1274,18 +1386,19 @@ absl::Status Overworld::SaveLargeAreaTransitions(int i, int parent_x_pos, int pa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j], by_screen3_large[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j],
|
||||
by_screen3_large[j]));
|
||||
}
|
||||
|
||||
// byScreen4 = Transitioning up
|
||||
std::array<uint16_t, 4> by_screen4_large = {0x2000, 0x2040, 0x2000, 0x2040};
|
||||
|
||||
|
||||
// Check south neighbor
|
||||
if ((i % 0x40) + 16 < 0x40 && i + 16 < kNumOverworldMaps) {
|
||||
auto& south_neighbor = overworld_maps_[i + 16];
|
||||
|
||||
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (south_neighbor.large_index()) {
|
||||
case 0: // From top right to bottom right of large area
|
||||
@@ -1306,79 +1419,90 @@ absl::Status Overworld::SaveLargeAreaTransitions(int i, int parent_x_pos, int pa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j], by_screen4_large[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j],
|
||||
by_screen4_large[j]));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveWideAreaTransitions(int i, int parent_x_pos, int parent_y_pos,
|
||||
int transition_target_north, int transition_target_west,
|
||||
int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2,
|
||||
int screen_change_3, int screen_change_4) {
|
||||
absl::Status Overworld::SaveWideAreaTransitions(
|
||||
int i, int parent_x_pos, int parent_y_pos, int transition_target_north,
|
||||
int transition_target_west, int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2, int screen_change_3,
|
||||
int screen_change_4) {
|
||||
// Set transition targets for both quadrants
|
||||
const uint16_t offsets[] = {0, 2};
|
||||
for (auto offset : offsets) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset, parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset, parent_y_pos * 0x0200));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset,
|
||||
parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset,
|
||||
parent_y_pos * 0x0200));
|
||||
}
|
||||
|
||||
// byScreen1 = Transitioning right
|
||||
std::array<uint16_t, 2> by_screen1_wide = {0x0060, 0x0060};
|
||||
|
||||
|
||||
// Check west neighbor
|
||||
if ((i % 0x40) - 1 >= 0) {
|
||||
auto& west_neighbor = overworld_maps_[i - 1];
|
||||
|
||||
|
||||
// From bottom right of large to left of wide
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea && west_neighbor.large_index() == 3) {
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
west_neighbor.large_index() == 3) {
|
||||
by_screen1_wide[0] = 0xF060;
|
||||
}
|
||||
// From bottom of tall to left of wide
|
||||
else if (west_neighbor.area_size() == AreaSizeEnum::TallArea && west_neighbor.large_index() == 2) {
|
||||
else if (west_neighbor.area_size() == AreaSizeEnum::TallArea &&
|
||||
west_neighbor.large_index() == 2) {
|
||||
by_screen1_wide[0] = 0xF060;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j], by_screen1_wide[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j],
|
||||
by_screen1_wide[j]));
|
||||
}
|
||||
|
||||
// byScreen2 = Transitioning left
|
||||
std::array<uint16_t, 2> by_screen2_wide = {0x0080, 0x0080};
|
||||
|
||||
|
||||
// Check east neighbor
|
||||
if ((i % 0x40) + 2 < 0x40 && i + 2 < kNumOverworldMaps) {
|
||||
auto& east_neighbor = overworld_maps_[i + 2];
|
||||
|
||||
|
||||
// From bottom left of large to right of wide
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea && east_neighbor.large_index() == 2) {
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
east_neighbor.large_index() == 2) {
|
||||
by_screen2_wide[1] = 0xF080;
|
||||
}
|
||||
// From bottom of tall to right of wide
|
||||
else if (east_neighbor.area_size() == AreaSizeEnum::TallArea && east_neighbor.large_index() == 2) {
|
||||
else if (east_neighbor.area_size() == AreaSizeEnum::TallArea &&
|
||||
east_neighbor.large_index() == 2) {
|
||||
by_screen2_wide[1] = 0xF080;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j], by_screen2_wide[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j],
|
||||
by_screen2_wide[j]));
|
||||
}
|
||||
|
||||
// byScreen3 = Transitioning down
|
||||
// byScreen3 = Transitioning down
|
||||
std::array<uint16_t, 2> by_screen3_wide = {0x1800, 0x1840};
|
||||
|
||||
|
||||
// Check north neighbor
|
||||
if ((i % 0x40) - 8 >= 0) {
|
||||
auto& north_neighbor = overworld_maps_[i - 8];
|
||||
|
||||
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (north_neighbor.large_index()) {
|
||||
case 2: // From bottom right of large to right of wide
|
||||
@@ -1399,18 +1523,19 @@ absl::Status Overworld::SaveWideAreaTransitions(int i, int parent_x_pos, int par
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j], by_screen3_wide[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j],
|
||||
by_screen3_wide[j]));
|
||||
}
|
||||
|
||||
// byScreen4 = Transitioning up
|
||||
std::array<uint16_t, 2> by_screen4_wide = {0x1000, 0x1040};
|
||||
|
||||
|
||||
// Check south neighbor
|
||||
if ((i % 0x40) + 8 < 0x40 && i + 8 < kNumOverworldMaps) {
|
||||
auto& south_neighbor = overworld_maps_[i + 8];
|
||||
|
||||
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (south_neighbor.large_index()) {
|
||||
case 0: // From top right of large to right of wide
|
||||
@@ -1434,37 +1559,42 @@ absl::Status Overworld::SaveWideAreaTransitions(int i, int parent_x_pos, int par
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j], by_screen4_wide[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j],
|
||||
by_screen4_wide[j]));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveTallAreaTransitions(int i, int parent_x_pos, int parent_y_pos,
|
||||
int transition_target_north, int transition_target_west,
|
||||
int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2,
|
||||
int screen_change_3, int screen_change_4) {
|
||||
absl::Status Overworld::SaveTallAreaTransitions(
|
||||
int i, int parent_x_pos, int parent_y_pos, int transition_target_north,
|
||||
int transition_target_west, int transition_pos_x, int transition_pos_y,
|
||||
int screen_change_1, int screen_change_2, int screen_change_3,
|
||||
int screen_change_4) {
|
||||
// Set transition targets for both quadrants
|
||||
const uint16_t offsets[] = {0, 16};
|
||||
for (auto offset : offsets) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset, parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset, parent_y_pos * 0x0200));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_north + (i * 2) + offset,
|
||||
(uint16_t)((parent_y_pos * 0x0200) - 0x00E0)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(transition_target_west + (i * 2) + offset,
|
||||
(uint16_t)((parent_x_pos * 0x0200) - 0x0100)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_x + (i * 2) + offset,
|
||||
parent_x_pos * 0x0200));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(transition_pos_y + (i * 2) + offset,
|
||||
parent_y_pos * 0x0200));
|
||||
}
|
||||
|
||||
// byScreen1 = Transitioning right
|
||||
std::array<uint16_t, 2> by_screen1_tall = {0x0060, 0x1060};
|
||||
|
||||
|
||||
// Check west neighbor
|
||||
if ((i % 0x40) - 1 >= 0) {
|
||||
auto& west_neighbor = overworld_maps_[i - 1];
|
||||
|
||||
|
||||
if (west_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (west_neighbor.large_index()) {
|
||||
case 1: // From bottom right of large to bottom of tall
|
||||
@@ -1485,18 +1615,19 @@ absl::Status Overworld::SaveTallAreaTransitions(int i, int parent_x_pos, int par
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j], by_screen1_tall[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_1 + (i * 2) + offsets[j],
|
||||
by_screen1_tall[j]));
|
||||
}
|
||||
|
||||
// byScreen2 = Transitioning left
|
||||
std::array<uint16_t, 2> by_screen2_tall = {0x0040, 0x1040};
|
||||
|
||||
|
||||
// Check east neighbor
|
||||
if ((i % 0x40) + 1 < 0x40 && i + 1 < kNumOverworldMaps) {
|
||||
auto& east_neighbor = overworld_maps_[i + 1];
|
||||
|
||||
|
||||
if (east_neighbor.area_size() == AreaSizeEnum::LargeArea) {
|
||||
switch (east_neighbor.large_index()) {
|
||||
case 0: // From bottom left of large to bottom of tall
|
||||
@@ -1517,51 +1648,58 @@ absl::Status Overworld::SaveTallAreaTransitions(int i, int parent_x_pos, int par
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j], by_screen2_tall[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_2 + (i * 2) + offsets[j],
|
||||
by_screen2_tall[j]));
|
||||
}
|
||||
|
||||
// byScreen3 = Transitioning down
|
||||
std::array<uint16_t, 2> by_screen3_tall = {0x1800, 0x1800};
|
||||
|
||||
|
||||
// Check north neighbor
|
||||
if ((i % 0x40) - 8 >= 0) {
|
||||
auto& north_neighbor = overworld_maps_[i - 8];
|
||||
|
||||
|
||||
// From bottom right of large to top of tall
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea && north_neighbor.large_index() == 3) {
|
||||
if (north_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
north_neighbor.large_index() == 3) {
|
||||
by_screen3_tall[0] = 0x17C0;
|
||||
}
|
||||
// From right of wide to top of tall
|
||||
else if (north_neighbor.area_size() == AreaSizeEnum::WideArea && north_neighbor.large_index() == 1) {
|
||||
else if (north_neighbor.area_size() == AreaSizeEnum::WideArea &&
|
||||
north_neighbor.large_index() == 1) {
|
||||
by_screen3_tall[0] = 0x17C0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j], by_screen3_tall[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_3 + (i * 2) + offsets[j],
|
||||
by_screen3_tall[j]));
|
||||
}
|
||||
|
||||
// byScreen4 = Transitioning up
|
||||
std::array<uint16_t, 2> by_screen4_tall = {0x2000, 0x2000};
|
||||
|
||||
|
||||
// Check south neighbor
|
||||
if ((i % 0x40) + 16 < 0x40 && i + 16 < kNumOverworldMaps) {
|
||||
auto& south_neighbor = overworld_maps_[i + 16];
|
||||
|
||||
|
||||
// From top right of large to bottom of tall
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea && south_neighbor.large_index() == 1) {
|
||||
if (south_neighbor.area_size() == AreaSizeEnum::LargeArea &&
|
||||
south_neighbor.large_index() == 1) {
|
||||
by_screen4_tall[1] = 0x1FC0;
|
||||
}
|
||||
// From right of wide to bottom of tall
|
||||
else if (south_neighbor.area_size() == AreaSizeEnum::WideArea && south_neighbor.large_index() == 1) {
|
||||
else if (south_neighbor.area_size() == AreaSizeEnum::WideArea &&
|
||||
south_neighbor.large_index() == 1) {
|
||||
by_screen4_tall[1] = 0x1FC0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j], by_screen4_tall[j]));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(screen_change_4 + (i * 2) + offsets[j],
|
||||
by_screen4_tall[j]));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -1569,7 +1707,7 @@ absl::Status Overworld::SaveTallAreaTransitions(int i, int parent_x_pos, int par
|
||||
|
||||
absl::Status Overworld::SaveLargeMapsExpanded() {
|
||||
util::logf("Saving Large Maps (v3+ Expanded)");
|
||||
|
||||
|
||||
// Use expanded memory locations for v3+
|
||||
int transition_target_north = zelda3::transition_target_northExpanded;
|
||||
int transition_target_west = zelda3::transition_target_westExpanded;
|
||||
@@ -1585,7 +1723,8 @@ absl::Status Overworld::SaveLargeMapsExpanded() {
|
||||
// Process all overworld maps (0xA0 for v3)
|
||||
for (int i = 0; i < kNumOverworldMaps; ++i) {
|
||||
// Skip if this map was already processed as part of a multi-area structure
|
||||
if (std::find(checked_map.begin(), checked_map.end(), i) != checked_map.end()) {
|
||||
if (std::find(checked_map.begin(), checked_map.end(), i) !=
|
||||
checked_map.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1599,20 +1738,20 @@ absl::Status Overworld::SaveLargeMapsExpanded() {
|
||||
// Handle transitions based on area size
|
||||
switch (overworld_maps_[i].area_size()) {
|
||||
case AreaSizeEnum::SmallArea:
|
||||
RETURN_IF_ERROR(SaveSmallAreaTransitions(i, parent_x_pos, parent_y_pos,
|
||||
transition_target_north, transition_target_west,
|
||||
transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2,
|
||||
screen_change_3, screen_change_4));
|
||||
RETURN_IF_ERROR(SaveSmallAreaTransitions(
|
||||
i, parent_x_pos, parent_y_pos, transition_target_north,
|
||||
transition_target_west, transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2, screen_change_3,
|
||||
screen_change_4));
|
||||
checked_map.emplace_back(i);
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::LargeArea:
|
||||
RETURN_IF_ERROR(SaveLargeAreaTransitions(i, parent_x_pos, parent_y_pos,
|
||||
transition_target_north, transition_target_west,
|
||||
transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2,
|
||||
screen_change_3, screen_change_4));
|
||||
RETURN_IF_ERROR(SaveLargeAreaTransitions(
|
||||
i, parent_x_pos, parent_y_pos, transition_target_north,
|
||||
transition_target_west, transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2, screen_change_3,
|
||||
screen_change_4));
|
||||
// Mark all 4 quadrants as processed
|
||||
checked_map.emplace_back(i);
|
||||
checked_map.emplace_back(i + 1);
|
||||
@@ -1621,22 +1760,22 @@ absl::Status Overworld::SaveLargeMapsExpanded() {
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::WideArea:
|
||||
RETURN_IF_ERROR(SaveWideAreaTransitions(i, parent_x_pos, parent_y_pos,
|
||||
transition_target_north, transition_target_west,
|
||||
transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2,
|
||||
screen_change_3, screen_change_4));
|
||||
RETURN_IF_ERROR(SaveWideAreaTransitions(
|
||||
i, parent_x_pos, parent_y_pos, transition_target_north,
|
||||
transition_target_west, transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2, screen_change_3,
|
||||
screen_change_4));
|
||||
// Mark both horizontal quadrants as processed
|
||||
checked_map.emplace_back(i);
|
||||
checked_map.emplace_back(i + 1);
|
||||
break;
|
||||
|
||||
case AreaSizeEnum::TallArea:
|
||||
RETURN_IF_ERROR(SaveTallAreaTransitions(i, parent_x_pos, parent_y_pos,
|
||||
transition_target_north, transition_target_west,
|
||||
transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2,
|
||||
screen_change_3, screen_change_4));
|
||||
RETURN_IF_ERROR(SaveTallAreaTransitions(
|
||||
i, parent_x_pos, parent_y_pos, transition_target_north,
|
||||
transition_target_west, transition_pos_x, transition_pos_y,
|
||||
screen_change_1, screen_change_2, screen_change_3,
|
||||
screen_change_4));
|
||||
// Mark both vertical quadrants as processed
|
||||
checked_map.emplace_back(i);
|
||||
checked_map.emplace_back(i + 8);
|
||||
@@ -2170,7 +2309,7 @@ absl::Status Overworld::SaveMap16Tiles() {
|
||||
|
||||
absl::Status Overworld::SaveEntrances() {
|
||||
util::logf("Saving Entrances");
|
||||
|
||||
|
||||
// Use expanded entrance tables if available
|
||||
if (expanded_entrances_) {
|
||||
for (int i = 0; i < kNumOverworldEntrances; i++) {
|
||||
@@ -2206,10 +2345,10 @@ absl::Status Overworld::SaveEntrances() {
|
||||
|
||||
absl::Status Overworld::SaveExits() {
|
||||
util::logf("Saving Exits");
|
||||
|
||||
// ASM version 0x03 added SW support and the exit leading to Zora's Domain specifically
|
||||
|
||||
// ASM version 0x03 added SW support and the exit leading to Zora's Domain specifically
|
||||
// needs to be updated because its camera values are incorrect.
|
||||
// We only update it if it was a vanilla ROM though because we don't know if the
|
||||
// We only update it if it was a vanilla ROM though because we don't know if the
|
||||
// user has already adjusted it or not.
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version == 0x00) {
|
||||
@@ -2219,7 +2358,7 @@ absl::Status Overworld::SaveExits() {
|
||||
// all_exits_[0x4D].SpecialUpdatePosition();
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < kNumOverworldExits; i++) {
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(OWExitRoomId + (i * 2), all_exits_[i].room_id_));
|
||||
@@ -2360,24 +2499,24 @@ absl::Status Overworld::SaveItems() {
|
||||
|
||||
absl::Status Overworld::SaveMapOverlays() {
|
||||
util::logf("Saving Map Overlays");
|
||||
|
||||
|
||||
// Generate the new overlay code that handles interactive overlays
|
||||
std::vector<uint8_t> new_overlay_code = {
|
||||
0xC2, 0x30, // REP #$30
|
||||
0xA5, 0x8A, // LDA $8A
|
||||
0x0A, 0x18, // ASL : CLC
|
||||
0x65, 0x8A, // ADC $8A
|
||||
0xAA, // TAX
|
||||
0xBF, 0x00, 0x00, 0x00, // LDA, X
|
||||
0x85, 0x00, // STA $00
|
||||
0xBF, 0x00, 0x00, 0x00, // LDA, X +2
|
||||
0x85, 0x02, // STA $02
|
||||
0x4B, // PHK
|
||||
0xF4, 0x00, 0x00, // This position +3 ?
|
||||
0xDC, 0x00, 0x00, // JML [$00 00]
|
||||
0xE2, 0x30, // SEP #$30
|
||||
0xAB, // PLB
|
||||
0x6B, // RTL
|
||||
0xC2, 0x30, // REP #$30
|
||||
0xA5, 0x8A, // LDA $8A
|
||||
0x0A, 0x18, // ASL : CLC
|
||||
0x65, 0x8A, // ADC $8A
|
||||
0xAA, // TAX
|
||||
0xBF, 0x00, 0x00, 0x00, // LDA, X
|
||||
0x85, 0x00, // STA $00
|
||||
0xBF, 0x00, 0x00, 0x00, // LDA, X +2
|
||||
0x85, 0x02, // STA $02
|
||||
0x4B, // PHK
|
||||
0xF4, 0x00, 0x00, // This position +3 ?
|
||||
0xDC, 0x00, 0x00, // JML [$00 00]
|
||||
0xE2, 0x30, // SEP #$30
|
||||
0xAB, // PLB
|
||||
0x6B, // RTL
|
||||
};
|
||||
|
||||
// Write overlay code to ROM
|
||||
@@ -2399,7 +2538,7 @@ absl::Status Overworld::SaveMapOverlays() {
|
||||
constexpr int kExpandedOverlaySpace = 0x120000;
|
||||
int pos = kExpandedOverlaySpace;
|
||||
int ptr_pos = kOverlayCodeStart + 32;
|
||||
|
||||
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
int snes_addr = PcToSnes(pos);
|
||||
RETURN_IF_ERROR(rom()->WriteLong(ptr_pos, snes_addr & 0xFFFFFF));
|
||||
@@ -2412,7 +2551,8 @@ absl::Status Overworld::SaveMapOverlays() {
|
||||
if (t + 2 < overlay_data.size()) {
|
||||
// Generate LDA/STA sequence for each overlay tile
|
||||
RETURN_IF_ERROR(rom()->WriteByte(pos, 0xA9)); // LDA #$
|
||||
RETURN_IF_ERROR(rom()->WriteShort(pos + 1, overlay_data[t] | (overlay_data[t + 1] << 8)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(
|
||||
pos + 1, overlay_data[t] | (overlay_data[t + 1] << 8)));
|
||||
pos += 3;
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteByte(pos, 0x8D)); // STA $xxxx
|
||||
@@ -2431,37 +2571,46 @@ absl::Status Overworld::SaveMapOverlays() {
|
||||
|
||||
absl::Status Overworld::SaveOverworldTilesType() {
|
||||
util::logf("Saving Overworld Tiles Types");
|
||||
|
||||
|
||||
for (int i = 0; i < kNumTileTypes; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteByte(overworldTilesType + i, all_tiles_types_[i]));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(overworldTilesType + i, all_tiles_types_[i]));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveCustomOverworldASM(bool enable_bg_color, bool enable_main_palette,
|
||||
bool enable_mosaic, bool enable_gfx_groups,
|
||||
bool enable_subscreen_overlay, bool enable_animated) {
|
||||
absl::Status Overworld::SaveCustomOverworldASM(bool enable_bg_color,
|
||||
bool enable_main_palette,
|
||||
bool enable_mosaic,
|
||||
bool enable_gfx_groups,
|
||||
bool enable_subscreen_overlay,
|
||||
bool enable_animated) {
|
||||
util::logf("Applying Custom Overworld ASM");
|
||||
|
||||
// Set the enable/disable settings
|
||||
uint8_t enable_value = enable_bg_color ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomAreaSpecificBGEnabled, enable_value));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomAreaSpecificBGEnabled, enable_value));
|
||||
|
||||
enable_value = enable_main_palette ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomMainPaletteEnabled, enable_value));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomMainPaletteEnabled, enable_value));
|
||||
|
||||
enable_value = enable_mosaic ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomMosaicEnabled, enable_value));
|
||||
|
||||
enable_value = enable_gfx_groups ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomTileGFXGroupEnabled, enable_value));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomTileGFXGroupEnabled, enable_value));
|
||||
|
||||
enable_value = enable_animated ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomAnimatedGFXEnabled, enable_value));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomAnimatedGFXEnabled, enable_value));
|
||||
|
||||
enable_value = enable_subscreen_overlay ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomSubscreenOverlayEnabled, enable_value));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomSubscreenOverlayEnabled, enable_value));
|
||||
|
||||
// Write the main palette table
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
@@ -2474,18 +2623,20 @@ absl::Status Overworld::SaveCustomOverworldASM(bool enable_bg_color, bool enable
|
||||
const auto& mosaic = overworld_maps_[i].mosaic_expanded();
|
||||
// .... udlr bit format
|
||||
uint8_t mosaic_byte = (mosaic[0] ? 0x08 : 0x00) | // up
|
||||
(mosaic[1] ? 0x04 : 0x00) | // down
|
||||
(mosaic[1] ? 0x04 : 0x00) | // down
|
||||
(mosaic[2] ? 0x02 : 0x00) | // left
|
||||
(mosaic[3] ? 0x01 : 0x00); // right
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomMosaicArray + i, mosaic_byte));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomMosaicArray + i, mosaic_byte));
|
||||
}
|
||||
|
||||
// Write the main and animated gfx tiles table
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomTileGFXGroupArray + (i * 8) + j,
|
||||
overworld_maps_[i].custom_tileset(j)));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteByte(OverworldCustomTileGFXGroupArray + (i * 8) + j,
|
||||
overworld_maps_[i].custom_tileset(j)));
|
||||
}
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomAnimatedGFXArray + i,
|
||||
overworld_maps_[i].animated_gfx()));
|
||||
@@ -2493,8 +2644,9 @@ absl::Status Overworld::SaveCustomOverworldASM(bool enable_bg_color, bool enable
|
||||
|
||||
// Write the subscreen overlay table
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(OverworldCustomSubscreenOverlayArray + (i * 2),
|
||||
overworld_maps_[i].subscreen_overlay()));
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(OverworldCustomSubscreenOverlayArray + (i * 2),
|
||||
overworld_maps_[i].subscreen_overlay()));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -2502,11 +2654,12 @@ absl::Status Overworld::SaveCustomOverworldASM(bool enable_bg_color, bool enable
|
||||
|
||||
absl::Status Overworld::SaveAreaSpecificBGColors() {
|
||||
util::logf("Saving Area Specific Background Colors");
|
||||
|
||||
|
||||
// Write area-specific background colors if enabled
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
uint16_t bg_color = overworld_maps_[i].area_specific_bg_color();
|
||||
RETURN_IF_ERROR(rom()->WriteShort(OverworldCustomAreaSpecificBGPalette + (i * 2), bg_color));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(
|
||||
OverworldCustomAreaSpecificBGPalette + (i * 2), bg_color));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -190,6 +190,7 @@ class Overworld {
|
||||
absl::Status SaveMapProperties();
|
||||
absl::Status SaveMusic();
|
||||
absl::Status SaveAreaSizes();
|
||||
void AssignMapSizes(std::vector<OverworldMap>& maps);
|
||||
|
||||
auto rom() const { return rom_; }
|
||||
auto mutable_rom() { return rom_; }
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
namespace yaze {
|
||||
namespace zelda3 {
|
||||
|
||||
OverworldMap::OverworldMap(int index, Rom *rom)
|
||||
OverworldMap::OverworldMap(int index, Rom* rom)
|
||||
: index_(index), parent_(index), rom_(rom) {
|
||||
LoadAreaInfo();
|
||||
|
||||
// Use ASM version byte as source of truth
|
||||
// Load parent ID from ROM data if available (for custom ASM versions)
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
|
||||
if (asm_version != 0xFF && asm_version >= 0x03) {
|
||||
// For v3+, parent ID is stored in expanded table
|
||||
parent_ = (*rom_)[kOverworldMapParentIdExpanded + index_];
|
||||
}
|
||||
|
||||
if (asm_version != 0xFF) {
|
||||
// Custom overworld ASM is applied - use custom logic
|
||||
if (asm_version == 0x00) {
|
||||
// Special case: version 0 means flag-enabled vanilla mode
|
||||
if (asm_version == 0x03) {
|
||||
LoadCustomOverworldData();
|
||||
} else {
|
||||
// Custom overworld ASM applied - set up custom tileset
|
||||
SetupCustomTileset(asm_version);
|
||||
}
|
||||
} else if (core::FeatureFlags::get().overworld.kLoadCustomOverworld) {
|
||||
@@ -38,21 +38,28 @@ OverworldMap::OverworldMap(int index, Rom *rom)
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
||||
std::vector<gfx::Tile16> &tiles16,
|
||||
OverworldBlockset &world_blockset) {
|
||||
std::vector<gfx::Tile16>& tiles16,
|
||||
OverworldBlockset& world_blockset) {
|
||||
game_state_ = game_state;
|
||||
world_ = world;
|
||||
if (large_map_) {
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
|
||||
// For large maps in vanilla ROMs, we need to handle special world graphics
|
||||
// This ensures proper rendering of special overworld areas like Zora's Domain
|
||||
if (large_map_ && asm_version == 0xFF) {
|
||||
if (parent_ != index_ && !initialized_) {
|
||||
if (index_ >= kSpecialWorldMapIdStart && index_ <= 0x8A &&
|
||||
index_ != 0x88) {
|
||||
// Most special world areas use the special graphics group
|
||||
area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup +
|
||||
(parent_ - kSpecialWorldMapIdStart)];
|
||||
area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1];
|
||||
} else if (index_ == 0x88) {
|
||||
// Triforce room has special hardcoded values
|
||||
area_graphics_ = 0x51;
|
||||
area_palette_ = 0x00;
|
||||
} else {
|
||||
// Fallback to standard area graphics
|
||||
area_graphics_ = (*rom_)[kAreaGfxIdPtr + parent_];
|
||||
area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_];
|
||||
}
|
||||
@@ -74,6 +81,11 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
||||
void OverworldMap::LoadAreaInfo() {
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
|
||||
// ZSCustomOverworld ASM Version System:
|
||||
// 0x00-0x02: Legacy versions with limited features
|
||||
// 0x03: Current version with full area size expansion and custom data support
|
||||
// 0xFF: Pure vanilla ROM (no ASM applied)
|
||||
|
||||
// Load message ID and area size based on ASM version
|
||||
if (asm_version < 3 || asm_version == 0xFF) {
|
||||
// v2 and vanilla: use original message table
|
||||
@@ -83,6 +95,7 @@ void OverworldMap::LoadAreaInfo() {
|
||||
// Load area size for v2/vanilla
|
||||
if (index_ < 0x80) {
|
||||
// For LW and DW, check the screen size byte
|
||||
// Note: v2 had a bug where large/small values were swapped
|
||||
uint8_t size_byte = (*rom_)[kOverworldScreenSize + (index_ & 0x3F)];
|
||||
switch (size_byte) {
|
||||
case 0:
|
||||
@@ -101,6 +114,7 @@ void OverworldMap::LoadAreaInfo() {
|
||||
}
|
||||
} else {
|
||||
// For SW, use hardcoded values for v2 compatibility
|
||||
// Zora's Domain areas (0x81, 0x82, 0x89, 0x8A) are large areas
|
||||
area_size_ =
|
||||
(index_ == 0x81 || index_ == 0x82 || index_ == 0x89 || index_ == 0x8A)
|
||||
? AreaSizeEnum::LargeArea
|
||||
@@ -108,6 +122,7 @@ void OverworldMap::LoadAreaInfo() {
|
||||
}
|
||||
} else {
|
||||
// v3: use expanded message table and area size table
|
||||
// All area sizes are now stored in the expanded table, supporting all size types
|
||||
message_id_ =
|
||||
(*rom_)[kOverworldMessagesExpanded + (parent_ * 2)] |
|
||||
((*rom_)[kOverworldMessagesExpanded + (parent_ * 2) + 1] << 8);
|
||||
@@ -172,10 +187,10 @@ void OverworldMap::LoadAreaInfo() {
|
||||
area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_];
|
||||
}
|
||||
} else {
|
||||
// Special World (SW) areas
|
||||
// Special World (SW) areas (index >= 0x80)
|
||||
// Message ID already loaded above based on ASM version
|
||||
|
||||
// For v3, use expanded sprite tables
|
||||
// For v3, use expanded sprite tables with full customization support
|
||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||
sprite_graphics_[0] =
|
||||
(*rom_)[kOverworldSpecialSpriteGfxGroupExpandedTemp + parent_ -
|
||||
@@ -214,20 +229,24 @@ void OverworldMap::LoadAreaInfo() {
|
||||
area_palette_ = (*rom_)[kOverworldPalettesScreenToSetNew + parent_];
|
||||
|
||||
// For v2/vanilla, use original palette table and handle special cases
|
||||
// These hardcoded cases are needed for vanilla compatibility
|
||||
if (asm_version < 3 || asm_version == 0xFF) {
|
||||
area_palette_ = (*rom_)[kOverworldMapPaletteIds + parent_];
|
||||
|
||||
// Handle special world area cases
|
||||
// Handle special world area cases based on ZScream documentation
|
||||
if (index_ == 0x88 || index_ == 0x93) {
|
||||
// Triforce room - special graphics and palette
|
||||
area_graphics_ = 0x51;
|
||||
area_palette_ = 0x00;
|
||||
} else if (index_ == 0x80) {
|
||||
// Master Sword area - use special graphics group
|
||||
area_graphics_ = (*rom_)[kOverworldSpecialGfxGroup +
|
||||
(parent_ - kSpecialWorldMapIdStart)];
|
||||
area_palette_ = (*rom_)[kOverworldSpecialPalGroup + 1];
|
||||
} else if (index_ == 0x81 || index_ == 0x82 || index_ == 0x89 ||
|
||||
index_ == 0x8A) {
|
||||
// Zora's Domain areas - use special sprite graphics
|
||||
// Zora's Domain areas - use special sprite graphics and area graphics
|
||||
// Note: These are the large area maps that were causing crashes
|
||||
sprite_graphics_[0] = 0x0E;
|
||||
sprite_graphics_[1] = 0x0E;
|
||||
sprite_graphics_[2] = 0x0E;
|
||||
@@ -253,7 +272,7 @@ void OverworldMap::LoadAreaInfo() {
|
||||
area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x43];
|
||||
area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x43];
|
||||
} else {
|
||||
// Default case
|
||||
// Default case - use basic graphics
|
||||
area_graphics_ = (*rom_)[kAreaGfxIdPtr + 0x00];
|
||||
area_palette_ = (*rom_)[kOverworldMapPaletteIds + 0x00];
|
||||
}
|
||||
@@ -578,7 +597,7 @@ void OverworldMap::LoadAreaGraphics() {
|
||||
|
||||
namespace palette_internal {
|
||||
|
||||
absl::Status SetColorsPalette(Rom &rom, int index, gfx::SnesPalette ¤t,
|
||||
absl::Status SetColorsPalette(Rom& rom, int index, gfx::SnesPalette& current,
|
||||
gfx::SnesPalette main, gfx::SnesPalette animated,
|
||||
gfx::SnesPalette aux1, gfx::SnesPalette aux2,
|
||||
gfx::SnesPalette hud, gfx::SnesColor bgrcolor,
|
||||
@@ -699,7 +718,7 @@ absl::Status SetColorsPalette(Rom &rom, int index, gfx::SnesPalette ¤t,
|
||||
} // namespace palette_internal
|
||||
|
||||
absl::StatusOr<gfx::SnesPalette> OverworldMap::GetPalette(
|
||||
const gfx::PaletteGroup &palette_group, int index, int previous_index,
|
||||
const gfx::PaletteGroup& palette_group, int index, int previous_index,
|
||||
int limit) {
|
||||
if (index == 255) {
|
||||
index = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup +
|
||||
@@ -713,10 +732,10 @@ absl::StatusOr<gfx::SnesPalette> OverworldMap::GetPalette(
|
||||
|
||||
absl::Status OverworldMap::LoadPalette() {
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
|
||||
|
||||
int previous_pal_id = 0;
|
||||
int previous_spr_pal_id = 0;
|
||||
|
||||
|
||||
if (index_ > 0) {
|
||||
// Load previous palette ID based on ASM version
|
||||
if (asm_version < 3 || asm_version == 0xFF) {
|
||||
@@ -725,7 +744,7 @@ absl::Status OverworldMap::LoadPalette() {
|
||||
// v3 uses expanded palette table
|
||||
previous_pal_id = (*rom_)[kOverworldPalettesScreenToSetNew + parent_ - 1];
|
||||
}
|
||||
|
||||
|
||||
previous_spr_pal_id = (*rom_)[kOverworldSpritePaletteIds + parent_ - 1];
|
||||
}
|
||||
|
||||
@@ -751,12 +770,12 @@ absl::Status OverworldMap::LoadPalette() {
|
||||
pal1 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup +
|
||||
(previous_pal_id * 4)];
|
||||
}
|
||||
|
||||
|
||||
if (pal2 == 0xFF) {
|
||||
pal2 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup +
|
||||
(previous_pal_id * 4) + 1];
|
||||
}
|
||||
|
||||
|
||||
if (pal3 == 0xFF) {
|
||||
pal3 = (*rom_)[rom_->version_constants().kOverworldMapPaletteGroup +
|
||||
(previous_pal_id * 4) + 2];
|
||||
@@ -769,11 +788,14 @@ absl::Status OverworldMap::LoadPalette() {
|
||||
GetPalette(ow_aux_pal_group, pal2, previous_pal_id, 20));
|
||||
|
||||
// Set background color based on world type and area-specific settings
|
||||
bool use_area_specific_bg = (*rom_)[OverworldCustomAreaSpecificBGEnabled] != 0x00;
|
||||
bool use_area_specific_bg =
|
||||
(*rom_)[OverworldCustomAreaSpecificBGEnabled] != 0x00;
|
||||
if (use_area_specific_bg) {
|
||||
// Use area-specific background color from custom array
|
||||
area_specific_bg_color_ = (*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2)] |
|
||||
((*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2) + 1] << 8);
|
||||
area_specific_bg_color_ =
|
||||
(*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2)] |
|
||||
((*rom_)[OverworldCustomAreaSpecificBGPalette + (parent_ * 2) + 1]
|
||||
<< 8);
|
||||
// Convert 15-bit SNES color to palette color
|
||||
bgr = gfx::SnesColor(area_specific_bg_color_);
|
||||
} else {
|
||||
@@ -806,15 +828,16 @@ absl::Status OverworldMap::LoadPalette() {
|
||||
if (pal4 == 0xFF) {
|
||||
pal4 = (*rom_)[kOverworldSpritePaletteGroup + (previous_spr_pal_id * 2)];
|
||||
}
|
||||
|
||||
|
||||
if (pal4 == 0xFF) {
|
||||
pal4 = 0; // Fallback to 0 if still 0xFF
|
||||
}
|
||||
|
||||
|
||||
if (pal5 == 0xFF) {
|
||||
pal5 = (*rom_)[kOverworldSpritePaletteGroup + (previous_spr_pal_id * 2) + 1];
|
||||
pal5 =
|
||||
(*rom_)[kOverworldSpritePaletteGroup + (previous_spr_pal_id * 2) + 1];
|
||||
}
|
||||
|
||||
|
||||
if (pal5 == 0xFF) {
|
||||
pal5 = 0; // Fallback to 0 if still 0xFF
|
||||
}
|
||||
@@ -840,7 +863,7 @@ absl::Status OverworldMap::LoadPalette() {
|
||||
|
||||
absl::Status OverworldMap::LoadOverlay() {
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
|
||||
|
||||
// Load overlays based on ROM version
|
||||
if (asm_version == 0xFF) {
|
||||
// Vanilla ROM - load overlay from overlay pointers
|
||||
@@ -855,15 +878,15 @@ absl::Status OverworldMap::LoadOverlay() {
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::LoadVanillaOverlayData() {
|
||||
|
||||
|
||||
// Load vanilla overlay for this map (interactive overlays for revealing holes/changing elements)
|
||||
int address = (kOverlayPointersBank << 16) +
|
||||
((*rom_)[kOverlayPointers + (index_ * 2) + 1] << 8) +
|
||||
(*rom_)[kOverlayPointers + (index_ * 2)];
|
||||
|
||||
|
||||
// Convert SNES address to PC address
|
||||
address = ((address & 0x7F0000) >> 1) | (address & 0x7FFF);
|
||||
|
||||
|
||||
// Check if custom overlay code is present
|
||||
if ((*rom_)[kOverlayData1] == 0x6B) {
|
||||
// Use custom overlay data pointer
|
||||
@@ -872,7 +895,7 @@ absl::Status OverworldMap::LoadVanillaOverlayData() {
|
||||
(*rom_)[kOverlayData2 + (index_ * 3)];
|
||||
address = ((address & 0x7F0000) >> 1) | (address & 0x7FFF);
|
||||
}
|
||||
|
||||
|
||||
// Validate address
|
||||
if (address >= rom_->size()) {
|
||||
has_overlay_ = false;
|
||||
@@ -880,15 +903,15 @@ absl::Status OverworldMap::LoadVanillaOverlayData() {
|
||||
overlay_data_.clear();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
|
||||
// Parse overlay data (interactive overlays)
|
||||
overlay_data_.clear();
|
||||
uint8_t b = (*rom_)[address];
|
||||
|
||||
|
||||
// Parse overlay commands until we hit END (0x60)
|
||||
while (b != 0x60 && address < rom_->size()) {
|
||||
overlay_data_.push_back(b);
|
||||
|
||||
|
||||
// Handle different overlay commands
|
||||
switch (b) {
|
||||
case 0xA9: // LDA #$
|
||||
@@ -957,28 +980,28 @@ absl::Status OverworldMap::LoadVanillaOverlayData() {
|
||||
address++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (address < rom_->size()) {
|
||||
b = (*rom_)[address];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add the END command if we found it
|
||||
if (b == 0x60) {
|
||||
overlay_data_.push_back(0x60);
|
||||
}
|
||||
|
||||
|
||||
// Set overlay ID based on map index (simplified)
|
||||
overlay_id_ = index_;
|
||||
has_overlay_ = !overlay_data_.empty();
|
||||
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
|
||||
int size, uint8_t *all_gfx) {
|
||||
int size, uint8_t* all_gfx) {
|
||||
// Ensure we don't go out of bounds
|
||||
int max_offset = static_graphics_offset * size + size;
|
||||
if (max_offset > rom_->graphics_buffer().size()) {
|
||||
@@ -988,7 +1011,7 @@ void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
auto byte = all_gfx[i + (static_graphics_offset * size)];
|
||||
switch (index) {
|
||||
@@ -1004,8 +1027,9 @@ void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::BuildTileset() {
|
||||
if (current_gfx_.size() == 0) current_gfx_.resize(0x10000, 0x00);
|
||||
|
||||
if (current_gfx_.size() == 0)
|
||||
current_gfx_.resize(0x10000, 0x00);
|
||||
|
||||
// Process the 8 main graphics sheets (slots 0-7)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (static_graphics_[i] != 0) {
|
||||
@@ -1013,7 +1037,7 @@ absl::Status OverworldMap::BuildTileset() {
|
||||
rom_->graphics_buffer().data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process sprite graphics (slots 8-15)
|
||||
for (int i = 8; i < 16; i++) {
|
||||
if (static_graphics_[i] != 0) {
|
||||
@@ -1021,19 +1045,20 @@ absl::Status OverworldMap::BuildTileset() {
|
||||
rom_->graphics_buffer().data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process animated graphics if available (slot 16)
|
||||
if (static_graphics_[16] != 0) {
|
||||
ProcessGraphicsBuffer(7, static_graphics_[16], 0x1000,
|
||||
rom_->graphics_buffer().data());
|
||||
}
|
||||
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::BuildTiles16Gfx(std::vector<gfx::Tile16> &tiles16,
|
||||
absl::Status OverworldMap::BuildTiles16Gfx(std::vector<gfx::Tile16>& tiles16,
|
||||
int count) {
|
||||
if (current_blockset_.size() == 0) current_blockset_.resize(0x100000, 0x00);
|
||||
if (current_blockset_.size() == 0)
|
||||
current_blockset_.resize(0x100000, 0x00);
|
||||
|
||||
const int offsets[] = {0x00, 0x08, 0x400, 0x408};
|
||||
auto yy = 0;
|
||||
@@ -1077,7 +1102,7 @@ absl::Status OverworldMap::BuildTiles16Gfx(std::vector<gfx::Tile16> &tiles16,
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::BuildBitmap(OverworldBlockset &world_blockset) {
|
||||
absl::Status OverworldMap::BuildBitmap(OverworldBlockset& world_blockset) {
|
||||
if (bitmap_data_.size() != 0) {
|
||||
bitmap_data_.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user