yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
room.h
Go to the documentation of this file.
1#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_H
2#define YAZE_APP_ZELDA3_DUNGEON_ROOM_H
3
4#include <yaze.h>
6
7#include <array>
8#include <cstdint>
9#include <functional>
10#include <map>
11#include <memory>
12#include <optional>
13#include <string_view>
14#include <tuple>
15#include <utility>
16#include <vector>
17
18#include "absl/status/statusor.h"
19#include "absl/types/span.h"
21
23#include "rom/rom.h"
34#include "zelda3/game_data.h"
36
37namespace yaze {
38namespace zelda3 {
39
40class DungeonState;
41class Room;
42class RoomLayerManager;
43struct DungeonStreamLayout;
44
45std::vector<SDL_Color> BuildDungeonRenderPalette(
46 const gfx::SnesPalette& dungeon_palette,
47 const gfx::SnesPalette* hud_palette = nullptr,
48 PaletteAddressMap* addresses = nullptr, int palette_id = 0);
49
50// Builds the same eight CGRAM rows as BuildDungeonRenderPalette, but keeps
51// them grouped for tools whose tile renderer indexes colors as
52// pixel + (tile_palette * 16).
53gfx::PaletteGroup BuildDungeonRenderPaletteGroup(
54 const gfx::SnesPalette& dungeon_palette,
55 const gfx::SnesPalette* hud_palette = nullptr);
56
57// Builds the editor-facing dungeon render group and resolves its HUD rows from
58// GameData. A null GameData, or one without HUD palettes, leaves those rows
59// blank while preserving the canonical dungeon rows.
61 const gfx::SnesPalette& dungeon_palette, const GameData* game_data);
62
63// Builds the sprite half of the underworld CGRAM palette for editor previews.
64// Room palette-set slots select row 8 left and rows 13/14 left. The inherited
65// Light World environment fallback occupies row 8 right, while the standard
66// underworld environment palette occupies row 14 right. Missing or invalid
67// palette selectors fall back to palette 0 in the corresponding ROM group.
68std::array<SDL_Color, 256> BuildDungeonSpriteRenderPalette(
69 const Room& room, const GameData* game_data);
70
72 std::span<uint16_t> cgram, const gfx::SnesPalette& dungeon_palette,
73 const gfx::SnesPalette* hud_palette = nullptr);
74
75// ROM addresses defined in dungeon_rom_addresses.h (use kPrefixed names)
76
78 uint8_t ID;
79 std::string Name;
83 LayerMergeType() = default;
84 LayerMergeType(uint8_t id, std::string name, bool see, bool top, bool trans) {
85 ID = id;
86 Name = name;
87 Layer2OnTop = top;
88 Layer2Translucent = trans;
89 Layer2Visible = see;
90 }
91 bool operator==(const LayerMergeType&) const = default;
92};
93
94// LayerMergeType(id, name, Layer2Visible, Layer2OnTop, Layer2Translucent)
95//
96// SNES Mode 1 Layer Priority: BG1 is ALWAYS rendered on top of BG2 by default.
97// The flags control COLOR MATH effects, not Z-order:
98// - Layer2Visible: Whether BG2 is enabled on main screen
99// - Layer2OnTop: Whether BG2 participates in sub-screen color math effects
100// (transparency, additive blending) - does NOT change draw order
101// - Layer2Translucent: Whether color math creates transparency effect
102const static LayerMergeType LayerMerge00{0x00, "Off", true, false, false};
103const static LayerMergeType LayerMerge01{0x01, "Parallax", true, false, false};
104const static LayerMergeType LayerMerge02{0x02, "Dark", true, true, true};
105const static LayerMergeType LayerMerge03{0x03, "On top", false, true, false};
106const static LayerMergeType LayerMerge04{0x04, "Translucent", true, true, true};
107const static LayerMergeType LayerMerge05{0x05, "Addition", true, true, true};
108const static LayerMergeType LayerMerge06{0x06, "Normal", true, false, false};
109const static LayerMergeType LayerMerge07{0x07, "Transparent", true, true, true};
110const static LayerMergeType LayerMerge08{0x08, "Dark room", true, true, true};
111
112const static LayerMergeType kLayerMergeTypeList[] = {
113 LayerMerge00, LayerMerge01, LayerMerge02, LayerMerge03, LayerMerge04,
114 LayerMerge05, LayerMerge06, LayerMerge07, LayerMerge08};
115
116// Fixed byte storage keeps unnamed ROM values representable for lossless
117// load/save and undo. Authoring controls validate their supported subset.
125
136
137// Pot item - items hidden under pots, rocks, skulls etc.
138// Each item has its own position from ROM data
139struct PotItem {
140 uint16_t position = 0; // Raw position word from ROM
141 uint8_t item = 0; // Item type (0 = nothing)
142
143 // Coordinates occupy bits 1..12; layer/control bits do not affect pixels.
144 int GetPixelX() const { return PotItemPixelX(position); }
145 int GetPixelY() const { return PotItemPixelY(position); }
146
147 // Get tile coordinates (8-pixel tiles)
148 int GetTileX() const { return GetPixelX() / 8; }
149 int GetTileY() const { return GetPixelY() / 8; }
150};
151
152enum TagKey : uint8_t {
218
219// Editor-authored water fill zones (Oracle of Secrets).
220// Stored as a 64x64 boolean map (0/1 per 8x8 tile). At runtime, the hack
221// consumes a compact offset list derived from these tiles.
223 std::array<uint8_t, 64 * 64> tiles{};
224 bool has_data = false;
225 uint8_t sram_bit_mask = 0; // Bit in $7EF411 (e.g. 0x01)
226};
227
228class Room {
229 public:
230 // Authoring state only: restoring metadata never replaces entity collections,
231 // room load state, ROM bytes, or dirty flags for unrelated save domains.
233 uint8_t palette = 0;
234 uint8_t blockset = 0;
235 uint8_t spriteset = 0;
236 uint8_t layout = 0;
237 uint8_t floor1 = 0;
238 uint8_t floor2 = 0;
239 uint16_t message = 0;
241 uint8_t layer2_mode = 0;
243 bool is_dark = false;
244 bool is_light = false;
249 uint8_t holewarp = 0;
250 uint8_t pit_target_layer = 0;
251 std::array<uint8_t, 4> staircase_rooms{};
252 std::array<uint8_t, 4> staircase_planes{};
253
254 bool operator==(const MetadataSnapshot&) const = default;
255 };
256
258 void RestoreMetadataSnapshot(const MetadataSnapshot& snapshot);
259
265
266 bool header = false;
267 bool object_stream = false;
269 bool sprites = false;
270 bool chests = false;
271 bool pot_items = false;
272 bool torches = false;
273 bool blocks = false;
274 bool custom_collision = false;
275 bool water_fill = false;
277 std::vector<BlockLoadOrder> block_load_orders;
278 };
279
281 Room(int room_id, Rom* rom, GameData* game_data = nullptr);
283
284 // Move-only type due to unique_ptr
287 Room(const Room&) = delete;
288 Room& operator=(const Room&) = delete;
289
290 void LoadRoomGraphics(
291 std::optional<uint8_t> entrance_blockset = std::nullopt);
293 const Room& room, const GraphicsContextIdentity& identity);
295 // LoadGraphicsSheetsIntoArena() removed - per-room graphics instead
296 void RenderRoomGraphics();
299 void LoadObjects();
300 void EnsureObjectsLoaded();
301 void LoadSprites();
302 void EnsureSpritesLoaded();
303 void LoadChests();
304 void LoadPotItems();
306 void LoadDoors();
307 void LoadTorches();
308 void LoadBlocks();
309 void LoadPits();
311 void ReloadGraphics(std::optional<uint8_t> entrance_blockset = std::nullopt);
312 void PrepareForRender(
313 std::optional<uint8_t> entrance_blockset = std::nullopt);
314
315 // Public getters and manipulators for sprites
316 const std::vector<zelda3::Sprite>& GetSprites() const { return sprites_; }
317 std::vector<zelda3::Sprite>& GetSprites() { return sprites_; }
318 bool sprites_dirty() const { return save_dirty_state_.sprites; }
321
322 // Public getters and manipulators for chests
323 const std::vector<chest_data>& GetChests() const { return chests_in_room_; }
324 std::vector<chest_data>& GetChests() { return chests_in_room_; }
325 bool chests_dirty() const { return save_dirty_state_.chests; }
328
329 // Public getters and manipulators for stairs
330 const std::vector<staircase>& GetStairs() const { return z3_staircases_; }
331 std::vector<staircase>& GetStairs() { return z3_staircases_; }
332
339 struct Door {
340 uint8_t position;
343
344 uint8_t byte1;
345 uint8_t byte2;
346
348 std::pair<int, int> GetTileCoords() const {
350 }
351
353 std::pair<int, int> GetPixelCoords() const {
355 }
356
361
366
368 std::tuple<int, int, int, int> GetBounds() const {
370 }
371
373 std::tuple<int, int, int, int> GetEditorBounds() const {
375 type);
376 }
377
379 std::string_view GetTypeName() const {
381 }
382
384 std::string_view GetDirectionName() const {
386 }
387
389 std::pair<uint8_t, uint8_t> EncodeBytes() const {
391 }
392
397 static Door FromRomBytes(uint8_t b1, uint8_t b2) {
398 Door door;
399 door.byte1 = b1;
400 door.byte2 = b2;
401 // Position index is in bits 4-7 of b1
402 // ASM does: (b1 & 0xF0) >> 3 which gives index * 2 for table lookup
403 // We store the raw index (0-15, typically 0-5)
404 door.position = (b1 >> 4) & 0x0F;
405 // Direction is in bits 0-1 of b1
406 door.direction = DoorDirectionFromRaw(b1 & 0x03);
407 // Door type is the full second byte
408 door.type = DoorTypeFromRaw(b2);
409 return door;
410 }
411 };
412
413 const std::vector<Door>& GetDoors() const { return doors_; }
414 std::vector<Door>& GetDoors() { return doors_; }
415 void AddDoor(const Door& door) {
416 doors_.push_back(door);
417 objects_loaded_ = true;
419 }
420 void RemoveDoor(size_t index) {
421 if (index < doors_.size()) {
422 doors_.erase(doors_.begin() + index);
423 objects_loaded_ = true;
425 }
426 }
427
428 // Public getters for pot items (items hidden under pots/bushes)
429 const std::vector<PotItem>& GetPotItems() const { return pot_items_; }
430 std::vector<PotItem>& GetPotItems() { return pot_items_; }
434
435 bool torches_dirty() const { return save_dirty_state_.torches; }
438 bool blocks_dirty() const { return save_dirty_state_.blocks; }
441
442 const RoomLayout& GetLayout() const { return layout_; }
443
444 // Public getters and manipulators for tile objects
445 const std::vector<RoomObject>& GetTileObjects() const {
446 return tile_objects_;
447 }
448 std::vector<RoomObject>& GetTileObjects() { return tile_objects_; }
449
450 // Methods for modifying tile objects
457 void AddTileObject(const RoomObject& object) {
458 tile_objects_.push_back(object);
459 objects_loaded_ = true;
461 }
462
463 // Enhanced object manipulation (Phase 3)
464 absl::Status AddObject(const RoomObject& object);
465 absl::Status RemoveObject(size_t index);
466 absl::Status UpdateObject(size_t index, const RoomObject& object);
467 absl::StatusOr<size_t> FindObjectAt(int x, int y, int layer) const;
468 bool ValidateObject(const RoomObject& object) const;
469
470 // Performance optimization: Mark objects as dirty when modified
472 dirty_state_.objects = true;
473 dirty_state_.textures = true;
475 }
481 bool is_special_table_object = false;
482 if ((object.options() & ObjectOption::Torch) != ObjectOption::Nothing) {
484 is_special_table_object = true;
485 }
486 if ((object.options() & ObjectOption::Block) != ObjectOption::Nothing) {
488 is_special_table_object = true;
489 }
490 if (!is_special_table_object) {
492 }
494 }
496 const std::vector<RoomObject>& objects) {
497 for (const auto& object : objects) {
499 }
500 }
513 dirty_state_.graphics = true;
514 dirty_state_.textures = true;
516 }
518 dirty_state_.layout = true;
519 dirty_state_.textures = true;
521 }
522 void RemoveTileObject(size_t index) {
523 if (index < tile_objects_.size()) {
525 tile_objects_.erase(tile_objects_.begin() + index);
526 objects_loaded_ = true;
528 }
529 }
530 size_t GetTileObjectCount() const { return tile_objects_.size(); }
531 RoomObject& GetTileObject(size_t index) { return tile_objects_[index]; }
532 const RoomObject& GetTileObject(size_t index) const {
533 return tile_objects_[index];
534 }
535
536 // =========================================================================
537 // Object Limit Tracking (ZScream Feature Parity)
538 // =========================================================================
539
546 std::map<DungeonLimit, int> GetLimitedObjectCounts() const;
547
551 bool HasExceededLimits() const;
552
556 std::vector<DungeonLimitInfo> GetExceededLimitDetails() const;
557
558 // Custom Collision access
560 return custom_collision_;
561 }
565 if (custom_collision_.has_data != has) {
568 }
569 }
570
571 uint8_t GetCollisionTile(int x, int y) const {
572 if (x < 0 || x >= 64 || y < 0 || y >= 64)
573 return 0;
574 return custom_collision_.tiles[y * 64 + x];
575 }
576
577 bool HasCollisionOverride(int x, int y) const {
578 return x >= 0 && x < 64 && y >= 0 && y < 64 &&
579 custom_collision_.HasOverride(y * 64 + x);
580 }
581
582 void SetCollisionTile(int x, int y, uint8_t tile) {
583 if (x < 0 || x >= 64 || y < 0 || y >= 64)
584 return;
585 custom_collision_.SetOverride(y * 64 + x, tile);
587 }
588
589 void ClearCollisionTile(int x, int y) {
590 if (x < 0 || x >= 64 || y < 0 || y >= 64)
591 return;
594 }
595
599
600 // Water fill zones (Oracle of Secrets)
604
605 bool GetWaterFillTile(int x, int y) const {
606 if (x < 0 || x >= 64 || y < 0 || y >= 64)
607 return false;
608 return water_fill_zone_.tiles[y * 64 + x] != 0;
609 }
610
611 void SetWaterFillTile(int x, int y, bool filled) {
612 if (x < 0 || x >= 64 || y < 0 || y >= 64)
613 return;
614 const uint8_t val = filled ? 1 : 0;
615 const size_t idx = static_cast<size_t>(y * 64 + x);
616 const uint8_t prev = water_fill_zone_.tiles[idx];
617 if (prev == val)
618 return;
619 water_fill_zone_.tiles[idx] = val;
620 if (val) {
623 } else {
624 if (water_fill_tile_count_ > 0) {
626 }
627 if (water_fill_tile_count_ == 0) {
629 }
630 }
631 water_fill_dirty_ = true;
632 }
633
641
643
644 uint8_t water_fill_sram_bit_mask() const {
646 }
647 void set_water_fill_sram_bit_mask(uint8_t mask) {
648 if (water_fill_zone_.sram_bit_mask != mask) {
650 water_fill_dirty_ = true;
651 }
652 }
653
654 bool water_fill_dirty() const { return water_fill_dirty_; }
657
658 bool header_dirty() const { return save_dirty_state_.header; }
661
670
672
674 SaveDirtySnapshot snapshot{
676 .object_stream = save_dirty_state_.object_stream,
677 .object_stream_header = save_dirty_state_.object_stream_header,
678 .sprites = save_dirty_state_.sprites,
679 .chests = save_dirty_state_.chests,
680 .pot_items = save_dirty_state_.pot_items,
681 .torches = save_dirty_state_.torches,
682 .blocks = save_dirty_state_.blocks,
683 .custom_collision = custom_collision_dirty_,
684 .water_fill = water_fill_dirty_,
685 .water_fill_sram_bit_mask = water_fill_zone_.sram_bit_mask,
686 };
687 for (size_t index = 0; index < tile_objects_.size(); ++index) {
688 const auto& object = tile_objects_[index];
689 if ((object.options() & ObjectOption::Block) != ObjectOption::Nothing) {
690 snapshot.block_load_orders.push_back(
691 {.tile_object_index = index,
692 .load_order = object.block_load_order()});
693 }
694 }
695 return snapshot;
696 }
697
708 water_fill_dirty_ = snapshot.water_fill;
710 for (const auto& block : snapshot.block_load_orders) {
711 if (block.tile_object_index >= tile_objects_.size())
712 continue;
713 auto& object = tile_objects_[block.tile_object_index];
714 if ((object.options() & ObjectOption::Block) != ObjectOption::Nothing) {
715 object.set_block_load_order(block.load_order);
716 }
717 }
718 }
719
720 // For undo/redo functionality
721 void SetTileObjects(const std::vector<RoomObject>& objects) {
723 tile_objects_ = objects;
724 objects_loaded_ = true;
727 }
728
729 // Public setters for LoadRoomFromRom function
731 const uint8_t raw_value = static_cast<uint8_t>(bg2);
732 const uint8_t normalized_value = raw_value <= 8 ? raw_value : 0;
733 const bool dark_room = normalized_value == 8;
734 const uint8_t next_layer2_mode =
735 dark_room ? static_cast<uint8_t>(layer2_mode_ & 0x07)
736 : normalized_value;
737 const LayerMergeType& next_merge =
738 kLayerMergeTypeList[dark_room ? 8 : next_layer2_mode];
739 const background2 normalized_bg2 =
740 static_cast<background2>(normalized_value);
741
742 if (bg2_ != normalized_bg2 || layer2_mode_ != next_layer2_mode ||
743 layer_merging_ != next_merge || is_dark_ != dark_room ||
744 is_light_ != dark_room) {
745 bg2_ = normalized_bg2;
746 layer2_mode_ = next_layer2_mode;
747 layer_merging_ = next_merge;
748 is_dark_ = dark_room;
749 is_light_ = dark_room;
752 }
753 }
760 void SetIsLight(bool is_light) {
761 if (is_light_ != is_light) {
762 is_light_ = is_light;
764 }
765 }
766 void SetPalette(uint8_t pal) {
767 if (palette_ != pal) {
768 palette_ = pal;
771 }
772 }
773 void SetBlockset(uint8_t bs) {
774 if (blockset_ != bs) {
775 blockset_ = bs;
779 }
780 }
781 void SetSpriteset(uint8_t ss) {
782 if (spriteset_ != ss) {
783 spriteset_ = ss;
786 }
787 }
788 void SetRenderEntranceBlockset(uint8_t entrance_blockset) {
789 if (render_entrance_blockset_ != entrance_blockset) {
790 render_entrance_blockset_ = entrance_blockset;
793 }
794 }
796 if (effect_ != effect) {
797 effect_ = effect;
800 }
801 }
803 if (tag1_ != tag1) {
804 tag1_ = tag1;
807 }
808 }
810 if (tag2_ != tag2) {
811 tag2_ = tag2;
814 }
815 }
816 void SetStaircasePlane(int index, uint8_t plane) {
817 if (index >= 0 && index < 4 && staircase_plane_[index] != plane) {
818 staircase_plane_[index] = plane;
820 }
821 }
822 void SetHolewarp(uint8_t hw) {
823 if (holewarp_ != hw) {
824 holewarp_ = hw;
826 }
827 }
828 void SetStaircaseRoom(int index, uint8_t room) {
829 if (index >= 0 && index < 4 && staircase_rooms_[index] != room) {
830 staircase_rooms_[index] = room;
832 }
833 }
834 // SetFloor1/SetFloor2 removed - use set_floor1()/set_floor2() instead
835 // (defined above)
836 void SetMessageId(uint16_t mid) {
837 if (message_id_ != mid) {
838 message_id_ = mid;
840 }
841 }
842
843 // Getters for LoadRoomFromRom function
844 bool IsLight() const { return is_light_; }
845
846 // Additional setters for LoadRoomFromRom function
847 void SetMessageIdDirect(uint16_t mid) {
848 if (message_id_ != mid) {
849 message_id_ = mid;
851 }
852 }
853 void SetLayer2Mode(uint8_t mode) {
854 const uint8_t normalized_mode = mode & 0x07;
855 if (layer2_mode_ != normalized_mode) {
856 layer2_mode_ = normalized_mode;
857 if (bg2_ != background2::DarkRoom) {
858 bg2_ = static_cast<background2>(normalized_mode);
859 layer_merging_ = kLayerMergeTypeList[normalized_mode];
860 }
863 }
864 }
866 if (layer_merging_ != merging) {
867 layer_merging_ = merging;
870 }
871 }
872 void SetIsDark(bool is_dark) {
873 if (is_dark_ != is_dark) {
874 is_dark_ = is_dark;
876 }
877 }
878 void SetBackgroundTileset(uint8_t tileset) {
879 if (background_tileset_ != tileset) {
880 background_tileset_ = tileset;
882 }
883 }
884 void SetSpriteTileset(uint8_t tileset) {
885 if (sprite_tileset_ != tileset) {
886 sprite_tileset_ = tileset;
888 }
889 }
890 void SetLayer2Behavior(uint8_t behavior) {
891 if (layer2_behavior_ != behavior) {
892 layer2_behavior_ = behavior;
894 }
895 }
897 if (tag1_ != tag1) {
898 tag1_ = tag1;
900 }
901 }
903 if (tag2_ != tag2) {
904 tag2_ = tag2;
906 }
907 }
908 void SetPitsTargetLayer(uint8_t layer) {
909 if (pits_.target_layer != layer) {
910 pits_.target_layer = layer;
912 }
913 }
914 void SetStair1TargetLayer(uint8_t layer) {
915 if (stair1_.target_layer != layer) {
916 stair1_.target_layer = layer;
918 }
919 }
920 void SetStair2TargetLayer(uint8_t layer) {
921 if (stair2_.target_layer != layer) {
922 stair2_.target_layer = layer;
924 }
925 }
926 void SetStair3TargetLayer(uint8_t layer) {
927 if (stair3_.target_layer != layer) {
928 stair3_.target_layer = layer;
930 }
931 }
932 void SetStair4TargetLayer(uint8_t layer) {
933 if (stair4_.target_layer != layer) {
934 stair4_.target_layer = layer;
936 }
937 }
938 void SetPitsTarget(uint8_t target) {
939 if (pits_.target != target) {
940 pits_.target = target;
942 }
943 }
944 void SetStair1Target(uint8_t target) {
945 if (stair1_.target != target) {
946 stair1_.target = target;
948 }
949 }
950 void SetStair2Target(uint8_t target) {
951 if (stair2_.target != target) {
952 stair2_.target = target;
954 }
955 }
956 void SetStair3Target(uint8_t target) {
957 if (stair3_.target != target) {
958 stair3_.target = target;
960 }
961 }
962 void SetStair4Target(uint8_t target) {
963 if (stair4_.target != target) {
964 stair4_.target = target;
966 }
967 }
968
969 // Loaded state
970 bool IsLoaded() const { return is_loaded_; }
971 void SetLoaded(bool loaded) { is_loaded_ = loaded; }
972 bool AreObjectsLoaded() const { return objects_loaded_; }
973 bool AreSpritesLoaded() const { return sprites_loaded_; }
974 bool AreChestsLoaded() const { return chests_loaded_; }
975 bool ArePotItemsLoaded() const { return pot_items_loaded_; }
976 bool AreTorchesLoaded() const { return torches_loaded_; }
977 // True once `LoadBlocks` has populated `tile_objects_` for this room.
978 // The `SaveAllBlocks` encoder uses this to distinguish header-only
979 // rooms (preserve their existing ROM block bytes) from rooms whose
980 // blocks have been fully materialized (encode from in-memory state,
981 // which may include edits/additions/deletions).
982 bool AreBlocksLoaded() const { return blocks_loaded_; }
983
984 // Read-only accessors for metadata
985 background2 bg2() const { return bg2_; }
986 EffectKey effect() const { return effect_; }
987 TagKey tag1() const { return tag1_; }
988 TagKey tag2() const { return tag2_; }
990 const LayerMergeType& layer_merging() const { return layer_merging_; }
991 uint8_t layer2_mode() const { return layer2_mode_; }
992 // The PPU layer settings the game uses for this room on entry, given the
993 // room's persistent flags (0: as first entered). See room_layer_registers.h.
994 RoomLayerRegisters GameLayerRegisters(uint16_t room_flags = 0) const;
995 uint8_t staircase_plane(int index) const {
996 return (index >= 0 && index < 4) ? staircase_plane_[index] : 0;
997 }
998 // Raw header byte. Use staircase_destination_room() for the room id.
999 uint8_t staircase_room(int index) const {
1000 return (index >= 0 && index < 4) ? staircase_rooms_[index] : 0;
1001 }
1002 // Destination room id of stair slot `index`, including this room's high
1003 // byte (see room_header_destination.h).
1004 int staircase_destination_room(int index) const {
1006 }
1007 // Destination room id of this room's pits and warp tiles.
1011
1012 int id() const { return room_id_; }
1013
1014 // Room header property accessors
1015 uint8_t blockset() const { return blockset_; }
1018 uint8_t spriteset() const { return spriteset_; }
1019 uint8_t palette() const { return palette_; }
1020
1021 // Resolves the room's palette-set ID to the concrete dungeon_main palette
1022 // index (0-19) via the two-level ROM lookup. Returns 0 when game data is
1023 // missing or the resolved index is out of range. See palette_structure.md
1024 // "Dungeon Main" section for the lookup algorithm.
1025 int ResolveDungeonPaletteId() const;
1026 uint8_t layout_id() const { return layout_id_; }
1027 // Raw header byte. Use holewarp_destination_room() for the room id.
1028 uint8_t holewarp() const { return holewarp_; }
1029 uint16_t message_id() const { return message_id_; }
1030
1031 // Layout ID setter (marks dirty)
1032 void SetLayoutId(uint8_t id) {
1033 if (layout_id_ != id) {
1034 layout_id_ = id;
1037 }
1038 }
1039
1040 // Floor graphics accessors
1041 uint8_t floor1() const { return floor1_graphics_; }
1042 uint8_t floor2() const { return floor2_graphics_; }
1043 void set_floor1(uint8_t value) {
1044 if (floor1_graphics_ != value) {
1045 floor1_graphics_ = value;
1048 }
1049 }
1050 void set_floor2(uint8_t value) {
1051 if (floor2_graphics_ != value) {
1052 floor2_graphics_ = value;
1055 }
1056 }
1057 // Enhanced object parsing methods
1058 void ParseObjectsFromLocation(int objects_location);
1059 void HandleSpecialObjects(short oid, uint8_t posX, uint8_t posY,
1060 int& nbr_of_staircase);
1061
1062 // Object saving (Phase 1, Task 1.3)
1063 absl::Status SaveObjects(const DungeonStreamLayout* layout = nullptr);
1064 // Read-only save plans expose half-open PC ranges for the same direct or
1065 // copy-on-write writes as the matching Save method. Clean streams return {}.
1066 absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1067 GetObjectSaveWriteRanges(const DungeonStreamLayout* layout = nullptr) const;
1068 absl::Status SaveObjectStreamHeader(
1069 const DungeonStreamLayout* layout = nullptr);
1070 absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1072 const DungeonStreamLayout* layout = nullptr) const;
1073 std::vector<uint8_t> EncodeObjects() const;
1074 absl::Status SaveSprites(const DungeonStreamLayout* layout = nullptr);
1075 absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1076 GetSpriteSaveWriteRanges(const DungeonStreamLayout* layout = nullptr) const;
1077 std::vector<uint8_t> EncodeSprites() const;
1078 absl::Status SaveRoomHeader();
1079
1080 auto blocks() const { return blocks_; }
1081 auto& mutable_blocks() { return blocks_; }
1082 auto rom() const { return rom_; }
1083 auto rom() { return rom_; }
1084 auto mutable_rom() { return rom_; }
1085 void SetRom(Rom* rom) { rom_ = rom; }
1086 auto game_data() { return game_data_; }
1087 const GameData* game_data() const { return game_data_; }
1088 void SetGameData(GameData* data) {
1089 if (game_data_ != data)
1091 game_data_ = data;
1092 }
1093
1100 std::map<uint16_t, std::vector<uint8_t>> overrides) {
1101 graphics_sheet_overrides_ = std::move(overrides);
1103 }
1104 const std::map<uint16_t, std::vector<uint8_t>>& graphics_sheet_overrides()
1105 const {
1107 }
1108
1113 bool SourceSheetsChanged() const;
1114
1115 // Helper to get version constants from game_data or default to US
1117 return kVersionConstantsMap.at(game_data_ ? game_data_->version
1118 : zelda3_version::US);
1119 }
1120 const std::array<uint8_t, 0x10000>& get_gfx_buffer() const {
1121 return current_gfx16_;
1122 }
1123 // Identifies the assembled pixels, including animated frame reloads. The
1124 // token survives moves and cannot collide with another room's reload count.
1125 uint64_t graphics_revision() const { return graphics_revision_; }
1126 // Identifies every source change that can alter a composed room image.
1127 // Unlike graphics_revision(), this also advances for object-only, layout,
1128 // palette, and direct composite invalidations.
1129 uint64_t composite_source_revision() const {
1131 }
1138 const std::vector<SDL_Color>& rendered_palette() const {
1139 return rendered_palette_;
1140 }
1141 // Palette-half expansion applied to nonzero raw 3bpp background pixels.
1142 int BackgroundPaletteOffset(int slot) const;
1143
1144 // Per-room background buffers (not shared via arena!)
1145 auto& bg1_buffer() { return bg1_buffer_; }
1146 auto& bg2_buffer() { return bg2_buffer_; }
1147 const auto& bg1_buffer() const { return bg1_buffer_; }
1148 const auto& bg2_buffer() const { return bg2_buffer_; }
1150 const auto& object_bg1_buffer() const { return object_bg1_buffer_; }
1152 const auto& object_bg2_buffer() const { return object_bg2_buffer_; }
1153
1158 void RenderComposite(const RoomLayerManager& layer_mgr, gfx::Bitmap& output);
1160
1162 void MarkCompositeDirty();
1163 bool IsCompositeDirty() const { return dirty_state_.composite; }
1164
1166 const DungeonState* GetDungeonState() const { return dungeon_state_.get(); }
1167
1168 private:
1170 std::vector<std::pair<uint32_t, std::vector<uint8_t>>> direct_writes;
1171 std::optional<std::pair<uint32_t, uint32_t>> direct_long_write;
1172 std::optional<DungeonStreamWritePlan> relocation;
1173
1174 std::vector<std::pair<uint32_t, uint32_t>> write_ranges() const;
1175 };
1176 absl::StatusOr<StreamSavePlan> PlanObjectSave(
1177 const DungeonStreamLayout* layout) const;
1178 absl::StatusOr<StreamSavePlan> PlanSpriteSave(
1179 const DungeonStreamLayout* layout) const;
1180 absl::StatusOr<StreamSavePlan> PlanObjectStreamHeaderSave(
1181 const DungeonStreamLayout* layout) const;
1182 absl::Status ApplyStreamSavePlan(const StreamSavePlan& plan);
1185
1186 // Returns the 4096-byte 8bpp source for a sheet: an override when one is
1187 // set, otherwise the GameData buffer. Null when neither covers the sheet.
1188 const uint8_t* GraphicsSheetSource(int sheet_id) const;
1189 // Notes the store revision of a sheet copied from GameData (not overrides).
1190 void RecordSourceSheet(int sheet_id);
1191
1192 std::array<uint8_t, 0x10000> current_gfx16_;
1193 std::map<uint16_t, std::vector<uint8_t>> graphics_sheet_overrides_;
1194 // Sheet id and store revision of each store sheet in current_gfx16_.
1195 std::vector<std::pair<uint16_t, uint64_t>> source_sheet_revisions_;
1199 std::vector<SDL_Color> rendered_palette_;
1201
1202 // Each room has its OWN background buffers and bitmaps
1203 // Each room has its OWN background buffers and bitmaps
1208
1209 struct DirtyState {
1210 bool graphics = true;
1211 bool objects = true;
1212 bool layout = true;
1213 bool textures = true;
1214 bool composite = true;
1215 };
1216
1218 bool header = false;
1219 bool object_stream = false;
1221 bool sprites = false;
1222 bool chests = false;
1223 bool pot_items = false;
1224 bool torches = false;
1225 bool blocks = false;
1226 };
1227
1228 static constexpr uint8_t kObjectHeaderFloor1Dirty = 1u << 0;
1229 static constexpr uint8_t kObjectHeaderFloor2Dirty = 1u << 1;
1230 static constexpr uint8_t kObjectHeaderLayoutDirty = 1u << 2;
1231
1232 // Composite bitmap for merged layer output
1234 mutable uint64_t composite_signature_ = 0;
1236 mutable bool has_composite_signature_ = false;
1239
1240 bool is_light_ = false;
1241 bool is_loaded_ = false;
1242 bool objects_loaded_ = false;
1243 bool sprites_loaded_ = false;
1244 bool chests_loaded_ = false;
1245 bool pot_items_loaded_ = false;
1246 bool torches_loaded_ = false;
1247 bool blocks_loaded_ = false;
1248 bool is_dark_ = false;
1249 bool is_floor_ = true;
1250
1251 // Performance optimization: Cache room properties to avoid unnecessary
1252 // re-renders
1253 uint8_t cached_blockset_ = 0xFF;
1254 uint8_t cached_spriteset_ = 0xFF;
1255 uint8_t cached_palette_ = 0xFF;
1256 uint8_t cached_layout_ = 0xFF;
1259 uint8_t cached_effect_ = 0xFF;
1262
1263 int room_id_ = 0;
1265
1266 uint8_t staircase_plane_[4]{};
1267 uint8_t staircase_rooms_[4]{};
1268
1269 // Room header properties (formerly public)
1270 uint8_t blockset_ = 0;
1273 uint8_t spriteset_ = 0;
1274 uint8_t palette_ = 0;
1275 uint8_t layout_id_ = 0;
1276 uint8_t holewarp_ = 0;
1277 uint16_t message_id_ = 0;
1278
1280 uint8_t sprite_tileset_ = 0;
1281 uint8_t layer2_behavior_ = 0;
1282 uint8_t floor1_graphics_ = 0;
1283 uint8_t floor2_graphics_ = 0;
1284 uint8_t layer2_mode_ = 0;
1285
1286 std::array<uint8_t, 16> blocks_;
1287 std::array<chest, 16> chest_list_;
1288
1289 std::vector<RoomObject> tile_objects_;
1290 // TODO: add separate door objects list when door section (F0 FF) is parsed
1291 std::vector<zelda3::Sprite> sprites_;
1292 std::vector<staircase> z3_staircases_;
1293 std::vector<chest_data> chests_in_room_;
1294 std::vector<Door> doors_;
1295 std::vector<PotItem> pot_items_;
1297
1303
1310
1313
1315 bool water_fill_dirty_ = false;
1317 std::unique_ptr<DungeonState> dungeon_state_;
1318};
1319
1320// Loads a room from the ROM.
1321Room LoadRoomFromRom(Rom* rom, int room_id);
1322
1323// Loads only the room header (metadata) from the ROM.
1324Room LoadRoomHeaderFromRom(Rom* rom, int room_id);
1325
1326struct RoomSize {
1328 int64_t room_size;
1329};
1330
1331// Calculates the size of a room in the ROM.
1332RoomSize CalculateRoomSize(Rom* rom, int room_id);
1333
1334// Dungeon-level save: aggregate torches from all rooms and write to ROM.
1335absl::Status SaveAllTorches(Rom* rom, absl::Span<const Room> rooms);
1336absl::Status SaveAllTorches(Rom* rom, int room_count,
1337 const std::function<const Room*(int)>& room_lookup);
1338// Validate and describe the exact torch writes without changing ROM or rooms.
1339// Returns no ranges when the merged table already matches the source ROM.
1340absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1341GetTorchSaveWriteRanges(const Rom* rom, int room_count,
1342 const std::function<const Room*(int)>& room_lookup);
1343
1344// Preserve pit count/pointer and table bytes, or encode an explicitly supplied
1345// dirty RoomsWithPitDamage table through the overload below.
1346absl::Status SaveAllPits(Rom* rom);
1347absl::Status SaveAllPits(Rom* rom, PitDamageTable* pit_damage_table);
1348
1349// Preserve blocks length and the four block regions (read from ROM,
1350// write back). No edit support; legacy callers without per-room state
1351// keep this path. New callers should use the room-aware overload below.
1352absl::Status SaveAllBlocks(Rom* rom);
1353
1354// Encode pushable blocks from loaded rooms back into the four
1355// pointer-dereferenced data regions while preserving unmaterialized entries.
1356// Existing blocks retain their committed `block_load_order_`; user-added
1357// blocks tail the buffer in creation order. After every ROM write succeeds,
1358// loaded objects are rebased to their emitted slots and encoded rooms become
1359// clean. Returns FailedPrecondition before mutation if a dirty room's blocks
1360// are not loaded, the final buffer is empty (the vanilla do-while scan requires
1361// one entry), or it exceeds the 128-entry vanilla cap (4 regions × 0x80 bytes /
1362// 4 bytes per entry).
1363absl::Status SaveAllBlocks(Rom* rom, int room_count,
1364 const std::function<const Room*(int)>& room_lookup);
1365// Validate and describe the room-aware block serializer's exact write spans
1366// without changing ROM bytes, dirty flags, or block load-order identities.
1367absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1368GetBlockSaveWriteRanges(const Rom* rom, int room_count,
1369 const std::function<const Room*(int)>& room_lookup);
1370
1371// Save custom collision maps for any rooms marked dirty.
1372//
1373// This writes into the ZScream expanded collision region and updates the room
1374// pointer table. Rooms not loaded (or not dirty) are preserved.
1375absl::Status SaveAllCollision(Rom* rom, absl::Span<Room> rooms);
1376absl::Status SaveAllCollision(Rom* rom, int room_count,
1377 const std::function<Room*(int)>& room_lookup);
1378
1379// Scan all room sprite pointers and return the highest used PC address end.
1381
1382// Legacy compatibility helper: relocate a room's sprite payload into free tail
1383// space and update its pointer. The old stream is deliberately preserved;
1384// manifest-backed saves should use DungeonStreamAllocator instead.
1385absl::Status RelocateSpriteData(Rom* rom, int room_id,
1386 const std::vector<uint8_t>& encoded_bytes);
1387
1388// Returns the complete set of PC ranges that the global chest serializer may
1389// write: the two-byte runtime length operand and the live pointer target's
1390// fixed-capacity data region. The three-byte pointer operand itself is read
1391// only and is deliberately excluded.
1392absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1393GetChestTableWriteRanges(const Rom* rom);
1394
1396 uint32_t pc = 0;
1397 std::vector<uint8_t> expected_bytes;
1398 std::vector<uint8_t> replacement_bytes;
1399
1400 bool operator==(const ChestWriteRun&) const = default;
1401
1402 uint32_t end() const {
1403 return pc + static_cast<uint32_t>(replacement_bytes.size());
1404 }
1405};
1406
1408 int room_id = 0;
1409 std::vector<uint8_t> encoded_chests;
1410
1411 bool operator==(const ChestDirtyRoomState&) const = default;
1412};
1413
1414// Chest serialization snapshot. It captures both the exact byte runs presented
1415// to manifest preflight and the source state required to apply those runs
1416// safely after other save domains have run. ApplyChestSavePlan reconstructs
1417// and compares the canonical plan before permitting any write.
1419 bool any_dirty = false;
1420 int room_limit = 0;
1421 uint32_t data_pc = 0;
1422 std::array<uint8_t, 3> pointer_operand{};
1424 std::vector<uint8_t> original_capacity_bytes;
1425 std::vector<ChestWriteRun> writes;
1426 std::vector<ChestDirtyRoomState> dirty_rooms;
1427
1428 bool operator==(const ChestSavePlan&) const = default;
1429
1430 std::vector<std::pair<uint32_t, uint32_t>> write_ranges() const {
1431 std::vector<std::pair<uint32_t, uint32_t>> ranges;
1432 ranges.reserve(writes.size());
1433 for (const ChestWriteRun& write : writes) {
1434 ranges.emplace_back(write.pc, write.end());
1435 }
1436 return ranges;
1437 }
1438};
1439
1440absl::StatusOr<ChestSavePlan> BuildChestSavePlan(
1441 const Rom* rom, int room_count,
1442 const std::function<const Room*(int)>& room_lookup);
1443absl::Status ApplyChestSavePlan(
1444 Rom* rom, const ChestSavePlan& plan,
1445 const std::function<const Room*(int)>& room_lookup);
1446
1447// Plan the exact PC ranges changed by the current dirty-room chest state.
1448// One-for-one edits return only the affected record bytes; growth/removal may
1449// return wider runs plus the two-byte runtime length operand. The same plan is
1450// used by manifest preflight and SaveAllChests so protected bytes that are not
1451// actually changing do not block an otherwise safe edit.
1452absl::StatusOr<std::vector<std::pair<uint32_t, uint32_t>>>
1453GetDirtyChestWriteRanges(const Rom* rom, int room_count,
1454 const std::function<const Room*(int)>& room_lookup);
1455
1456// Aggregate chests from all rooms and write to ROM. Dirty rooms replace their
1457// existing occurrences one-for-one in physical-table order. Untouched and
1458// unknown-room records retain their exact bytes and relative order; surplus
1459// occurrences are removed and additional records are appended by room ID.
1460absl::Status SaveAllChests(Rom* rom, absl::Span<const Room> rooms);
1461absl::Status SaveAllChests(Rom* rom, int room_count,
1462 const std::function<const Room*(int)>& room_lookup);
1463
1464// Save pot items for all rooms. Preserves ROM data for rooms not loaded.
1465absl::Status SaveAllPotItems(Rom* rom, absl::Span<const Room> rooms);
1466absl::Status SaveAllPotItems(Rom* rom, absl::Span<const Room> rooms,
1467 const DungeonStreamLayout* repack_layout);
1468absl::Status SaveAllPotItems(
1469 Rom* rom, int room_count,
1470 const std::function<const Room*(int)>& room_lookup);
1471absl::Status SaveAllPotItems(Rom* rom, int room_count,
1472 const std::function<const Room*(int)>& room_lookup,
1473 const DungeonStreamLayout* repack_layout);
1474
1475// RoomEffect names defined in room.cc to avoid static initialization order issues
1476extern const std::string RoomEffect[8];
1477
1478constexpr std::array<std::string_view, 297> kRoomNames = {
1479 "Ganon",
1480 "Hyrule Castle (North Corridor)",
1481 "Behind Sanctuary (Switch)",
1482 "Houlihan",
1483 "Turtle Rock (Crysta-Roller)",
1484 "Empty",
1485 "Swamp Palace (Arrghus[Boss])",
1486 "Tower of Hera (Moldorm[Boss])",
1487 "Cave (Healing Fairy)",
1488 "Palace of Darkness",
1489 "Palace of Darkness (Stalfos Trap)",
1490 "Palace of Darkness (Turtle)",
1491 "Ganon's Tower (Entrance)",
1492 "Ganon's Tower (Agahnim2[Boss])",
1493 "Ice Palace (Entrance )",
1494 "Empty Clone ",
1495 "Ganon Evacuation Route",
1496 "Hyrule Castle (Bombable Stock )",
1497 "Sanctuary",
1498 "Turtle Rock (Hokku-Bokku Key 2)",
1499 "Turtle Rock (Big Key )",
1500 "Turtle Rock",
1501 "Swamp Palace (Swimming Treadmill)",
1502 "Tower of Hera (Moldorm Fall )",
1503 "Cave",
1504 "Palace of Darkness (Dark Maze)",
1505 "Palace of Darkness (Big Chest )",
1506 "Palace of Darkness (Mimics / Moving Wall )",
1507 "Ganon's Tower (Ice Armos)",
1508 "Ganon's Tower (Final Hallway)",
1509 "Ice Palace (Bomb Floor / Bari )",
1510 "Ice Palace (Pengator / Big Key )",
1511 "Agahnim's Tower (Agahnim[Boss])",
1512 "Hyrule Castle (Key-rat )",
1513 "Hyrule Castle (Sewer Text Trigger )",
1514 "Turtle Rock (West Exit to Balcony)",
1515 "Turtle Rock (Double Hokku-Bokku / Big chest )",
1516 "Empty Clone ",
1517 "Swamp Palace (Statue )",
1518 "Tower of Hera (Big Chest)",
1519 "Swamp Palace (Entrance )",
1520 "Skull Woods (Mothula[Boss])",
1521 "Palace of Darkness (Big Hub )",
1522 "Palace of Darkness (Map Chest / Fairy )",
1523 "Cave",
1524 "Empty Clone ",
1525 "Ice Palace (Compass )",
1526 "Cave (Kakariko Well HP)",
1527 "Agahnim's Tower (Maiden Sacrifice Chamber)",
1528 "Tower of Hera (Hardhat Beetles )",
1529 "Hyrule Castle (Sewer Key Chest )",
1530 "Desert Palace (Lanmolas[Boss])",
1531 "Swamp Palace (Push Block Puzzle / Pre-Big Key )",
1532 "Swamp Palace (Big Key / BS )",
1533 "Swamp Palace (Big Chest )",
1534 "Swamp Palace (Map Chest / Water Fill )",
1535 "Swamp Palace (Key Pot )",
1536 "Skull Woods (Gibdo Key / Mothula Hole )",
1537 "Palace of Darkness (Bombable Floor )",
1538 "Palace of Darkness (Spike Block / Conveyor )",
1539 "Cave",
1540 "Ganon's Tower (Torch 2)",
1541 "Ice Palace (Stalfos Knights / Conveyor Hellway)",
1542 "Ice Palace (Map Chest )",
1543 "Agahnim's Tower (Final Bridge )",
1544 "Hyrule Castle (First Dark )",
1545 "Hyrule Castle (6 Ropes )",
1546 "Desert Palace (Torch Puzzle / Moving Wall )",
1547 "Thieves Town (Big Chest )",
1548 "Thieves Town (Jail Cells )",
1549 "Swamp Palace (Compass Chest )",
1550 "Empty Clone ",
1551 "Empty Clone ",
1552 "Skull Woods (Gibdo Torch Puzzle )",
1553 "Palace of Darkness (Entrance )",
1554 "Palace of Darkness (Warps / South Mimics )",
1555 "Ganon's Tower (Mini-Helmasaur Conveyor )",
1556 "Ganon's Tower (Moldorm )",
1557 "Ice Palace (Bomb-Jump )",
1558 "Ice Palace Clone (Fairy )",
1559 "Hyrule Castle (West Corridor)",
1560 "Hyrule Castle (Throne )",
1561 "Hyrule Castle (East Corridor)",
1562 "Desert Palace (Popos 2 / Beamos Hellway )",
1563 "Swamp Palace (Upstairs Pits )",
1564 "Castle Secret Entrance / Uncle Death ",
1565 "Skull Woods (Key Pot / Trap )",
1566 "Skull Woods (Big Key )",
1567 "Skull Woods (Big Chest )",
1568 "Skull Woods (Final Section Entrance )",
1569 "Palace of Darkness (Helmasaur King[Boss])",
1570 "Ganon's Tower (Spike Pit )",
1571 "Ganon's Tower (Ganon-Ball Z)",
1572 "Ganon's Tower (Gauntlet 1/2/3)",
1573 "Ice Palace (Lonely Firebar)",
1574 "Ice Palace (Hidden Chest / Spike Floor )",
1575 "Hyrule Castle (West Entrance )",
1576 "Hyrule Castle (Main Entrance )",
1577 "Hyrule Castle (East Entrance )",
1578 "Desert Palace (Final Section Entrance )",
1579 "Thieves Town (West Attic )",
1580 "Thieves Town (East Attic )",
1581 "Swamp Palace (Hidden Chest / Hidden Door )",
1582 "Skull Woods (Compass Chest )",
1583 "Skull Woods (Key Chest / Trap )",
1584 "Empty Clone ",
1585 "Palace of Darkness (Rupee )",
1586 "Ganon's Tower (Mimics s)",
1587 "Ganon's Tower (Lanmolas )",
1588 "Ganon's Tower (Gauntlet 4/5)",
1589 "Ice Palace (Pengators )",
1590 "Empty Clone ",
1591 "Hyrule Castle (Small Corridor to Jail Cells)",
1592 "Hyrule Castle (Boomerang Chest )",
1593 "Hyrule Castle (Map Chest )",
1594 "Desert Palace (Big Chest )",
1595 "Desert Palace (Map Chest )",
1596 "Desert Palace (Big Key Chest )",
1597 "Swamp Palace (Water Drain )",
1598 "Tower of Hera (Entrance )",
1599 "Empty Clone ",
1600 "Empty Clone ",
1601 "Empty Clone ",
1602 "Ganon's Tower",
1603 "Ganon's Tower (East Side Collapsing Bridge / Exploding Wall )",
1604 "Ganon's Tower (Winder / Warp Maze )",
1605 "Ice Palace (Hidden Chest / Bombable Floor )",
1606 "Ice Palace ( Big Spike Traps )",
1607 "Hyrule Castle (Jail Cell )",
1608 "Hyrule Castle",
1609 "Hyrule Castle (Basement Chasm )",
1610 "Desert Palace (West Entrance )",
1611 "Desert Palace (Main Entrance )",
1612 "Desert Palace (East Entrance )",
1613 "Empty Clone ",
1614 "Tower of Hera (Tile )",
1615 "Empty Clone ",
1616 "Eastern Palace (Fairy )",
1617 "Empty Clone ",
1618 "Ganon's Tower (Block Puzzle / Spike Skip / Map Chest )",
1619 "Ganon's Tower (East and West Downstairs / Big Chest )",
1620 "Ganon's Tower (Tile / Torch Puzzle )",
1621 "Ice Palace",
1622 "Empty Clone ",
1623 "Misery Mire (Vitreous[Boss])",
1624 "Misery Mire (Final Switch )",
1625 "Misery Mire (Dark Bomb Wall / Switches )",
1626 "Misery Mire (Dark Cane Floor Switch Puzzle )",
1627 "Empty Clone ",
1628 "Ganon's Tower (Final Collapsing Bridge )",
1629 "Ganon's Tower (Torches 1 )",
1630 "Misery Mire (Torch Puzzle / Moving Wall )",
1631 "Misery Mire (Entrance )",
1632 "Eastern Palace (Eyegore Key )",
1633 "Empty Clone ",
1634 "Ganon's Tower (Many Spikes / Warp Maze )",
1635 "Ganon's Tower (Invisible Floor Maze )",
1636 "Ganon's Tower (Compass Chest / Invisible Floor )",
1637 "Ice Palace (Big Chest )",
1638 "Ice Palace",
1639 "Misery Mire (Pre-Vitreous )",
1640 "Misery Mire (Fish )",
1641 "Misery Mire (Bridge Key Chest )",
1642 "Misery Mire",
1643 "Turtle Rock (Trinexx[Boss])",
1644 "Ganon's Tower (Wizzrobes s)",
1645 "Ganon's Tower (Moldorm Fall )",
1646 "Tower of Hera (Fairy )",
1647 "Eastern Palace (Stalfos Spawn )",
1648 "Eastern Palace (Big Chest )",
1649 "Eastern Palace (Map Chest )",
1650 "Thieves Town (Moving Spikes / Key Pot )",
1651 "Thieves Town (Blind The Thief[Boss])",
1652 "Empty Clone ",
1653 "Ice Palace",
1654 "Ice Palace (Ice Bridge )",
1655 "Agahnim's Tower (Circle of Pots)",
1656 "Misery Mire (Hourglass )",
1657 "Misery Mire (Slug )",
1658 "Misery Mire (Spike Key Chest )",
1659 "Turtle Rock (Pre-Trinexx )",
1660 "Turtle Rock (Dark Maze)",
1661 "Turtle Rock (Chain Chomps )",
1662 "Turtle Rock (Map Chest / Key Chest / Roller )",
1663 "Eastern Palace (Big Key )",
1664 "Eastern Palace (Lobby Cannonballs )",
1665 "Eastern Palace (Dark Antifairy / Key Pot )",
1666 "Thieves Town (Hellway)",
1667 "Thieves Town (Conveyor Toilet)",
1668 "Empty Clone ",
1669 "Ice Palace (Block Puzzle )",
1670 "Ice Palace Clone (Switch )",
1671 "Agahnim's Tower (Dark Bridge )",
1672 "Misery Mire (Compass Chest / Tile )",
1673 "Misery Mire (Big Hub )",
1674 "Misery Mire (Big Chest )",
1675 "Turtle Rock (Final Crystal Switch Puzzle )",
1676 "Turtle Rock (Laser Bridge)",
1677 "Turtle Rock",
1678 "Turtle Rock (Torch Puzzle)",
1679 "Eastern Palace (Armos Knights[Boss])",
1680 "Eastern Palace (Entrance )",
1681 "??",
1682 "Thieves Town (North West Entrance )",
1683 "Thieves Town (North East Entrance )",
1684 "Empty Clone ",
1685 "Ice Palace (Hole to Kholdstare )",
1686 "Empty Clone ",
1687 "Agahnim's Tower (Dark Maze)",
1688 "Misery Mire (Conveyor Slug / Big Key )",
1689 "Misery Mire (Mire02 / Wizzrobes )",
1690 "Empty Clone ",
1691 "Empty Clone ",
1692 "Turtle Rock (Laser Key )",
1693 "Turtle Rock (Entrance )",
1694 "Empty Clone ",
1695 "Eastern Palace (Zeldagamer / Pre-Armos Knights )",
1696 "Eastern Palace (Canonball ",
1697 "Eastern Palace",
1698 "Thieves Town (Main (South West) Entrance )",
1699 "Thieves Town (South East Entrance )",
1700 "Empty Clone ",
1701 "Ice Palace (Kholdstare[Boss])",
1702 "Cave",
1703 "Agahnim's Tower (Entrance )",
1704 "Cave (Lost Woods HP)",
1705 "Cave (Lumberjack's Tree HP)",
1706 "Cave (1/2 Magic)",
1707 "Cave (Lost Old Man Final Cave)",
1708 "Cave (Lost Old Man Final Cave)",
1709 "Cave",
1710 "Cave",
1711 "Cave",
1712 "Empty Clone ",
1713 "Cave (Spectacle Rock HP)",
1714 "Cave",
1715 "Empty Clone ",
1716 "Cave",
1717 "Cave (Spiral Cave)",
1718 "Cave (Crystal Switch / 5 Chests )",
1719 "Cave (Lost Old Man Starting Cave)",
1720 "Cave (Lost Old Man Starting Cave)",
1721 "House",
1722 "House (Old Woman (Sahasrahla's Wife?))",
1723 "House (Angry Brothers)",
1724 "House (Angry Brothers)",
1725 "Empty Clone ",
1726 "Empty Clone ",
1727 "Cave",
1728 "Cave",
1729 "Cave",
1730 "Cave",
1731 "Empty Clone ",
1732 "Cave",
1733 "Cave",
1734 "Cave",
1735
1736 "Chest Minigame",
1737 "Houses",
1738 "Sick Boy house",
1739 "Tavern",
1740 "Link's House",
1741 "Sarashrala Hut",
1742 "Chest Minigame",
1743 "Library",
1744 "Chicken House",
1745 "Witch Shop",
1746 "A Aginah's Cave",
1747 "Dam",
1748 "Mimic Cave",
1749 "Mire Shed",
1750 "Cave",
1751 "Shop",
1752 "Shop",
1753 "Archery Minigame",
1754 "DW Church/Shop",
1755 "Grave Cave",
1756 "Fairy Fountain",
1757 "Fairy Upgrade",
1758 "Pyramid Fairy",
1759 "Spike Cave",
1760 "Chest Minigame",
1761 "Blind Hut",
1762 "Bonzai Cave",
1763 "Circle of bush Cave",
1764 "Big Bomb Shop, C-House",
1765 "Blind Hut 2",
1766 "Hype Cave",
1767 "Shop",
1768 "Ice Cave",
1769 "Smith",
1770 "Fortune Teller",
1771 "MiniMoldorm Cave",
1772 "Under Rock Caves",
1773 "Smith",
1774 "Cave",
1775 "Mazeblock Cave",
1776 "Smith Peg Cave"};
1777
1778// RoomTag names defined in room.cc to avoid static initialization order issues
1779extern const std::string RoomTag[65];
1780
1781} // namespace zelda3
1782} // namespace yaze
1783
1784#endif
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:49
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
static std::pair< uint8_t, uint8_t > EncodeDoorBytes(uint8_t position, DoorType type, DoorDirection direction)
Encode door data for ROM storage.
static std::pair< int, int > PositionToPixelCoords(uint8_t position, DoorDirection direction)
Convert encoded position to pixel coordinates.
static std::tuple< int, int, int, int > GetDoorEditorBounds(uint8_t position, DoorDirection direction, DoorType type)
Get the editor interaction bounds for a typed door.
static std::tuple< int, int, int, int > GetDoorBounds(uint8_t position, DoorDirection direction)
Get the bounding rectangle for a door.
static std::pair< int, int > PositionToTileCoords(uint8_t position, DoorDirection direction)
Convert encoded position to tile coordinates.
Interface for accessing dungeon game state.
RoomLayerManager - Manages layer visibility and compositing.
uint8_t holewarp() const
Definition room.h:1028
bool ValidateObject(const RoomObject &object) const
Definition room.cc:2826
const std::array< uint8_t, 0x10000 > & get_gfx_buffer() const
Definition room.h:1120
SaveDirtyState save_dirty_state_
Definition room.h:1238
destination pits_
Definition room.h:1305
std::vector< RoomObject > tile_objects_
Definition room.h:1289
std::vector< SDL_Color > rendered_palette_
Definition room.h:1199
void MarkPotItemsDirty()
Definition room.h:432
uint8_t cached_blockset_
Definition room.h:1253
EffectKey effect_
Definition room.h:1300
gfx::BackgroundBuffer object_bg1_buffer_
Definition room.h:1206
uint8_t palette_
Definition room.h:1274
void SetTag2Direct(TagKey tag2)
Definition room.h:902
bool HasExceededLimits() const
Check if any object limits are exceeded.
Definition room.cc:4797
void ClearObjectStreamHeaderDirty()
Definition room.h:509
uint8_t render_entrance_blockset_
Definition room.h:1271
uint8_t cached_layout_
Definition room.h:1256
const CustomCollisionMap & custom_collision() const
Definition room.h:559
uint8_t staircase_plane_[4]
Definition room.h:1266
absl::Status UpdateObject(size_t index, const RoomObject &object)
Definition room.cc:2799
void ClearSaveDirtyState()
Definition room.h:671
TagKey cached_tag2_
Definition room.h:1261
WaterFillZoneMap & water_fill_zone()
Definition room.h:602
void AddTileObject(const RoomObject &object)
Definition room.h:457
void MarkLayoutDirty()
Definition room.h:517
const std::map< uint16_t, std::vector< uint8_t > > & graphics_sheet_overrides() const
Definition room.h:1104
bool ArePotItemsLoaded() const
Definition room.h:975
void SetStair4Target(uint8_t target)
Definition room.h:962
void SetPitsTarget(uint8_t target)
Definition room.h:938
void SetIsLight(bool is_light)
Definition room.h:760
void LoadChests()
Definition room.cc:2946
void EnsureSpritesLoaded()
Definition room.cc:1033
uint64_t graphics_revision_
Definition room.h:1196
void MarkObjectsDirty()
Definition room.h:471
gfx::BackgroundBuffer bg2_buffer_
Definition room.h:1205
uint8_t resolved_main_blockset_
Definition room.h:1272
void ClearTileObjects()
Definition room.h:451
void MarkChestsDirty()
Definition room.h:326
const std::vector< chest_data > & GetChests() const
Definition room.h:323
int holewarp_destination_room() const
Definition room.h:1008
uint8_t cached_floor2_graphics_
Definition room.h:1258
std::vector< zelda3::Sprite > sprites_
Definition room.h:1291
auto mutable_rom()
Definition room.h:1084
CustomCollisionMap custom_collision_
Definition room.h:1311
GameData * game_data_
Definition room.h:1184
void MarkSaveDirtyForTileObject(const RoomObject &object)
Definition room.h:480
void SetLoaded(bool loaded)
Definition room.h:971
uint8_t GetCollisionTile(int x, int y) const
Definition room.h:571
void RenderComposite(const RoomLayerManager &layer_mgr, gfx::Bitmap &output)
Definition room.cc:1248
void ClearObjectStreamDirty()
Definition room.h:505
void ClearCustomCollisionDirty()
Definition room.h:597
const std::vector< SDL_Color > & rendered_palette() const
Definition room.h:1138
void CopyRoomGraphicsToBuffer()
Definition room.cc:1106
destination stair2_
Definition room.h:1307
void set_water_fill_sram_bit_mask(uint8_t mask)
Definition room.h:647
uint16_t message_id() const
Definition room.h:1029
const uint8_t * GraphicsSheetSource(int sheet_id) const
Definition room.cc:1179
bool custom_collision_dirty() const
Definition room.h:596
RoomLayerRegisters GameLayerRegisters(uint16_t room_flags=0) const
Definition room.cc:943
uint8_t cached_palette_
Definition room.h:1255
gfx::SnesPalette rendered_dungeon_palette_
Definition room.h:1198
void ClearHeaderDirty()
Definition room.h:660
uint8_t blockset() const
Definition room.h:1015
std::vector< staircase > & GetStairs()
Definition room.h:331
uint64_t composite_rendered_source_revision_
Definition room.h:1235
zelda3_version_pointers version_constants() const
Definition room.h:1116
void set_floor2(uint8_t value)
Definition room.h:1050
void RestoreMetadataSnapshot(const MetadataSnapshot &snapshot)
Definition room.cc:886
void ClearPotItemsDirty()
Definition room.h:433
const WaterFillZoneMap & water_fill_zone() const
Definition room.h:601
int staircase_destination_room(int index) const
Definition room.h:1004
uint8_t cached_effect_
Definition room.h:1259
void SetGraphicsSheetOverrides(std::map< uint16_t, std::vector< uint8_t > > overrides)
Definition room.h:1099
std::vector< Door > doors_
Definition room.h:1294
bool HasUnsavedChanges() const
Definition room.h:662
auto game_data()
Definition room.h:1086
void SetStaircaseRoom(int index, uint8_t room)
Definition room.h:828
static constexpr uint8_t kObjectHeaderFloor1Dirty
Definition room.h:1228
uint8_t layer2_behavior_
Definition room.h:1281
const gfx::Bitmap & composite_bitmap() const
Definition room.h:1159
int WaterFillTileCount() const
Definition room.h:642
absl::Status RemoveObject(size_t index)
Definition room.cc:2786
void SetStair1TargetLayer(uint8_t layer)
Definition room.h:914
void set_floor1(uint8_t value)
Definition room.h:1043
void MarkGraphicsDirty()
Definition room.h:512
void LoadBlocks()
Definition room.cc:4515
bool SourceSheetsChanged() const
Definition room.cc:1217
void SetLayer2Mode(uint8_t mode)
Definition room.h:853
RoomLayout layout_
Definition room.h:1296
uint8_t layer2_mode_
Definition room.h:1284
void LoadLayoutTilesToBuffer()
Definition room.cc:1522
uint8_t staircase_room(int index) const
Definition room.h:999
void MarkTileObjectCollectionDirty()
Definition room.h:501
auto & mutable_blocks()
Definition room.h:1081
bool sprites_loaded_
Definition room.h:1243
void SetTag2(TagKey tag2)
Definition room.h:809
const std::vector< Door > & GetDoors() const
Definition room.h:413
std::vector< DungeonLimitInfo > GetExceededLimitDetails() const
Get list of exceeded limits with details.
Definition room.cc:4802
bool IsLoaded() const
Definition room.h:970
auto & object_bg2_buffer()
Definition room.h:1151
void ParseObjectsFromLocation(int objects_location)
Definition room.cc:1961
void MarkBlocksDirty()
Definition room.h:439
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetObjectSaveWriteRanges(const DungeonStreamLayout *layout=nullptr) const
Definition room.cc:2437
uint8_t layer2_mode() const
Definition room.h:991
uint8_t cached_floor1_graphics_
Definition room.h:1257
bool custom_collision_dirty_
Definition room.h:1312
static constexpr uint8_t kObjectHeaderFloor2Dirty
Definition room.h:1229
void ReloadGraphics(std::optional< uint8_t > entrance_blockset=std::nullopt)
Definition room.cc:1047
absl::Status ApplyStreamSavePlan(const StreamSavePlan &plan)
Definition room.cc:2318
bool pot_items_dirty() const
Definition room.h:431
void set_has_custom_collision(bool has)
Definition room.h:564
void ClearWaterFillZone()
Definition room.h:634
const auto & object_bg1_buffer() const
Definition room.h:1150
void RecordSourceSheet(int sheet_id)
Definition room.cc:1201
std::vector< zelda3::Sprite > & GetSprites()
Definition room.h:317
void SetTag1Direct(TagKey tag1)
Definition room.h:896
void LoadTorches()
Definition room.cc:3006
bool IsCompositeDirty() const
Definition room.h:1163
void SetLayoutId(uint8_t id)
Definition room.h:1032
void SetHolewarp(uint8_t hw)
Definition room.h:822
std::vector< Door > & GetDoors()
Definition room.h:414
TagKey tag2() const
Definition room.h:988
destination stair4_
Definition room.h:1309
void SetStair2Target(uint8_t target)
Definition room.h:950
bool object_stream_dirty() const
Definition room.h:504
size_t GetTileObjectCount() const
Definition room.h:530
const auto & object_bg2_buffer() const
Definition room.h:1152
bool sprites_dirty() const
Definition room.h:318
uint8_t floor2() const
Definition room.h:1042
bool header_dirty() const
Definition room.h:658
CustomCollisionMap & custom_collision()
Definition room.h:562
void SetCollision(CollisionKey collision)
Definition room.h:754
bool object_stream_header_dirty() const
Definition room.h:506
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetObjectStreamHeaderSaveWriteRanges(const DungeonStreamLayout *layout=nullptr) const
Definition room.cc:2557
const std::vector< staircase > & GetStairs() const
Definition room.h:330
void ClearChestsDirty()
Definition room.h:327
gfx::BackgroundBuffer bg1_buffer_
Definition room.h:1204
bool torches_loaded_
Definition room.h:1246
void MarkSpritesDirty()
Definition room.h:319
bool has_water_fill_zone() const
Definition room.h:603
uint8_t palette() const
Definition room.h:1019
void ClearCollisionTile(int x, int y)
Definition room.h:589
RoomObject & GetTileObject(size_t index)
Definition room.h:531
void SetStaircasePlane(int index, uint8_t plane)
Definition room.h:816
absl::Status SaveObjects(const DungeonStreamLayout *layout=nullptr)
Definition room.cc:2442
void SetIsDark(bool is_dark)
Definition room.h:872
void MarkTorchesDirty()
Definition room.h:436
bool objects_loaded_
Definition room.h:1242
WaterFillZoneMap water_fill_zone_
Definition room.h:1314
auto rom() const
Definition room.h:1082
std::map< DungeonLimit, int > GetLimitedObjectCounts() const
Count limited objects in this room.
Definition room.cc:4699
void RenderRoomGraphics()
Definition room.cc:1254
void RestoreSaveDirtySnapshot(const SaveDirtySnapshot &snapshot)
Definition room.h:698
PaletteAddressMap rendered_palette_addresses_
Definition room.h:1200
absl::Status SaveRoomHeader()
Definition room.cc:2681
gfx::Bitmap composite_bitmap_
Definition room.h:1233
std::map< uint16_t, std::vector< uint8_t > > graphics_sheet_overrides_
Definition room.h:1193
bool HasCollisionOverride(int x, int y) const
Definition room.h:577
const gfx::SnesPalette & rendered_dungeon_palette() const
Definition room.h:1132
Room & operator=(Room &&)
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetSpriteSaveWriteRanges(const DungeonStreamLayout *layout=nullptr) const
Definition room.cc:2667
bool chests_dirty() const
Definition room.h:325
uint8_t sprite_tileset_
Definition room.h:1280
uint64_t composite_signature_
Definition room.h:1234
std::vector< RoomObject > & GetTileObjects()
Definition room.h:448
uint16_t message_id_
Definition room.h:1277
TagKey tag1() const
Definition room.h:987
std::vector< PotItem > & GetPotItems()
Definition room.h:430
CollisionKey collision() const
Definition room.h:989
const RoomLayout & GetLayout() const
Definition room.h:442
void MarkTileObjectDomainsDirtyForSnapshot(const std::vector< RoomObject > &objects)
Definition room.h:495
void SetMessageIdDirect(uint16_t mid)
Definition room.h:847
void AddDoor(const Door &door)
Definition room.h:415
void LoadRoomGraphics(std::optional< uint8_t > entrance_blockset=std::nullopt)
Definition room.cc:953
uint8_t staircase_rooms_[4]
Definition room.h:1267
const auto & bg1_buffer() const
Definition room.h:1147
bool water_fill_dirty_
Definition room.h:1315
gfx::Bitmap & GetCompositeBitmap(RoomLayerManager &layer_mgr)
Get a composite bitmap of all layers merged.
Definition room.cc:1230
std::vector< uint8_t > EncodeObjects() const
Definition room.cc:2067
void SetEffect(EffectKey effect)
Definition room.h:795
absl::Status SaveObjectStreamHeader(const DungeonStreamLayout *layout=nullptr)
Definition room.cc:2564
gfx::BackgroundBuffer object_bg2_buffer_
Definition room.h:1207
uint8_t spriteset() const
Definition room.h:1018
void ClearWaterFillDirty()
Definition room.h:655
Room & operator=(const Room &)=delete
absl::StatusOr< StreamSavePlan > PlanObjectSave(const DungeonStreamLayout *layout) const
Definition room.cc:2332
absl::StatusOr< StreamSavePlan > PlanSpriteSave(const DungeonStreamLayout *layout) const
Definition room.cc:2574
uint8_t holewarp_
Definition room.h:1276
uint8_t layout_id_
Definition room.h:1275
std::array< uint8_t, 16 > blocks_
Definition room.h:1286
void SetTag1(TagKey tag1)
Definition room.h:802
void SetBackgroundTileset(uint8_t tileset)
Definition room.h:878
void SetStair3TargetLayer(uint8_t layer)
Definition room.h:926
void SetRenderEntranceBlockset(uint8_t entrance_blockset)
Definition room.h:788
const std::vector< zelda3::Sprite > & GetSprites() const
Definition room.h:316
uint8_t floor2_graphics_
Definition room.h:1283
background2 bg2_
Definition room.h:1304
std::array< chest, 16 > chest_list_
Definition room.h:1287
absl::Status SaveSprites(const DungeonStreamLayout *layout=nullptr)
Definition room.cc:2672
uint64_t graphics_revision() const
Definition room.h:1125
auto & bg1_buffer()
Definition room.h:1145
void PrepareForRender(std::optional< uint8_t > entrance_blockset=std::nullopt)
Definition room.cc:1058
const std::vector< RoomObject > & GetTileObjects() const
Definition room.h:445
bool IsLight() const
Definition room.h:844
uint8_t floor1_graphics_
Definition room.h:1282
DungeonState * GetDungeonState()
Definition room.h:1165
const LayerMergeType & layer_merging() const
Definition room.h:990
void ClearBlocksDirty()
Definition room.h:440
auto blocks() const
Definition room.h:1080
void MarkWaterFillDirty()
Definition room.h:656
void SetLayerMerging(LayerMergeType merging)
Definition room.h:865
void SetPitsTargetLayer(uint8_t layer)
Definition room.h:908
void LoadObjects()
Definition room.cc:1891
void ClearTorchesDirty()
Definition room.h:437
void LoadPotItems()
Definition room.cc:4611
int BackgroundPaletteOffset(int slot) const
Definition room.cc:1085
void MarkObjectStreamDirty()
Definition room.h:476
absl::StatusOr< StreamSavePlan > PlanObjectStreamHeaderSave(const DungeonStreamLayout *layout) const
Definition room.cc:2451
void ClearSpritesDirty()
Definition room.h:320
const PaletteAddressMap & rendered_palette_addresses() const
Definition room.h:1135
bool blocks_dirty() const
Definition room.h:438
bool GetWaterFillTile(int x, int y) const
Definition room.h:605
uint8_t blockset_
Definition room.h:1270
EffectKey effect() const
Definition room.h:986
void SetSpriteTileset(uint8_t tileset)
Definition room.h:884
void SetStair1Target(uint8_t target)
Definition room.h:944
bool pot_items_loaded_
Definition room.h:1245
destination stair3_
Definition room.h:1308
void SetBg2(background2 bg2)
Definition room.h:730
std::vector< chest_data > & GetChests()
Definition room.h:324
static constexpr uint8_t kObjectHeaderLayoutDirty
Definition room.h:1230
bool torches_dirty() const
Definition room.h:435
void EnsureObjectsLoaded()
Definition room.cc:1026
uint64_t composite_source_revision_
Definition room.h:1197
void MarkHeaderDirty()
Definition room.h:659
bool AreObjectsLoaded() const
Definition room.h:972
void SetSpriteset(uint8_t ss)
Definition room.h:781
uint8_t floor1() const
Definition room.h:1041
uint64_t composite_source_revision() const
Definition room.h:1129
void SetTileObjects(const std::vector< RoomObject > &objects)
Definition room.h:721
void MarkCompositeDirty()
Mark composite bitmap as needing regeneration.
Definition room.cc:1243
int ResolveDungeonPaletteId() const
Definition room.cc:921
std::unique_ptr< DungeonState > dungeon_state_
Definition room.h:1317
void LoadAnimatedGraphics()
Definition room.cc:1840
std::vector< uint8_t > EncodeSprites() const
Definition room.cc:2155
void SetCollisionTile(int x, int y, uint8_t tile)
Definition room.h:582
std::vector< chest_data > chests_in_room_
Definition room.h:1293
void SetBlockset(uint8_t bs)
Definition room.h:773
uint8_t spriteset_
Definition room.h:1273
LayerMergeType layer_merging_
Definition room.h:1298
SaveDirtySnapshot CaptureSaveDirtySnapshot() const
Definition room.h:673
background2 bg2() const
Definition room.h:985
bool water_fill_dirty() const
Definition room.h:654
bool chests_loaded_
Definition room.h:1244
void EnsurePotItemsLoaded()
Definition room.cc:1040
uint8_t staircase_plane(int index) const
Definition room.h:995
bool has_composite_signature_
Definition room.h:1236
void MarkCustomCollisionDirty()
Definition room.h:598
const RoomObject & GetTileObject(size_t index) const
Definition room.h:532
std::vector< std::pair< uint16_t, uint64_t > > source_sheet_revisions_
Definition room.h:1195
bool AreTorchesLoaded() const
Definition room.h:976
uint8_t cached_spriteset_
Definition room.h:1254
std::array< uint8_t, 0x10000 > current_gfx16_
Definition room.h:1192
std::vector< staircase > z3_staircases_
Definition room.h:1292
uint8_t render_entrance_blockset() const
Definition room.h:1016
std::vector< PotItem > pot_items_
Definition room.h:1295
bool blocks_loaded_
Definition room.h:1247
void LoadSprites()
Definition room.cc:2886
bool AreBlocksLoaded() const
Definition room.h:982
TagKey cached_tag1_
Definition room.h:1260
destination stair1_
Definition room.h:1306
const DungeonState * GetDungeonState() const
Definition room.h:1166
int water_fill_tile_count_
Definition room.h:1316
bool AreSpritesLoaded() const
Definition room.h:973
uint8_t background_tileset_
Definition room.h:1279
void SetStair3Target(uint8_t target)
Definition room.h:956
DirtyState dirty_state_
Definition room.h:1237
void HandleSpecialObjects(short oid, uint8_t posX, uint8_t posY, int &nbr_of_staircase)
Definition room.cc:2848
void SetStair4TargetLayer(uint8_t layer)
Definition room.h:932
absl::Status AddObject(const RoomObject &object)
Definition room.cc:2772
absl::StatusOr< size_t > FindObjectAt(int x, int y, int layer) const
Definition room.cc:2816
void RemoveTileObject(size_t index)
Definition room.h:522
void SetPalette(uint8_t pal)
Definition room.h:766
uint8_t layout_id() const
Definition room.h:1026
bool has_custom_collision() const
Definition room.h:563
MetadataSnapshot CaptureMetadataSnapshot() const
Definition room.cc:861
const std::vector< PotItem > & GetPotItems() const
Definition room.h:429
void SetRom(Rom *rom)
Definition room.h:1085
uint8_t water_fill_sram_bit_mask() const
Definition room.h:644
void RemoveDoor(size_t index)
Definition room.h:420
void SetStair2TargetLayer(uint8_t layer)
Definition room.h:920
Room(const Room &)=delete
const auto & bg2_buffer() const
Definition room.h:1148
const GameData * game_data() const
Definition room.h:1087
void RenderObjectsToBackground()
Definition room.cc:1588
friend ResolvedGraphicsContext DescribeDungeonGraphicsContext(const Room &room, const GraphicsContextIdentity &identity)
CollisionKey collision_
Definition room.h:1299
bool AreChestsLoaded() const
Definition room.h:974
void SetGameData(GameData *data)
Definition room.h:1088
auto & object_bg1_buffer()
Definition room.h:1149
auto & bg2_buffer()
Definition room.h:1146
uint8_t resolved_main_blockset() const
Definition room.h:1017
void SetLayer2Behavior(uint8_t behavior)
Definition room.h:890
void SetWaterFillTile(int x, int y, bool filled)
Definition room.h:611
void SetMessageId(uint16_t mid)
Definition room.h:836
int id() const
Definition room.h:1012
zelda3_bg2_effect
Background layer 2 effects.
Definition zelda.h:369
absl::Status SaveAllChests(Rom *rom, absl::Span< const Room > rooms)
Definition room.cc:4366
constexpr DoorDirection DoorDirectionFromRaw(uint8_t raw_dir)
Convert raw direction byte to DoorDirection enum.
Definition door_types.h:353
const std::string RoomTag[65]
Definition room.cc:280
constexpr DoorDimensions GetDoorDimensions(DoorDirection dir)
Get door dimensions based on direction.
Definition door_types.h:253
DoorType
Door types from ALTTP.
Definition door_types.h:33
constexpr int ResolveHeaderDestinationRoom(int source_room_id, uint8_t header_byte)
constexpr int PotItemPixelX(uint16_t word)
Room LoadRoomHeaderFromRom(Rom *rom, int room_id)
Definition room.cc:680
@ Ganon_Room
Definition room.h:134
@ Moving_Floor
Definition room.h:129
@ Effect_Nothing
Definition room.h:127
@ Red_Flashes
Definition room.h:132
@ Moving_Water
Definition room.h:130
@ Torch_Show_Floor
Definition room.h:133
absl::StatusOr< ChestSavePlan > BuildChestSavePlan(const Rom *rom, int room_count, const std::function< const Room *(int)> &room_lookup)
Definition room.cc:4269
int FindMaxUsedSpriteAddress(Rom *rom)
Definition room.cc:2193
absl::Status RelocateSpriteData(Rom *rom, int room_id, const std::vector< uint8_t > &encoded_bytes)
Definition room.cc:2233
@ Moving_Water_Collision
Definition room.h:123
@ One_Collision
Definition room.h:119
@ Moving_Floor_Collision
Definition room.h:122
@ Both_With_Scroll
Definition room.h:121
gfx::PaletteGroup BuildDungeonRenderPaletteGroup(const gfx::SnesPalette &dungeon_palette, const gfx::SnesPalette *hud_palette)
Definition room.cc:164
@ Kill_boss_Again
Definition room.h:216
@ Secret_Wall_Right
Definition room.h:181
@ Kill_Enemy_to_clear_level
Definition room.h:190
@ NE_Kill_Enemy_to_Open
Definition room.h:155
@ S_Kill_Enemy_for_Chest
Definition room.h:201
@ N_Push_Block_to_Open
Definition room.h:170
@ E_Kill_Enemy_to_Open
Definition room.h:159
@ Light_Torches_to_Open
Definition room.h:204
@ N_Kill_Enemy_to_Open
Definition room.h:160
@ W_Kill_Enemy_for_Chest
Definition room.h:198
@ Water_Twin
Definition room.h:180
@ N_Kill_Enemy_for_Chest
Definition room.h:200
@ Clear_Level_to_Open
Definition room.h:174
@ Push_Block_to_Open
Definition room.h:172
@ E_Kill_Enemy_for_Chest
Definition room.h:199
@ Secret_Wall_Left
Definition room.h:182
@ NE_Push_Block_to_Open
Definition room.h:165
@ Open_Chest_for_Holes_8
Definition room.h:212
@ S_Kill_Enemy_to_Open
Definition room.h:161
@ S_Push_Block_to_Open
Definition room.h:171
@ Trigger_activated_Chest
Definition room.h:192
@ SW_Kill_Enemy_for_Chest
Definition room.h:196
@ SE_Kill_Enemy_for_Chest
Definition room.h:197
@ Pull_lever_to_Bomb_Wall
Definition room.h:193
@ Pull_Switch_to_bomb_Wall
Definition room.h:185
@ Agahnim_Room
Definition room.h:209
@ Water_Gate
Definition room.h:179
@ SE_Kill_Enemy_to_Move_Block
Definition room.h:191
@ NE_Kill_Enemy_for_Chest
Definition room.h:195
@ SE_Push_Block_to_Open
Definition room.h:167
@ Pull_Lever_to_Open
Definition room.h:173
@ W_Push_Block_to_Open
Definition room.h:168
@ E_Push_Block_to_Open
Definition room.h:169
@ Kill_to_open_Ganon_Door
Definition room.h:214
@ SW_Push_Block_to_Open
Definition room.h:166
@ Turn_on_Water
Definition room.h:178
@ W_Kill_Enemy_to_Open
Definition room.h:158
@ Open_Chest_Activate_Holes_0
Definition room.h:187
@ Clear_Room_for_Chest
Definition room.h:203
@ Clear_Room_to_Open
Definition room.h:163
@ NW_Push_Block_to_Open
Definition room.h:164
@ Switch_Open_Door_Toggle
Definition room.h:176
@ SW_Kill_Enemy_to_Open
Definition room.h:156
@ Clear_Quadrant_for_Chest
Definition room.h:202
@ NW_Kill_Enemy_to_Open
Definition room.h:154
@ Switch_Open_Door_Hold
Definition room.h:175
@ SE_Kill_Enemy_to_Open
Definition room.h:157
@ Turn_off_Water
Definition room.h:177
@ Clear_Quadrant_to_Open
Definition room.h:162
@ Push_Block_for_Chest
Definition room.h:213
@ NW_Kill_Enemy_for_Chest
Definition room.h:194
@ Light_Torches_to_get_Chest
Definition room.h:215
absl::Status SaveAllPotItems(Rom *rom, absl::Span< const Room > rooms)
Definition room.cc:4491
gfx::PaletteGroup BuildDungeonRenderPaletteGroupFromGameData(const gfx::SnesPalette &dungeon_palette, const GameData *game_data)
Definition room.cc:191
RoomSize CalculateRoomSize(Rom *rom, int room_id)
Definition room.cc:630
void LoadDungeonRenderPaletteToCgram(std::span< uint16_t > cgram, const gfx::SnesPalette &dungeon_palette, const gfx::SnesPalette *hud_palette)
Definition room.cc:256
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetChestTableWriteRanges(const Rom *rom)
Definition room.cc:3945
absl::Status SaveAllTorches(Rom *rom, absl::Span< const Room > rooms)
Definition room.cc:3331
constexpr int PotItemPixelY(uint16_t word)
constexpr std::string_view GetDoorDirectionName(DoorDirection dir)
Get human-readable name for door direction.
Definition door_types.h:204
absl::Status SaveAllPits(Rom *rom)
Definition room.cc:3358
absl::Status SaveAllBlocks(Rom *rom)
Definition room.cc:3543
std::vector< SDL_Color > BuildDungeonRenderPalette(const gfx::SnesPalette &dungeon_palette, const gfx::SnesPalette *hud_palette, PaletteAddressMap *addresses, int palette_id)
Definition room.cc:138
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetDirtyChestWriteRanges(const Rom *rom, int room_count, const std::function< const Room *(int)> &room_lookup)
Definition room.cc:4276
Room LoadRoomFromRom(Rom *rom, int room_id)
Definition room.cc:655
constexpr DoorType DoorTypeFromRaw(uint8_t raw_type)
Convert raw type byte to DoorType enum.
Definition door_types.h:345
constexpr std::array< std::string_view, 297 > kRoomNames
Definition room.h:1478
constexpr std::string_view GetDoorTypeName(DoorType type)
Get human-readable name for door type.
Definition door_types.h:110
absl::Status ApplyChestSavePlan(Rom *rom, const ChestSavePlan &plan, const std::function< const Room *(int)> &room_lookup)
Definition room.cc:4283
const std::string RoomEffect[8]
Definition room.cc:270
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetTorchSaveWriteRanges(const Rom *rom, int room_count, const std::function< const Room *(int)> &room_lookup)
Definition room.cc:3343
std::array< SDL_Color, 256 > BuildDungeonSpriteRenderPalette(const Room &room, const GameData *game_data)
Definition room.cc:200
DoorDirection
Door direction on room walls.
Definition door_types.h:18
absl::Status SaveAllCollision(Rom *rom, absl::Span< Room > rooms)
Definition room.cc:3933
absl::StatusOr< std::vector< std::pair< uint32_t, uint32_t > > > GetBlockSaveWriteRanges(const Rom *rom, int room_count, const std::function< const Room *(int)> &room_lookup)
Definition room.cc:3830
constexpr DoorDimensions GetEditorDoorDimensions(DoorDirection dir, DoorType type)
Get visible editor dimensions for compatibility with UI callers.
Definition door_types.h:309
std::array< std::optional< PaletteColorAddress >, 128 > PaletteAddressMap
Room transition destination.
Definition zelda.h:448
uint8_t target_layer
Definition zelda.h:451
uint8_t target
Definition zelda.h:450
bool operator==(const ChestDirtyRoomState &) const =default
std::vector< uint8_t > encoded_chests
Definition room.h:1409
std::vector< uint8_t > original_capacity_bytes
Definition room.h:1424
bool operator==(const ChestSavePlan &) const =default
std::vector< std::pair< uint32_t, uint32_t > > write_ranges() const
Definition room.h:1430
uint16_t original_byte_length
Definition room.h:1423
std::vector< ChestWriteRun > writes
Definition room.h:1425
std::array< uint8_t, 3 > pointer_operand
Definition room.h:1422
std::vector< ChestDirtyRoomState > dirty_rooms
Definition room.h:1426
std::vector< uint8_t > expected_bytes
Definition room.h:1397
std::vector< uint8_t > replacement_bytes
Definition room.h:1398
bool operator==(const ChestWriteRun &) const =default
uint32_t end() const
Definition room.h:1402
std::array< uint8_t, 64 *64 > tiles
bool HasOverride(size_t offset) const
void SetOverride(size_t offset, uint8_t tile)
Door dimensions in tiles (8x8 pixel tiles)
Definition door_types.h:221
zelda3_version version
Definition game_data.h:84
LayerMergeType(uint8_t id, std::string name, bool see, bool top, bool trans)
Definition room.h:84
bool operator==(const LayerMergeType &) const =default
int GetPixelX() const
Definition room.h:144
int GetPixelY() const
Definition room.h:145
int GetTileY() const
Definition room.h:149
int GetTileX() const
Definition room.h:148
uint16_t position
Definition room.h:140
int64_t room_size_pointer
Definition room.h:1327
Represents a door in a dungeon room.
Definition room.h:339
std::tuple< int, int, int, int > GetEditorBounds() const
Get editor interaction bounds (x, y, width, height in pixels)
Definition room.h:373
std::tuple< int, int, int, int > GetBounds() const
Get bounding rectangle (x, y, width, height in pixels)
Definition room.h:368
std::string_view GetTypeName() const
Get human-readable type name.
Definition room.h:379
uint8_t byte1
Original ROM byte 1 (position data)
Definition room.h:344
DoorDimensions GetDimensions() const
Get door dimensions in tiles.
Definition room.h:358
DoorType type
Door type (determines appearance/behavior)
Definition room.h:341
static Door FromRomBytes(uint8_t b1, uint8_t b2)
Definition room.h:397
std::pair< uint8_t, uint8_t > EncodeBytes() const
Encode door data for ROM storage.
Definition room.h:389
DoorDirection direction
Which wall the door is on.
Definition room.h:342
DoorDimensions GetEditorDimensions() const
Get editor interaction dimensions in tiles.
Definition room.h:363
uint8_t position
Encoded position (5-bit, 0-31)
Definition room.h:340
std::string_view GetDirectionName() const
Get human-readable direction name.
Definition room.h:384
std::pair< int, int > GetPixelCoords() const
Get pixel coordinates for this door.
Definition room.h:353
uint8_t byte2
Original ROM byte 2 (type + direction)
Definition room.h:345
std::pair< int, int > GetTileCoords() const
Get tile coordinates for this door.
Definition room.h:348
bool operator==(const MetadataSnapshot &) const =default
std::array< uint8_t, 4 > staircase_planes
Definition room.h:252
std::array< uint8_t, 4 > staircase_rooms
Definition room.h:251
std::vector< BlockLoadOrder > block_load_orders
Definition room.h:277
std::vector< std::pair< uint32_t, uint32_t > > write_ranges() const
Definition room.cc:2292
std::optional< std::pair< uint32_t, uint32_t > > direct_long_write
Definition room.h:1171
std::optional< DungeonStreamWritePlan > relocation
Definition room.h:1172
std::vector< std::pair< uint32_t, std::vector< uint8_t > > > direct_writes
Definition room.h:1170
std::array< uint8_t, 64 *64 > tiles
Definition room.h:223
ROM data pointers for different game versions.
Definition zelda.h:71
Public YAZE API umbrella header.