yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
downwards_routines.cc
Go to the documentation of this file.
2
5
6namespace yaze {
7namespace zelda3 {
8namespace draw_routines {
9
10namespace {
11
12void DrawDownwardsCorners2x1(const DrawContext& ctx, bool edge_is_left) {
13 if (ctx.tiles.size() < 6) {
14 return;
15 }
16
17 // USDASM caches tile 0 as the solid column. Tiles 1-2 form the opening
18 // cap, tile 3 repeats for size+10 rows, and tiles 4-5 form the closing cap.
19 // The routine name's "+12" is the minimum extent, not an X offset.
20 const int body_count = (ctx.object.size_ & 0x0F) + 10;
21 const int edge_x = ctx.object.x_ + (edge_is_left ? 0 : 1);
22 const int fill_x = ctx.object.x_ + (edge_is_left ? 1 : 0);
23 int y = ctx.object.y_;
24
25 if (!DrawRoutineUtils::ExistingTileMatchesAny(ctx, edge_x, y, {0x00E3})) {
26 DrawRoutineUtils::WriteTile8(ctx.target_bg, edge_x, y, ctx.tiles[1]);
27 DrawRoutineUtils::WriteTile8(ctx.target_bg, edge_x, y + 1, ctx.tiles[2]);
28 DrawRoutineUtils::WriteTile8(ctx.target_bg, fill_x, y, ctx.tiles[0]);
29 DrawRoutineUtils::WriteTile8(ctx.target_bg, fill_x, y + 1, ctx.tiles[0]);
30 y += 2;
31 }
32
33 for (int i = 0; i < body_count; ++i, ++y) {
34 DrawRoutineUtils::WriteTile8(ctx.target_bg, edge_x, y, ctx.tiles[3]);
35 DrawRoutineUtils::WriteTile8(ctx.target_bg, fill_x, y, ctx.tiles[0]);
36 }
37
38 DrawRoutineUtils::WriteTile8(ctx.target_bg, edge_x, y, ctx.tiles[4]);
39 DrawRoutineUtils::WriteTile8(ctx.target_bg, edge_x, y + 1, ctx.tiles[5]);
40 DrawRoutineUtils::WriteTile8(ctx.target_bg, fill_x, y, ctx.tiles[0]);
41 DrawRoutineUtils::WriteTile8(ctx.target_bg, fill_x, y + 1, ctx.tiles[0]);
42}
43
44} // namespace
45
47 // Pattern: Draws 2x2 tiles downward (object 0x60)
48 // Size byte determines how many times to repeat (1-15 or 32)
49 int size = ctx.object.size_;
50 if (size == 0)
51 size = 32; // Special case for object 0x60
52
53 for (int s = 0; s < size; s++) {
54 if (ctx.tiles.size() >= 4) {
55 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
56 // Assembly uses indirect pointers: $BF, $CB, $C2, $CE
57 // tiles[0] → $BF → (col 0, row 0) = top-left
58 // tiles[1] → $CB → (col 0, row 1) = bottom-left
59 // tiles[2] → $C2 → (col 1, row 0) = top-right
60 // tiles[3] → $CE → (col 1, row 1) = bottom-right
62 ctx.object.y_ + (s * 2),
63 ctx.tiles[0]); // col 0, row 0
65 ctx.object.y_ + (s * 2) + 1,
66 ctx.tiles[1]); // col 0, row 1
68 ctx.object.y_ + (s * 2),
69 ctx.tiles[2]); // col 1, row 0
71 ctx.object.y_ + (s * 2) + 1,
72 ctx.tiles[3]); // col 1, row 1
73 }
74 }
75}
76
78 // Pattern: Draws 4x2 tiles downward (objects 0x61-0x62)
79 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order (per ZScream)
80 int size = ctx.object.size_;
81 if (size == 0)
82 size = 26; // Special case
83
84 for (int s = 0; s < size; s++) {
85 if (ctx.tiles.size() >= 8) {
86 // Draw 4x2 pattern in ROW-MAJOR order (matching ZScream)
87 // Row 0: tiles 0, 1, 2, 3 at x+0, x+1, x+2, x+3
89 ctx.object.y_ + (s * 2), ctx.tiles[0]);
91 ctx.object.y_ + (s * 2), ctx.tiles[1]);
93 ctx.object.y_ + (s * 2), ctx.tiles[2]);
95 ctx.object.y_ + (s * 2), ctx.tiles[3]);
96 // Row 1: tiles 4, 5, 6, 7 at x+0, x+1, x+2, x+3
98 ctx.object.y_ + (s * 2) + 1, ctx.tiles[4]);
100 ctx.object.y_ + (s * 2) + 1, ctx.tiles[5]);
102 ctx.object.y_ + (s * 2) + 1, ctx.tiles[6]);
104 ctx.object.y_ + (s * 2) + 1, ctx.tiles[7]);
105 } else if (ctx.tiles.size() >= 4) {
106 // Fallback: with 4 tiles draw 4x1 row pattern
108 ctx.object.y_ + (s * 2), ctx.tiles[0]);
110 ctx.object.y_ + (s * 2), ctx.tiles[1]);
112 ctx.object.y_ + (s * 2), ctx.tiles[2]);
114 ctx.object.y_ + (s * 2), ctx.tiles[3]);
115 }
116 }
117}
118
120 // USDASM $01:8AA4 calls RoomDraw_GetSize_1to16, so the encoded size nibble
121 // is the zero-based repeat count. ObjectDrawer dispatches this routine once
122 // per background because the registry marks it as a BothBG writer.
123 const int count = (ctx.object.size_ & 0x0F) + 1;
124 if (ctx.tiles.size() < 8) {
125 return;
126 }
127
128 for (int s = 0; s < count; ++s) {
129 const int y = ctx.object.y_ + (s * 2);
132 ctx.tiles[1]);
134 ctx.tiles[2]);
136 ctx.tiles[3]);
138 ctx.tiles[4]);
140 ctx.tiles[5]);
142 ctx.tiles[6]);
144 ctx.tiles[7]);
145 }
146}
147
149 // Pattern: Draws 4x2 decoration downward with spacing (objects 0x65-0x66)
150 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order with 6-tile Y
151 // spacing.
152 int size = ctx.object.size_ & 0x0F;
153
154 // Assembly: GetSize_1to16, so count = size + 1
155 int count = size + 1;
156
157 for (int s = 0; s < count; s++) {
158 if (ctx.tiles.size() >= 8) {
159 // Draw 4x2 pattern in ROW-MAJOR order:
160 // Row 0: tiles[0..3], Row 1: tiles[4..7].
161 const int base_y = ctx.object.y_ + (s * 6);
163 ctx.tiles[0]);
164 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y,
165 ctx.tiles[1]);
166 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y,
167 ctx.tiles[2]);
168 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y,
169 ctx.tiles[3]);
170 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_, base_y + 1,
171 ctx.tiles[4]);
172 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
173 ctx.tiles[5]);
174 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
175 ctx.tiles[6]);
176 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y + 1,
177 ctx.tiles[7]);
178 }
179 }
180}
181
183 // Pattern: Draws 2x2 tiles downward (objects 0x67-0x68)
184 int size = ctx.object.size_ & 0x0F;
185
186 // Assembly: GetSize_1to16, so count = size + 1
187 int count = size + 1;
188
189 for (int s = 0; s < count; s++) {
190 if (ctx.tiles.size() >= 4) {
191 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
192 // tiles[0] → col 0, row 0 = top-left
193 // tiles[1] → col 0, row 1 = bottom-left
194 // tiles[2] → col 1, row 0 = top-right
195 // tiles[3] → col 1, row 1 = bottom-right
197 ctx.object.y_ + (s * 2),
198 ctx.tiles[0]); // col 0, row 0
200 ctx.object.y_ + (s * 2) + 1,
201 ctx.tiles[1]); // col 0, row 1
203 ctx.object.y_ + (s * 2),
204 ctx.tiles[2]); // col 1, row 0
206 ctx.object.y_ + (s * 2) + 1,
207 ctx.tiles[3]); // col 1, row 1
208 }
209 }
210}
211
213 // Pattern: Vertical rail with corner/middle/end (object 0x69).
214 // ASM: RoomDraw_DownwardsHasEdge1x1_1to16_plus3 ($01:8EC3) loads A=2 then
215 // falls into RoomDraw_DownwardsHasEdge1x1_1to16, which calls
216 // RoomDraw_GetSize_1to16_timesA ($01:B0AF) to set $B2 = composite_size + A.
217 // For the _plus3 variant that yields count = size + 2 middle tiles, matching
218 // the horizontal counterpart RoomDraw_RightwardsHasEdge1x1_1to16_plus3
219 // ($01:8EF0) which uses the same A=2. Total span = 1 corner + (size+2)
220 // middles + 1 end = size + 4 tiles.
221 int size = ctx.object.size_ & 0x0F;
222 int count = size + 2;
223
224 if (ctx.tiles.size() < 3)
225 return;
226
227 int y = ctx.object.y_;
228 // USDASM $01:8EC9-$01:8ED4 suppresses the leading corner when the existing
229 // tile already contains the small vertical rail corner.
231 {0x00E3})) {
233 }
234 y++;
235 for (int s = 0; s < count; s++) {
237 y++;
238 }
240}
241
243 // Pattern: 1x1 edge tiles downward (objects 0x6A-0x6B)
244 int size = ctx.object.size_ & 0x0F;
245
246 // Assembly: GetSize_1to16, so count = size + 1
247 int count = size + 1;
248
249 for (int s = 0; s < count; s++) {
250 if (ctx.tiles.size() >= 1) {
251 // Use first 8x8 tile from span
253 ctx.object.y_ + s, ctx.tiles[0]);
254 }
255 }
256}
257
259 DrawDownwardsCorners2x1(ctx, /*edge_is_left=*/true);
260}
261
263 DrawDownwardsCorners2x1(ctx, /*edge_is_left=*/false);
264}
265
267 const int size = ctx.object.size_ & 0x0F;
268 const int count = size + 1;
269 if (ctx.tiles.size() < 16) {
270 return;
271 }
272
273 for (int s = 0; s < count; ++s) {
274 const int base_y = ctx.object.y_ + (s * 4);
275 for (int x = 0; x < 4; ++x) {
276 for (int y = 0; y < 4; ++y) {
278 base_y + y, ctx.tiles[x * 4 + y]);
279 }
280 }
281 }
282}
283
285 const int size = ctx.object.size_ & 0x0F;
286 const int count = size + 4;
287 if (ctx.tiles.empty()) {
288 return;
289 }
290
291 for (int s = 0; s < count; ++s) {
293 ctx.object.y_ + s, ctx.tiles[0]);
294 }
295}
296
298 const int size = ctx.object.size_ & 0x0F;
299 const int count = size + 1;
300 if (ctx.tiles.size() < 16) {
301 return;
302 }
303
304 for (int s = 0; s < count; ++s) {
305 const int base_y = ctx.object.y_ + (s * 6);
306 for (int x = 0; x < 4; ++x) {
307 for (int y = 0; y < 4; ++y) {
309 base_y + y, ctx.tiles[x * 4 + y]);
310 }
311 }
312 }
313}
314
316 const int size = ctx.object.size_ & 0x0F;
317 const int count = size + 1;
318 if (ctx.tiles.size() < 8) {
319 return;
320 }
321
322 for (int s = 0; s < count; ++s) {
323 const int base_y = ctx.object.y_ + (s * 6);
324 for (int x = 0; x < 2; ++x) {
325 for (int y = 0; y < 4; ++y) {
327 base_y + y, ctx.tiles[x * 4 + y]);
328 }
329 }
330 }
331}
332
334 const int size = ctx.object.size_ & 0x0F;
335 const int count = size + 1;
336 if (ctx.tiles.size() < 12) {
337 return;
338 }
339
340 for (int s = 0; s < count; ++s) {
341 const int base_y = ctx.object.y_ + (s * 8);
342 for (int x = 0; x < 3; ++x) {
343 for (int y = 0; y < 4; ++y) {
345 base_y + y, ctx.tiles[x * 4 + y]);
346 }
347 }
348 }
349}
350
352 const int size = ctx.object.size_ & 0x0F;
353 const int count = size + 1;
354 if (ctx.tiles.size() < 4) {
355 return;
356 }
357
358 for (int s = 0; s < count; ++s) {
359 const int base_y = ctx.object.y_ + (s * 14);
360 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
361 ctx.tiles[0]);
362 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
363 ctx.tiles[1]);
364 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
365 ctx.tiles[2]);
366 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
367 ctx.tiles[3]);
368 }
369}
370
372 const int size = ctx.object.size_ & 0x0F;
373 const int count = size + 2;
374 if (ctx.tiles.empty()) {
375 return;
376 }
377
378 for (int s = 0; s < count; ++s) {
380 ctx.object.y_ + s, ctx.tiles[0]);
381 }
382}
383
385 const int size = ctx.object.size_ & 0x0F;
386 const int count = size + 1;
387 if (ctx.tiles.size() < 8) {
388 return;
389 }
390
391 for (int s = 0; s < count; ++s) {
392 const int base_y = ctx.object.y_ + (s * 12);
393 for (int x = 0; x < 2; ++x) {
394 for (int y = 0; y < 4; ++y) {
396 base_y + y, ctx.tiles[x * 4 + y]);
397 }
398 }
399 }
400}
401
403 const int size = ctx.object.size_ & 0x0F;
404 const int count = size + 1;
405 if (ctx.tiles.size() < 12) {
406 return;
407 }
408
409 for (int s = 0; s < count; ++s) {
410 const int base_y = ctx.object.y_ + (s * 6);
411 for (int x = 0; x < 3; ++x) {
412 for (int y = 0; y < 4; ++y) {
414 base_y + y, ctx.tiles[x * 4 + y]);
415 }
416 }
417 }
418}
419
421 const int size = ctx.object.size_ & 0x0F;
422 const int middle_rows = size + 1;
423 const int total_rows = size + 6; // 2 top + (size+1) middle + 3 bottom.
424
425 if (ctx.tiles.size() >= 12) {
426 // USDASM $01:8F0C:
427 // - Top cap: 2x2 (tiles 0..3, column-major)
428 // - Middle: repeated 2x1 rows (tiles 4..5)
429 // - Bottom cap: 2 columns x 3 rows (tiles 6..11)
431 ctx.object.y_ + 0, ctx.tiles[0]);
433 ctx.object.y_ + 1, ctx.tiles[1]);
435 ctx.object.y_ + 0, ctx.tiles[2]);
437 ctx.object.y_ + 1, ctx.tiles[3]);
438
439 int base_y = ctx.object.y_ + 2;
440 for (int row = 0; row < middle_rows; ++row) {
442 base_y + row, ctx.tiles[4]);
444 base_y + row, ctx.tiles[5]);
445 }
446
447 const int cap_y = base_y + middle_rows;
448 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 0,
449 ctx.tiles[6]);
450 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 1,
451 ctx.tiles[7]);
452 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 2,
453 ctx.tiles[8]);
454 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 0,
455 ctx.tiles[9]);
456 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 1,
457 ctx.tiles[10]);
458 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 2,
459 ctx.tiles[11]);
460 return;
461 }
462
463 if (ctx.tiles.empty() || total_rows <= 0) {
464 return;
465 }
466 const gfx::TileInfo& left = ctx.tiles[0];
467 const gfx::TileInfo& right =
468 ctx.tiles.size() > 1 ? ctx.tiles[1] : ctx.tiles[0];
469 for (int row = 0; row < total_rows; ++row) {
471 ctx.object.y_ + row, left);
473 ctx.object.y_ + row, right);
474 }
475}
476
478 const int size = ctx.object.size_ & 0x0F;
479 const int count = size + 1;
480 if (ctx.tiles.size() < 4) {
481 return;
482 }
483
484 for (int s = 0; s < count; ++s) {
485 const int base_y = ctx.object.y_ + (s * 4);
486 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
487 ctx.tiles[0]);
488 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
489 ctx.tiles[1]);
490 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
491 ctx.tiles[2]);
492 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
493 ctx.tiles[3]);
494 }
495}
496
498 // USDASM RoomDraw_DownwardsCannonHole3x4_1to16 ($01:9CEB), objects
499 // 0x85/0x86. size+1 segments of two row-major 3-tile rows: the first from
500 // words 0..5, the middle ones from words 6..11 (PHX/PLX), and a closing
501 // segment from words 12..17 (ADC #$000C). Height is 2*size+4.
502 if (ctx.tiles.size() < 18) {
503 return;
504 }
505 const int count = (ctx.object.size_ & 0x0F) + 1; // GetSize_1to16
506 auto draw_segment = [&](int segment, int first) {
507 for (int y = 0; y < 2; ++y) {
508 for (int x = 0; x < 3; ++x) {
510 ctx.object.y_ + segment * 2 + y,
511 ctx.tiles[first + y * 3 + x]);
512 }
513 }
514 };
515 draw_segment(0, 0);
516 for (int s = 1; s < count; ++s) {
517 draw_segment(s, 6);
518 }
519 draw_segment(count, 12);
520}
521
523 const int size = ctx.object.size_ & 0x0F;
524 const int middle_rows = (size + 2) * 2;
525 if (ctx.tiles.size() < 4) {
526 return;
527 }
528
529 // USDASM $01:97B5:
530 // - top row uses tiles 0..1
531 // - remaining rows use tiles 2..3, repeated 2*(size+2) times
533 ctx.object.y_ + 0, ctx.tiles[0]);
535 ctx.object.y_ + 0, ctx.tiles[1]);
536 for (int row = 0; row < middle_rows; ++row) {
538 ctx.object.y_ + 1 + row, ctx.tiles[2]);
540 ctx.object.y_ + 1 + row, ctx.tiles[3]);
541 }
542}
543
545 const int size = ctx.object.size_ & 0x0F;
546 const int count = size + 1;
547 if (ctx.tiles.size() < 4) {
548 return;
549 }
550
551 for (int s = 0; s < count; ++s) {
552 const int base_y = ctx.object.y_ + (s * 2);
553 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
554 ctx.tiles[0]);
555 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
556 ctx.tiles[1]);
557 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
558 ctx.tiles[2]);
559 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
560 ctx.tiles[3]);
561 }
562}
563
567
569 const int count = (ctx.object.size_ & 0x0F) + 8;
570 if (ctx.tiles.empty()) {
571 return;
572 }
573
574 for (int row = 0; row < count; ++row) {
576 ctx.object.y_ + row, ctx.tiles[0]);
577 }
578}
579
580void RegisterDownwardsRoutines(std::vector<DrawRoutineInfo>& registry) {
581 using Category = DrawRoutineInfo::Category;
582
583 registry.push_back(
584 DrawRoutineInfo{.id = 7, // RoomDraw_Downwards2x2_1to15or32
585 .name = "Downwards2x2_1to15or32",
586 .function = DrawDownwards2x2_1to15or32,
587 .draws_to_both_bgs = false,
588 .base_width = 2,
589 .base_height = 2,
590 .min_tiles = 4, // 2x2 block
591 .category = Category::Downwards});
592
593 registry.push_back(DrawRoutineInfo{
594 .id = 8, // RoomDraw_Downwards4x2_1to15or26
595 .name = "Downwards4x2_1to15or26",
596 .function = DrawDownwards4x2_1to15or26,
597 // USDASM: RoomDraw_Downwards4x2_1to15or26 ($01:8A89) jumps to
598 // RoomDraw_Downwards4x2VariableSpacing ($01:B220) which writes through
599 // the current tilemap pointers (single-layer).
600 .draws_to_both_bgs = false,
601 .base_width = 4,
602 .base_height = 2,
603 .min_tiles = 8, // 4x2 block
604 .category = Category::Downwards});
605
606 registry.push_back(
607 DrawRoutineInfo{.id = 9, // RoomDraw_Downwards4x2_1to16_BothBG
608 .name = "Downwards4x2_1to16_BothBG",
610 .draws_to_both_bgs = true,
611 .base_width = 4,
612 .base_height = 2,
613 .min_tiles = 8, // 4x2 block
614 .category = Category::Downwards});
615
616 registry.push_back(
617 DrawRoutineInfo{.id = 10, // RoomDraw_DownwardsDecor4x2spaced4_1to16
618 .name = "DownwardsDecor4x2spaced4_1to16",
620 .draws_to_both_bgs = false,
621 .base_width = 4,
622 .base_height = 2,
623 .min_tiles = 8, // 4x2 block
624 .category = Category::Downwards});
625
626 registry.push_back(DrawRoutineInfo{.id = 11, // RoomDraw_Downwards2x2_1to16
627 .name = "Downwards2x2_1to16",
628 .function = DrawDownwards2x2_1to16,
629 .draws_to_both_bgs = false,
630 .base_width = 2,
631 .base_height = 2,
632 .min_tiles = 4, // 2x2 block
633 .category = Category::Downwards});
634
635 registry.push_back(
636 DrawRoutineInfo{.id = 12, // RoomDraw_DownwardsHasEdge1x1_1to16_plus3
637 .name = "DownwardsHasEdge1x1_1to16_plus3",
639 .draws_to_both_bgs = false,
640 .base_width = 1,
641 // size=0 footprint = corner + 2 middles + end = 4 rows
642 // (mirrors horizontal kRightwardsHasEdge1x1_1to16_plus3
643 // base_width=4; both share ASM A=2 path).
644 .base_height = 4,
645 .min_tiles = 3, // top edge + middle + bottom edge
646 .category = Category::Downwards});
647
648 registry.push_back(
649 DrawRoutineInfo{.id = 13, // RoomDraw_DownwardsEdge1x1_1to16
650 .name = "DownwardsEdge1x1_1to16",
651 .function = DrawDownwardsEdge1x1_1to16,
652 .draws_to_both_bgs = false,
653 .base_width = 1,
654 .base_height = 1,
655 .min_tiles = 1, // single repeated tile
656 .category = Category::Downwards});
657
658 registry.push_back(DrawRoutineInfo{
659 .id = 14, // RoomDraw_DownwardsLeftCorners2x1_1to16_plus12
660 .name = "DownwardsLeftCorners2x1_1to16_plus12",
662 .draws_to_both_bgs = false,
663 .base_width = 2,
664 .base_height = 14,
665 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
666 .category = Category::Downwards});
667
668 registry.push_back(DrawRoutineInfo{
669 .id = 15, // RoomDraw_DownwardsRightCorners2x1_1to16_plus12
670 .name = "DownwardsRightCorners2x1_1to16_plus12",
672 .draws_to_both_bgs = false,
673 .base_width = 2,
674 .base_height = 14,
675 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
676 .category = Category::Downwards});
677
678 registry.push_back(
680 .name = "DownwardsFloor4x4_1to16",
681 .function = DrawDownwardsFloor4x4_1to16,
682 .draws_to_both_bgs = false,
683 .base_width = 4,
684 .base_height = 4,
685 .min_tiles = 16,
686 .category = Category::Downwards});
687
688 registry.push_back(
690 .name = "Downwards1x1Solid_1to16_plus3",
692 .draws_to_both_bgs = false,
693 .base_width = 1,
694 .base_height = 1,
695 .min_tiles = 1,
696 .category = Category::Downwards});
697
698 registry.push_back(
700 .name = "DownwardsDecor4x4spaced2_1to16",
702 .draws_to_both_bgs = false,
703 .base_width = 4,
704 .base_height = 4,
705 .min_tiles = 16,
706 .category = Category::Downwards});
707
708 registry.push_back(
710 .name = "DownwardsPillar2x4spaced2_1to16",
712 .draws_to_both_bgs = false,
713 .base_width = 2,
714 .base_height = 4,
715 .min_tiles = 8,
716 .category = Category::Downwards});
717
718 registry.push_back(
720 .name = "DownwardsDecor3x4spaced4_1to16",
722 .draws_to_both_bgs = false,
723 .base_width = 3,
724 .base_height = 4,
725 .min_tiles = 12,
726 .category = Category::Downwards});
727
728 registry.push_back(
730 .name = "DownwardsDecor2x2spaced12_1to16",
732 .draws_to_both_bgs = false,
733 .base_width = 2,
734 .base_height = 2,
735 .min_tiles = 4,
736 .category = Category::Downwards});
737
738 registry.push_back(
740 .name = "DownwardsLine1x1_1to16plus1",
742 .draws_to_both_bgs = false,
743 .base_width = 1,
744 .base_height = 1,
745 .min_tiles = 1,
746 .category = Category::Downwards});
747
748 registry.push_back(
750 .name = "DownwardsDecor2x4spaced8_1to16",
752 .draws_to_both_bgs = false,
753 .base_width = 2,
754 .base_height = 4,
755 .min_tiles = 8,
756 .category = Category::Downwards});
757
758 registry.push_back(
760 .name = "DownwardsDecor3x4spaced2_1to16",
762 .draws_to_both_bgs = false,
763 .base_width = 3,
764 .base_height = 4,
765 .min_tiles = 12,
766 .category = Category::Downwards});
767
768 registry.push_back(
770 .name = "DownwardsBigRail3x1_1to16plus5",
772 .draws_to_both_bgs = false,
773 .base_width = 2,
774 .base_height = 6,
775 .min_tiles = 12,
776 .category = Category::Downwards});
777
778 registry.push_back(
780 .name = "DownwardsBlock2x2spaced2_1to16",
782 .draws_to_both_bgs = false,
783 .base_width = 2,
784 .base_height = 2,
785 .min_tiles = 4,
786 .category = Category::Downwards});
787
788 registry.push_back(
790 .name = "DownwardsCannonHole3x4_1to16",
792 .draws_to_both_bgs = false,
793 .base_width = 3,
794 .base_height = 4,
795 .min_tiles = 12,
796 .category = Category::Downwards});
797
798 registry.push_back(
800 .name = "DownwardsBar2x5_1to16",
801 .function = DrawDownwardsBar2x5_1to16,
802 .draws_to_both_bgs = false,
803 .base_width = 2,
804 .base_height = 5,
805 .min_tiles = 4,
806 .category = Category::Downwards});
807
808 registry.push_back(
810 .name = "DownwardsPots2x2_1to16",
811 .function = DrawDownwardsPots2x2_1to16,
812 .draws_to_both_bgs = false,
813 .base_width = 2,
814 .base_height = 2,
815 .min_tiles = 4,
816 .category = Category::Downwards});
817
818 registry.push_back(
820 .name = "DownwardsHammerPegs2x2_1to16",
822 .draws_to_both_bgs = false,
823 .base_width = 2,
824 .base_height = 2,
825 .min_tiles = 4,
826 .category = Category::Downwards});
827
828 registry.push_back(
830 .name = "DownwardsEdge1x1_1to16plus7",
832 .draws_to_both_bgs = false,
833 .base_width = 1,
834 .base_height = 8,
835 .min_tiles = 1,
836 .category = Category::Downwards});
837}
838
839} // namespace draw_routines
840} // namespace zelda3
841} // namespace yaze
SNES 16-bit tile metadata container.
Definition snes_tile.h:52
bool ExistingTileMatchesAny(const gfx::BackgroundBuffer &bg, int tile_x, int tile_y, std::initializer_list< uint16_t > tile_ids)
void WriteTile8(gfx::BackgroundBuffer &bg, int tile_x, int tile_y, const gfx::TileInfo &tile_info)
Write an 8x8 tile to the background buffer.
void DrawDownwardsCorners2x1(const DrawContext &ctx, bool edge_is_left)
void DrawDownwards1x1Solid_1to16_plus3(const DrawContext &ctx)
Draw downwards 1x1 solid line with +3 extension.
void DrawDownwardsDecor2x4spaced8_1to16(const DrawContext &ctx)
Draw downwards 2x4 decoration with 8-tile spacing.
void DrawDownwards4x2_1to15or26(const DrawContext &ctx)
Draw 4x2 tiles downward pattern (1-15 or 26 iterations)
void DrawDownwardsEdge1x1_1to16(const DrawContext &ctx)
Draw 1x1 edge tiles downward (1-16 iterations)
void DrawDownwardsBar2x5_1to16(const DrawContext &ctx)
Draw downwards 2x5 bar pattern.
void DrawDownwardsDecor2x2spaced12_1to16(const DrawContext &ctx)
Draw downwards 2x2 decoration with 12-tile spacing.
void DrawDownwards2x2_1to15or32(const DrawContext &ctx)
Draw 2x2 tiles downward pattern (1-15 or 32 iterations)
void DrawDownwards2x2_1to16(const DrawContext &ctx)
Draw 2x2 tiles downward pattern (1-16 iterations)
void RegisterDownwardsRoutines(std::vector< DrawRoutineInfo > &registry)
Register all downwards draw routines to the registry.
void DrawDownwardsDecor4x4spaced2_1to16(const DrawContext &ctx)
Draw downwards 4x4 decoration with 2-tile spacing.
void DrawDownwardsEdge1x1_1to16plus7(const DrawContext &ctx)
Draw a single tile downward for size + 8 rows.
void DrawDownwardsHasEdge1x1_1to16_plus3(const DrawContext &ctx)
Draw 1x1 tiles with edge detection +3 downward.
void DrawDownwardsLine1x1_1to16plus1(const DrawContext &ctx)
Draw downwards 1x1 line with +1 extension.
void DrawDownwardsCannonHole3x4_1to16(const DrawContext &ctx)
Draw downwards cannon-hole 3x4 pattern.
void DrawDownwardsLeftCorners2x1_1to16_plus12(const DrawContext &ctx)
Draw left corner 2x1 tiles with opening and closing caps.
void DrawDownwardsPots2x2_1to16(const DrawContext &ctx)
Draw downwards 2x2 pots pattern.
void DrawDownwardsBlock2x2spaced2_1to16(const DrawContext &ctx)
Draw downwards 2x2 block pattern with 2-tile spacing.
void DrawDownwardsBigRail3x1_1to16plus5(const DrawContext &ctx)
Draw downwards big rail pattern (3x1 family, +5 extension)
void DrawDownwardsFloor4x4_1to16(const DrawContext &ctx)
Draw downwards 4x4 floor blocks.
void DrawDownwardsRightCorners2x1_1to16_plus12(const DrawContext &ctx)
Draw right corner 2x1 tiles with opening and closing caps.
void DrawDownwardsHammerPegs2x2_1to16(const DrawContext &ctx)
Draw downwards 2x2 hammer pegs pattern.
void DrawDownwardsDecor4x2spaced4_1to16(const DrawContext &ctx)
Draw 4x2 decoration downward with spacing (1-16 iterations)
void DrawDownwardsPillar2x4spaced2_1to16(const DrawContext &ctx)
Draw downwards 2x4 pillar with 2-tile spacing.
void DrawDownwardsDecor3x4spaced2_1to16(const DrawContext &ctx)
Draw downwards 3x4 decoration with 2-tile spacing.
void DrawDownwardsDecor3x4spaced4_1to16(const DrawContext &ctx)
Draw downwards 3x4 decoration with 4-tile spacing.
void DrawDownwards4x2_1to16_BothBG(const DrawContext &ctx)
Draw 4x2 tiles downward pattern for both BG layers.
Context passed to draw routines containing all necessary state.
std::span< const gfx::TileInfo > tiles
gfx::BackgroundBuffer & target_bg
Metadata about a draw routine.