6#include "absl/strings/str_format.h"
20 : rom_(rom), room_id_(room_id), room_gfx_buffer_(room_gfx_buffer) {
31 return absl::FailedPreconditionError(
"ROM not loaded");
35 return absl::FailedPreconditionError(
"Draw routines not initialized");
39 auto mutable_obj =
const_cast<RoomObject&
>(object);
41 mutable_obj.EnsureTilesLoaded();
47 if (mutable_obj.tiles().empty()) {
49 if (
object.id_ == 0x001 ||
object.id_ == 0x002 ||
50 object.id_ == 0x061 ||
object.id_ == 0x062 ||
51 (
object.id_ >= 0x100 &&
object.id_ <= 0x103)) {
52 printf(
"[DrawObject] Object 0x%03X at (%d,%d) has NO TILES - skipping!\n",
53 object.id_,
object.x_,
object.y_);
55 LOG_DEBUG(
"ObjectDrawer",
"Object 0x%03X at (%d,%d) has NO TILES - skipping",
56 object.id_,
object.x_,
object.y_);
57 return absl::OkStatus();
62 int subtype =
object.size_ & 0x1F;
71 if (
object.all_bgs_) {
82 if (
object.id_ == 0x001 ||
object.id_ == 0x002 ||
83 object.id_ == 0x061 ||
object.id_ == 0x062 ||
84 (
object.id_ >= 0x100 &&
object.id_ <= 0x103)) {
85 printf(
"[DrawObject] obj=0x%03X pos=(%d,%d) size=%d -> routine=%d tiles=%zu\n",
86 object.id_,
object.x_,
object.y_,
object.size_, routine_id,
87 mutable_obj.tiles().size());
93 for (
size_t i = 0; i < std::min(
size_t(4), mutable_obj.tiles().size()); i++) {
94 tile_ids += absl::StrFormat(
"0x%03X,", mutable_obj.tiles()[i].id_);
96 if (mutable_obj.tiles().size() > 4) tile_ids +=
"...";
99 "Object 0x%03X at (%d,%d) size=%d -> routine=%d tiles=[%s] (count=%zu)",
100 object.id_,
object.x_,
object.y_,
object.size_, routine_id,
101 tile_ids.c_str(), mutable_obj.tiles().size());
103 if (routine_id < 0 || routine_id >=
static_cast<int>(
draw_routines_.size())) {
104 printf(
"[DrawObject] Object 0x%03X: NO ROUTINE (id=%d, max=%zu) - using fallback 1x1\n",
107 "Object 0x%03X: NO ROUTINE (id=%d, max=%zu) - using fallback 1x1",
110 if (!mutable_obj.tiles().empty()) {
111 const auto& tile_info = mutable_obj.tiles()[0];
112 WriteTile8(target_bg,
object.x_,
object.y_, tile_info);
114 return absl::OkStatus();
123 draw_routines_[routine_id](
this, object, bg1, mutable_obj.tiles(), state);
124 draw_routines_[routine_id](
this, object, bg2, mutable_obj.tiles(), state);
137 printf(
"[BG2 Mask] Object 0x%03X at (%d,%d) size=%d -> marking %dx%d pixels transparent\n",
138 object.id_,
object.x_,
object.y_,
object.size_, pixel_width, pixel_height);
144 if (layout_bg1 !=
nullptr) {
145 printf(
"[BG2 Mask] Also marking layout buffer transparent for object 0x%03X\n",
object.id_);
152 return absl::OkStatus();
161 absl::Status status = absl::OkStatus();
162 for (
const auto&
object : objects) {
163 auto s =
DrawObject(
object, bg1, bg2, palette_group, state, layout_bg1);
164 if (!s.ok() && status.ok()) {
171 auto& bg1_bmp = bg1.
bitmap();
172 auto& bg2_bmp = bg2.
bitmap();
175 if (bg1_bmp.modified() && bg1_bmp.surface() &&
176 bg1_bmp.mutable_data().size() > 0) {
177 SDL_LockSurface(bg1_bmp.surface());
180 size_t surface_size = bg1_bmp.surface()->h * bg1_bmp.surface()->pitch;
181 size_t buffer_size = bg1_bmp.mutable_data().size();
183 if (surface_size >= buffer_size) {
186 memcpy(bg1_bmp.surface()->pixels, bg1_bmp.mutable_data().data(),
189 LOG_DEBUG(
"ObjectDrawer",
"BG1 Surface too small: surf=%zu buf=%zu", surface_size, buffer_size);
191 SDL_UnlockSurface(bg1_bmp.surface());
194 if (bg2_bmp.modified() && bg2_bmp.surface() &&
195 bg2_bmp.mutable_data().size() > 0) {
196 SDL_LockSurface(bg2_bmp.surface());
197 size_t surface_size = bg2_bmp.surface()->h * bg2_bmp.surface()->pitch;
198 size_t buffer_size = bg2_bmp.mutable_data().size();
200 if (surface_size >= buffer_size) {
201 memcpy(bg2_bmp.surface()->pixels, bg2_bmp.mutable_data().data(),
204 LOG_DEBUG(
"ObjectDrawer",
"BG2 Surface too small: surf=%zu buf=%zu", surface_size, buffer_size);
206 SDL_UnlockSurface(bg2_bmp.surface());
231 static constexpr int kBothBGRoutines[] = {
245 for (
int id : kBothBGRoutines) {
246 if (routine_id ==
id)
return true;
277 for (
int id = 0x01;
id <= 0x02;
id++) {
282 for (
int id = 0x03;
id <= 0x04;
id++) {
285 for (
int id = 0x05;
id <= 0x06;
id++) {
288 for (
int id = 0x07;
id <= 0x08;
id++) {
292 for (
int id = 0x0A;
id <= 0x0B;
id++) {
299 for (
int id : {0x0C, 0x0D, 0x10, 0x11, 0x14}) {
303 for (
int id : {0x0E, 0x0F, 0x12, 0x13}) {
308 for (
int id : {0x15, 0x18, 0x19, 0x1C, 0x1D, 0x20}) {
312 for (
int id : {0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F}) {
320 for (
int id = 0x23;
id <= 0x2E;
id++) {
345 for (
int id = 0x3F;
id <= 0x46;
id++) {
394 for (
int id = 0x61;
id <= 0x62;
id++) {
397 for (
int id = 0x63;
id <= 0x64;
id++) {
400 for (
int id = 0x65;
id <= 0x66;
id++) {
403 for (
int id = 0x67;
id <= 0x68;
id++) {
407 for (
int id = 0x6A;
id <= 0x6B;
id++) {
489 for (
int id = 0x97;
id <= 0x9F;
id++) {
559 for (
int id = 0xC5;
id <= 0xCA;
id++) {
603 for (
int id = 0xE0;
id <= 0xE8;
id++) {
607 for (
int id = 0xE9;
id <= 0xEF;
id++) {
612 for (
int id = 0xF0;
id <= 0xF7;
id++) {
616 for (
int id = 0xF9;
id <= 0xFD;
id++) {
628 for (
int id = 0x100;
id <= 0x103;
id++) {
632 for (
int id = 0x104;
id <= 0x107;
id++) {
635 for (
int id = 0x108;
id <= 0x10F;
id++) {
638 for (
int id = 0x110;
id <= 0x113;
id++) {
641 for (
int id = 0x114;
id <= 0x117;
id++) {
645 for (
int id = 0x118;
id <= 0x11B;
id++) {
686 for (
int id = 0x130;
id <= 0x133;
id++) {
721 for (
int id = 0xF83;
id <= 0xF89;
id++) {
724 for (
int id = 0xF8A;
id <= 0xF8C;
id++) {
753 for (
int id = 0xF9B;
id <= 0xF9D;
id++) {
758 for (
int id = 0xF9E;
id <= 0xFA1;
id++) {
762 for (
int id = 0xFA2;
id <= 0xFA5;
id++) {
766 for (
int id = 0xFA6;
id <= 0xFA9;
id++) {
790 for (
int id = 0xFB4;
id <= 0xFB9;
id++) {
800 for (
int id = 0xFBE;
id <= 0xFC6;
id++) {
819 for (
int id = 0xFCF;
id <= 0xFD3;
id++) {
827 for (
int id = 0xFD6;
id <= 0xFDA;
id++) {
845 for (
int id = 0xFE3;
id <= 0xFE5;
id++) {
888 for (
int id = 0xFFC;
id <= 0xFFE;
id++) {
901 std::span<const gfx::TileInfo> tiles,
908 std::span<const gfx::TileInfo> tiles,
915 std::span<const gfx::TileInfo> tiles,
922 std::span<const gfx::TileInfo> tiles,
929 std::span<const gfx::TileInfo> tiles,
936 std::span<const gfx::TileInfo> tiles,
943 std::span<const gfx::TileInfo> tiles,
950 std::span<const gfx::TileInfo> tiles,
957 std::span<const gfx::TileInfo> tiles,
964 std::span<const gfx::TileInfo> tiles,
971 std::span<const gfx::TileInfo> tiles,
978 std::span<const gfx::TileInfo> tiles,
985 std::span<const gfx::TileInfo> tiles,
992 std::span<const gfx::TileInfo> tiles,
999 std::span<const gfx::TileInfo> tiles,
1006 std::span<const gfx::TileInfo> tiles,
1013 std::span<const gfx::TileInfo> tiles,
1020 std::span<const gfx::TileInfo> tiles,
1027 std::span<const gfx::TileInfo> tiles,
1034 std::span<const gfx::TileInfo> tiles,
1042 std::span<const gfx::TileInfo> tiles,
1049 std::span<const gfx::TileInfo> tiles,
1056 std::span<const gfx::TileInfo> tiles,
1063 std::span<const gfx::TileInfo> tiles,
1070 std::span<const gfx::TileInfo> tiles,
1077 std::span<const gfx::TileInfo> tiles,
1084 std::span<const gfx::TileInfo> tiles,
1091 std::span<const gfx::TileInfo> tiles,
1098 std::span<const gfx::TileInfo> tiles,
1105 std::span<const gfx::TileInfo> tiles,
1112 std::span<const gfx::TileInfo> tiles,
1119 std::span<const gfx::TileInfo> tiles,
1126 std::span<const gfx::TileInfo> tiles,
1133 std::span<const gfx::TileInfo> tiles,
1140 std::span<const gfx::TileInfo> tiles,
1147 std::span<const gfx::TileInfo> tiles,
1154 std::span<const gfx::TileInfo> tiles,
1161 std::span<const gfx::TileInfo> tiles,
1168 std::span<const gfx::TileInfo> tiles,
1175 std::span<const gfx::TileInfo> tiles,
1182 std::span<const gfx::TileInfo> tiles,
1189 std::span<const gfx::TileInfo> tiles,
1196 std::span<const gfx::TileInfo> tiles,
1203 std::span<const gfx::TileInfo> tiles,
1210 std::span<const gfx::TileInfo> tiles,
1217 std::span<const gfx::TileInfo> tiles,
1224 std::span<const gfx::TileInfo> tiles,
1231 std::span<const gfx::TileInfo> tiles,
1238 std::span<const gfx::TileInfo> tiles,
1245 std::span<const gfx::TileInfo> tiles,
1252 std::span<const gfx::TileInfo> tiles,
1259 std::span<const gfx::TileInfo> tiles,
1266 std::span<const gfx::TileInfo> tiles,
1273 std::span<const gfx::TileInfo> tiles,
1280 std::span<const gfx::TileInfo> tiles,
1287 std::span<const gfx::TileInfo> tiles,
1301 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1310 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1320 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1329 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1338 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1347 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1356 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1365 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1374 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1385 std::span<const gfx::TileInfo> tiles,
1393 std::span<const gfx::TileInfo> tiles,
1401 std::span<const gfx::TileInfo> tiles,
1409 std::span<const gfx::TileInfo> tiles,
1417 std::span<const gfx::TileInfo> tiles,
1425 std::span<const gfx::TileInfo> tiles,
1433 std::span<const gfx::TileInfo> tiles,
1441 std::span<const gfx::TileInfo> tiles,
1449 std::span<const gfx::TileInfo> tiles,
1457 std::span<const gfx::TileInfo> tiles,
1469 std::span<const gfx::TileInfo> tiles,
1477 std::span<const gfx::TileInfo> tiles,
1485 std::span<const gfx::TileInfo> tiles,
1493 std::span<const gfx::TileInfo> tiles,
1505 std::span<const gfx::TileInfo> tiles,
1513 std::span<const gfx::TileInfo> tiles,
1521 std::span<const gfx::TileInfo> tiles,
1529 std::span<const gfx::TileInfo> tiles,
1543 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1552 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1561 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1570 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1579 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1588 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1597 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1606 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1615 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1624 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1633 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1642 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1651 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr};
1660 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr,
nullptr};
1671 DrawContext ctx{bg, obj, tiles, state,
nullptr, 0,
nullptr,
nullptr};
1785 int size = obj.
size_ & 0x0F;
1786 int count = (size + 1) * 2;
1788 if (tiles.size() < 5)
return;
1791 for (
int row = 0; row < 5; row++) {
1796 for (
int s = 0; s < count; s++) {
1797 int col_x = obj.
x_ + 1 + s;
1798 for (
int row = 0; row < 5; row++) {
1800 size_t tile_idx = std::min(
size_t(5 + row), tiles.size() - 1);
1801 self->
WriteTile8(bg, col_x, obj.
y_ + row, tiles[tile_idx]);
1806 int last_x = obj.
x_ + 1 + count;
1807 for (
int row = 0; row < 5; row++) {
1808 size_t tile_idx = std::min(
size_t(10 + row), tiles.size() - 1);
1809 self->
WriteTile8(bg, last_x, obj.
y_ + row, tiles[tile_idx]);
1819 int size = obj.
size_ & 0x0F;
1820 int count = (size + 1) * 2;
1822 if (tiles.size() < 3)
return;
1825 for (
int row = 0; row < 3; row++) {
1830 for (
int s = 0; s < count; s++) {
1831 int col_x = obj.
x_ + 1 + s;
1832 for (
int row = 0; row < 3; row++) {
1838 int last_x = obj.
x_ + 1 + count;
1839 for (
int row = 0; row < 3; row++) {
1840 size_t tile_idx = std::min(
size_t(3 + row), tiles.size() - 1);
1841 self->
WriteTile8(bg, last_x, obj.
y_ + row, tiles[tile_idx]);
1958 printf(
"[DrawDoor] idx=%d type=%d dir=%d pos=%d\n",
1959 door_index,
static_cast<int>(door.
type),
1963 printf(
"[DrawDoor] SKIPPED - rom=%p loaded=%d gfx=%p\n",
1968 auto& bitmap = bg1.
bitmap();
1969 if (!bitmap.is_active() || bitmap.width() == 0) {
1970 printf(
"[DrawDoor] SKIPPED - bitmap not active or zero width\n");
1978 int door_height = dims.height_tiles;
1980 printf(
"[DrawDoor] tile_pos=(%d,%d) dims=%dx%d\n",
1981 tile_x, tile_y, door_width, door_height);
1990 int offset_table_addr = 0;
1999 int type_value =
static_cast<int>(door.
type);
2000 int type_index = type_value / 2;
2003 int table_entry_addr = offset_table_addr + (type_index * 2);
2004 if (table_entry_addr + 1 >=
static_cast<int>(
rom_->
size())) {
2010 const auto& rom_data =
rom_->
data();
2011 uint16_t tile_offset = rom_data[table_entry_addr] |
2012 (rom_data[table_entry_addr + 1] << 8);
2015 constexpr int kRoomDrawObjectDataBase = 0x1B52;
2016 int tile_data_addr = kRoomDrawObjectDataBase + tile_offset;
2018 printf(
"[DrawDoor] offset_table=0x%X type_idx=%d tile_offset=0x%X tile_addr=0x%X\n",
2019 offset_table_addr, type_index, tile_offset, tile_data_addr);
2022 int tiles_per_door = door_width * door_height;
2023 int data_size = tiles_per_door * 2;
2024 if (tile_data_addr < 0 || tile_data_addr + data_size >
static_cast<int>(
rom_->
size())) {
2025 printf(
"[DrawDoor] INVALID ADDRESS - falling back to indicator\n");
2034 printf(
"[DrawDoor] Reading %d tiles from 0x%X:\n", tiles_per_door, tile_data_addr);
2037 int bitmap_width = bitmap.width();
2039 for (
int dx = 0; dx < door_width; dx++) {
2040 for (
int dy = 0; dy < door_height; dy++) {
2041 int addr = tile_data_addr + (tile_idx * 2);
2042 uint16_t tile_word = rom_data[addr] | (rom_data[addr + 1] << 8);
2045 int pixel_x = (tile_x + dx) * 8;
2046 int pixel_y = (tile_y + dy) * 8;
2049 printf(
" [%d] word=0x%04X id=%d pal=%d pixel=(%d,%d)\n",
2050 tile_idx, tile_word, tile_info.id_, tile_info.palette_, pixel_x, pixel_y);
2056 uint8_t priority = tile_info.over_ ? 1 : 0;
2057 const auto& bitmap_data = bitmap.vector();
2058 for (
int py = 0; py < 8; py++) {
2059 int dest_y = pixel_y + py;
2060 if (dest_y < 0 || dest_y >= bitmap.height())
continue;
2061 for (
int px = 0; px < 8; px++) {
2062 int dest_x = pixel_x + px;
2063 if (dest_x < 0 || dest_x >= bitmap_width)
continue;
2064 int dest_index = dest_y * bitmap_width + dest_x;
2065 if (dest_index <
static_cast<int>(bitmap_data.size()) &&
2066 bitmap_data[dest_index] != 255) {
2067 priority_buffer[dest_index] = priority;
2077 "DrawDoor: type=%s dir=%s pos=%d at tile(%d,%d) size=%dx%d "
2078 "offset_table=0x%X tile_offset=0x%X tile_addr=0x%X",
2081 door.
position, tile_x, tile_y, door_width, door_height,
2082 offset_table_addr, tile_offset, tile_data_addr);
2086 int width,
int height,
DoorType type,
2154 int pixel_x = tile_x * 8;
2155 int pixel_y = tile_y * 8;
2156 int pixel_width = width * 8;
2157 int pixel_height = height * 8;
2159 int bitmap_width = bitmap.
width();
2160 int bitmap_height = bitmap.
height();
2163 for (
int py = 0; py < pixel_height; py++) {
2164 for (
int px = 0; px < pixel_width; px++) {
2165 int dest_x = pixel_x + px;
2166 int dest_y = pixel_y + py;
2168 if (dest_x >= 0 && dest_x < bitmap_width &&
2169 dest_y >= 0 && dest_y < bitmap_height) {
2171 bool is_border = (px < 2 || px >= pixel_width - 2 ||
2172 py < 2 || py >= pixel_height - 2);
2173 uint8_t final_color = is_border ? (color_idx + 5) : color_idx;
2175 int offset = (dest_y * bitmap_width) + dest_x;
2183 std::span<const gfx::TileInfo> tiles,
2190 bool is_open =
false;
2202 if (is_open && tiles.size() >= 8) {
2204 if (tiles.size() >= 8) {
2214 if (tiles.size() >= 4) {
2223 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2227 LOG_DEBUG(
"ObjectDrawer",
"DrawNothing for object 0x%02X (logic/invisible)", obj.
id_);
2232 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2236 int size = obj.
size_;
2241 bool is_ceiling = (obj.
id_ == 0x00 || obj.
id_ == 0xB8 || obj.
id_ == 0xB9);
2242 if (is_ceiling && tiles.size() >= 4) {
2243 printf(
"[Ceiling Draw] obj=0x%02X pos=(%d,%d) size=%d tiles=%zu\n",
2244 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
2245 printf(
" Tile IDs: [%d, %d, %d, %d]\n",
2246 tiles[0].id_, tiles[1].id_, tiles[2].id_, tiles[3].id_);
2247 printf(
" Palettes: [%d, %d, %d, %d]\n",
2248 tiles[0].palette_, tiles[1].palette_, tiles[2].palette_, tiles[3].palette_);
2252 "DrawRightwards2x2: obj=%04X pos=(%d,%d) size=%d tiles=%zu",
2253 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
2255 for (
int s = 0; s < size; s++) {
2256 if (tiles.size() >= 4) {
2269 "DrawRightwards2x2: SKIPPING - tiles.size()=%zu < 4",
2277 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2281 int size = obj.
size_;
2286 printf(
"[Wall Draw 2x4] obj=0x%03X pos=(%d,%d) size=%d tiles=%zu\n",
2287 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
2290 "DrawRightwards2x4: obj=%04X pos=(%d,%d) size=%d tiles=%zu",
2291 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
2293 for (
int s = 0; s < size; s++) {
2294 if (tiles.size() >= 8) {
2306 }
else if (tiles.size() >= 4) {
2318 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2322 int size = obj.
size_ & 0x0F;
2323 int count = size + 1;
2326 "DrawRightwards2x4_1to16: obj=%04X pos=(%d,%d) size=%d count=%d tiles=%zu",
2327 obj.
id_, obj.
x_, obj.
y_, size, count, tiles.size());
2329 for (
int s = 0; s < count; s++) {
2330 if (tiles.size() >= 8) {
2342 }
else if (tiles.size() >= 4) {
2354 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2362 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2365 int size = obj.
size_ & 0x0F;
2369 int count = size + 1;
2371 for (
int s = 0; s < count; s++) {
2372 if (tiles.size() >= 4) {
2385 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2389 int size = obj.
size_ & 0x0F;
2394 int count = size + 7;
2396 if (tiles.size() < 5)
return;
2398 for (
int s = 0; s < count; s++) {
2402 int tile_x = obj.
x_ + s;
2403 int tile_y = obj.
y_ - s;
2405 WriteTile8(bg, tile_x, tile_y + 0, tiles[0]);
2406 WriteTile8(bg, tile_x, tile_y + 1, tiles[1]);
2407 WriteTile8(bg, tile_x, tile_y + 2, tiles[2]);
2408 WriteTile8(bg, tile_x, tile_y + 3, tiles[3]);
2409 WriteTile8(bg, tile_x, tile_y + 4, tiles[4]);
2415 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2419 int size = obj.
size_ & 0x0F;
2424 int count = size + 7;
2426 if (tiles.size() < 5)
return;
2428 for (
int s = 0; s < count; s++) {
2432 int tile_x = obj.
x_ + s;
2433 int tile_y = obj.
y_ + s;
2435 WriteTile8(bg, tile_x, tile_y + 0, tiles[0]);
2436 WriteTile8(bg, tile_x, tile_y + 1, tiles[1]);
2437 WriteTile8(bg, tile_x, tile_y + 2, tiles[2]);
2438 WriteTile8(bg, tile_x, tile_y + 3, tiles[3]);
2439 WriteTile8(bg, tile_x, tile_y + 4, tiles[4]);
2445 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2451 int size = obj.
size_ & 0x0F;
2452 int count = size + 6;
2454 if (tiles.size() < 5)
return;
2456 for (
int s = 0; s < count; s++) {
2457 int tile_x = obj.
x_ + s;
2458 int tile_y = obj.
y_ - s;
2460 WriteTile8(bg, tile_x, tile_y + 0, tiles[0]);
2461 WriteTile8(bg, tile_x, tile_y + 1, tiles[1]);
2462 WriteTile8(bg, tile_x, tile_y + 2, tiles[2]);
2463 WriteTile8(bg, tile_x, tile_y + 3, tiles[3]);
2464 WriteTile8(bg, tile_x, tile_y + 4, tiles[4]);
2471 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2477 int size = obj.
size_ & 0x0F;
2478 int count = size + 6;
2480 if (tiles.size() < 5)
return;
2482 for (
int s = 0; s < count; s++) {
2483 int tile_x = obj.
x_ + s;
2484 int tile_y = obj.
y_ + s;
2486 WriteTile8(bg, tile_x, tile_y + 0, tiles[0]);
2487 WriteTile8(bg, tile_x, tile_y + 1, tiles[1]);
2488 WriteTile8(bg, tile_x, tile_y + 2, tiles[2]);
2489 WriteTile8(bg, tile_x, tile_y + 3, tiles[3]);
2490 WriteTile8(bg, tile_x, tile_y + 4, tiles[4]);
2497 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2505 if (tiles.size() >= 16) {
2508 for (
int xx = 0; xx < 4; xx++) {
2509 for (
int yy = 0; yy < 4; yy++) {
2513 }
else if (tiles.size() >= 8) {
2517 for (
int xx = 0; xx < 2; xx++) {
2518 for (
int yy = 0; yy < 4; yy++) {
2522 }
else if (tiles.size() >= 4) {
2525 for (
int xx = 0; xx < 2; xx++) {
2526 for (
int yy = 0; yy < 2; yy++) {
2535 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2537 int size = obj.
size_ & 0x0F;
2540 int count = (size * 2) + 1;
2542 for (
int s = 0; s < count; s++) {
2543 if (tiles.size() >= 2) {
2553 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2558 int size = obj.
size_ & 0x0F;
2559 int count = (size + 1) * 2;
2561 if (tiles.size() < 3)
return;
2570 for (
int s = 0; s < count; s++) {
2581 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2586 int size = obj.
size_ & 0x0F;
2587 int count = size + 1;
2589 if (tiles.size() < 3)
return;
2598 for (
int s = 0; s < count; s++) {
2609 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2611 int size = obj.
size_ & 0x0F;
2614 int count = size + 10;
2616 for (
int s = 0; s < count; s++) {
2617 if (tiles.size() >= 2) {
2627 const std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2629 int size = obj.
size_ & 0x0F;
2632 int count = size + 10;
2634 for (
int s = 0; s < count; s++) {
2635 if (tiles.size() >= 2) {
2644 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2647 if (tiles.size() >= 1) {
2655 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2657 int size = obj.
size_ & 0x0F;
2660 int count = size + 1;
2663 if (obj.
id_ == 0xBA && tiles.size() >= 16) {
2664 printf(
"[Large Ceiling Draw] obj=0x%02X pos=(%d,%d) size=%d tiles=%zu\n",
2665 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
2666 printf(
" First 4 Tile IDs: [%d, %d, %d, %d]\n",
2667 tiles[0].id_, tiles[1].id_, tiles[2].id_, tiles[3].id_);
2668 printf(
" First 4 Palettes: [%d, %d, %d, %d]\n",
2669 tiles[0].palette_, tiles[1].palette_, tiles[2].palette_, tiles[3].palette_);
2672 for (
int s = 0; s < count; s++) {
2673 if (tiles.size() >= 16) {
2676 for (
int x = 0; x < 4; ++x) {
2677 for (
int y = 0; y < 4; ++y) {
2678 WriteTile8(bg, obj.
x_ + (s * 4) + x, obj.
y_ + y, tiles[x * 4 + y]);
2687 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2689 int size = obj.
size_ & 0x0F;
2692 int count = size + 4;
2694 for (
int s = 0; s < count; s++) {
2695 if (tiles.size() >= 1) {
2704 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2709 if (state && state->IsDoorSwitchActive(
room_id_)) {
2711 if (tiles.size() >= 2) {
2716 if (tiles.size() > tile_index) {
2723 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2725 int size = obj.
size_ & 0x0F;
2728 int count = size + 1;
2730 for (
int s = 0; s < count; s++) {
2731 if (tiles.size() >= 16) {
2733 for (
int x = 0; x < 4; ++x) {
2734 for (
int y = 0; y < 4; ++y) {
2735 WriteTile8(bg, obj.
x_ + (s * 6) + x, obj.
y_ + y, tiles[x * 4 + y]);
2744 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2747 int size = obj.
size_ & 0x0F;
2750 int count = size + 1;
2752 for (
int s = 0; s < count; s++) {
2753 if (tiles.size() >= 6) {
2755 for (
int x = 0; x < 2; ++x) {
2756 for (
int y = 0; y < 3; ++y) {
2757 WriteTile8(bg, obj.
x_ + (s * 4) + x, obj.
y_ + y, tiles[x * 3 + y]);
2766 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2771 int size = obj.
size_ & 0x0F;
2774 int count = size + 1;
2776 for (
int s = 0; s < count; s++) {
2777 if (tiles.size() >= 8) {
2780 for (
int x = 0; x < 2; ++x) {
2781 for (
int y = 0; y < 4; ++y) {
2782 WriteTile8(bg, obj.
x_ + (s * 4) + x, obj.
y_ + y, tiles[x * 4 + y]);
2791 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2796 int size = obj.
size_ & 0x0F;
2799 int count = size + 1;
2801 for (
int s = 0; s < count; s++) {
2802 if (tiles.size() >= 12) {
2805 for (
int x = 0; x < 4; ++x) {
2806 for (
int y = 0; y < 3; ++y) {
2807 WriteTile8(bg, obj.
x_ + (s * 8) + x, obj.
y_ + y, tiles[x * 3 + y]);
2816 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2819 int size = obj.
size_ & 0x0F;
2822 int count = size + 1;
2824 for (
int s = 0; s < count; s++) {
2825 if (tiles.size() >= 8) {
2827 for (
int x = 0; x < 4; ++x) {
2828 for (
int y = 0; y < 2; ++y) {
2829 WriteTile8(bg, obj.
x_ + (s * 6) + x, obj.
y_ + y, tiles[x * 2 + y]);
2838 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2840 int size = obj.
size_ & 0x0F;
2843 int count = size + 1;
2845 for (
int s = 0; s < count; s++) {
2846 if (tiles.size() >= 4) {
2862 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2867 int size = obj.
size_ & 0x0F;
2868 int count = size + 1;
2870 for (
int s = 0; s < count; s++) {
2871 if (tiles.size() >= 8) {
2889 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2894 int size = obj.
size_ & 0x0F;
2895 int count = size + 1;
2897 if (tiles.size() < 8)
return;
2899 for (
int s = 0; s < count; s++) {
2901 int base_x = obj.
x_ + (s * 12);
2902 for (
int row = 0; row < 8; row++) {
2910 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2914 int size = obj.
size_ & 0x0F;
2915 int count = size + 1;
2917 for (
int s = 0; s < count; s++) {
2918 if (tiles.size() >= 12) {
2919 int base_x = obj.
x_ + (s * 4);
2935 }
else if (tiles.size() >= 8) {
2937 int base_x = obj.
x_ + (s * 4);
2954 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2957 int size = obj.
size_ & 0x0F;
2958 int count = size + 2;
2960 for (
int s = 0; s < count; s++) {
2961 if (tiles.size() >= 1) {
2969 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
2972 int size = obj.
size_ & 0x0F;
2973 int count = size + 1;
2975 for (
int s = 0; s < count; s++) {
2976 if (tiles.size() >= 12) {
2977 int base_x = obj.
x_ + (s * 6);
2999 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3003 int size = obj.
size_ & 0x0F;
3004 int count = size + 1;
3006 for (
int s = 0; s < count; s++) {
3007 if (tiles.size() >= 16) {
3008 int base_x = obj.
x_ + (s * 6);
3010 for (
int col = 0; col < 4; col++) {
3011 for (
int row = 0; row < 4; row++) {
3012 int tile_idx = col * 4 + row;
3013 WriteTile8(bg, base_x + col, obj.
y_ + row, tiles[tile_idx]);
3022 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3030 int size = obj.
size_ & 0x0F;
3031 int middle_count = size + 2;
3033 if (tiles.size() < 15)
return;
3049 for (
int s = 0; s < middle_count; s++) {
3069 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3073 int size = obj.
size_ & 0x0F;
3074 int count = size + 1;
3076 for (
int s = 0; s < count; s++) {
3077 if (tiles.size() >= 4) {
3078 int base_x = obj.
x_ + (s * 4);
3094 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3097 int size = obj.
size_;
3101 for (
int s = 0; s < size; s++) {
3102 if (tiles.size() >= 4) {
3120 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3123 int size = obj.
size_;
3128 printf(
"[Wall Draw 4x2 Vertical] obj=0x%03X pos=(%d,%d) size=%d tiles=%zu\n",
3129 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
3132 for (
int s = 0; s < size; s++) {
3133 if (tiles.size() >= 8) {
3145 }
else if (tiles.size() >= 4) {
3157 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3165 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3168 int size = obj.
size_ & 0x0F;
3171 int count = size + 1;
3173 for (
int s = 0; s < count; s++) {
3174 if (tiles.size() >= 8) {
3194 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3196 int size = obj.
size_ & 0x0F;
3199 int count = size + 1;
3201 for (
int s = 0; s < count; s++) {
3202 if (tiles.size() >= 4) {
3218 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3220 int size = obj.
size_ & 0x0F;
3223 int count = size + 2;
3225 for (
int s = 0; s < count; s++) {
3226 if (tiles.size() >= 1) {
3235 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3240 int size = obj.
size_ & 0x0F;
3241 int count = (size + 1) * 2;
3243 if (tiles.size() < 3)
return;
3245 int tile_y = obj.
y_;
3252 for (
int s = 0; s < count; s++) {
3263 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3265 int size = obj.
size_ & 0x0F;
3268 int count = size + 1;
3270 for (
int s = 0; s < count; s++) {
3271 if (tiles.size() >= 1) {
3280 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3282 int size = obj.
size_ & 0x0F;
3285 int count = size + 10;
3287 for (
int s = 0; s < count; s++) {
3288 if (tiles.size() >= 2) {
3298 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3300 int size = obj.
size_ & 0x0F;
3303 int count = size + 10;
3305 for (
int s = 0; s < count; s++) {
3306 if (tiles.size() >= 2) {
3318 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3322 int size = obj.
size_ & 0x0F;
3323 int count = size + 1;
3325 for (
int s = 0; s < count; s++) {
3326 if (tiles.size() >= 16) {
3328 for (
int col = 0; col < 4; col++) {
3329 for (
int row = 0; row < 4; row++) {
3330 int tile_idx = col * 4 + row;
3331 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 4) + row, tiles[tile_idx]);
3340 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3343 int size = obj.
size_ & 0x0F;
3344 int count = size + 4;
3346 for (
int s = 0; s < count; s++) {
3347 if (tiles.size() >= 1) {
3355 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3359 int size = obj.
size_ & 0x0F;
3360 int count = size + 1;
3362 for (
int s = 0; s < count; s++) {
3363 if (tiles.size() >= 16) {
3365 for (
int col = 0; col < 4; col++) {
3366 for (
int row = 0; row < 4; row++) {
3367 int tile_idx = col * 4 + row;
3368 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 6) + row, tiles[tile_idx]);
3377 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3381 int size = obj.
size_ & 0x0F;
3382 int count = size + 1;
3384 for (
int s = 0; s < count; s++) {
3385 if (tiles.size() >= 8) {
3387 for (
int col = 0; col < 2; col++) {
3388 for (
int row = 0; row < 4; row++) {
3389 int tile_idx = col * 4 + row;
3390 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 6) + row, tiles[tile_idx]);
3399 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3403 int size = obj.
size_ & 0x0F;
3404 int count = size + 1;
3406 for (
int s = 0; s < count; s++) {
3407 if (tiles.size() >= 12) {
3409 for (
int col = 0; col < 3; col++) {
3410 for (
int row = 0; row < 4; row++) {
3411 int tile_idx = col * 4 + row;
3412 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 8) + row, tiles[tile_idx]);
3421 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3425 int size = obj.
size_ & 0x0F;
3426 int count = size + 1;
3428 for (
int s = 0; s < count; s++) {
3429 if (tiles.size() >= 4) {
3431 for (
int col = 0; col < 2; col++) {
3432 for (
int row = 0; row < 2; row++) {
3433 int tile_idx = col * 2 + row;
3434 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 14) + row, tiles[tile_idx]);
3443 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3446 int size = obj.
size_ & 0x0F;
3447 int count = size + 2;
3449 for (
int s = 0; s < count; s++) {
3450 if (tiles.size() >= 1) {
3458 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3462 int size = obj.
size_ & 0x0F;
3463 int count = size + 1;
3466 if (obj.
id_ == 0x80 && tiles.size() >= 8) {
3467 printf(
"[Vertical Ceiling Draw] obj=0x%02X pos=(%d,%d) size=%d tiles=%zu\n",
3468 obj.
id_, obj.
x_, obj.
y_, size, tiles.size());
3469 printf(
" Tile IDs: [%d, %d, %d, %d, %d, %d, %d, %d]\n",
3470 tiles[0].id_, tiles[1].id_, tiles[2].id_, tiles[3].id_,
3471 tiles[4].id_, tiles[5].id_, tiles[6].id_, tiles[7].id_);
3472 printf(
" Palettes: [%d, %d, %d, %d, %d, %d, %d, %d]\n",
3473 tiles[0].palette_, tiles[1].palette_, tiles[2].palette_, tiles[3].palette_,
3474 tiles[4].palette_, tiles[5].palette_, tiles[6].palette_, tiles[7].palette_);
3477 for (
int s = 0; s < count; s++) {
3478 if (tiles.size() >= 8) {
3480 for (
int col = 0; col < 2; col++) {
3481 for (
int row = 0; row < 4; row++) {
3482 int tile_idx = col * 4 + row;
3483 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 10) + row, tiles[tile_idx]);
3496 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3499 int size = obj.
size_ & 0x0F;
3500 int count = size + 1;
3502 for (
int s = 0; s < count; s++) {
3503 if (tiles.size() >= 12) {
3505 for (
int col = 0; col < 3; col++) {
3506 for (
int row = 0; row < 4; row++) {
3507 int tile_idx = col * 4 + row;
3508 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 6) + row, tiles[tile_idx]);
3517 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3525 int size = obj.
size_ & 0x0F;
3526 int middle_count = size + 1;
3528 if (tiles.size() < 12)
return;
3542 for (
int s = 0; s < middle_count; s++) {
3561 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3564 int size = obj.
size_ & 0x0F;
3565 int count = size + 1;
3567 for (
int s = 0; s < count; s++) {
3568 if (tiles.size() >= 4) {
3569 int base_y = obj.
y_ + (s * 4);
3581 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3585 int size = obj.
size_ & 0x0F;
3586 int count = size + 1;
3588 for (
int s = 0; s < count; s++) {
3589 if (tiles.size() >= 18) {
3591 for (
int col = 0; col < 3; col++) {
3592 for (
int row = 0; row < 6; row++) {
3593 int tile_idx = col * 6 + row;
3594 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 6) + row, tiles[tile_idx]);
3603 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3606 int size = obj.
size_ & 0x0F;
3607 int count = size + 1;
3609 for (
int s = 0; s < count; s++) {
3610 if (tiles.size() >= 6) {
3612 for (
int col = 0; col < 2; col++) {
3613 for (
int row = 0; row < 3; row++) {
3614 int tile_idx = col * 3 + row;
3615 WriteTile8(bg, obj.
x_ + col, obj.
y_ + (s * 3) + row, tiles[tile_idx]);
3624 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3627 int size = obj.
size_ & 0x0F;
3628 int count = size + 1;
3630 for (
int s = 0; s < count; s++) {
3631 if (tiles.size() >= 4) {
3632 int base_y = obj.
y_ + (s * 2);
3644 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3647 int size = obj.
size_ & 0x0F;
3648 int count = size + 1;
3650 for (
int s = 0; s < count; s++) {
3651 if (tiles.size() >= 4) {
3652 int base_y = obj.
y_ + (s * 2);
3664 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3667 int size = obj.
size_ & 0x0F;
3668 int count = size + 8;
3670 for (
int s = 0; s < count; s++) {
3671 if (tiles.size() >= 1) {
3679 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3682 int size = obj.
size_ & 0x0F;
3683 int count = size + 1;
3685 for (
int s = 0; s < count; s++) {
3686 if (tiles.size() >= 4) {
3687 int base_x = obj.
x_ + (s * 2);
3699 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3702 int size = obj.
size_ & 0x0F;
3703 int count = size + 1;
3705 for (
int s = 0; s < count; s++) {
3706 if (tiles.size() >= 4) {
3707 int base_x = obj.
x_ + (s * 2);
3723 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3727 int count = (obj.
size_ & 0x0F) + 4;
3729 if (tiles.empty()) {
3730 LOG_DEBUG(
"ObjectDrawer",
"DiagonalCeilingTopLeft: No tiles for obj 0x%02X", obj.
id_);
3735 "DiagonalCeilingTopLeft: obj=0x%02X pos=(%d,%d) size=%d count=%d",
3739 int tiles_in_row = count;
3740 for (
int row = 0; row < count && tiles_in_row > 0; row++) {
3741 for (
int col = 0; col < tiles_in_row; col++) {
3750 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3754 int count = (obj.
size_ & 0x0F) + 4;
3756 if (tiles.empty())
return;
3759 for (
int row = 0; row < count; row++) {
3760 int tiles_in_row = row + 1;
3761 for (
int col = 0; col < tiles_in_row; col++) {
3769 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3773 int count = (obj.
size_ & 0x0F) + 4;
3775 if (tiles.empty())
return;
3778 int tiles_in_row = count;
3779 for (
int row = 0; row < count && tiles_in_row > 0; row++) {
3780 for (
int col = 0; col < tiles_in_row; col++) {
3789 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
3793 int count = (obj.
size_ & 0x0F) + 4;
3795 if (tiles.empty())
return;
3798 int tiles_in_row = count;
3799 for (
int row = 0; row < count && tiles_in_row > 0; row++) {
3800 for (
int col = 0; col < tiles_in_row; col++) {
3813 std::span<const gfx::TileInfo> tiles) {
3829 if (tiles.size() < 16)
return;
3832 int width = (obj.
size_ & 0x0F) + 4;
3833 int height = ((obj.
size_ >> 4) & 0x0F) + 1;
3836 printf(
"[DrawClosedChestPlatform] obj=0x%03X pos=(%d,%d) size=0x%02X -> width=%d height=%d\n",
3842 size_t tile_idx = 0;
3843 for (
int row = 0; row < height * 3; ++row) {
3844 for (
int col = 0; col < width * 2; ++col) {
3845 WriteTile8(bg, obj.
x_ + col, obj.
y_ + row, tiles[tile_idx % tiles.size()]);
3853 std::span<const gfx::TileInfo> tiles) {
3856 if (tiles.size() < 6)
return;
3858 int count = ((obj.
size_ >> 4) & 0x0F) + 4;
3861 for (
int row = 0; row < count; ++row) {
3862 for (
int col = 0; col < 3; ++col) {
3863 size_t tile_idx = (row * 3 + col) % tiles.size();
3871 std::span<const gfx::TileInfo> tiles) {
3874 if (tiles.size() < 6)
return;
3876 int count = ((obj.
size_ >> 4) & 0x0F) + 4;
3878 for (
int row = 0; row < count; ++row) {
3879 for (
int col = 0; col < 3; ++col) {
3880 size_t tile_idx = (row * 3 + col) % tiles.size();
3888 std::span<const gfx::TileInfo> tiles) {
3904 if (tiles.size() < 8)
return;
3907 int width = (obj.
size_ & 0x0F) + 1;
3910 int segments = ((obj.
size_ >> 4) & 0x0F) * 2 + 5;
3913 printf(
"[DrawOpenChestPlatform] obj=0x%03X pos=(%d,%d) size=0x%02X -> width=%d segments=%d\n",
3922 int tile_offset = 0;
3923 for (
int seg = 0; seg < segments; ++seg) {
3924 for (
int col = 0; col < width; ++col) {
3925 size_t tile_idx = tile_offset % tiles.size();
3934 for (
int col = 0; col < width; ++col) {
3935 size_t tile_idx = tile_offset % tiles.size();
3936 WriteTile8(bg, obj.
x_ + col, obj.
y_ + segments, tiles[tile_idx]);
3940 for (
int col = 0; col < width; ++col) {
3941 size_t tile_idx = tile_offset % tiles.size();
3942 WriteTile8(bg, obj.
x_ + col, obj.
y_ + segments + 1, tiles[tile_idx]);
3952 int tile_y,
int pixel_width,
3954 auto& bitmap = bg1.
bitmap();
3955 if (!bitmap.is_active() || bitmap.width() == 0) {
3956 printf(
"[MarkBG1Transparent] Bitmap not ready, skipping\n");
3961 int start_px = tile_x * 8;
3962 int start_py = tile_y * 8;
3963 int canvas_width = bitmap.width();
3964 int canvas_height = bitmap.height();
3965 auto& data = bitmap.mutable_data();
3967 int pixels_marked = 0;
3971 for (
int py = start_py; py < start_py + pixel_height && py < canvas_height;
3973 if (py < 0)
continue;
3974 for (
int px = start_px; px < start_px + pixel_width && px < canvas_width;
3976 if (px < 0)
continue;
3977 int idx = py * canvas_width + px;
3978 if (idx >= 0 && idx <
static_cast<int>(data.size())) {
3984 bitmap.set_modified(
true);
3987 printf(
"[MarkBG1Transparent] Marked %d pixels transparent at tile(%d,%d) pixel(%d,%d) size(%d,%d)\n",
3988 pixels_marked, tile_x, tile_y, start_px, start_py, pixel_width, pixel_height);
3995 auto& bitmap = bg.
bitmap();
3996 if (!bitmap.is_active() || bitmap.width() == 0) {
4006 LOG_DEBUG(
"ObjectDrawer",
"ERROR: No graphics data available");
4015 uint8_t priority = tile_info.
over_ ? 1 : 0;
4016 int pixel_x = tile_x * 8;
4017 int pixel_y = tile_y * 8;
4019 int width = bitmap.width();
4022 const auto& bitmap_data = bitmap.vector();
4023 for (
int py = 0; py < 8; py++) {
4024 int dest_y = pixel_y + py;
4025 if (dest_y < 0 || dest_y >= bitmap.height())
continue;
4027 for (
int px = 0; px < 8; px++) {
4028 int dest_x = pixel_x + px;
4029 if (dest_x < 0 || dest_x >= width)
continue;
4031 int dest_index = dest_y * width + dest_x;
4034 if (dest_index <
static_cast<int>(bitmap_data.size()) &&
4035 bitmap_data[dest_index] != 255) {
4036 priority_buffer[dest_index] = priority;
4043 return tile_x >= 0 && tile_x < kMaxTilesX && tile_y >= 0 &&
4049 int pixel_y,
const uint8_t* tiledata) {
4052 if (!tiledata)
return;
4056 LOG_DEBUG(
"ObjectDrawer",
"ERROR: Invalid bitmap - active=%d, size=%dx%d",
4065 constexpr int kGfxBufferSize = 0x10000;
4066 constexpr int kMaxTileRow = 63;
4068 int tile_col = tile_info.
id_ % 16;
4069 int tile_row = tile_info.
id_ / 16;
4072 if (tile_row > kMaxTileRow) {
4073 LOG_DEBUG(
"ObjectDrawer",
"Tile ID 0x%03X out of bounds (row %d > %d)",
4074 tile_info.
id_, tile_row, kMaxTileRow);
4078 int tile_base_x = tile_col * 8;
4079 int tile_base_y = tile_row * 1024;
4082 static int draw_debug_count = 0;
4083 if (draw_debug_count < 5) {
4084 int sample_index = tile_base_y + tile_base_x;
4085 printf(
"[DrawTile] id=%d (col=%d,row=%d) -> gfx offset=%d (0x%04X)\n",
4086 tile_info.
id_, tile_col, tile_row, sample_index, sample_index);
4087 printf(
" First 8 pixels at tile: ");
4088 for (
int i = 0; i < 8; i++) {
4089 printf(
"%02X ", tiledata[sample_index + i]);
4104 uint8_t pal = tile_info.
palette_ & 0x07;
4105 uint8_t palette_offset;
4106 if (pal >= 2 && pal <= 7) {
4108 palette_offset = (pal - 2) * 15;
4115 bool any_pixels_written =
false;
4117 for (
int py = 0; py < 8; py++) {
4121 for (
int px = 0; px < 8; px++) {
4127 int src_index = (src_row * 128) + src_col + tile_base_x + tile_base_y;
4128 uint8_t pixel = tiledata[src_index];
4132 uint8_t final_color = (pixel - 1) + palette_offset;
4133 int dest_x = pixel_x + px;
4134 int dest_y = pixel_y + py;
4136 if (dest_x >= 0 && dest_x < bitmap.
width() &&
4137 dest_y >= 0 && dest_y < bitmap.
height()) {
4138 int dest_index = dest_y * bitmap.
width() + dest_x;
4139 if (dest_index >= 0 &&
4140 dest_index <
static_cast<int>(bitmap.
mutable_data().size())) {
4142 any_pixels_written =
true;
4150 if (any_pixels_written) {
4161 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
4174 if (tiles.empty())
return;
4176 int length = (obj.
size_ & 0x0F) + 1;
4177 int obj_subid = obj.
id_ & 0x0F;
4181 switch (obj_subid) {
4182 case 0x03: dx = 1; dy = 0;
break;
4183 case 0x04: dx = 0; dy = 1;
break;
4184 case 0x05: dx = 1; dy = 1;
break;
4185 case 0x06: dx = -1; dy = 1;
break;
4186 case 0x07: dx = 1; dy = 0;
break;
4187 case 0x08: dx = 0; dy = 1;
break;
4188 case 0x09: dx = 1; dy = 1;
break;
4189 case 0x0A: dx = 1; dy = 0;
break;
4190 case 0x0B: dx = 0; dy = 1;
break;
4191 case 0x0C: dx = 1; dy = 1;
break;
4192 case 0x0E: dx = 1; dy = 0;
break;
4193 case 0x0F: dx = 0; dy = 1;
break;
4194 default: dx = 1; dy = 0;
break;
4198 for (
int i = 0; i < length; ++i) {
4199 int tile_idx = i % tiles.size();
4200 WriteTile8(bg, obj.
x_ + (i * dx), obj.
y_ + (i * dy), tiles[tile_idx]);
4206 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
4211 if (tiles.size() >= 4) {
4221 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
4224 if (tiles.size() >= 16) {
4226 }
else if (tiles.size() >= 8) {
4229 for (
int xx = 0; xx < 2; xx++) {
4230 for (
int yy = 0; yy < 4; yy++) {
4234 }
else if (tiles.size() >= 4) {
4242 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
4246 if (tiles.size() >= 16) {
4248 }
else if (tiles.size() >= 12) {
4251 for (
int xx = 0; xx < 3; xx++) {
4252 for (
int yy = 0; yy < 4; yy++) {
4256 }
else if (tiles.size() >= 8) {
4259 for (
int xx = 0; xx < 2; xx++) {
4260 for (
int yy = 0; yy < 4; yy++) {
4264 }
else if (tiles.size() >= 4) {
4271 std::span<const gfx::TileInfo> tiles, [[maybe_unused]]
const DungeonState* state) {
4275 if (tiles.size() >= 16) {
4277 }
else if (tiles.size() >= 12) {
4280 for (
int xx = 0; xx < 4; xx++) {
4281 for (
int yy = 0; yy < 3; yy++) {
4285 }
else if (tiles.size() >= 8) {
4288 for (
int xx = 0; xx < 2; xx++) {
4289 for (
int yy = 0; yy < 4; yy++) {
4293 }
else if (tiles.size() >= 4) {
4300 std::span<const gfx::TileInfo> tiles,
4301 int width,
int height) {
4303 if (tiles.size() >=
static_cast<size_t>(width * height)) {
4304 for (
int y = 0; y < height; ++y) {
4305 for (
int x = 0; x < width; ++x) {
4318 std::span<const gfx::TileInfo> tiles,
4322 constexpr int kWidth = 4;
4323 constexpr int kHeight = 5;
4325 if (tiles.size() >= kWidth * kHeight) {
4328 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4329 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4341 std::span<const gfx::TileInfo> tiles,
4345 constexpr int kWidth = 3;
4346 constexpr int kHeight = 6;
4348 if (tiles.size() >= kWidth * kHeight) {
4350 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4351 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4363 std::span<const gfx::TileInfo> tiles,
4367 constexpr int kWidth = 6;
4368 constexpr int kHeight = 3;
4370 if (tiles.size() >= kWidth * kHeight) {
4372 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4373 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4385 std::span<const gfx::TileInfo> tiles,
4389 constexpr int kWidth = 3;
4390 constexpr int kHeight = 5;
4392 if (tiles.size() >= kWidth * kHeight) {
4394 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4395 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4411 std::span<const gfx::TileInfo> tiles,
4415 constexpr int kWidth = 2;
4416 constexpr int kHeight = 6;
4418 if (tiles.size() >= kWidth * kHeight) {
4420 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4421 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4425 }
else if (tiles.size() >= 4) {
4433 std::span<const gfx::TileInfo> tiles,
4437 constexpr int kWidth = 6;
4438 constexpr int kHeight = 2;
4440 if (tiles.size() >= kWidth * kHeight) {
4442 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4443 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4447 }
else if (tiles.size() >= 4) {
4455 std::span<const gfx::TileInfo> tiles,
4460 constexpr int kWidth = 4;
4461 constexpr int kHeight = 4;
4463 if (tiles.size() >= kWidth * kHeight) {
4465 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4466 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4478 std::span<const gfx::TileInfo> tiles,
4482 constexpr int kWidth = 6;
4483 constexpr int kHeight = 6;
4485 if (tiles.size() >= kWidth * kHeight) {
4487 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4488 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4500 std::span<const gfx::TileInfo> tiles,
4510 std::span<const gfx::TileInfo> tiles,
4514 constexpr int kWidth = 3;
4515 constexpr int kHeight = 4;
4517 if (tiles.size() >= kWidth * kHeight) {
4519 for (
int x = 0; x < kWidth && tid < static_cast<int>(tiles.size()); ++x) {
4520 for (
int y = 0; y < kHeight && tid < static_cast<int>(tiles.size()); ++y) {
4532 std::span<const gfx::TileInfo> tiles,
4544 constexpr int kWidth = 3;
4545 constexpr int kSectionHeight = 3;
4547 if (tiles.size() >= 18) {
4550 for (
int x = 0; x < kWidth; ++x) {
4551 for (
int y = 0; y < kSectionHeight; ++y) {
4557 for (
int x = 0; x < kWidth; ++x) {
4558 for (
int y = 0; y < kSectionHeight; ++y) {
4559 WriteTile8(bg, obj.
x_ + x, obj.
y_ + kSectionHeight + y, tiles[tid++]);
4562 }
else if (tiles.size() >= 9) {
4565 for (
int x = 0; x < kWidth; ++x) {
4566 for (
int y = 0; y < kSectionHeight; ++y) {
4578 std::span<const gfx::TileInfo> tiles,
4584 if (tiles.size() >= 4) {
4594 std::span<const gfx::TileInfo> tiles,
4603 int num_tiles =
static_cast<int>(tiles.size());
4604 if (num_tiles == 0)
return;
4606 for (
int x = 0; x < 8; ++x) {
4607 for (
int y = 0; y < 8; ++y) {
4617 std::span<const gfx::TileInfo> tiles,
4623 if (tiles.size() >= 12) {
4625 for (
int x = 0; x < 4; ++x) {
4626 for (
int y = 0; y < 3; ++y) {
4635 std::span<const gfx::TileInfo> tiles,
4648 if (tiles.size() < 2)
return;
4651 for (
int col = 0; col < 3; ++col) {
4652 int x = obj.
x_ + (col * 2);
4677 std::span<const gfx::TileInfo> tiles,
4684 if (tiles.size() < 16)
return;
4687 for (
int x = 0; x < 4; ++x) {
4688 for (
int y = 0; y < 4; ++y) {
4696 std::span<const gfx::TileInfo> tiles,
4713 constexpr int kBlockSize = 4;
4715 if (tiles.size() >= 32) {
4718 for (
int y = 0; y < kBlockSize; ++y) {
4719 for (
int x = 0; x < kBlockSize; ++x) {
4726 for (
int y = 0; y < kBlockSize; ++y) {
4727 for (
int x = 0; x < kBlockSize; ++x) {
4728 WriteTile8(bg, obj.
x_ + x, obj.
y_ + kBlockSize + y, tiles[tid++]);
4734 for (
int y = 0; y < kBlockSize; ++y) {
4735 for (
int x = 0; x < kBlockSize; ++x) {
4736 WriteTile8(bg, obj.
x_ + x + 4, obj.
y_ + kBlockSize + y, tiles[tid++]);
4739 }
else if (tiles.size() >= 16) {
4742 for (
int y = 0; y < kBlockSize; ++y) {
4743 for (
int x = 0; x < kBlockSize; ++x) {
4766 int size =
object.size_;
4770 switch (routine_id) {
4776 if (routine_id == 0 || routine_id == 7) {
4777 if (size == 0) size = 32;
4780 if (size == 0) size = 16;
4783 if (routine_id == 0 || routine_id == 4) {
4797 int effective_size = (size == 0) ? 26 : (size & 0x0F);
4799 width = effective_size * 16;
4808 int count = size + 1;
4823 int count = size + 7;
4825 height = (count + 4) * 8;
4835 int count = size + 6;
4837 height = (count + 4) * 8;
4844 int effective_size = (size == 0) ? 26 : (size & 0x0F);
4847 height = effective_size * 16;
4855 int count = size + 1;
4857 height = count * 16;
4868 height = 16 + size * 16;
4875 int count = (size & 0x0F) + 1;
4891 int tile_count =
object.tiles().size();
4892 if (tile_count >= 16) {
4893 width = height = 32;
4895 width = height = 16;
4904 int count = (size * 2) + 1;
4915 int count = (size + 1) * 2;
4916 width = (count + 2) * 8;
4925 int count = size + 1;
4926 width = (count + 2) * 8;
4934 width = (size + 4) * 8;
4942 width = 8 + size * 8;
4956 int count = size + 1;
4958 width = ((count - 1) * 6 + 4) * 8;
4968 int count = size + 1;
4970 width = ((count - 1) * 4 + 2) * 8;
4980 int count = size + 1;
4982 width = ((count - 1) * 4 + 2) * 8;
4992 int count = size + 1;
4994 width = ((count - 1) * 8 + 4) * 8;
5004 int count = size + 1;
5006 width = ((count - 1) * 6 + 4) * 8;
5015 int count = size + 1;
5017 width = ((count - 1) * 14 + 2) * 8;
5025 width = 8 + size * 8;
5038 int count = size + 1;
5039 width = count * 4 * 8;
5048 int count = size + 1;
5049 width = ((count - 1) * 12 + 1) * 8;
5058 int count = size + 1;
5059 width = count * 4 * 8;
5068 int count = size + 1;
5070 height = count * 4 * 8;
5078 height = (size + 4) * 8;
5085 int count = size + 1;
5087 height = ((count - 1) * 6 + 4) * 8;
5094 int count = size + 1;
5096 height = ((count - 1) * 6 + 4) * 8;
5103 int count = size + 1;
5105 height = ((count - 1) * 6 + 4) * 8;
5112 int count = size + 1;
5114 height = ((count - 1) * 14 + 2) * 8;
5122 height = (size + 2) * 8;
5129 int count = size + 1;
5131 height = ((count - 1) * 12 + 4) * 8;
5138 width = (size + 2) * 8;
5146 int count = size + 1;
5147 width = ((count - 1) * 6 + 4) * 8;
5155 int count = size + 1;
5156 width = ((count - 1) * 6 + 4) * 8;
5164 width = (size + 6) * 8;
5172 int count = size + 1;
5173 width = ((count - 1) * 4 + 2) * 8;
5188 int size_x = (size & 0x0F) + 1;
5189 int size_y = ((size >> 4) & 0x0F) + 1;
5190 width = size_x * 32;
5191 height = size_y * 32;
5205 int count = size + 1;
5207 height = ((count - 1) * 5 + 4) * 8;
5217 height = (size + 6) * 8;
5224 int count = size + 1;
5226 height = ((count - 1) * 4 + 2) * 8;
5233 int count = size + 1;
5235 height = count * 6 * 8;
5242 int count = size + 1;
5244 height = ((count - 1) * 3 + 3) * 8;
5252 int count = size + 1;
5254 height = count * 2 * 8;
5261 width = (size + 8) * 8;
5270 int count = size + 1;
5271 width = count * 2 * 8;
5283 int count = (size & 0x0F) + 2;
5292 int count = (size & 0x0F) + 2;
5421 int count = (size + 1) * 2;
5422 width = (2 + count) * 8;
5431 int count = (size + 1) * 2;
5432 width = (2 + count) * 8;
5465 int size_h = (
object.size_ & 0x0F);
5466 int size_v = (
object.size_ >> 4) & 0x0F;
5467 width = (size_h + 1) * 8;
5468 height = (size_v + 1) * 8;
5473 return {width, height};
5477 [[maybe_unused]] std::span<const gfx::TileInfo> tiles,
5483 int subtype = obj.
size_ & 0x1F;
5484 auto result = manager.GetObjectInternal(obj.
id_, subtype);
5486 LOG_DEBUG(
"ObjectDrawer",
"Custom object 0x%03X subtype %d not found: %s",
5487 obj.
id_, subtype, result.status().message().data());
5491 auto custom_obj = result.value();
5492 if (!custom_obj || custom_obj->IsEmpty())
return;
5494 int tile_x = obj.
x_;
5495 int tile_y = obj.
y_;
5497 for (
const auto& entry : custom_obj->tiles) {
5502 WriteTile8(bg, tile_x + entry.rel_x, tile_y + entry.rel_y, tile_info);
5512 if (item_id == 0)
return;
5514 auto& bitmap = bg.
bitmap();
5515 if (!bitmap.is_active() || bitmap.width() == 0)
return;
5519 int pixel_x = (x * 8) + 2;
5520 int pixel_y = (y * 8) + 2;
5595 int bitmap_width = bitmap.width();
5596 int bitmap_height = bitmap.height();
5598 for (
int py = 0; py < 4; py++) {
5599 for (
int px = 0; px < 4; px++) {
5600 int dest_x = pixel_x + px;
5601 int dest_y = pixel_y + py;
5604 if (dest_x >= 0 && dest_x < bitmap_width &&
5605 dest_y >= 0 && dest_y < bitmap_height) {
5606 int offset = (dest_y * bitmap_width) + dest_x;
5607 bitmap.WriteToPixel(offset, color_idx);
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
std::vector< uint8_t > & mutable_priority_data()
Represents a bitmap image optimized for SNES ROM hacking.
void WriteToPixel(int position, uint8_t value)
Write a value to a pixel at the given position.
void set_modified(bool modified)
std::vector< uint8_t > & mutable_data()
SNES 16-bit tile metadata container.
static CustomObjectManager & Get()
static DrawRoutineRegistry & Get()
Interface for accessing dungeon game state.
Draws dungeon objects to background buffers using game patterns.
void DrawDiagonalAcute_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
int GetDrawRoutineId(int16_t object_id) const
Get draw routine ID for an object.
void WriteTile8(gfx::BackgroundBuffer &bg, int tile_x, int tile_y, const gfx::TileInfo &tile_info)
void DrawDiagonalGrave_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawBed4x5(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawClosedChestPlatform(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles)
void DrawRightwards2x4_1to15or26(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards2x4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawTileToBitmap(gfx::Bitmap &bitmap, const gfx::TileInfo &tile_info, int pixel_x, int pixel_y, const uint8_t *tiledata)
Draw a single tile directly to bitmap.
void InitializeDrawRoutines()
Initialize draw routine registry Must be called before drawing objects.
void DrawRightwardsPillar2x4spaced4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsBottomCorners1x2_1to16_plus13(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards4x4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawUtility6x3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsEdge1x1_1to16plus7(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
std::vector< DrawRoutine > draw_routines_
void DrawRightwardsDecor4x2spaced8_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsHammerPegs2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsPillar2x4spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawHorizontalTurtleRockPipe(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwards2x2_1to15or32(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDiagonalCeilingBottomRight(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsBlock2x2spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawSingle2x2(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
std::pair< int, int > CalculateObjectDimensions(const RoomObject &object)
Calculate the dimensions (width, height) of an object in pixels.
void DrawDoorSwitcherer(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards2x2_1to15or32(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
const uint8_t * room_gfx_buffer_
void DrawUtility3x5(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawSingle4x3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRupeeFloor(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsEdge1x1_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsBar2x3_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
static bool RoutineDrawsToBothBGs(int routine_id)
void DrawDownwardsDecor2x4spaced8_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawNothing(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
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.
void DrawDownwardsDecor4x2spaced4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsLine1x1_1to16plus1(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDoor(const DoorDef &door, int door_index, gfx::BackgroundBuffer &bg1, gfx::BackgroundBuffer &bg2, const DungeonState *state=nullptr)
Draw a door to background buffers.
void DrawDiagonalCeilingTopLeft(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsTopCorners1x2_1to16_plus13(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsHasEdge1x1_1to16_plus3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDiagonalAcute_1to16_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawPotItem(uint8_t item_id, int x, int y, gfx::BackgroundBuffer &bg)
Draw a pot item visualization.
void DrawLargeCanvasObject(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, int width, int height)
void Draw4x4Corner_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawBigLightBeam(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsCannonHole3x6_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwards2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsLine1x1_1to16plus1(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawVerticalTurtleRockPipe(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards4x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawCorner4x4(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsHasEdge1x1_1to16_plus3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsHammerPegs2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards2x4_1to16_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawCustomObject(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsStatue2x3spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDiagonalCeilingTopRight(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawWaterFace(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsDecor4x3spaced4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsShelf4x4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDiagonalGrave_1to16_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawMovingWallEast(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles)
void DrawDownwardsPots2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
std::unordered_map< int16_t, int > object_to_routine_map_
void DrawDownwardsFloor4x4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsDecor3x4spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsPots2x2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawActual4x4(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawOpenChestPlatform(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles)
void DrawRightwards1x1Solid_1to16_plus3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void MarkBG1Transparent(gfx::BackgroundBuffer &bg1, int tile_x, int tile_y, int pixel_width, int pixel_height)
Mark BG1 pixels as transparent where BG2 overlay objects are drawn.
void DrawChest(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsDecor4x4spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void CustomDraw(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawSolidWallDecor3x4(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDiagonalCeilingBottomLeft(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsCannonHole4x3_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawWeirdCornerBottom_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
bool routines_initialized_
void DrawRightwards3x6(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsHasEdge1x1_1to16_plus2(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwards4x2_1to15or26(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
ObjectDrawer(Rom *rom, int room_id, const uint8_t *room_gfx_buffer=nullptr)
void DrawRightwardsDecor4x4spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawSingle4x4(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawLightBeam(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
absl::Status DrawObject(const RoomObject &object, gfx::BackgroundBuffer &bg1, gfx::BackgroundBuffer &bg2, const gfx::PaletteGroup &palette_group, const DungeonState *state=nullptr, gfx::BackgroundBuffer *layout_bg1=nullptr)
Draw a room object to background buffers.
void DrawWeirdCornerTop_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwards4x2_1to16_BothBG(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsDecor3x4spaced4_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsRightCorners2x1_1to16_plus12(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
static constexpr int kMaxTilesY
void DrawRightwardsDoubled2x2spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawBossShell4x4(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwards1x2_1to16_plus2(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawGanonTriforceFloorDecor(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsBar4x3_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
bool IsValidTilePosition(int tile_x, int tile_y) const
void DrawRightwardsDecor2x2spaced12_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsBlock2x2spaced2_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDoorIndicator(gfx::Bitmap &bitmap, int tile_x, int tile_y, int width, int height, DoorType type, DoorDirection direction)
void DrawDownwardsHasEdge1x1_1to16_plus23(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwards1x1Solid_1to16_plus3(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawSomariaLine(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawArcheryGameTargetDoor(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawRightwardsBigRail1x3_1to16plus5(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawMovingWallWest(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles)
void DrawDownwardsLeftCorners2x1_1to16_plus12(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsDecor2x2spaced12_1to16(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
void DrawDownwardsBigRail3x1_1to16plus5(const RoomObject &obj, gfx::BackgroundBuffer &bg, std::span< const gfx::TileInfo > tiles, const DungeonState *state=nullptr)
const std::vector< gfx::TileInfo > & tiles() const
#define LOG_DEBUG(category, format,...)
TileInfo WordToTileInfo(uint16_t word)
constexpr int kDiagonalGrave_1to16_BothBG
constexpr int kCorner4x4_BothBG
constexpr int kRightwards2x4_1to16_BothBG
constexpr int kDownwards4x2_1to15or26
constexpr int kRightwards2x2_1to15or32
constexpr int kWeirdCornerBottom_BothBG
constexpr int kRightwards2x4_1to15or26
constexpr int kDownwards4x2_1to16_BothBG
constexpr int kCustomObject
constexpr int kWeirdCornerTop_BothBG
constexpr int kDiagonalAcute_1to16_BothBG
constexpr int kDownwardsHasEdge1x1_1to16_plus23
void DrawTableRock4x4_1to16(const DrawContext &ctx)
Draw 4x4 table rock pattern.
void DrawInterRoomFatStairsDownA(const DrawContext &ctx)
Draw inter-room fat stairs going down A (Type 2 object 0x12E)
void DrawAutoStairs(const DrawContext &ctx)
Draw auto stairs (Type 2/3 objects 0x130-0x133, 0x21B-0x21D, 0x233)
void DrawSpittingWaterFace(const DrawContext &ctx)
Draw spitting water face (Type 3 object 0x201)
void Draw4x4BlocksIn4x4SuperSquare(const DrawContext &ctx)
Draw 4x4 solid blocks in a super square grid.
void DrawBigHole4x4_1to16(const DrawContext &ctx)
Draw 4x4 big hole pattern.
void Draw4x4FloorTwoIn4x4SuperSquare(const DrawContext &ctx)
Draw two 4x4 floor pattern variant.
void DrawSpike2x2In4x4SuperSquare(const DrawContext &ctx)
Draw 2x2 spike pattern in super square units.
void DrawSpiralStairs(const DrawContext &ctx, bool going_up, bool is_upper)
Draw spiral stairs (Type 2 objects 0x138-0x13B)
void DrawBombableFloor(const DrawContext &ctx)
Draw bombable floor (Type 3 object 0x247)
void DrawDrenchingWaterFace(const DrawContext &ctx)
Draw drenching water face (Type 3 object 0x202)
void DrawEmptyWaterFace(const DrawContext &ctx)
Draw empty water face (Type 3 object 0x200)
void Draw4x4FloorIn4x4SuperSquare(const DrawContext &ctx)
Draw 4x4 floor pattern in super square units.
void DrawInterRoomFatStairsUp(const DrawContext &ctx)
Draw inter-room fat stairs going up (Type 2 object 0x12D)
void Draw3x3FloorIn4x4SuperSquare(const DrawContext &ctx)
Draw 3x3 floor pattern in super square units.
void DrawStraightInterRoomStairs(const DrawContext &ctx)
Draw straight inter-room stairs (Type 3 objects 0x21E-0x229)
void DrawInterRoomFatStairsDownB(const DrawContext &ctx)
Draw inter-room fat stairs going down B (Type 2 object 0x12F)
void DrawWaterOverlay8x8_1to16(const DrawContext &ctx)
Draw water overlay 8x8 pattern.
void Draw4x4FloorOneIn4x4SuperSquare(const DrawContext &ctx)
Draw single 4x4 floor pattern variant.
void DrawBigKeyLock(const DrawContext &ctx)
Draw big key lock (Type 3 object 0x218)
void DrawPrisonCell(const DrawContext &ctx)
Draw prison cell with bars (Type 3 objects 0x20D, 0x217)
DoorType
Door types from ALTTP.
@ TopShutterLower
Top-sided shutter door (lower layer)
@ FancyDungeonExitLower
Fancy dungeon exit (lower layer)
@ FancyDungeonExit
Fancy dungeon exit.
@ SmallKeyDoor
Small key door.
@ SmallKeyStairsDown
Small key stairs (downwards)
@ BombableCaveExit
Bombable cave exit.
@ SmallKeyStairsUp
Small key stairs (upwards)
@ DungeonSwapMarker
Dungeon swap marker.
@ NormalDoor
Normal door (upper layer)
@ BombableDoor
Bombable door.
@ LayerSwapMarker
Layer swap marker.
@ BottomShutterLower
Bottom-sided shutter door (lower layer)
@ ExplodingWall
Exploding wall.
@ TopSidedShutter
Top-sided shutter door.
@ LitCaveExitLower
Lit cave exit (lower layer)
@ DoubleSidedShutterLower
Double-sided shutter (lower layer)
@ UnopenableBigKeyDoor
Unopenable, double-sided big key door.
@ NormalDoorLower
Normal door (lower layer)
@ BottomSidedShutter
Bottom-sided shutter door.
@ SmallKeyStairsDownLower
Small key stairs (lower layer; downwards)
@ CurtainDoor
Curtain door.
@ WaterfallDoor
Waterfall door.
@ BigKeyDoor
Big key door.
@ EyeWatchDoor
Eye watch door.
@ SmallKeyStairsUpLower
Small key stairs (lower layer; upwards)
@ DoubleSidedShutter
Double sided shutter door.
constexpr int kDoorGfxDown
constexpr std::string_view GetDoorDirectionName(DoorDirection dir)
Get human-readable name for door direction.
constexpr int kDoorGfxLeft
constexpr std::string_view GetDoorTypeName(DoorType type)
Get human-readable name for door type.
DoorDirection
Door direction on room walls.
@ South
Bottom wall (horizontal door, 4x3 tiles)
@ North
Top wall (horizontal door, 4x3 tiles)
@ East
Right wall (vertical door, 3x4 tiles)
@ West
Left wall (vertical door, 3x4 tiles)
constexpr int kDoorGfxRight
Represents a group of palettes.
int width_tiles
Width in 8x8 tiles.
Context passed to draw routines containing all necessary state.
std::pair< int, int > GetTileCoords() const
DoorDimensions GetDimensions() const