yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
room_layout.cc
Go to the documentation of this file.
1#include "room_layout.h"
2
3#include "absl/strings/str_format.h"
4#include "rom/snes.h"
5#include "util/log.h"
8
9namespace yaze::zelda3 {
10
11namespace {
12// kLayerTerminator unused
13// ReadWord unused
14} // namespace
15
16absl::StatusOr<int> RoomLayout::GetLayoutAddress(int layout_id) const {
17 if (!rom_ || !rom_->is_loaded()) {
18 return absl::FailedPreconditionError("ROM not loaded");
19 }
20
21 if (layout_id < 0 ||
22 layout_id >= static_cast<int>(kRoomLayoutPointers.size())) {
23 return absl::InvalidArgumentError(
24 absl::StrFormat("Invalid layout id %d", layout_id));
25 }
26
27 uint32_t snes_addr = kRoomLayoutPointers[layout_id];
28 int pc_addr = SnesToPc(static_cast<int>(snes_addr));
29 if (pc_addr < 0 || pc_addr >= static_cast<int>(rom_->size())) {
30 return absl::OutOfRangeError(
31 absl::StrFormat("Layout pointer %d out of range", layout_id));
32 }
33 return pc_addr;
34}
35
36absl::Status RoomLayout::LoadLayout(int layout_id) {
37 objects_.clear();
38
39 auto addr_result = GetLayoutAddress(layout_id);
40 if (!addr_result.ok()) {
41 return addr_result.status();
42 }
43
44 int pos = addr_result.value();
45 const auto& rom_data = rom_->data();
46 int layer = 0;
47
48 // DEBUG: Use printf for visibility (LOG_DEBUG may be filtered)
49 printf("[RoomLayout] Loading layout %d from PC address 0x%05X\n",
50 layout_id, pos);
51 fflush(stdout); // Ensure output is visible
52 LOG_DEBUG("[RoomLayout]", "Loading layout %d from PC address 0x%05X",
53 layout_id, pos);
54
55 int obj_index = 0;
56 while (pos + 2 < static_cast<int>(rom_->size())) {
57 uint8_t b1 = rom_data[pos];
58 uint8_t b2 = rom_data[pos + 1];
59
60 if (b1 == 0xFF && b2 == 0xFF) {
61 // $FF $FF is the END terminator for this layout
62 // Each RoomLayout_XX in ROM is a single block terminated by $FF $FF
63 // We should NOT continue reading - that would read the NEXT layout's data
64 printf("[RoomLayout] Layout %d terminated at pos=0x%05X after %d objects\n",
65 layout_id, pos, obj_index);
66 fflush(stdout);
67 break;
68 }
69
70 if (pos + 2 >= static_cast<int>(rom_->size())) {
71 break;
72 }
73
74 uint8_t b3 = rom_data[pos + 2];
75 pos += 3;
76
78 b1, b2, b3, static_cast<uint8_t>(layer));
79 obj.SetRom(rom_);
81 objects_.push_back(obj);
82
83 // Enhanced debug logging for ALL layouts to trace rendering issues
84 // DEBUG: Use printf for wall/corner objects (LOG_DEBUG may be filtered)
85 if (obj.id_ == 0x001 || obj.id_ == 0x002 ||
86 obj.id_ == 0x061 || obj.id_ == 0x062 ||
87 (obj.id_ >= 0x100 && obj.id_ <= 0x103)) {
88 printf("[RoomLayout] Layout %d obj[%d]: bytes=[%02X,%02X,%02X] -> id=0x%03X x=%d y=%d size=%d layer=%d tiles=%zu\n",
89 layout_id, obj_index, b1, b2, b3,
90 obj.id_, obj.x_, obj.y_, obj.size_, layer, obj.tiles().size());
91 fflush(stdout); // Ensure output is visible
92 }
93 LOG_DEBUG("[RoomLayout]",
94 "Layout %d obj[%d]: bytes=[%02X,%02X,%02X] -> id=0x%03X x=%d y=%d size=%d layer=%d tiles=%zu",
95 layout_id, obj_index, b1, b2, b3,
96 obj.id_, obj.x_, obj.y_, obj.size_, layer, obj.tiles().size());
97 obj_index++;
98 }
99
100 printf("[RoomLayout] Layout %d loaded with %zu objects\n",
101 layout_id, objects_.size());
102 fflush(stdout); // Ensure output is visible
103 LOG_DEBUG("[RoomLayout]", "Layout %d loaded with %zu objects",
104 layout_id, objects_.size());
105
106 return absl::OkStatus();
107}
108
109absl::Status RoomLayout::Draw(int room_id, const uint8_t* gfx_data,
112 const gfx::PaletteGroup& palette_group,
113 DungeonState* state) const {
114 if (!rom_ || !rom_->is_loaded()) {
115 return absl::FailedPreconditionError("ROM not loaded");
116 }
117
118 if (objects_.empty()) {
119 return absl::OkStatus();
120 }
121
122 ObjectDrawer drawer(rom_, room_id, gfx_data);
123 return drawer.DrawObjectList(objects_, bg1, bg2, palette_group, state);
124}
125
126} // namespace yaze::zelda3
auto data() const
Definition rom.h:135
auto size() const
Definition rom.h:134
bool is_loaded() const
Definition rom.h:128
Interface for accessing dungeon game state.
Draws dungeon objects to background buffers using game patterns.
absl::Status DrawObjectList(const std::vector< RoomObject > &objects, gfx::BackgroundBuffer &bg1, gfx::BackgroundBuffer &bg2, const gfx::PaletteGroup &palette_group, const DungeonState *state=nullptr, gfx::BackgroundBuffer *layout_bg1=nullptr)
Draw all objects in a room.
std::vector< RoomObject > objects_
Definition room_layout.h:37
absl::Status Draw(int room_id, const uint8_t *gfx_data, gfx::BackgroundBuffer &bg1, gfx::BackgroundBuffer &bg2, const gfx::PaletteGroup &palette_group, DungeonState *state) const
absl::StatusOr< int > GetLayoutAddress(int layout_id) const
absl::Status LoadLayout(int layout_id)
static RoomObject DecodeObjectFromBytes(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t layer)
const std::vector< gfx::TileInfo > & tiles() const
Definition room_object.h:88
void SetRom(Rom *rom)
Definition room_object.h:68
#define LOG_DEBUG(category, format,...)
Definition log.h:103
Zelda 3 specific classes and functions.
Definition editor.h:35
uint32_t SnesToPc(uint32_t addr) noexcept
Definition snes.h:8
Represents a group of palettes.