1#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_OBJECT_H
2#define YAZE_APP_ZELDA3_DUNGEON_ROOM_OBJECT_H
8#include "absl/status/status.h"
9#include "absl/strings/str_format.h"
89 uint8_t
x()
const {
return x_; }
90 uint8_t
y()
const {
return y_; }
101 const std::vector<gfx::TileInfo>&
tiles()
const {
111 absl::StatusOr<std::span<const gfx::TileInfo>>
GetTiles()
const;
114 absl::StatusOr<const gfx::TileInfo*>
GetTile(
int index)
const;
221 mutable std::vector<gfx::TileInfo>
tiles_;
270 return object_id == 0xF99 || object_id == 0xFB1;
287 uint8_t list_index) {
288 if (list_index > 2) {
291 if (list_index == 1) {
302constexpr static inline const char* Type1RoomObjectNames[] = {
304 "Wall (top, north) ↔",
305 "Wall (top, south) ↔",
306 "Wall (bottom, north) ↔",
307 "Wall (bottom, south) ↔",
308 "Wall columns (north) ↔",
309 "Wall columns (south) ↔",
310 "Deep wall (north) ↔",
311 "Deep wall (south) ↔",
312 "Diagonal wall A ◤ (top) ↔",
313 "Diagonal wall A ◣ (top) ↔",
314 "Diagonal wall A ◥ (top) ↔",
315 "Diagonal wall A ◢ (top) ↔",
316 "Diagonal wall B ◤ (top) ↔",
317 "Diagonal wall B ◣ (top) ↔",
318 "Diagonal wall B ◥ (top) ↔",
319 "Diagonal wall B ◢ (top) ↔",
320 "Diagonal wall C ◤ (top) ↔",
321 "Diagonal wall C ◣ (top) ↔",
322 "Diagonal wall C ◥ (top) ↔",
323 "Diagonal wall C ◢ (top) ↔",
324 "Diagonal wall A ◤ (bottom) ↔",
325 "Diagonal wall A ◣ (bottom) ↔",
326 "Diagonal wall A ◥ (bottom) ↔",
327 "Diagonal wall A ◢ (bottom) ↔",
328 "Diagonal wall B ◤ (bottom) ↔",
329 "Diagonal wall B ◣ (bottom) ↔",
330 "Diagonal wall B ◥ (bottom) ↔",
331 "Diagonal wall B ◢ (bottom) ↔",
332 "Diagonal wall C ◤ (bottom) ↔",
333 "Diagonal wall C ◣ (bottom) ↔",
334 "Diagonal wall C ◥ (bottom) ↔",
335 "Diagonal wall C ◢ (bottom) ↔",
338 "Pit edge ┏━┓ A (north) ↔",
339 "Pit edge ┏━┓ B (north) ↔",
340 "Pit edge ┏━┓ C (north) ↔",
341 "Pit edge ┏━┓ D (north) ↔",
342 "Pit edge ┏━┓ E (north) ↔",
343 "Pit edge ┗━┛ (south) ↔",
344 "Pit edge ━━━ (south) ↔",
345 "Pit edge ━━━ (north) ↔",
346 "Pit edge ━━┛ (south) ↔",
347 "Pit edge ┗━━ (south) ↔",
348 "Pit edge ━━┓ (north) ↔",
349 "Pit edge ┏━━ (north) ↔",
350 "Rail wall (north) ↔",
351 "Rail wall (south) ↔",
358 "Drapes (west, odd) ↔",
361 "Wall decors (north) ↔",
362 "Wall decors (south) ↔",
365 "Supports (north) ↔",
366 "Water edge ┏━┓ (concave) ↔",
367 "Water edge ┗━┛ (concave) ↔",
368 "Water edge ┏━┓ (convex) ↔",
369 "Water edge ┗━┛ (convex) ↔",
370 "Water edge ┏━┛ (concave) ↔",
371 "Water edge ┗━┓ (concave) ↔",
372 "Water edge ┗━┓ (convex) ↔",
373 "Water edge ┏━┛ (convex) ↔",
376 "Floor tiles 4x2 A ↔",
377 "Floor tiles 4x2 B ↔",
378 "Supports (south) ↔",
384 "Cannon hole A (north) ↔",
385 "Cannon hole A (south) ↔",
388 "Wall torches (north) ↔",
389 "Wall torches (south) ↔",
394 "Cannon hole B (north) ↔",
395 "Cannon hole B (south) ↔",
400 "Wall (top, west) ↕",
401 "Wall (top, east) ↕",
402 "Wall (bottom, west) ↕",
403 "Wall (bottom, east) ↕",
404 "Wall columns (west) ↕",
405 "Wall columns (east) ↕",
406 "Deep wall (west) ↕",
407 "Deep wall (east) ↕",
411 "Rail wall (west) ↕",
412 "Rail wall (east) ↕",
421 "Wall decors (west) ↕",
422 "Wall decors (east) ↕",
424 "Water edge (west) ↕",
425 "Water edge (east) ↕",
430 "Wall torches (west) ↕",
431 "Wall torches (east) ↕",
432 "Wall decors tight A (west) ↕",
433 "Wall decors tight A (east) ↕",
434 "Wall decors tight B (west) ↕",
435 "Wall decors tight B (east) ↕",
436 "Cannon hole (west) ↕",
437 "Cannon hole (east) ↕",
442 "Jump ledge (west) ↕",
443 "Jump ledge (east) ↕",
447 "Wall flair (west) ↕",
448 "Wall flair (east) ↕",
463 "Diagonal ceiling A ◤",
464 "Diagonal ceiling A ◣",
465 "Diagonal ceiling A ◥",
466 "Diagonal ceiling A ◢",
468 "Diagonal layer 2 mask A ◤",
469 "Diagonal layer 2 mask A ◣",
470 "Diagonal layer 2 mask A ◥",
471 "Diagonal layer 2 mask A ◢",
472 "Diagonal layer 2 mask B ◤",
473 "Diagonal layer 2 mask B ◣",
474 "Diagonal layer 2 mask B ◥",
475 "Diagonal layer 2 mask B ◢",
479 "Jump ledge (north) ↔",
480 "Jump ledge (south) ↔",
482 "Rug trim (north) ↔",
483 "Rug trim (south) ↔",
484 "Archery game curtains ↔",
485 "Wall flair (north) ↔",
486 "Wall flair (south) ↔",
490 "Fake pressure plates ↔",
496 "Chest platform (tall) ⇲",
497 "Layer 2 pit mask (large) ⇲",
498 "Layer 2 pit mask (medium) ⇲",
501 "Layer 2 mask (large) ⇲",
504 "Flood water (medium) ⇲ ",
508 "Moving wall (west) ⇲",
509 "Moving wall (east) ⇲",
514 "Wall moved check A (logic)",
515 "Wall moved check B (logic)",
516 "Wall moved check C (logic)",
517 "Wall moved check D (logic)",
518 "Layer 2 mask (medium) ⇲",
519 "Flood water (large) ⇲",
520 "Layer 2 swim mask ⇲",
521 "Flood water B (large) ⇲",
523 "Chest platform (short) ⇲",
530 "Conveyor upwards ⇲",
531 "Conveyor downwards ⇲",
532 "Conveyor leftwards ⇲",
533 "Conveyor rightwards ⇲",
534 "Heavy current water ⇲",
553constexpr static inline const char* Type2RoomObjectNames[] = {
554 "Corner (top, concave) ▛",
555 "Corner (top, concave) ▙",
556 "Corner (top, concave) ▜",
557 "Corner (top, concave) ▟",
558 "Corner (top, convex) ▟",
559 "Corner (top, convex) ▜",
560 "Corner (top, convex) ▙",
561 "Corner (top, convex) ▛",
562 "Corner (bottom, concave) ▛",
563 "Corner (bottom, concave) ▙",
564 "Corner (bottom, concave) ▜",
565 "Corner (bottom, concave) ▟",
566 "Corner (bottom, convex) ▟",
567 "Corner (bottom, convex) ▜",
568 "Corner (bottom, convex) ▙",
569 "Corner (bottom, convex) ▛",
570 "Kinked corner north (bottom) ▜",
571 "Kinked corner south (bottom) ▟",
572 "Kinked corner north (bottom) ▛",
573 "Kinked corner south (bottom) ▙",
574 "Kinked corner west (bottom) ▙",
575 "Kinked corner west (bottom) ▛",
576 "Kinked corner east (bottom) ▟",
577 "Kinked corner east (bottom) ▜",
578 "Deep corner (concave) ▛",
579 "Deep corner (concave) ▙",
580 "Deep corner (concave) ▜",
581 "Deep corner (concave) ▟",
584 "Star tile (disabled)",
585 "Star tile (enabled)",
597 "Rightwards 2x2 decor",
598 "Rightwards 6x3 decor",
599 "Interroom stairs (up)",
600 "Interroom stairs (down)",
601 "Interroom stairs B (down)",
602 "Intraroom stairs north B",
603 "Intraroom stairs north (separate layers)",
604 "Intraroom stairs north (merged layers)",
605 "Intraroom stairs north (swim layer)",
607 "Water-hop stairs A",
608 "Water-hop stairs B",
610 "Interroom spiral stairs up (top)",
611 "Interroom spiral stairs down (top)",
612 "Interroom spiral stairs up (bottom)",
613 "Interroom spiral stairs down (bottom)",
614 "Sanctuary wall (north)",
615 "Sanctuary pew (right end)",
620constexpr static inline const char* Type3RoomObjectNames[] = {
621 "Waterfall face (empty)",
622 "Waterfall face (short)",
623 "Waterfall face (long)",
624 "Somaria path endpoint",
625 "Somaria path intersection ╋",
626 "Somaria path corner ┏",
627 "Somaria path corner ┗",
628 "Somaria path corner ┓",
629 "Somaria path corner ┛",
630 "Somaria path intersection ┳",
631 "Somaria path intersection ┻",
632 "Somaria path intersection ┣",
633 "Somaria path intersection ┫",
634 "Prison cell bars (alt)",
635 "Somaria path 2-way endpoint",
636 "Somaria path crossover",
637 "Babasu hole (north)",
638 "Babasu hole (south)",
641 "Unused / Warp door",
642 "Kholdstare's shell",
648 "Intraroom stairs south",
649 "Intraroom stairs south (separate layers)",
650 "Intraroom stairs south (merged layers)",
651 "Interroom straight stairs up (north, top)",
652 "Interroom straight stairs down (north, top)",
653 "Interroom straight stairs up (south, top)",
654 "Interroom straight stairs down (south, top)",
655 "Deep corner (convex) ▟",
656 "Deep corner (convex) ▜",
657 "Deep corner (convex) ▙",
658 "Deep corner (convex) ▛",
659 "Interroom straight stairs up (north, bottom)",
660 "Interroom straight stairs down (north, bottom)",
661 "Interroom straight stairs up (south, bottom)",
662 "Interroom straight stairs down (south, bottom)",
664 "Single 2x2 decor A",
665 "Liftable large block",
667 "Agahnim's boss room",
669 "Single 2x2 decor B",
672 "Intraroom stairs south (swim layer)",
673 "Intraroom stairs south (long)",
687 "Pipe-rock intersection ⯊",
688 "Pipe-rock intersection ⯋",
689 "Pipe-rock intersection ◖",
690 "Pipe-rock intersection ◗",
693 "Fake bombable floor",
694 "Single 2x2 decor C",
700 "Warp tile (disabled)",
702 "Single 2x2 decor D",
705 "Fortune teller room",
717 "Arrow game hole (west)",
718 "Arrow game hole (east)",
720 "Fake pressure plate",
722 "4-way shooter block",
724 "Wall crack (north)",
725 "Wall crack (south)",
729 "Water grate (north)",
730 "Water grate (south)",
731 "Water grate (west)",
732 "Water grate (east)",
736 "Layer 2 mask (full)",
740 "Triforce wall ornament",
741 "Triforce floor tiles",
744 "Vitreous goo damage",
754 if (object_id < 0x100) {
756 constexpr size_t kType1Count =
757 sizeof(Type1RoomObjectNames) /
sizeof(Type1RoomObjectNames[0]);
758 if (object_id >= 0 && object_id <
static_cast<int>(kType1Count)) {
759 return Type1RoomObjectNames[object_id];
761 return absl::StrFormat(
"Unknown Type1 (0x%02X)", object_id);
762 }
else if (object_id >= 0x100 && object_id < 0x200) {
764 int idx = object_id - 0x100;
765 constexpr size_t kType2Count =
766 sizeof(Type2RoomObjectNames) /
sizeof(Type2RoomObjectNames[0]);
767 if (idx >= 0 && idx <
static_cast<int>(kType2Count)) {
768 return Type2RoomObjectNames[idx];
770 return absl::StrFormat(
"Unknown Type2 (0x%03X)", object_id);
771 }
else if (object_id >= 0xF80) {
773 int idx = object_id - 0xF80;
774 constexpr size_t kType3Count =
775 sizeof(Type3RoomObjectNames) /
sizeof(Type3RoomObjectNames[0]);
776 if (idx >= 0 && idx <
static_cast<int>(kType3Count)) {
777 return Type3RoomObjectNames[idx];
779 return absl::StrFormat(
"Unknown Type3 (0x%03X)", object_id);
781 return absl::StrFormat(
"Unknown (0x%03X)", object_id);
786 if (object_id < 0x100)
788 if (object_id < 0x200)
790 if (object_id >= 0xF80)
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
absl::StatusOr< const gfx::TileInfo * > GetTile(int index) const
static RoomObject DecodeObjectFromBytes(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t layer)
std::vector< uint8_t > preview_object_data_
std::vector< gfx::TileInfo > tiles_
uint8_t torch_reserved_bit_
void set_size(uint8_t size)
std::vector< gfx::TileInfo > & mutable_tiles()
uint8_t block_behavior_layer_
bool IsTrackedTileCacheCurrent() const
ObjectBytes EncodeObjectToBytes() const
const std::vector< gfx::TileInfo > & tiles() const
uint64_t tile_cache_revision_
void RefreshDerivedFlagsFromId()
void MarkTileCacheCurrent()
void MarkTileCacheUntracked()
static int DetermineObjectType(uint8_t b1, uint8_t b3)
absl::Status LoadTilesWithParser()
void set_block_behavior_layer(uint8_t layer)
int block_load_order() const
static constexpr int kBlockLoadOrderNew
void set_torch_reserved_bit(uint8_t reserved)
absl::StatusOr< std::span< const gfx::TileInfo > > GetTiles() const
uint8_t block_behavior_layer() const
const Rom * tile_cache_rom_identity_
void InvalidateTileCache()
RoomObject(int16_t id, uint8_t x, uint8_t y, uint8_t size, uint8_t layer=0)
uint8_t GetLayerValue() const
void set_block_load_order(int order)
uint8_t torch_reserved_bit() const
RoomObject CopyForNewPlacement() const
void set_options(ObjectOption options)
uint8_t DefaultRoomObjectSizeForPlacement(int object_id)
bool IsRoomObjectSizeEditable(int object_id)
constexpr int kRoomObjectSubtype3
RoomObject::LayerType MapRoomObjectListIndexToDrawLayer(uint8_t list_index)
ObjectOption operator|(ObjectOption lhs, ObjectOption rhs)
int GetObjectSubtype(int object_id)
ObjectOption operator^(ObjectOption lhs, ObjectOption rhs)
uint8_t CanonicalRoomObjectSize(int object_id, uint8_t requested_size)
constexpr int kRoomObjectSubtype1
constexpr int kRoomObjectSubtype2
constexpr int kRoomObjectTileAddress
ObjectOption operator~(ObjectOption option)
std::string GetObjectName(int object_id)
constexpr bool IsStatefulChestObjectId(int object_id)
ObjectOption operator&(ObjectOption lhs, ObjectOption rhs)
absl::Status ValidateRoomObjectStreamEntryForSave(const RoomObject &object)
constexpr int kRoomObjectTileAddressFloor