3#include "absl/strings/str_format.h"
19 auto tile_id_str = parser.
GetString(
"tile").value();
22 if (!ParseHexString(tile_id_str, &tile_id)) {
23 return absl::InvalidArgumentError(
"Invalid tile ID format. Must be hex.");
28 auto ow_status = overworld.
Load(rom);
29 if (!ow_status.ok()) {
35 if (!matches_or.ok()) {
36 return matches_or.status();
38 const auto& matches = matches_or.value();
42 formatter.
AddField(
"tile_id", absl::StrFormat(
"0x%03X", tile_id));
43 formatter.
AddField(
"matches_found",
static_cast<int>(matches.size()));
46 for (
const auto& match : matches) {
48 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", match.map_id));
50 formatter.
AddField(
"local_x", match.local_x);
51 formatter.
AddField(
"local_y", match.local_y);
52 formatter.
AddField(
"global_x", match.global_x);
53 formatter.
AddField(
"global_y", match.global_y);
59 return absl::OkStatus();
65 auto screen_id_str = parser.
GetString(
"screen").value();
68 if (!ParseHexString(screen_id_str, &screen_id)) {
69 return absl::InvalidArgumentError(
"Invalid screen ID format. Must be hex.");
74 auto ow_status = overworld.
Load(rom);
75 if (!ow_status.ok()) {
81 if (!summary_or.ok()) {
82 return summary_or.status();
84 const auto& summary = summary_or.value();
87 formatter.
AddField(
"screen_id", absl::StrFormat(
"0x%02X", summary.map_id));
91 formatter.
AddField(
"x", summary.map_x);
92 formatter.
AddField(
"y", summary.map_y);
93 formatter.
AddField(
"local_index", summary.local_index);
97 formatter.
AddField(
"label", summary.area_size);
98 formatter.
AddField(
"is_large", summary.is_large_map);
99 formatter.
AddField(
"parent", absl::StrFormat(
"0x%02X", summary.parent_map));
100 formatter.
AddField(
"quadrant", summary.large_quadrant);
104 absl::StrFormat(
"0x%04X", summary.message_id));
106 absl::StrFormat(
"0x%02X", summary.area_graphics));
108 absl::StrFormat(
"0x%02X", summary.area_palette));
110 absl::StrFormat(
"0x%02X", summary.main_palette));
112 absl::StrFormat(
"0x%02X", summary.animated_gfx));
113 formatter.
AddField(
"subscreen_overlay",
114 absl::StrFormat(
"0x%04X", summary.subscreen_overlay));
115 formatter.
AddField(
"area_specific_bg_color",
116 absl::StrFormat(
"0x%04X", summary.area_specific_bg_color));
121 if (entrances_or.ok()) {
122 for (
const auto& entrance : entrances_or.value()) {
123 if (entrance.map_id_ == screen_id) {
125 formatter.
AddField(
"entrance_id", entrance.entrance_id_);
126 formatter.
AddField(
"x", entrance.x_);
127 formatter.
AddField(
"y", entrance.y_);
128 formatter.
AddField(
"is_hole",
false);
136 for (
const auto& hole : holes_or.value()) {
137 if (hole.map_id_ == screen_id) {
139 formatter.
AddField(
"entrance_id", hole.entrance_id_);
142 formatter.
AddField(
"is_hole",
true);
153 for (
const auto& exit : exits_or.value()) {
154 if (exit.map_id_ == screen_id) {
156 formatter.
AddField(
"room_id", exit.room_id_);
166 for (uint8_t gfx : summary.sprite_graphics) {
172 for (uint8_t pal : summary.sprite_palettes) {
178 for (uint8_t music : summary.area_music) {
179 formatter.
AddArrayItem(absl::StrFormat(
"0x%02X", music));
184 for (uint8_t sgfx : summary.static_graphics) {
185 formatter.
AddArrayItem(absl::StrFormat(
"0x%02X", sgfx));
190 formatter.
AddField(
"enabled", summary.has_overlay);
191 formatter.
AddField(
"id", absl::StrFormat(
"0x%04X", summary.overlay_id));
196 return absl::OkStatus();
202 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
206 auto ow_status = overworld.
Load(rom);
207 if (!ow_status.ok()) {
213 if (screen_id_str !=
"all") {
215 if (!ParseHexString(screen_id_str, &map_id)) {
216 return absl::InvalidArgumentError(
217 "Invalid screen ID format. Must be hex.");
224 if (!warps_or.ok()) {
225 return warps_or.status();
227 const auto& warps = warps_or.value();
231 formatter.
AddField(
"screen_filter", screen_id_str);
232 formatter.
AddField(
"total_warps",
static_cast<int>(warps.size()));
235 for (
const auto& warp : warps) {
238 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", warp.map_id));
241 absl::StrFormat(
"(%d,%d)", warp.pixel_x, warp.pixel_y));
242 formatter.
AddField(
"map_pos", absl::StrFormat(
"0x%04X", warp.map_pos));
244 if (warp.entrance_id.has_value()) {
246 absl::StrFormat(
"0x%02X", warp.entrance_id.value()));
248 if (warp.entrance_name.has_value()) {
249 formatter.
AddField(
"entrance_name", warp.entrance_name.value());
251 if (warp.room_id.has_value()) {
253 absl::StrFormat(
"0x%04X", warp.room_id.value()));
256 formatter.
AddField(
"deleted", warp.deleted);
257 formatter.
AddField(
"is_hole", warp.is_hole);
263 return absl::OkStatus();
269 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
273 auto ow_status = overworld.
Load(rom);
274 if (!ow_status.ok()) {
280 if (screen_id_str !=
"all") {
282 if (!ParseHexString(screen_id_str, &map_id)) {
283 return absl::InvalidArgumentError(
284 "Invalid screen ID format. Must be hex.");
291 if (!sprites_or.ok()) {
292 return sprites_or.status();
294 const auto& sprites = sprites_or.value();
298 formatter.
AddField(
"screen_filter", screen_id_str);
299 formatter.
AddField(
"total_sprites",
static_cast<int>(sprites.size()));
302 for (
const auto& sprite : sprites) {
305 absl::StrFormat(
"0x%02X", sprite.sprite_id));
306 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", sprite.map_id));
309 absl::StrFormat(
"(%d,%d)", sprite.x, sprite.y));
311 if (sprite.sprite_name.has_value()) {
312 formatter.
AddField(
"name", sprite.sprite_name.value());
320 return absl::OkStatus();
326 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
330 auto ow_status = overworld.
Load(rom);
331 if (!ow_status.ok()) {
336 std::optional<int> map_filter;
337 if (screen_id_str !=
"all") {
339 if (!ParseHexString(screen_id_str, &map_id)) {
340 return absl::InvalidArgumentError(
341 "Invalid screen ID format. Must be hex.");
352 formatter.
AddField(
"screen_filter", screen_id_str);
356 for (
const auto& item : items) {
357 if (map_filter.has_value() &&
358 static_cast<int>(item.room_map_id_) != map_filter.value()) {
362 std::string world_name =
"Unknown";
369 formatter.
AddField(
"item_id", absl::StrFormat(
"0x%02X", item.id_));
371 if (item.id_ < item_names.size()) {
372 formatter.
AddField(
"item_name", item_names[item.id_]);
375 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", item.room_map_id_));
376 formatter.
AddField(
"world", world_name);
378 absl::StrFormat(
"(%d,%d)", item.game_x_, item.game_y_));
380 absl::StrFormat(
"(%d,%d)", item.x_, item.y_));
386 formatter.
AddField(
"total_items", total_items);
389 return absl::OkStatus();
395 auto entrance_id_str = parser.
GetString(
"entrance").value();
398 if (!ParseHexString(entrance_id_str, &entrance_id)) {
399 return absl::InvalidArgumentError(
400 "Invalid entrance ID format. Must be hex.");
405 auto ow_status = overworld.
Load(rom);
406 if (!ow_status.ok()) {
412 if (!details_or.ok()) {
413 return details_or.status();
415 const auto& details = details_or.value();
420 absl::StrFormat(
"0x%02X", details.entrance_id));
421 formatter.
AddField(
"map_id", absl::StrFormat(
"0x%02X", details.map_id));
424 absl::StrFormat(
"(%d,%d)", details.x, details.y));
425 formatter.
AddField(
"area_position", absl::StrFormat(
"(%d,%d)", details.area_x,
427 formatter.
AddField(
"map_pos", absl::StrFormat(
"0x%04X", details.map_pos));
428 formatter.
AddField(
"is_hole", details.is_hole);
430 if (details.entrance_name.has_value()) {
431 formatter.
AddField(
"name", details.entrance_name.value());
436 return absl::OkStatus();
442 auto screen_id_str = parser.
GetString(
"screen").value_or(
"all");
446 auto ow_status = overworld.
Load(rom);
447 if (!ow_status.ok()) {
459 formatter.
BeginObject(
"Overworld Tile Statistics");
460 formatter.
AddField(
"screen_filter", screen_id_str);
461 formatter.
AddField(
"status",
"partial_implementation");
463 "Comprehensive tile statistics not yet implemented. "
464 "Use overworld-find-tile for specific tile analysis.");
465 formatter.
AddField(
"total_tiles", 0);
466 formatter.
AddField(
"unique_tiles", 0);
472 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.
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.
auto overworld_maps() const
#define ASSIGN_OR_RETURN(type_variable_name, expression)
absl::StatusOr< int > InferWorldFromMapId(int map_id)
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)
absl::StatusOr< std::vector< OverworldEntrance > > LoadEntrances(Rom *rom)
absl::StatusOr< std::vector< OverworldItem > > LoadItems(Rom *rom, std::vector< OverworldMap > &overworld_maps)
absl::StatusOr< std::vector< OverworldExit > > LoadExits(Rom *rom)
absl::StatusOr< std::vector< OverworldEntrance > > LoadHoles(Rom *rom)
std::optional< int > map_id
std::optional< int > map_id
static const std::vector< std::string > & GetItemNames()