yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_commands.cc
Go to the documentation of this file.
2
3#include "absl/strings/str_format.h"
5#include "cli/util/hex_util.h"
7
8namespace yaze {
9namespace cli {
10namespace handlers {
11
13
15 Rom* rom, const resources::ArgumentParser& parser,
16 resources::OutputFormatter& formatter) {
17 auto tile_id_str = parser.GetString("tile").value();
18
19 int tile_id;
20 if (!ParseHexString(tile_id_str, &tile_id)) {
21 return absl::InvalidArgumentError("Invalid tile ID format. Must be hex.");
22 }
23
24 // Load the Overworld from ROM
25 zelda3::Overworld overworld(rom);
26 auto ow_status = overworld.Load(rom);
27 if (!ow_status.ok()) {
28 return ow_status;
29 }
30
31 // Call the helper function to find tile matches
32 auto matches_or = overworld::FindTileMatches(overworld, tile_id);
33 if (!matches_or.ok()) {
34 return matches_or.status();
35 }
36 const auto& matches = matches_or.value();
37
38 // Format the output
39 formatter.BeginObject("Overworld Tile Search");
40 formatter.AddField("tile_id", absl::StrFormat("0x%03X", tile_id));
41 formatter.AddField("matches_found", static_cast<int>(matches.size()));
42
43 formatter.BeginArray("matches");
44 for (const auto& match : matches) {
45 formatter.BeginObject();
46 formatter.AddField("map_id", absl::StrFormat("0x%02X", match.map_id));
47 formatter.AddField("world", overworld::WorldName(match.world));
48 formatter.AddField("local_x", match.local_x);
49 formatter.AddField("local_y", match.local_y);
50 formatter.AddField("global_x", match.global_x);
51 formatter.AddField("global_y", match.global_y);
52 formatter.EndObject();
53 }
54 formatter.EndArray();
55 formatter.EndObject();
56
57 return absl::OkStatus();
58}
59
61 Rom* rom, const resources::ArgumentParser& parser,
62 resources::OutputFormatter& formatter) {
63 auto screen_id_str = parser.GetString("screen").value();
64
65 int screen_id;
66 if (!ParseHexString(screen_id_str, &screen_id)) {
67 return absl::InvalidArgumentError("Invalid screen ID format. Must be hex.");
68 }
69
70 // Load the Overworld from ROM
71 zelda3::Overworld overworld(rom);
72 auto ow_status = overworld.Load(rom);
73 if (!ow_status.ok()) {
74 return ow_status;
75 }
76
77 // Call the helper function to build the map summary
78 auto summary_or = overworld::BuildMapSummary(overworld, screen_id);
79 if (!summary_or.ok()) {
80 return summary_or.status();
81 }
82 const auto& summary = summary_or.value();
83
84 // Format the output using OutputFormatter
85 formatter.BeginObject("Overworld Map Description");
86 formatter.AddField("screen_id", absl::StrFormat("0x%02X", summary.map_id));
87 formatter.AddField("world", overworld::WorldName(summary.world));
88
89 formatter.BeginObject("grid");
90 formatter.AddField("x", summary.map_x);
91 formatter.AddField("y", summary.map_y);
92 formatter.AddField("local_index", summary.local_index);
93 formatter.EndObject();
94
95 formatter.BeginObject("size");
96 formatter.AddField("label", summary.area_size);
97 formatter.AddField("is_large", summary.is_large_map);
98 formatter.AddField("parent", absl::StrFormat("0x%02X", summary.parent_map));
99 formatter.AddField("quadrant", summary.large_quadrant);
100 formatter.EndObject();
101
102 formatter.AddField("message_id",
103 absl::StrFormat("0x%04X", summary.message_id));
104 formatter.AddField("area_graphics",
105 absl::StrFormat("0x%02X", summary.area_graphics));
106 formatter.AddField("area_palette",
107 absl::StrFormat("0x%02X", summary.area_palette));
108 formatter.AddField("main_palette",
109 absl::StrFormat("0x%02X", summary.main_palette));
110 formatter.AddField("animated_gfx",
111 absl::StrFormat("0x%02X", summary.animated_gfx));
112 formatter.AddField("subscreen_overlay",
113 absl::StrFormat("0x%04X", summary.subscreen_overlay));
114 formatter.AddField("area_specific_bg_color",
115 absl::StrFormat("0x%04X", summary.area_specific_bg_color));
116
117 // Format array fields
118 formatter.BeginArray("sprite_graphics");
119 for (uint8_t gfx : summary.sprite_graphics) {
120 formatter.AddArrayItem(absl::StrFormat("0x%02X", gfx));
121 }
122 formatter.EndArray();
123
124 formatter.BeginArray("sprite_palettes");
125 for (uint8_t pal : summary.sprite_palettes) {
126 formatter.AddArrayItem(absl::StrFormat("0x%02X", pal));
127 }
128 formatter.EndArray();
129
130 formatter.BeginArray("area_music");
131 for (uint8_t music : summary.area_music) {
132 formatter.AddArrayItem(absl::StrFormat("0x%02X", music));
133 }
134 formatter.EndArray();
135
136 formatter.BeginArray("static_graphics");
137 for (uint8_t sgfx : summary.static_graphics) {
138 formatter.AddArrayItem(absl::StrFormat("0x%02X", sgfx));
139 }
140 formatter.EndArray();
141
142 formatter.BeginObject("overlay");
143 formatter.AddField("enabled", summary.has_overlay);
144 formatter.AddField("id", absl::StrFormat("0x%04X", summary.overlay_id));
145 formatter.EndObject();
146
147 formatter.EndObject();
148
149 return absl::OkStatus();
150}
151
153 Rom* rom, const resources::ArgumentParser& parser,
154 resources::OutputFormatter& formatter) {
155 auto screen_id_str = parser.GetString("screen").value_or("all");
156
157 // Load the Overworld from ROM
158 zelda3::Overworld overworld(rom);
159 auto ow_status = overworld.Load(rom);
160 if (!ow_status.ok()) {
161 return ow_status;
162 }
163
164 // Build the query
166 if (screen_id_str != "all") {
167 int map_id;
168 if (!ParseHexString(screen_id_str, &map_id)) {
169 return absl::InvalidArgumentError(
170 "Invalid screen ID format. Must be hex.");
171 }
172 query.map_id = map_id;
173 }
174
175 // Call the helper function to collect warp entries
176 auto warps_or = overworld::CollectWarpEntries(overworld, query);
177 if (!warps_or.ok()) {
178 return warps_or.status();
179 }
180 const auto& warps = warps_or.value();
181
182 // Format the output
183 formatter.BeginObject("Overworld Warps");
184 formatter.AddField("screen_filter", screen_id_str);
185 formatter.AddField("total_warps", static_cast<int>(warps.size()));
186
187 formatter.BeginArray("warps");
188 for (const auto& warp : warps) {
189 formatter.BeginObject();
190 formatter.AddField("type", overworld::WarpTypeName(warp.type));
191 formatter.AddField("map_id", absl::StrFormat("0x%02X", warp.map_id));
192 formatter.AddField("world", overworld::WorldName(warp.world));
193 formatter.AddField("position",
194 absl::StrFormat("(%d,%d)", warp.pixel_x, warp.pixel_y));
195 formatter.AddField("map_pos", absl::StrFormat("0x%04X", warp.map_pos));
196
197 if (warp.entrance_id.has_value()) {
198 formatter.AddField("entrance_id",
199 absl::StrFormat("0x%02X", warp.entrance_id.value()));
200 }
201 if (warp.entrance_name.has_value()) {
202 formatter.AddField("entrance_name", warp.entrance_name.value());
203 }
204 if (warp.room_id.has_value()) {
205 formatter.AddField("room_id",
206 absl::StrFormat("0x%04X", warp.room_id.value()));
207 }
208
209 formatter.AddField("deleted", warp.deleted);
210 formatter.AddField("is_hole", warp.is_hole);
211 formatter.EndObject();
212 }
213 formatter.EndArray();
214 formatter.EndObject();
215
216 return absl::OkStatus();
217}
218
220 Rom* rom, const resources::ArgumentParser& parser,
221 resources::OutputFormatter& formatter) {
222 auto screen_id_str = parser.GetString("screen").value_or("all");
223
224 // Load the Overworld from ROM
225 zelda3::Overworld overworld(rom);
226 auto ow_status = overworld.Load(rom);
227 if (!ow_status.ok()) {
228 return ow_status;
229 }
230
231 // Build the query
233 if (screen_id_str != "all") {
234 int map_id;
235 if (!ParseHexString(screen_id_str, &map_id)) {
236 return absl::InvalidArgumentError(
237 "Invalid screen ID format. Must be hex.");
238 }
239 query.map_id = map_id;
240 }
241
242 // Call the helper function to collect sprites
243 auto sprites_or = overworld::CollectOverworldSprites(overworld, query);
244 if (!sprites_or.ok()) {
245 return sprites_or.status();
246 }
247 const auto& sprites = sprites_or.value();
248
249 // Format the output
250 formatter.BeginObject("Overworld Sprites");
251 formatter.AddField("screen_filter", screen_id_str);
252 formatter.AddField("total_sprites", static_cast<int>(sprites.size()));
253
254 formatter.BeginArray("sprites");
255 for (const auto& sprite : sprites) {
256 formatter.BeginObject();
257 formatter.AddField("sprite_id",
258 absl::StrFormat("0x%02X", sprite.sprite_id));
259 formatter.AddField("map_id", absl::StrFormat("0x%02X", sprite.map_id));
260 formatter.AddField("world", overworld::WorldName(sprite.world));
261 formatter.AddField("position",
262 absl::StrFormat("(%d,%d)", sprite.x, sprite.y));
263
264 if (sprite.sprite_name.has_value()) {
265 formatter.AddField("name", sprite.sprite_name.value());
266 }
267
268 formatter.EndObject();
269 }
270 formatter.EndArray();
271 formatter.EndObject();
272
273 return absl::OkStatus();
274}
275
277 Rom* rom, const resources::ArgumentParser& parser,
278 resources::OutputFormatter& formatter) {
279 auto entrance_id_str = parser.GetString("entrance").value();
280
281 int entrance_id;
282 if (!ParseHexString(entrance_id_str, &entrance_id)) {
283 return absl::InvalidArgumentError(
284 "Invalid entrance ID format. Must be hex.");
285 }
286
287 // Load the Overworld from ROM
288 zelda3::Overworld overworld(rom);
289 auto ow_status = overworld.Load(rom);
290 if (!ow_status.ok()) {
291 return ow_status;
292 }
293
294 // Call the helper function to get entrance details
295 auto details_or = overworld::GetEntranceDetails(overworld, entrance_id);
296 if (!details_or.ok()) {
297 return details_or.status();
298 }
299 const auto& details = details_or.value();
300
301 // Format the output
302 formatter.BeginObject("Overworld Entrance");
303 formatter.AddField("entrance_id",
304 absl::StrFormat("0x%02X", details.entrance_id));
305 formatter.AddField("map_id", absl::StrFormat("0x%02X", details.map_id));
306 formatter.AddField("world", overworld::WorldName(details.world));
307 formatter.AddField("position",
308 absl::StrFormat("(%d,%d)", details.x, details.y));
309 formatter.AddField("area_position", absl::StrFormat("(%d,%d)", details.area_x,
310 details.area_y));
311 formatter.AddField("map_pos", absl::StrFormat("0x%04X", details.map_pos));
312 formatter.AddField("is_hole", details.is_hole);
313
314 if (details.entrance_name.has_value()) {
315 formatter.AddField("name", details.entrance_name.value());
316 }
317
318 formatter.EndObject();
319
320 return absl::OkStatus();
321}
322
324 Rom* rom, const resources::ArgumentParser& parser,
325 resources::OutputFormatter& formatter) {
326 auto screen_id_str = parser.GetString("screen").value_or("all");
327
328 // Load the Overworld from ROM
329 zelda3::Overworld overworld(rom);
330 auto ow_status = overworld.Load(rom);
331 if (!ow_status.ok()) {
332 return ow_status;
333 }
334
335 // TODO: Implement comprehensive tile statistics
336 // The AnalyzeTileUsage helper requires a specific tile_id,
337 // so we need a different approach to gather overall tile statistics.
338 // This could involve:
339 // 1. Iterating through all tiles in the overworld maps
340 // 2. Building a frequency map of tile usage
341 // 3. Computing statistics like unique tiles, most common tiles, etc.
342
343 formatter.BeginObject("Overworld Tile Statistics");
344 formatter.AddField("screen_filter", screen_id_str);
345 formatter.AddField("status", "partial_implementation");
346 formatter.AddField("message",
347 "Comprehensive tile statistics not yet implemented. "
348 "Use overworld-find-tile for specific tile analysis.");
349 formatter.AddField("total_tiles", 0);
350 formatter.AddField("unique_tiles", 0);
351
352 formatter.BeginArray("tile_counts");
353 formatter.EndArray();
354 formatter.EndObject();
355
356 return absl::OkStatus();
357}
358
359} // namespace handlers
360} // namespace cli
361} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
absl::Status Execute(Rom *rom, const resources::ArgumentParser &parser, resources::OutputFormatter &formatter) override
Execute the command business logic.
Utility for parsing common CLI argument patterns.
std::optional< std::string > GetString(const std::string &name) const
Parse a named argument (e.g., –format=json or –format json)
Utility for consistent output formatting across commands.
void BeginArray(const std::string &key)
Begin an array.
void AddArrayItem(const std::string &item)
Add an item to current array.
void BeginObject(const std::string &title="")
Start a JSON object or text section.
void EndObject()
End a JSON object or text section.
void AddField(const std::string &key, const std::string &value)
Add a key-value pair.
Represents the full Overworld data, light and dark world.
Definition overworld.h:217
absl::Status Load(Rom *rom)
Load all overworld data from ROM.
Definition overworld.cc:36
absl::StatusOr< MapSummary > BuildMapSummary(zelda3::Overworld &overworld, int map_id)
absl::StatusOr< std::vector< WarpEntry > > CollectWarpEntries(const zelda3::Overworld &overworld, const WarpQuery &query)
absl::StatusOr< EntranceDetails > GetEntranceDetails(const zelda3::Overworld &overworld, uint8_t entrance_id)
absl::StatusOr< std::vector< OverworldSprite > > CollectOverworldSprites(const zelda3::Overworld &overworld, const SpriteQuery &query)
absl::StatusOr< std::vector< TileMatch > > FindTileMatches(zelda3::Overworld &overworld, uint16_t tile_id, const TileSearchOptions &options)
std::string WarpTypeName(WarpType type)
std::string WorldName(int world)
bool ParseHexString(absl::string_view str, int *out)
Definition hex_util.h:17