3#include "absl/strings/numbers.h"
4#include "absl/strings/str_format.h"
16 auto tile_id_str = parser.
GetString(
"tile").value();
19 if (!absl::SimpleHexAtoi(tile_id_str, &tile_id)) {
20 return absl::InvalidArgumentError(
"Invalid tile ID format. Must be hex.");
25 auto ow_status = overworld.
Load(rom);
26 if (!ow_status.ok()) {
32 if (!matches_or.ok()) {
33 return matches_or.status();
35 const auto& matches = matches_or.value();
39 formatter.
AddField(
"tile_id", absl::StrFormat(
"0x%03X", tile_id));
40 formatter.
AddField(
"matches_found",
static_cast<int>(matches.size()));
43 for (
const auto& match : matches) {
45 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", match.map_id));
47 formatter.
AddField(
"local_x", match.local_x);
48 formatter.
AddField(
"local_y", match.local_y);
49 formatter.
AddField(
"global_x", match.global_x);
50 formatter.
AddField(
"global_y", match.global_y);
56 return absl::OkStatus();
62 auto screen_id_str = parser.
GetString(
"screen").value();
65 if (!absl::SimpleHexAtoi(screen_id_str, &screen_id)) {
66 return absl::InvalidArgumentError(
"Invalid screen ID format. Must be hex.");
71 auto ow_status = overworld.
Load(rom);
72 if (!ow_status.ok()) {
78 if (!summary_or.ok()) {
79 return summary_or.status();
81 const auto& summary = summary_or.value();
85 formatter.
AddField(
"screen_id", absl::StrFormat(
"0x%02X", summary.map_id));
89 formatter.
AddField(
"x", summary.map_x);
90 formatter.
AddField(
"y", summary.map_y);
91 formatter.
AddField(
"local_index", summary.local_index);
95 formatter.
AddField(
"label", summary.area_size);
96 formatter.
AddField(
"is_large", summary.is_large_map);
97 formatter.
AddField(
"parent", absl::StrFormat(
"0x%02X", summary.parent_map));
98 formatter.
AddField(
"quadrant", summary.large_quadrant);
101 formatter.
AddField(
"message_id", absl::StrFormat(
"0x%04X", summary.message_id));
102 formatter.
AddField(
"area_graphics", absl::StrFormat(
"0x%02X", summary.area_graphics));
103 formatter.
AddField(
"area_palette", absl::StrFormat(
"0x%02X", summary.area_palette));
104 formatter.
AddField(
"main_palette", absl::StrFormat(
"0x%02X", summary.main_palette));
105 formatter.
AddField(
"animated_gfx", absl::StrFormat(
"0x%02X", summary.animated_gfx));
106 formatter.
AddField(
"subscreen_overlay", absl::StrFormat(
"0x%04X", summary.subscreen_overlay));
107 formatter.
AddField(
"area_specific_bg_color", absl::StrFormat(
"0x%04X", summary.area_specific_bg_color));
111 for (uint8_t gfx : summary.sprite_graphics) {
117 for (uint8_t pal : summary.sprite_palettes) {
123 for (uint8_t music : summary.area_music) {
124 formatter.
AddArrayItem(absl::StrFormat(
"0x%02X", music));
129 for (uint8_t sgfx : summary.static_graphics) {
130 formatter.
AddArrayItem(absl::StrFormat(
"0x%02X", sgfx));
135 formatter.
AddField(
"enabled", summary.has_overlay);
136 formatter.
AddField(
"id", absl::StrFormat(
"0x%04X", summary.overlay_id));
141 return absl::OkStatus();
147 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
151 auto ow_status = overworld.
Load(rom);
152 if (!ow_status.ok()) {
158 if (screen_id_str !=
"all") {
160 if (!absl::SimpleHexAtoi(screen_id_str, &map_id)) {
161 return absl::InvalidArgumentError(
"Invalid screen ID format. Must be hex.");
168 if (!warps_or.ok()) {
169 return warps_or.status();
171 const auto& warps = warps_or.value();
175 formatter.
AddField(
"screen_filter", screen_id_str);
176 formatter.
AddField(
"total_warps",
static_cast<int>(warps.size()));
179 for (
const auto& warp : warps) {
182 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", warp.map_id));
184 formatter.
AddField(
"position", absl::StrFormat(
"(%d,%d)", warp.pixel_x, warp.pixel_y));
185 formatter.
AddField(
"map_pos", absl::StrFormat(
"0x%04X", warp.map_pos));
187 if (warp.entrance_id.has_value()) {
188 formatter.
AddField(
"entrance_id", absl::StrFormat(
"0x%02X", warp.entrance_id.value()));
190 if (warp.entrance_name.has_value()) {
191 formatter.
AddField(
"entrance_name", warp.entrance_name.value());
193 if (warp.room_id.has_value()) {
194 formatter.
AddField(
"room_id", absl::StrFormat(
"0x%04X", warp.room_id.value()));
197 formatter.
AddField(
"deleted", warp.deleted);
198 formatter.
AddField(
"is_hole", warp.is_hole);
204 return absl::OkStatus();
210 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
214 auto ow_status = overworld.
Load(rom);
215 if (!ow_status.ok()) {
221 if (screen_id_str !=
"all") {
223 if (!absl::SimpleHexAtoi(screen_id_str, &map_id)) {
224 return absl::InvalidArgumentError(
"Invalid screen ID format. Must be hex.");
231 if (!sprites_or.ok()) {
232 return sprites_or.status();
234 const auto& sprites = sprites_or.value();
238 formatter.
AddField(
"screen_filter", screen_id_str);
239 formatter.
AddField(
"total_sprites",
static_cast<int>(sprites.size()));
242 for (
const auto& sprite : sprites) {
244 formatter.
AddField(
"sprite_id", absl::StrFormat(
"0x%02X", sprite.sprite_id));
245 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", sprite.map_id));
247 formatter.
AddField(
"position", absl::StrFormat(
"(%d,%d)", sprite.x, sprite.y));
249 if (sprite.sprite_name.has_value()) {
250 formatter.
AddField(
"name", sprite.sprite_name.value());
258 return absl::OkStatus();
264 auto entrance_id_str = parser.
GetString(
"entrance").value();
267 if (!absl::SimpleHexAtoi(entrance_id_str, &entrance_id)) {
268 return absl::InvalidArgumentError(
269 "Invalid entrance ID format. Must be hex.");
274 auto ow_status = overworld.
Load(rom);
275 if (!ow_status.ok()) {
281 if (!details_or.ok()) {
282 return details_or.status();
284 const auto& details = details_or.value();
288 formatter.
AddField(
"entrance_id", absl::StrFormat(
"0x%02X", details.entrance_id));
289 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", details.map_id));
291 formatter.
AddField(
"position", absl::StrFormat(
"(%d,%d)", details.x, details.y));
292 formatter.
AddField(
"area_position", absl::StrFormat(
"(%d,%d)", details.area_x, details.area_y));
293 formatter.
AddField(
"map_pos", absl::StrFormat(
"0x%04X", details.map_pos));
294 formatter.
AddField(
"is_hole", details.is_hole);
296 if (details.entrance_name.has_value()) {
297 formatter.
AddField(
"name", details.entrance_name.value());
302 return absl::OkStatus();
308 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
312 auto ow_status = overworld.
Load(rom);
313 if (!ow_status.ok()) {
325 formatter.
BeginObject(
"Overworld Tile Statistics");
326 formatter.
AddField(
"screen_filter", screen_id_str);
327 formatter.
AddField(
"status",
"partial_implementation");
329 "Comprehensive tile statistics not yet implemented. "
330 "Use overworld-find-tile for specific tile analysis.");
331 formatter.
AddField(
"total_tiles", 0);
332 formatter.
AddField(
"unique_tiles", 0);
338 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
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)
Represents the full Overworld data, light and dark world.
absl::Status Load(Rom *rom)
Load all overworld data from ROM.
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)
std::optional< int > map_id
std::optional< int > map_id