7#include "absl/strings/str_format.h"
53 if (object_id >= 0x000 && object_id <= 0x00F) {
58 if (object_id == 0x020 || object_id == 0x021 || object_id == 0x022) {
63 if (object_id >= 0x030 && object_id <= 0x03F) {
66 if (object_id >= 0x040 && object_id <= 0x04F) {
71 if (object_id >= 0x138 && object_id <= 0x13B) {
74 if (object_id == 0x12D || object_id == 0x12E) {
79 if (object_id >= 0x0F0 && object_id <= 0x0FF) {
84 if (object_id >= 0x0D4 && object_id <= 0x0DF) {
89 if (object_id >= 0x0E0 && object_id <= 0x0EF) {
94 if (object_id >= 0x100 && object_id <= 0x10F) {
99 if (object_id >= 0x110 && object_id <= 0x11F) {
104 if (object_id >= 0x200 && object_id <= 0x2FF) {
115 if (layer_filter >= 0 &&
static_cast<int>(obj.
layer_) != layer_filter) {
126 for (
int dx = 0; dx < width; ++dx) {
127 int gx = tile_x + dx;
130 if (gx >= 0 && gx < kRoomWidth && gy >= 0 && gy <
kRoomHeight) {
142 const std::vector<zelda3::Room::Door>& doors) {
143 for (
const auto& door : doors) {
144 auto [tile_x, tile_y] = door.GetTileCoords();
147 for (
int dx = 0; dx < 2; ++dx) {
148 int gx = tile_x + dx;
151 if (gx >= 0 && gx < kRoomWidth && gy >= 0 && gy <
kRoomHeight) {
161 const std::vector<staircase>& stairs) {
162 for (
const auto& stair : stairs) {
165 int tile_x = stair.id;
166 int tile_y = stair.room;
168 if (tile_x >= 0 && tile_x < kRoomWidth && tile_y >= 0 &&
178 const std::vector<chest_data>& chests) {
206 if ((tile >= 0xB2 && tile <= 0xB6) || (tile >= 0xBB && tile <= 0xBE)) {
209 if (tile >= 0xD0 && tile <= 0xD3) {
218 if (!map_or.ok() || !map_or.value().has_data) {
222 const auto& map = map_or.value().tiles;
225 uint8_t tile = map[
static_cast<size_t>(y *
kRoomWidth + x)];
245 auto room_id_str = parser.
GetString(
"room").value();
246 auto layer_opt = parser.
GetString(
"layer");
249 if (!ParseHexString(room_id_str, &room_id)) {
250 return absl::InvalidArgumentError(
251 "Invalid room ID format. Must be hex (e.g., 0x07).");
254 int layer_filter = -1;
255 if (layer_opt.has_value()) {
256 if (!ParseHexString(layer_opt.value(), &layer_filter)) {
257 return absl::InvalidArgumentError(
258 "Invalid layer format. Must be 0, 1, or 2.");
260 if (layer_filter < 0 || layer_filter > 2) {
261 return absl::InvalidArgumentError(
"Layer must be 0, 1, or 2.");
269 std::vector<std::string> grid(kRoomHeight, std::string(kRoomWidth, kCharFloor));
272 for (
int x = 0; x < kRoomWidth; ++x) {
273 grid[0][x] = kCharWall;
274 grid[kRoomHeight - 1][x] = kCharWall;
276 for (
int y = 0; y < kRoomHeight; ++y) {
277 grid[y][0] = kCharWall;
278 grid[y][kRoomWidth - 1] = kCharWall;
283 for (
const auto& obj : objects) {
284 PlaceObject(grid, obj, layer_filter);
297 OverlayCustomCollision(grid, rom, room_id);
301 formatter.
AddField(
"room_id", absl::StrFormat(
"0x%02X", room_id));
303 formatter.
AddField(
"width", kRoomWidth);
304 formatter.
AddField(
"height", kRoomHeight);
306 layer_filter >= 0 ? absl::StrFormat(
"%d", layer_filter)
308 formatter.
AddField(
"object_count",
static_cast<int>(objects.size()));
327 formatter.
AddField(
"N/s/E/W",
"stop_tiles");
333 std::string header =
" ";
334 for (
int x = 0; x < kRoomWidth; x += 10) {
335 header += absl::StrFormat(
"%-10d", x);
340 for (
int y = 0; y < kRoomHeight; ++y) {
341 std::string row = absl::StrFormat(
"%2d %s", y, grid[y]);
348 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.
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)
const std::vector< chest_data > & GetChests() const
const std::vector< Door > & GetDoors() const
const std::vector< staircase > & GetStairs() const
const std::vector< RoomObject > & GetTileObjects() const
char ClassifyObject(uint16_t object_id)
constexpr char kCharStopE
constexpr char kCharStopS
constexpr char kCharChest
void PlaceObject(std::vector< std::string > &grid, const zelda3::RoomObject &obj, int layer_filter)
void PlaceDoors(std::vector< std::string > &grid, const std::vector< zelda3::Room::Door > &doors)
constexpr char kCharBlock
constexpr char kCharStopN
constexpr char kCharStair
char ClassifyCustomCollisionTile(uint8_t tile)
void PlaceStairs(std::vector< std::string > &grid, const std::vector< staircase > &stairs)
constexpr char kCharTrackV
constexpr char kCharStopW
constexpr char kCharFloor
constexpr int kRoomHeight
constexpr char kCharTrackH
constexpr char kCharUnknown
void OverlayCustomCollision(std::vector< std::string > &grid, Rom *rom, int room_id)
constexpr char kCharSpike
constexpr char kCharTrackX
constexpr char kCharSwitch
constexpr char kCharTorch
constexpr char kCharWater
void PlaceChests(std::vector< std::string > &grid, const std::vector< chest_data > &chests)
bool ParseHexString(absl::string_view str, int *out)
absl::StatusOr< CustomCollisionMap > LoadCustomCollisionMap(Rom *rom, int room_id)
Room LoadRoomFromRom(Rom *rom, int room_id)
constexpr std::array< std::string_view, 297 > kRoomNames