yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_exit.h
Go to the documentation of this file.
1#ifndef YAZE_APP_ZELDA3_OVERWORLD_EXIT_H
2#define YAZE_APP_ZELDA3_OVERWORLD_EXIT_H
3
4#include <cstdint>
5#include <iostream>
6
7#include "app/rom.h"
8#include "zelda3/common.h"
9
10namespace yaze::zelda3 {
11
12constexpr int kNumOverworldExits = 0x4F;
13constexpr int OWExitRoomId = 0x15D8A; // 0x15E07 Credits sequences
14// 105C2 Ending maps
15// 105E2 Sprite Group Table for Ending
16constexpr int OWExitMapId = 0x15E28;
17constexpr int OWExitVram = 0x15E77;
18constexpr int OWExitYScroll = 0x15F15;
19constexpr int OWExitXScroll = 0x15FB3;
20constexpr int OWExitYPlayer = 0x16051;
21constexpr int OWExitXPlayer = 0x160EF;
22constexpr int OWExitYCamera = 0x1618D;
23constexpr int OWExitXCamera = 0x1622B;
24constexpr int OWExitDoorPosition = 0x15724;
25constexpr int OWExitUnk1 = 0x162C9;
26constexpr int OWExitUnk2 = 0x16318;
27constexpr int OWExitDoorType1 = 0x16367;
28constexpr int OWExitDoorType2 = 0x16405;
29
30constexpr int OWExitMapIdWhirlpool = 0x16AE5; // JP = ;016849
31constexpr int OWExitVramWhirlpool = 0x16B07; // JP = ;01686B
32constexpr int OWExitYScrollWhirlpool = 0x16B29; // JP = ;01688D
33constexpr int OWExitXScrollWhirlpool = 0x16B4B; // JP = ;016DE7
34constexpr int OWExitYPlayerWhirlpool = 0x16B6D; // JP = ;016E09
35constexpr int OWExitXPlayerWhirlpool = 0x16B8F; // JP = ;016E2B
36constexpr int OWExitYCameraWhirlpool = 0x16BB1; // JP = ;016E4D
37constexpr int OWExitXCameraWhirlpool = 0x16BD3; // JP = ;016E6F
38constexpr int OWExitUnk1Whirlpool = 0x16BF5; // JP = ;016E91
39constexpr int OWExitUnk2Whirlpool = 0x16C17; // JP = ;016EB3
40constexpr int OWWhirlpoolPosition = 0x16CF8; // JP = ;016F94
41
42class OverworldExit : public GameEntity {
43 public:
44 uint16_t y_scroll_;
45 uint16_t x_scroll_;
46 uint16_t y_player_; // CRITICAL: Changed from uint8_t to uint16_t (0-4088 range)
47 uint16_t x_player_; // CRITICAL: Changed from uint8_t to uint16_t (0-4088 range)
48 uint16_t y_camera_; // Changed from uint8_t to uint16_t for consistency
49 uint16_t x_camera_; // Changed from uint8_t to uint16_t for consistency
52 uint16_t door_type_1_;
53 uint16_t door_type_2_;
54 uint16_t room_id_;
55 uint16_t map_pos_; // Position in the vram
56 uint8_t entrance_id_;
57 uint8_t area_x_;
58 uint8_t area_y_;
59 bool is_hole_ = false;
60 bool deleted_ = false;
61 bool is_automatic_ = false;
62 bool large_map_ = false;
63
64 OverworldExit() = default;
65 OverworldExit(uint16_t room_id, uint8_t map_id, uint16_t vram_location,
66 uint16_t y_scroll, uint16_t x_scroll, uint16_t player_y,
67 uint16_t player_x, uint16_t camera_y, uint16_t camera_x,
68 uint8_t scroll_mod_y, uint8_t scroll_mod_x,
69 uint16_t door_type_1, uint16_t door_type_2,
70 bool deleted = false)
71 : map_pos_(vram_location),
72 entrance_id_(0),
73 area_x_(0),
74 area_y_(0),
75 room_id_(room_id),
76 y_scroll_(y_scroll),
77 x_scroll_(x_scroll),
78 y_player_(player_y), // No cast - preserve full 16-bit value
79 x_player_(player_x), // No cast - preserve full 16-bit value
80 y_camera_(camera_y), // No cast - preserve full 16-bit value
81 x_camera_(camera_x), // No cast - preserve full 16-bit value
82 scroll_mod_y_(scroll_mod_y),
83 scroll_mod_x_(scroll_mod_x),
84 door_type_1_(door_type_1),
85 door_type_2_(door_type_2),
86 is_hole_(false),
87 deleted_(deleted) {
88 // Initialize entity variables with full 16-bit coordinates
89 x_ = player_x;
90 y_ = player_y;
91 map_id_ = map_id;
93
94 int mapX = (map_id_ - ((map_id_ / 8) * 8));
95 int mapY = (map_id_ / 8);
96
97 area_x_ = (uint8_t)((std::abs(x_ - (mapX * 512)) / 16));
98 area_y_ = (uint8_t)((std::abs(y_ - (mapY * 512)) / 16));
99
100 if (door_type_1 != 0) {
101 int p = (door_type_1 & 0x7FFF) >> 1;
102 entrance_id_ = (uint8_t)(p % 64);
103 area_y_ = (uint8_t)(p >> 6);
104 }
105
106 if (door_type_2 != 0) {
107 int p = (door_type_2 & 0x7FFF) >> 1;
108 entrance_id_ = (uint8_t)(p % 64);
109 area_y_ = (uint8_t)(p >> 6);
110 }
111
112 if (map_id_ >= 64) {
113 map_id_ -= 64;
114 }
115
116 mapX = (map_id_ - ((map_id_ / 8) * 8));
117 mapY = (map_id_ / 8);
118
119 area_x_ = (uint8_t)((std::abs(x_ - (mapX * 512)) / 16));
120 area_y_ = (uint8_t)((std::abs(y_ - (mapY * 512)) / 16));
121
122 map_pos_ = (uint16_t)((((area_y_) << 6) | (area_x_ & 0x3F)) << 1);
123 }
124
125 // Overworld overworld
126 void UpdateMapProperties(uint16_t map_id) override {
127 // CRITICAL FIX: Sync player position from base entity coordinates
128 // The drag system in overworld_editor.cc updates x_/y_ (base GameEntity fields),
129 // but exit auto-calculation uses x_player_/y_player_ for scroll/camera computation.
130 // Without this sync, dragged exits retain old scroll values, causing save corruption.
131 // Matches ZScream ExitMode.cs:229-244 where PlayerX/PlayerY are updated during drag,
132 // then UpdateMapStuff recalculates scroll/camera from those values.
133 x_player_ = static_cast<uint16_t>(x_);
134 y_player_ = static_cast<uint16_t>(y_);
135
136 map_id_ = map_id;
137
138 int large = 256;
139 int mapid = map_id;
140
141 if (map_id < 128) {
142 large = large_map_ ? 768 : 256;
143 // if (overworld.overworld_map(map_id)->Parent() != map_id) {
144 // mapid = overworld.overworld_map(map_id)->Parent();
145 // }
146 }
147
148 int mapX = map_id - ((map_id / 8) * 8);
149 int mapY = map_id / 8;
150
151 area_x_ = (uint8_t)((std::abs(x_ - (mapX * 512)) / 16));
152 area_y_ = (uint8_t)((std::abs(y_ - (mapY * 512)) / 16));
153
154 if (map_id >= 64) {
155 map_id -= 64;
156 }
157
158 int mapx = (map_id & 7) << 9;
159 int mapy = (map_id & 56) << 6;
160
161 if (is_automatic_) {
162 // Auto-calculate scroll and camera from player position
163 // Matches ZScream ExitOW.cs:256-309
164 x_scroll_ = x_player_ - 120;
165 y_scroll_ = y_player_ - 80;
166
167 if (x_scroll_ < mapx) {
168 x_scroll_ = mapx;
169 }
170
171 if (y_scroll_ < mapy) {
172 y_scroll_ = mapy;
173 }
174
175 if (x_scroll_ > mapx + large) {
176 x_scroll_ = mapx + large;
177 }
178
179 if (y_scroll_ > mapy + large + 32) {
180 y_scroll_ = mapy + large + 32;
181 }
182
183 x_camera_ = x_player_ + 0x07;
184 y_camera_ = y_player_ + 0x1F;
185
186 if (x_camera_ < mapx + 127) {
187 x_camera_ = mapx + 127;
188 }
189
190 if (y_camera_ < mapy + 111) {
191 y_camera_ = mapy + 111;
192 }
193
194 if (x_camera_ > mapx + 127 + large) {
195 x_camera_ = mapx + 127 + large;
196 }
197
198 if (y_camera_ > mapy + 143 + large) {
199 y_camera_ = mapy + 143 + large;
200 }
201 }
202
203 short vram_x_scroll = (short)(x_scroll_ - mapx);
204 short vram_y_scroll = (short)(y_scroll_ - mapy);
205
206 map_pos_ = (uint16_t)(((vram_y_scroll & 0xFFF0) << 3) |
207 ((vram_x_scroll & 0xFFF0) >> 3));
208 }
209};
210
211absl::StatusOr<std::vector<OverworldExit>> LoadExits(Rom* rom);
212absl::Status SaveExits(Rom* rom, const std::vector<OverworldExit>& exits);
213
214} // namespace yaze::zelda3
215
216#endif // YAZE_APP_ZELDA3_OVERWORLD_EXIT_H_
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:74
Base class for all overworld and dungeon entities.
Definition common.h:17
enum yaze::zelda3::GameEntity::EntityType entity_type_
void UpdateMapProperties(uint16_t map_id) override
OverworldExit(uint16_t room_id, uint8_t map_id, uint16_t vram_location, uint16_t y_scroll, uint16_t x_scroll, uint16_t player_y, uint16_t player_x, uint16_t camera_y, uint16_t camera_x, uint8_t scroll_mod_y, uint8_t scroll_mod_x, uint16_t door_type_1, uint16_t door_type_2, bool deleted=false)
Zelda 3 specific classes and functions.
constexpr int OWExitYScroll
constexpr int OWWhirlpoolPosition
constexpr int OWExitXCameraWhirlpool
constexpr int OWExitDoorType2
constexpr int OWExitYScrollWhirlpool
constexpr int OWExitYCamera
constexpr int OWExitDoorPosition
constexpr int OWExitYCameraWhirlpool
constexpr int OWExitXScroll
constexpr int OWExitRoomId
constexpr int OWExitXCamera
constexpr int OWExitUnk1
constexpr int OWExitYPlayer
constexpr int OWExitVramWhirlpool
absl::StatusOr< std::vector< OverworldExit > > LoadExits(Rom *rom)
constexpr int OWExitMapIdWhirlpool
constexpr int OWExitMapId
constexpr int OWExitUnk2
constexpr int OWExitUnk1Whirlpool
constexpr int OWExitDoorType1
constexpr int kNumOverworldExits
constexpr int OWExitXPlayerWhirlpool
constexpr int OWExitUnk2Whirlpool
constexpr int OWExitYPlayerWhirlpool
absl::Status SaveExits(Rom *rom, const std::vector< OverworldExit > &exits)
constexpr int OWExitXPlayer
constexpr int OWExitVram
constexpr int OWExitXScrollWhirlpool