Refactor Overworld Editor and enhance settings management for v3 features
- Removed the outdated ZEML layout file and associated references to streamline the OverworldEditor. - Introduced the OverworldEditorManager class to encapsulate v3 settings management, improving code organization and maintainability. - Updated the OverworldEditor to utilize ImGui for layout, enhancing user interaction and flexibility. - Enhanced the changelog with detailed descriptions of new features and improvements, including a comprehensive undo/redo system and advanced palette management. - Removed deprecated diagnostic patterns from the clangd configuration to improve code quality checks.
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/snes.h"
|
||||
#include "app/zelda3/overworld/overworld_entrance.h"
|
||||
#include "app/zelda3/overworld/overworld_exit.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/log.h"
|
||||
#include "util/macro.h"
|
||||
@@ -38,6 +40,7 @@ absl::Status Overworld::Load(Rom* rom) {
|
||||
}
|
||||
|
||||
FetchLargeMaps();
|
||||
LoadTileTypes();
|
||||
RETURN_IF_ERROR(LoadEntrances());
|
||||
RETURN_IF_ERROR(LoadHoles());
|
||||
RETURN_IF_ERROR(LoadExits());
|
||||
@@ -437,14 +440,6 @@ absl::Status Overworld::LoadExits() {
|
||||
}
|
||||
|
||||
absl::Status Overworld::LoadItems() {
|
||||
// byte asmVersion = ROM.DATA[Constants.OverworldCustomASMHasBeenApplied];
|
||||
|
||||
// // Version 0x03 of the OW ASM added item support for the SW.
|
||||
// int maxOW = asmVersion >= 0x03 && asmVersion != 0xFF ? Constants.NumberOfOWMaps : 0x80;
|
||||
|
||||
// int pointerSNES = ROM.ReadLong(Constants.overworldItemsAddress);
|
||||
// this.ItemPointerAddress = Utils.SnesToPc(pointerSNES); // 0x1BC2F9 -> 0x0DC2F9
|
||||
|
||||
// Version 0x03 of the OW ASM added item support for the SW.
|
||||
uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
|
||||
@@ -606,6 +601,10 @@ absl::Status Overworld::Save(Rom* rom) {
|
||||
RETURN_IF_ERROR(SaveOverworldMaps())
|
||||
RETURN_IF_ERROR(SaveEntrances())
|
||||
RETURN_IF_ERROR(SaveExits())
|
||||
RETURN_IF_ERROR(SaveItems())
|
||||
RETURN_IF_ERROR(SaveMapOverlays())
|
||||
RETURN_IF_ERROR(SaveOverworldTilesType())
|
||||
RETURN_IF_ERROR(SaveAreaSpecificBGColors())
|
||||
RETURN_IF_ERROR(SaveMusic())
|
||||
RETURN_IF_ERROR(SaveAreaSizes())
|
||||
return absl::OkStatus();
|
||||
@@ -751,6 +750,17 @@ 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;
|
||||
|
||||
for (int i = 0; i < kNumMapsPerWorld; ++i) {
|
||||
@@ -794,7 +804,7 @@ absl::Status Overworld::SaveLargeMaps() {
|
||||
0x04));
|
||||
}
|
||||
|
||||
// Check 5 and 6
|
||||
// Check 5 and 6 - transition targets
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(kTransitionTargetNorth + (i * 2),
|
||||
(uint16_t)((parent_y_pos * 0x200) - 0xE0)));
|
||||
@@ -823,7 +833,7 @@ absl::Status Overworld::SaveLargeMaps() {
|
||||
rom()->WriteShort(kTransitionTargetWest + (i * 2) + 18,
|
||||
(uint16_t)((parent_x_pos * 0x200) - 0x100)));
|
||||
|
||||
// Check 7 and 8
|
||||
// Check 7 and 8 - transition positions
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldTransitionPositionX + (i * 2),
|
||||
(parent_x_pos * 0x200)));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldTransitionPositionY + (i * 2),
|
||||
@@ -836,7 +846,6 @@ absl::Status Overworld::SaveLargeMaps() {
|
||||
rom()->WriteShort(kOverworldTransitionPositionY + (i * 2) + 02,
|
||||
(parent_y_pos * 0x200)));
|
||||
|
||||
// problematic
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(kOverworldTransitionPositionX + (i * 2) + 16,
|
||||
(parent_x_pos * 0x200)));
|
||||
@@ -851,7 +860,7 @@ absl::Status Overworld::SaveLargeMaps() {
|
||||
rom()->WriteShort(kOverworldTransitionPositionY + (i * 2) + 18,
|
||||
(parent_y_pos * 0x200)));
|
||||
|
||||
// Check 9
|
||||
// Check 9 - simple vanilla large area transitions
|
||||
RETURN_IF_ERROR(rom()->WriteShort(
|
||||
kOverworldScreenTileMapChangeByScreen1 + (i * 2) + 00, 0x0060));
|
||||
RETURN_IF_ERROR(rom()->WriteShort(
|
||||
@@ -1069,6 +1078,580 @@ 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) {
|
||||
// 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_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) {
|
||||
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) {
|
||||
by_screen1_small = 0xF060;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
by_screen2_small = 0xF040;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
by_screen3_small = 0x17C0;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
by_screen4_small = 0x0FC0;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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
|
||||
by_screen1_large[2] = 0x0060;
|
||||
break;
|
||||
case 3: // From bottom right to top left of large area
|
||||
by_screen1_large[0] = 0xF060;
|
||||
break;
|
||||
}
|
||||
} else if (west_neighbor.area_size() == AreaSizeEnum::TallArea) {
|
||||
switch (west_neighbor.large_index()) {
|
||||
case 0: // From bottom of tall to bottom left of large
|
||||
by_screen1_large[2] = 0x0060;
|
||||
break;
|
||||
case 2: // From bottom of tall to top left of large
|
||||
by_screen1_large[0] = 0xF060;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; 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
|
||||
by_screen2_large[3] = 0x0080;
|
||||
break;
|
||||
case 2: // From bottom left to top right of large area
|
||||
by_screen2_large[1] = 0xF080;
|
||||
break;
|
||||
}
|
||||
} else if (east_neighbor.area_size() == AreaSizeEnum::TallArea) {
|
||||
switch (east_neighbor.large_index()) {
|
||||
case 0: // From bottom of tall to bottom right of large
|
||||
by_screen2_large[3] = 0x0080;
|
||||
break;
|
||||
case 2: // From bottom of tall to top right of large
|
||||
by_screen2_large[1] = 0xF080;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; 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
|
||||
by_screen3_large[1] = 0x1800;
|
||||
break;
|
||||
case 3: // From bottom right to top left of large area
|
||||
by_screen3_large[0] = 0x17C0;
|
||||
break;
|
||||
}
|
||||
} else if (north_neighbor.area_size() == AreaSizeEnum::WideArea) {
|
||||
switch (north_neighbor.large_index()) {
|
||||
case 0: // From right of wide to top right of large
|
||||
by_screen3_large[1] = 0x1800;
|
||||
break;
|
||||
case 1: // From right of wide to top left of large
|
||||
by_screen3_large[0] = 0x17C0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; 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
|
||||
by_screen4_large[3] = 0x2000;
|
||||
break;
|
||||
case 1: // From top right to bottom left of large area
|
||||
by_screen4_large[2] = 0x1FC0;
|
||||
break;
|
||||
}
|
||||
} else if (south_neighbor.area_size() == AreaSizeEnum::WideArea) {
|
||||
switch (south_neighbor.large_index()) {
|
||||
case 0: // From right of wide to bottom right of large
|
||||
by_screen4_large[3] = 0x2000;
|
||||
break;
|
||||
case 1: // From right of wide to bottom left of large
|
||||
by_screen4_large[2] = 0x1FC0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 4; 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) {
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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]));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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]));
|
||||
}
|
||||
|
||||
// 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
|
||||
by_screen3_wide[1] = 0x1800;
|
||||
break;
|
||||
case 3: // From bottom right of large to left of wide
|
||||
by_screen3_wide[0] = 0x17C0;
|
||||
break;
|
||||
}
|
||||
} else if (north_neighbor.area_size() == AreaSizeEnum::WideArea) {
|
||||
switch (north_neighbor.large_index()) {
|
||||
case 0: // From right of wide to right of wide
|
||||
by_screen3_wide[1] = 0x1800;
|
||||
break;
|
||||
case 1: // From right of wide to left of wide
|
||||
by_screen3_wide[0] = 0x07C0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; 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
|
||||
by_screen4_wide[1] = 0x1000;
|
||||
break;
|
||||
case 1: // From top right of large to left of wide
|
||||
by_screen4_wide[0] = 0x0FC0;
|
||||
break;
|
||||
}
|
||||
} else if (south_neighbor.area_size() == AreaSizeEnum::WideArea) {
|
||||
if (south_neighbor.large_index() == 1) {
|
||||
by_screen4_wide[0] = 0x0FC0;
|
||||
}
|
||||
switch (south_neighbor.large_index()) {
|
||||
case 0: // From right of wide to right of wide
|
||||
by_screen4_wide[1] = 0x1000;
|
||||
break;
|
||||
case 1: // From right of wide to left of wide
|
||||
by_screen4_wide[0] = 0x0FC0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; 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) {
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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
|
||||
by_screen1_tall[1] = 0x0060;
|
||||
break;
|
||||
case 3: // From bottom right of large to top of tall
|
||||
by_screen1_tall[0] = 0xF060;
|
||||
break;
|
||||
}
|
||||
} else if (west_neighbor.area_size() == AreaSizeEnum::TallArea) {
|
||||
switch (west_neighbor.large_index()) {
|
||||
case 0: // From bottom of tall to bottom of tall
|
||||
by_screen1_tall[1] = 0x0060;
|
||||
break;
|
||||
case 2: // From bottom of tall to top of tall
|
||||
by_screen1_tall[0] = 0xF060;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; 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
|
||||
by_screen2_tall[1] = 0x0040;
|
||||
break;
|
||||
case 2: // From bottom left of large to top of tall
|
||||
by_screen2_tall[0] = 0xF040;
|
||||
break;
|
||||
}
|
||||
} else if (east_neighbor.area_size() == AreaSizeEnum::TallArea) {
|
||||
switch (east_neighbor.large_index()) {
|
||||
case 0: // From bottom of tall to bottom of tall
|
||||
by_screen2_tall[1] = 0x0040;
|
||||
break;
|
||||
case 2: // From bottom of tall to top of tall
|
||||
by_screen2_tall[0] = 0xF040;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; 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) {
|
||||
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) {
|
||||
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]));
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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 absl::OkStatus();
|
||||
}
|
||||
|
||||
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;
|
||||
int transition_pos_x = zelda3::kOverworldTransitionPositionXExpanded;
|
||||
int transition_pos_y = zelda3::kOverworldTransitionPositionYExpanded;
|
||||
int screen_change_1 = zelda3::kOverworldScreenTileMapChangeByScreen1Expanded;
|
||||
int screen_change_2 = zelda3::kOverworldScreenTileMapChangeByScreen2Expanded;
|
||||
int screen_change_3 = zelda3::kOverworldScreenTileMapChangeByScreen3Expanded;
|
||||
int screen_change_4 = zelda3::kOverworldScreenTileMapChangeByScreen4Expanded;
|
||||
|
||||
std::vector<uint8_t> checked_map;
|
||||
|
||||
// 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()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int parent_y_pos = (overworld_maps_[i].parent() % 0x40) / 8;
|
||||
int parent_x_pos = (overworld_maps_[i].parent() % 0x40) % 8;
|
||||
|
||||
// Write the map parent ID to expanded parent table
|
||||
RETURN_IF_ERROR(rom()->WriteByte(zelda3::kOverworldMapParentIdExpanded + i,
|
||||
overworld_maps_[i].parent()));
|
||||
|
||||
// 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));
|
||||
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));
|
||||
// Mark all 4 quadrants as processed
|
||||
checked_map.emplace_back(i);
|
||||
checked_map.emplace_back(i + 1);
|
||||
checked_map.emplace_back(i + 8);
|
||||
checked_map.emplace_back(i + 9);
|
||||
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));
|
||||
// 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));
|
||||
// Mark both vertical quadrants as processed
|
||||
checked_map.emplace_back(i);
|
||||
checked_map.emplace_back(i + 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<uint64_t> GetAllTile16(OverworldMapTiles& map_tiles_) {
|
||||
std::vector<uint64_t> all_tile_16; // Ensure it's 64 bits
|
||||
@@ -1592,24 +2175,26 @@ absl::Status Overworld::SaveMap16Tiles() {
|
||||
|
||||
absl::Status Overworld::SaveEntrances() {
|
||||
util::logf("Saving Entrances");
|
||||
int ow_entrance_map_ptr = kOverworldEntranceMap;
|
||||
int ow_entrance_pos_ptr = kOverworldEntrancePos;
|
||||
int ow_entrance_id_ptr = kOverworldEntranceEntranceId;
|
||||
int num_entrances = kNumOverworldEntrances;
|
||||
|
||||
// Use expanded entrance tables if available
|
||||
if (expanded_entrances_) {
|
||||
ow_entrance_map_ptr = kOverworldEntranceMapExpanded;
|
||||
ow_entrance_pos_ptr = kOverworldEntrancePosExpanded;
|
||||
ow_entrance_id_ptr = kOverworldEntranceEntranceIdExpanded;
|
||||
expanded_entrances_ = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumOverworldEntrances; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntranceMap + (i * 2),
|
||||
all_entrances_[i].map_id_))
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntrancePos + (i * 2),
|
||||
all_entrances_[i].map_pos_))
|
||||
RETURN_IF_ERROR(rom()->WriteByte(kOverworldEntranceEntranceId + i,
|
||||
all_entrances_[i].entrance_id_))
|
||||
for (int i = 0; i < kNumOverworldEntrances; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntranceMapExpanded + (i * 2),
|
||||
all_entrances_[i].map_id_))
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntrancePosExpanded + (i * 2),
|
||||
all_entrances_[i].map_pos_))
|
||||
RETURN_IF_ERROR(rom()->WriteByte(kOverworldEntranceEntranceIdExpanded + i,
|
||||
all_entrances_[i].entrance_id_))
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < kNumOverworldEntrances; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntranceMap + (i * 2),
|
||||
all_entrances_[i].map_id_))
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverworldEntrancePos + (i * 2),
|
||||
all_entrances_[i].map_pos_))
|
||||
RETURN_IF_ERROR(rom()->WriteByte(kOverworldEntranceEntranceId + i,
|
||||
all_entrances_[i].entrance_id_))
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumOverworldHoles; i++) {
|
||||
@@ -1626,6 +2211,20 @@ 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
|
||||
// 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
|
||||
// user has already adjusted it or not.
|
||||
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version == 0x00) {
|
||||
// Apply special fix for Zora's Domain exit (index 0x4D)
|
||||
// TODO: Implement SpecialUpdatePosition for OverworldExit
|
||||
// if (all_exits_.size() > 0x4D) {
|
||||
// all_exits_[0x4D].SpecialUpdatePosition();
|
||||
// }
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumOverworldExits; i++) {
|
||||
RETURN_IF_ERROR(
|
||||
rom()->WriteShort(OWExitRoomId + (i * 2), all_exits_[i].room_id_));
|
||||
@@ -1764,6 +2363,160 @@ absl::Status Overworld::SaveItems() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// Write overlay code to ROM
|
||||
constexpr int kOverlayCodeStart = 0x077657;
|
||||
RETURN_IF_ERROR(rom()->WriteVector(kOverlayCodeStart, new_overlay_code));
|
||||
|
||||
// Set up overlay pointers
|
||||
int ptr_start = kOverlayCodeStart + 0x20;
|
||||
int snes_ptr_start = PcToSnes(ptr_start);
|
||||
|
||||
// Write overlay pointer addresses in the code
|
||||
RETURN_IF_ERROR(rom()->WriteLong(kOverlayCodeStart + 10, snes_ptr_start));
|
||||
RETURN_IF_ERROR(rom()->WriteLong(kOverlayCodeStart + 16, snes_ptr_start + 2));
|
||||
|
||||
int pea_addr = PcToSnes(kOverlayCodeStart + 27);
|
||||
RETURN_IF_ERROR(rom()->WriteShort(kOverlayCodeStart + 23, pea_addr));
|
||||
|
||||
// Write overlay data to expanded space
|
||||
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));
|
||||
ptr_pos += 3;
|
||||
|
||||
// Write overlay data for each map that has overlays
|
||||
if (overworld_maps_[i].has_overlay()) {
|
||||
const auto& overlay_data = overworld_maps_[i].overlay_data();
|
||||
for (size_t t = 0; t < overlay_data.size(); t += 3) {
|
||||
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)));
|
||||
pos += 3;
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteByte(pos, 0x8D)); // STA $xxxx
|
||||
RETURN_IF_ERROR(rom()->WriteShort(pos + 1, overlay_data[t + 2]));
|
||||
pos += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_ERROR(rom()->WriteByte(pos, 0x6B)); // RTL
|
||||
pos++;
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
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 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) {
|
||||
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));
|
||||
|
||||
enable_value = enable_main_palette ? 0xFF : 0x00;
|
||||
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));
|
||||
|
||||
enable_value = enable_animated ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomAnimatedGFXEnabled, enable_value));
|
||||
|
||||
enable_value = enable_subscreen_overlay ? 0xFF : 0x00;
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomSubscreenOverlayEnabled, enable_value));
|
||||
|
||||
// Write the main palette table
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
RETURN_IF_ERROR(rom()->WriteByte(OverworldCustomMainPaletteArray + i,
|
||||
overworld_maps_[i].main_palette()));
|
||||
}
|
||||
|
||||
// Write the mosaic table
|
||||
for (int i = 0; i < kNumOverworldMaps; i++) {
|
||||
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[2] ? 0x02 : 0x00) | // left
|
||||
(mosaic[3] ? 0x01 : 0x00); // right
|
||||
|
||||
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(OverworldCustomAnimatedGFXArray + i,
|
||||
overworld_maps_[i].animated_gfx()));
|
||||
}
|
||||
|
||||
// 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 absl::OkStatus();
|
||||
}
|
||||
|
||||
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 absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveMapProperties() {
|
||||
util::logf("Saving Map Properties");
|
||||
for (int i = 0; i < kDarkWorldMapIdStart; i++) {
|
||||
|
||||
@@ -150,9 +150,36 @@ class Overworld {
|
||||
absl::Status Save(Rom *rom);
|
||||
absl::Status SaveOverworldMaps();
|
||||
absl::Status SaveLargeMaps();
|
||||
absl::Status SaveLargeMapsExpanded();
|
||||
absl::Status 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 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 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 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 SaveEntrances();
|
||||
absl::Status SaveExits();
|
||||
absl::Status SaveItems();
|
||||
absl::Status SaveMapOverlays();
|
||||
absl::Status SaveOverworldTilesType();
|
||||
absl::Status 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 SaveAreaSpecificBGColors();
|
||||
|
||||
absl::Status CreateTile32Tilemap();
|
||||
absl::Status SaveMap16Expanded();
|
||||
|
||||
Reference in New Issue
Block a user