21 return absl::InvalidArgumentError(
"Cannot load exits without a ROM");
23 const int NumberOfOverworldExits = 0x4F;
24 std::vector<OverworldExit> exits;
25 for (
int i = 0; i < NumberOfOverworldExits; i++) {
26 uint16_t exit_room_id;
29 uint16_t exit_y_scroll;
30 uint16_t exit_x_scroll;
31 uint16_t exit_y_player;
32 uint16_t exit_x_player;
33 uint16_t exit_y_camera;
34 uint16_t exit_x_camera;
35 uint8_t exit_scroll_mod_y;
36 uint8_t exit_scroll_mod_x;
37 uint16_t exit_door_type_1;
38 uint16_t exit_door_type_2;
46 exit_scroll_mod_x,
OWExitUnk2 + i, exit_door_type_1,
50 exits.emplace_back(exit_room_id, exit_map_id, exit_vram, exit_y_scroll,
51 exit_x_scroll, exit_y_player, exit_x_player,
52 exit_y_camera, exit_x_camera, exit_scroll_mod_y,
53 exit_scroll_mod_x, exit_door_type_1, exit_door_type_2,
54 exit_x_player == 0xFFFF && exit_y_player == 0xFFFF);
69 int area_size_x = 256;
70 int area_size_y = 256;
74 if (context !=
nullptr) {
75 const auto* overworld =
static_cast<const Overworld*
>(context);
76 if (
const auto* map = overworld->overworld_map(map_id)) {
77 const auto area_size = map->area_size();
79 area_size_x = area_size_y = 768;
90 uint8_t normalized_map_id = map_id % 0x40;
94 int mapX = normalized_map_id % 8;
95 int mapY = normalized_map_id / 8;
99 game_x_ =
static_cast<int>((std::abs(
x_ - (mapX * 512)) / 16));
100 game_y_ =
static_cast<int>((std::abs(
y_ - (mapY * 512)) / 16));
104 int max_game_x = (area_size_x == 256) ? 31 : 63;
105 int max_game_y = (area_size_y == 256) ? 31 : 63;
111 int mapx = (normalized_map_id & 7) << 9;
112 int mapy = (normalized_map_id & 56) << 6;
120 x_scroll_ =
static_cast<uint16_t
>(std::clamp(
121 static_cast<int>(
x_player_) - 120, mapx, mapx + area_size_x));
122 y_scroll_ =
static_cast<uint16_t
>(std::clamp(
123 static_cast<int>(
y_player_) - 80, mapy, mapy + area_size_y + 32));
124 x_camera_ =
static_cast<uint16_t
>(std::clamp(
125 static_cast<int>(
x_player_) + 7, mapx + 127, mapx + 127 + area_size_x));
127 static_cast<uint16_t
>(std::clamp(
static_cast<int>(
y_player_) + 31,
128 mapy + 111, mapy + 143 + area_size_y));
133 int16_t vram_x_scroll =
static_cast<int16_t
>(
x_scroll_ - mapx);
134 int16_t vram_y_scroll =
static_cast<int16_t
>(
y_scroll_ - mapy);
136 map_pos_ =
static_cast<uint16_t
>(((vram_y_scroll & 0xFFF0) << 3) |
137 ((vram_x_scroll & 0xFFF0) >> 3));
140absl::Status
SaveExits(
Rom* rom,
const std::vector<OverworldExit>& exits) {
141 if (rom ==
nullptr) {
142 return absl::InvalidArgumentError(
"Cannot save exits without a ROM");
145 return absl::InvalidArgumentError(
"Saving exits requires all 79 records");
153 constexpr TableRange kTables[] = {
169 const size_t rom_size = rom->
vector().size();
170 for (
const auto& table : kTables) {
171 if (table.address > rom_size || table.bytes > rom_size - table.address) {
172 return absl::OutOfRangeError(
"ROM does not contain complete exit tables");
179 const bool destination_changed =
180 stored_room != exits[i].room_id_ || stored_map != exits[i].map_id_;
192 exits[i].deleted_ ? 0xFFFF : exits[i].y_player_));
195 exits[i].deleted_ ? 0xFFFF : exits[i].x_player_));
209 if (!destination_changed) {
212 if (exits[i].room_id_ == 0x0180) {
215 }
else if (exits[i].room_id_ == 0x0181) {
218 }
else if (exits[i].room_id_ == 0x0182) {
224 return absl::OkStatus();