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
11 // Pattern: Draws 2x2 tiles downward (object 0x60)
12 // Size byte determines how many times to repeat (1-15 or 32)
13 int size = ctx.object.size_;
14 if (size == 0)
15 size = 32; // Special case for object 0x60
16
17 for (int s = 0; s < size; s++) {
18 if (ctx.tiles.size() >= 4) {
19 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
20 // Assembly uses indirect pointers: $BF, $CB, $C2, $CE
21 // tiles[0] → $BF → (col 0, row 0) = top-left
22 // tiles[1] → $CB → (col 0, row 1) = bottom-left
23 // tiles[2] → $C2 → (col 1, row 0) = top-right
24 // tiles[3] → $CE → (col 1, row 1) = bottom-right
26 ctx.object.y_ + (s * 2),
27 ctx.tiles[0]); // col 0, row 0
29 ctx.object.y_ + (s * 2) + 1,
30 ctx.tiles[1]); // col 0, row 1
32 ctx.object.y_ + (s * 2),
33 ctx.tiles[2]); // col 1, row 0
35 ctx.object.y_ + (s * 2) + 1,
36 ctx.tiles[3]); // col 1, row 1
37 }
38 }
39}
40
42 // Pattern: Draws 4x2 tiles downward (objects 0x61-0x62)
43 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order (per ZScream)
44 int size = ctx.object.size_;
45 if (size == 0)
46 size = 26; // Special case
47
48 for (int s = 0; s < size; s++) {
49 if (ctx.tiles.size() >= 8) {
50 // Draw 4x2 pattern in ROW-MAJOR order (matching ZScream)
51 // Row 0: tiles 0, 1, 2, 3 at x+0, x+1, x+2, x+3
53 ctx.object.y_ + (s * 2), ctx.tiles[0]);
55 ctx.object.y_ + (s * 2), ctx.tiles[1]);
57 ctx.object.y_ + (s * 2), ctx.tiles[2]);
59 ctx.object.y_ + (s * 2), ctx.tiles[3]);
60 // Row 1: tiles 4, 5, 6, 7 at x+0, x+1, x+2, x+3
62 ctx.object.y_ + (s * 2) + 1, ctx.tiles[4]);
64 ctx.object.y_ + (s * 2) + 1, ctx.tiles[5]);
66 ctx.object.y_ + (s * 2) + 1, ctx.tiles[6]);
68 ctx.object.y_ + (s * 2) + 1, ctx.tiles[7]);
69 } else if (ctx.tiles.size() >= 4) {
70 // Fallback: with 4 tiles draw 4x1 row pattern
72 ctx.object.y_ + (s * 2), ctx.tiles[0]);
74 ctx.object.y_ + (s * 2), ctx.tiles[1]);
76 ctx.object.y_ + (s * 2), ctx.tiles[2]);
78 ctx.object.y_ + (s * 2), ctx.tiles[3]);
79 }
80 }
81}
82
84 // USDASM $01:8AA4 calls RoomDraw_GetSize_1to16, so the encoded size nibble
85 // is the zero-based repeat count. ObjectDrawer dispatches this routine once
86 // per background because the registry marks it as a BothBG writer.
87 const int count = (ctx.object.size_ & 0x0F) + 1;
88 if (ctx.tiles.size() < 8) {
89 return;
90 }
91
92 for (int s = 0; s < count; ++s) {
93 const int y = ctx.object.y_ + (s * 2);
96 ctx.tiles[1]);
98 ctx.tiles[2]);
100 ctx.tiles[3]);
102 ctx.tiles[4]);
104 ctx.tiles[5]);
106 ctx.tiles[6]);
108 ctx.tiles[7]);
109 }
110}
111
113 // Pattern: Draws 4x2 decoration downward with spacing (objects 0x65-0x66)
114 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order with 6-tile Y
115 // spacing.
116 int size = ctx.object.size_ & 0x0F;
117
118 // Assembly: GetSize_1to16, so count = size + 1
119 int count = size + 1;
120
121 for (int s = 0; s < count; s++) {
122 if (ctx.tiles.size() >= 8) {
123 // Draw 4x2 pattern in ROW-MAJOR order:
124 // Row 0: tiles[0..3], Row 1: tiles[4..7].
125 const int base_y = ctx.object.y_ + (s * 6);
127 ctx.tiles[0]);
128 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y,
129 ctx.tiles[1]);
130 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y,
131 ctx.tiles[2]);
132 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y,
133 ctx.tiles[3]);
134 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_, base_y + 1,
135 ctx.tiles[4]);
136 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
137 ctx.tiles[5]);
138 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
139 ctx.tiles[6]);
140 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y + 1,
141 ctx.tiles[7]);
142 }
143 }
144}
145
147 // Pattern: Draws 2x2 tiles downward (objects 0x67-0x68)
148 int size = ctx.object.size_ & 0x0F;
149
150 // Assembly: GetSize_1to16, so count = size + 1
151 int count = size + 1;
152
153 for (int s = 0; s < count; s++) {
154 if (ctx.tiles.size() >= 4) {
155 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
156 // tiles[0] → col 0, row 0 = top-left
157 // tiles[1] → col 0, row 1 = bottom-left
158 // tiles[2] → col 1, row 0 = top-right
159 // tiles[3] → col 1, row 1 = bottom-right
161 ctx.object.y_ + (s * 2),
162 ctx.tiles[0]); // col 0, row 0
164 ctx.object.y_ + (s * 2) + 1,
165 ctx.tiles[1]); // col 0, row 1
167 ctx.object.y_ + (s * 2),
168 ctx.tiles[2]); // col 1, row 0
170 ctx.object.y_ + (s * 2) + 1,
171 ctx.tiles[3]); // col 1, row 1
172 }
173 }
174}
175
177 // Pattern: Vertical rail with corner/middle/end (object 0x69).
178 // ASM: RoomDraw_DownwardsHasEdge1x1_1to16_plus3 ($01:8EC3) loads A=2 then
179 // falls into RoomDraw_DownwardsHasEdge1x1_1to16, which calls
180 // RoomDraw_GetSize_1to16_timesA ($01:B0AF) to set $B2 = composite_size + A.
181 // For the _plus3 variant that yields count = size + 2 middle tiles, matching
182 // the horizontal counterpart RoomDraw_RightwardsHasEdge1x1_1to16_plus3
183 // ($01:8EF0) which uses the same A=2. Total span = 1 corner + (size+2)
184 // middles + 1 end = size + 4 tiles.
185 int size = ctx.object.size_ & 0x0F;
186 int count = size + 2;
187
188 if (ctx.tiles.size() < 3)
189 return;
190
191 int y = ctx.object.y_;
192 // USDASM $01:8EC9-$01:8ED4 suppresses the leading corner when the existing
193 // tile already contains the small vertical rail corner.
195 {0x00E3})) {
197 }
198 y++;
199 for (int s = 0; s < count; s++) {
201 y++;
202 }
204}
205
207 // Pattern: 1x1 edge tiles downward (objects 0x6A-0x6B)
208 int size = ctx.object.size_ & 0x0F;
209
210 // Assembly: GetSize_1to16, so count = size + 1
211 int count = size + 1;
212
213 for (int s = 0; s < count; s++) {
214 if (ctx.tiles.size() >= 1) {
215 // Use first 8x8 tile from span
217 ctx.object.y_ + s, ctx.tiles[0]);
218 }
219 }
220}
221
223 // Pattern: Left corner 2x1 tiles with +12 offset downward (object 0x6C)
224 const int size = ctx.object.size_ & 0x0F;
225 // USDASM $01:9045 - Object_Size_N_to_N_plus_15 with N=0x0A.
226 const int count = size + 10;
227 if (count <= 0 || ctx.tiles.empty()) {
228 return;
229 }
230
231 const int base_x = ctx.object.x_ + 12;
232 int current_y = ctx.object.y_;
233
234 const gfx::TileInfo& fill = ctx.tiles[0];
235 const gfx::TileInfo& start_top_left =
236 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
237 const gfx::TileInfo& start_bottom_left =
238 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
239 const gfx::TileInfo& body_left = ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
240 const gfx::TileInfo& end_top_left =
241 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_left;
242 const gfx::TileInfo& end_bottom_left =
243 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
244
246 current_y, {0x00E3})) {
247 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y,
248 start_top_left);
249 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
250 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
251 start_bottom_left);
252 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
253 fill);
254 current_y += 2;
255 }
256
257 for (int s = 0; s < count; ++s) {
258 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s,
259 body_left);
260 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
261 fill);
262 }
263
264 current_y += count;
265 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, end_top_left);
266 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
267 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
268 end_bottom_left);
269 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1, fill);
270}
271
273 // Pattern: Right corner 2x1 tiles with +12 offset downward (object 0x6D)
274 const int size = ctx.object.size_ & 0x0F;
275 // USDASM $01:908F - mirrored variant of the left-corner routine.
276 const int count = size + 10;
277 if (count <= 0 || ctx.tiles.empty()) {
278 return;
279 }
280
281 const int base_x = ctx.object.x_ + 12;
282 int current_y = ctx.object.y_;
283
284 const gfx::TileInfo& fill = ctx.tiles[0];
285 const gfx::TileInfo& start_top_right =
286 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
287 const gfx::TileInfo& start_bottom_right =
288 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
289 const gfx::TileInfo& body_right = ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
290 const gfx::TileInfo& end_top_right =
291 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_right;
292 const gfx::TileInfo& end_bottom_right =
293 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
294
296 current_y, {0x00E3})) {
297 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
298 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
299 start_top_right);
300 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
301 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
302 start_bottom_right);
303 current_y += 2;
304 }
305
306 for (int s = 0; s < count; ++s) {
307 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s, fill);
308 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
309 body_right);
310 }
311
312 current_y += count;
313 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
314 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
315 end_top_right);
316 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
317 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
318 end_bottom_right);
319}
320
322 const int size = ctx.object.size_ & 0x0F;
323 const int count = size + 1;
324 if (ctx.tiles.size() < 16) {
325 return;
326 }
327
328 for (int s = 0; s < count; ++s) {
329 const int base_y = ctx.object.y_ + (s * 4);
330 for (int x = 0; x < 4; ++x) {
331 for (int y = 0; y < 4; ++y) {
333 base_y + y, ctx.tiles[x * 4 + y]);
334 }
335 }
336 }
337}
338
340 const int size = ctx.object.size_ & 0x0F;
341 const int count = size + 4;
342 if (ctx.tiles.empty()) {
343 return;
344 }
345
346 for (int s = 0; s < count; ++s) {
348 ctx.object.y_ + s + 3, ctx.tiles[0]);
349 }
350}
351
353 const int size = ctx.object.size_ & 0x0F;
354 const int count = size + 1;
355 if (ctx.tiles.size() < 16) {
356 return;
357 }
358
359 for (int s = 0; s < count; ++s) {
360 const int base_y = ctx.object.y_ + (s * 6);
361 for (int x = 0; x < 4; ++x) {
362 for (int y = 0; y < 4; ++y) {
364 base_y + y, ctx.tiles[x * 4 + y]);
365 }
366 }
367 }
368}
369
371 const int size = ctx.object.size_ & 0x0F;
372 const int count = size + 1;
373 if (ctx.tiles.size() < 8) {
374 return;
375 }
376
377 for (int s = 0; s < count; ++s) {
378 const int base_y = ctx.object.y_ + (s * 6);
379 for (int x = 0; x < 2; ++x) {
380 for (int y = 0; y < 4; ++y) {
382 base_y + y, ctx.tiles[x * 4 + y]);
383 }
384 }
385 }
386}
387
389 const int size = ctx.object.size_ & 0x0F;
390 const int count = size + 1;
391 if (ctx.tiles.size() < 12) {
392 return;
393 }
394
395 for (int s = 0; s < count; ++s) {
396 const int base_y = ctx.object.y_ + (s * 8);
397 for (int x = 0; x < 3; ++x) {
398 for (int y = 0; y < 4; ++y) {
400 base_y + y, ctx.tiles[x * 4 + y]);
401 }
402 }
403 }
404}
405
407 const int size = ctx.object.size_ & 0x0F;
408 const int count = size + 1;
409 if (ctx.tiles.size() < 4) {
410 return;
411 }
412
413 for (int s = 0; s < count; ++s) {
414 const int base_y = ctx.object.y_ + (s * 14);
415 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
416 ctx.tiles[0]);
417 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
418 ctx.tiles[1]);
419 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
420 ctx.tiles[2]);
421 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
422 ctx.tiles[3]);
423 }
424}
425
427 const int size = ctx.object.size_ & 0x0F;
428 const int count = size + 2;
429 if (ctx.tiles.empty()) {
430 return;
431 }
432
433 for (int s = 0; s < count; ++s) {
435 ctx.object.y_ + s, ctx.tiles[0]);
436 }
437}
438
440 const int size = ctx.object.size_ & 0x0F;
441 const int count = size + 1;
442 if (ctx.tiles.size() < 8) {
443 return;
444 }
445
446 for (int s = 0; s < count; ++s) {
447 const int base_y = ctx.object.y_ + (s * 12);
448 for (int x = 0; x < 2; ++x) {
449 for (int y = 0; y < 4; ++y) {
451 base_y + y, ctx.tiles[x * 4 + y]);
452 }
453 }
454 }
455}
456
458 const int size = ctx.object.size_ & 0x0F;
459 const int count = size + 1;
460 if (ctx.tiles.size() < 12) {
461 return;
462 }
463
464 for (int s = 0; s < count; ++s) {
465 const int base_y = ctx.object.y_ + (s * 6);
466 for (int x = 0; x < 3; ++x) {
467 for (int y = 0; y < 4; ++y) {
469 base_y + y, ctx.tiles[x * 4 + y]);
470 }
471 }
472 }
473}
474
476 const int size = ctx.object.size_ & 0x0F;
477 const int middle_rows = size + 1;
478 const int total_rows = size + 6; // 2 top + (size+1) middle + 3 bottom.
479
480 if (ctx.tiles.size() >= 12) {
481 // USDASM $01:8F0C:
482 // - Top cap: 2x2 (tiles 0..3, column-major)
483 // - Middle: repeated 2x1 rows (tiles 4..5)
484 // - Bottom cap: 2 columns x 3 rows (tiles 6..11)
486 ctx.object.y_ + 0, ctx.tiles[0]);
488 ctx.object.y_ + 1, ctx.tiles[1]);
490 ctx.object.y_ + 0, ctx.tiles[2]);
492 ctx.object.y_ + 1, ctx.tiles[3]);
493
494 int base_y = ctx.object.y_ + 2;
495 for (int row = 0; row < middle_rows; ++row) {
497 base_y + row, ctx.tiles[4]);
499 base_y + row, ctx.tiles[5]);
500 }
501
502 const int cap_y = base_y + middle_rows;
503 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 0,
504 ctx.tiles[6]);
505 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 1,
506 ctx.tiles[7]);
507 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 2,
508 ctx.tiles[8]);
509 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 0,
510 ctx.tiles[9]);
511 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 1,
512 ctx.tiles[10]);
513 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 2,
514 ctx.tiles[11]);
515 return;
516 }
517
518 if (ctx.tiles.empty() || total_rows <= 0) {
519 return;
520 }
521 const gfx::TileInfo& left = ctx.tiles[0];
522 const gfx::TileInfo& right =
523 ctx.tiles.size() > 1 ? ctx.tiles[1] : ctx.tiles[0];
524 for (int row = 0; row < total_rows; ++row) {
526 ctx.object.y_ + row, left);
528 ctx.object.y_ + row, right);
529 }
530}
531
533 const int size = ctx.object.size_ & 0x0F;
534 const int count = size + 1;
535 if (ctx.tiles.size() < 4) {
536 return;
537 }
538
539 for (int s = 0; s < count; ++s) {
540 const int base_y = ctx.object.y_ + (s * 4);
541 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
542 ctx.tiles[0]);
543 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
544 ctx.tiles[1]);
545 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
546 ctx.tiles[2]);
547 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
548 ctx.tiles[3]);
549 }
550}
551
553 const int size = ctx.object.size_ & 0x0F;
554 const int repeat_count = size + 1;
555 if (ctx.tiles.size() < 12) {
556 return;
557 }
558
559 auto draw_segment = [&](int base_y, int tile_base) {
560 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
561 ctx.tiles[tile_base + 0]);
562 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
563 ctx.tiles[tile_base + 1]);
564 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 0,
565 ctx.tiles[tile_base + 2]);
566 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
567 ctx.tiles[tile_base + 3]);
568 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
569 ctx.tiles[tile_base + 4]);
570 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
571 ctx.tiles[tile_base + 5]);
572 };
573
574 // USDASM $01:9CEB:
575 // - Repeat the left 3x2 segment (tiles 0..5) size+1 times
576 // - Append one 3x2 edge segment (tiles 6..11)
577 for (int s = 0; s < repeat_count; ++s) {
578 draw_segment(ctx.object.y_ + (s * 2), /*tile_base=*/0);
579 }
580 draw_segment(ctx.object.y_ + (repeat_count * 2), /*tile_base=*/6);
581}
582
584 const int size = ctx.object.size_ & 0x0F;
585 const int middle_rows = (size + 2) * 2;
586 if (ctx.tiles.size() < 4) {
587 return;
588 }
589
590 // USDASM $01:97B5:
591 // - top row uses tiles 0..1
592 // - remaining rows use tiles 2..3, repeated 2*(size+2) times
594 ctx.object.y_ + 0, ctx.tiles[0]);
596 ctx.object.y_ + 0, ctx.tiles[1]);
597 for (int row = 0; row < middle_rows; ++row) {
599 ctx.object.y_ + 1 + row, ctx.tiles[2]);
601 ctx.object.y_ + 1 + row, ctx.tiles[3]);
602 }
603}
604
606 const int size = ctx.object.size_ & 0x0F;
607 const int count = size + 1;
608 if (ctx.tiles.size() < 4) {
609 return;
610 }
611
612 for (int s = 0; s < count; ++s) {
613 const int base_y = ctx.object.y_ + (s * 2);
614 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
615 ctx.tiles[0]);
616 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
617 ctx.tiles[1]);
618 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
619 ctx.tiles[2]);
620 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
621 ctx.tiles[3]);
622 }
623}
624
628
630 const int count = (ctx.object.size_ & 0x0F) + 8;
631 if (ctx.tiles.empty()) {
632 return;
633 }
634
635 for (int row = 0; row < count; ++row) {
637 ctx.object.y_ + row, ctx.tiles[0]);
638 }
639}
640
641void RegisterDownwardsRoutines(std::vector<DrawRoutineInfo>& registry) {
642 using Category = DrawRoutineInfo::Category;
643
644 registry.push_back(
645 DrawRoutineInfo{.id = 7, // RoomDraw_Downwards2x2_1to15or32
646 .name = "Downwards2x2_1to15or32",
647 .function = DrawDownwards2x2_1to15or32,
648 .draws_to_both_bgs = false,
649 .base_width = 2,
650 .base_height = 2,
651 .min_tiles = 4, // 2x2 block
652 .category = Category::Downwards});
653
654 registry.push_back(DrawRoutineInfo{
655 .id = 8, // RoomDraw_Downwards4x2_1to15or26
656 .name = "Downwards4x2_1to15or26",
657 .function = DrawDownwards4x2_1to15or26,
658 // USDASM: RoomDraw_Downwards4x2_1to15or26 ($01:8A89) jumps to
659 // RoomDraw_Downwards4x2VariableSpacing ($01:B220) which writes through
660 // the current tilemap pointers (single-layer).
661 .draws_to_both_bgs = false,
662 .base_width = 4,
663 .base_height = 2,
664 .min_tiles = 8, // 4x2 block
665 .category = Category::Downwards});
666
667 registry.push_back(
668 DrawRoutineInfo{.id = 9, // RoomDraw_Downwards4x2_1to16_BothBG
669 .name = "Downwards4x2_1to16_BothBG",
671 .draws_to_both_bgs = true,
672 .base_width = 4,
673 .base_height = 2,
674 .min_tiles = 8, // 4x2 block
675 .category = Category::Downwards});
676
677 registry.push_back(
678 DrawRoutineInfo{.id = 10, // RoomDraw_DownwardsDecor4x2spaced4_1to16
679 .name = "DownwardsDecor4x2spaced4_1to16",
681 .draws_to_both_bgs = false,
682 .base_width = 4,
683 .base_height = 2,
684 .min_tiles = 8, // 4x2 block
685 .category = Category::Downwards});
686
687 registry.push_back(DrawRoutineInfo{.id = 11, // RoomDraw_Downwards2x2_1to16
688 .name = "Downwards2x2_1to16",
689 .function = DrawDownwards2x2_1to16,
690 .draws_to_both_bgs = false,
691 .base_width = 2,
692 .base_height = 2,
693 .min_tiles = 4, // 2x2 block
694 .category = Category::Downwards});
695
696 registry.push_back(
697 DrawRoutineInfo{.id = 12, // RoomDraw_DownwardsHasEdge1x1_1to16_plus3
698 .name = "DownwardsHasEdge1x1_1to16_plus3",
700 .draws_to_both_bgs = false,
701 .base_width = 1,
702 // size=0 footprint = corner + 2 middles + end = 4 rows
703 // (mirrors horizontal kRightwardsHasEdge1x1_1to16_plus3
704 // base_width=4; both share ASM A=2 path).
705 .base_height = 4,
706 .min_tiles = 3, // top edge + middle + bottom edge
707 .category = Category::Downwards});
708
709 registry.push_back(
710 DrawRoutineInfo{.id = 13, // RoomDraw_DownwardsEdge1x1_1to16
711 .name = "DownwardsEdge1x1_1to16",
712 .function = DrawDownwardsEdge1x1_1to16,
713 .draws_to_both_bgs = false,
714 .base_width = 1,
715 .base_height = 1,
716 .min_tiles = 1, // single repeated tile
717 .category = Category::Downwards});
718
719 registry.push_back(DrawRoutineInfo{
720 .id = 14, // RoomDraw_DownwardsLeftCorners2x1_1to16_plus12
721 .name = "DownwardsLeftCorners2x1_1to16_plus12",
723 .draws_to_both_bgs = false,
724 .base_width = 2,
725 .base_height = 1,
726 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
727 .category = Category::Downwards});
728
729 registry.push_back(DrawRoutineInfo{
730 .id = 15, // RoomDraw_DownwardsRightCorners2x1_1to16_plus12
731 .name = "DownwardsRightCorners2x1_1to16_plus12",
733 .draws_to_both_bgs = false,
734 .base_width = 2,
735 .base_height = 1,
736 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
737 .category = Category::Downwards});
738
739 registry.push_back(
741 .name = "DownwardsFloor4x4_1to16",
742 .function = DrawDownwardsFloor4x4_1to16,
743 .draws_to_both_bgs = false,
744 .base_width = 4,
745 .base_height = 4,
746 .min_tiles = 16,
747 .category = Category::Downwards});
748
749 registry.push_back(
751 .name = "Downwards1x1Solid_1to16_plus3",
753 .draws_to_both_bgs = false,
754 .base_width = 1,
755 .base_height = 1,
756 .min_tiles = 1,
757 .category = Category::Downwards});
758
759 registry.push_back(
761 .name = "DownwardsDecor4x4spaced2_1to16",
763 .draws_to_both_bgs = false,
764 .base_width = 4,
765 .base_height = 4,
766 .min_tiles = 16,
767 .category = Category::Downwards});
768
769 registry.push_back(
771 .name = "DownwardsPillar2x4spaced2_1to16",
773 .draws_to_both_bgs = false,
774 .base_width = 2,
775 .base_height = 4,
776 .min_tiles = 8,
777 .category = Category::Downwards});
778
779 registry.push_back(
781 .name = "DownwardsDecor3x4spaced4_1to16",
783 .draws_to_both_bgs = false,
784 .base_width = 3,
785 .base_height = 4,
786 .min_tiles = 12,
787 .category = Category::Downwards});
788
789 registry.push_back(
791 .name = "DownwardsDecor2x2spaced12_1to16",
793 .draws_to_both_bgs = false,
794 .base_width = 2,
795 .base_height = 2,
796 .min_tiles = 4,
797 .category = Category::Downwards});
798
799 registry.push_back(
801 .name = "DownwardsLine1x1_1to16plus1",
803 .draws_to_both_bgs = false,
804 .base_width = 1,
805 .base_height = 1,
806 .min_tiles = 1,
807 .category = Category::Downwards});
808
809 registry.push_back(
811 .name = "DownwardsDecor2x4spaced8_1to16",
813 .draws_to_both_bgs = false,
814 .base_width = 2,
815 .base_height = 4,
816 .min_tiles = 8,
817 .category = Category::Downwards});
818
819 registry.push_back(
821 .name = "DownwardsDecor3x4spaced2_1to16",
823 .draws_to_both_bgs = false,
824 .base_width = 3,
825 .base_height = 4,
826 .min_tiles = 12,
827 .category = Category::Downwards});
828
829 registry.push_back(
831 .name = "DownwardsBigRail3x1_1to16plus5",
833 .draws_to_both_bgs = false,
834 .base_width = 2,
835 .base_height = 6,
836 .min_tiles = 12,
837 .category = Category::Downwards});
838
839 registry.push_back(
841 .name = "DownwardsBlock2x2spaced2_1to16",
843 .draws_to_both_bgs = false,
844 .base_width = 2,
845 .base_height = 2,
846 .min_tiles = 4,
847 .category = Category::Downwards});
848
849 registry.push_back(
851 .name = "DownwardsCannonHole3x4_1to16",
853 .draws_to_both_bgs = false,
854 .base_width = 3,
855 .base_height = 4,
856 .min_tiles = 12,
857 .category = Category::Downwards});
858
859 registry.push_back(
861 .name = "DownwardsBar2x5_1to16",
862 .function = DrawDownwardsBar2x5_1to16,
863 .draws_to_both_bgs = false,
864 .base_width = 2,
865 .base_height = 5,
866 .min_tiles = 4,
867 .category = Category::Downwards});
868
869 registry.push_back(
871 .name = "DownwardsPots2x2_1to16",
872 .function = DrawDownwardsPots2x2_1to16,
873 .draws_to_both_bgs = false,
874 .base_width = 2,
875 .base_height = 2,
876 .min_tiles = 4,
877 .category = Category::Downwards});
878
879 registry.push_back(
881 .name = "DownwardsHammerPegs2x2_1to16",
883 .draws_to_both_bgs = false,
884 .base_width = 2,
885 .base_height = 2,
886 .min_tiles = 4,
887 .category = Category::Downwards});
888
889 registry.push_back(
891 .name = "DownwardsEdge1x1_1to16plus7",
893 .draws_to_both_bgs = false,
894 .base_width = 1,
895 .base_height = 8,
896 .min_tiles = 1,
897 .category = Category::Downwards});
898}
899
900} // namespace draw_routines
901} // namespace zelda3
902} // 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 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 +12 offset downward.
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 +12 offset downward.
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.