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 // Pattern: Same as above but draws to both BG1 and BG2 (objects 0x63-0x64)
86 // Note: BothBG would require access to both buffers - simplified for now
87}
88
90 // Pattern: Draws 4x2 decoration downward with spacing (objects 0x65-0x66)
91 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order with 6-tile Y
92 // spacing.
93 int size = ctx.object.size_ & 0x0F;
94
95 // Assembly: GetSize_1to16, so count = size + 1
96 int count = size + 1;
97
98 for (int s = 0; s < count; s++) {
99 if (ctx.tiles.size() >= 8) {
100 // Draw 4x2 pattern in ROW-MAJOR order:
101 // Row 0: tiles[0..3], Row 1: tiles[4..7].
102 const int base_y = ctx.object.y_ + (s * 6);
104 ctx.tiles[0]);
105 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y,
106 ctx.tiles[1]);
107 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y,
108 ctx.tiles[2]);
109 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y,
110 ctx.tiles[3]);
111 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_, base_y + 1,
112 ctx.tiles[4]);
113 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
114 ctx.tiles[5]);
115 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
116 ctx.tiles[6]);
117 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 3, base_y + 1,
118 ctx.tiles[7]);
119 }
120 }
121}
122
124 // Pattern: Draws 2x2 tiles downward (objects 0x67-0x68)
125 int size = ctx.object.size_ & 0x0F;
126
127 // Assembly: GetSize_1to16, so count = size + 1
128 int count = size + 1;
129
130 for (int s = 0; s < count; s++) {
131 if (ctx.tiles.size() >= 4) {
132 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
133 // tiles[0] → col 0, row 0 = top-left
134 // tiles[1] → col 0, row 1 = bottom-left
135 // tiles[2] → col 1, row 0 = top-right
136 // tiles[3] → col 1, row 1 = bottom-right
138 ctx.object.y_ + (s * 2),
139 ctx.tiles[0]); // col 0, row 0
141 ctx.object.y_ + (s * 2) + 1,
142 ctx.tiles[1]); // col 0, row 1
144 ctx.object.y_ + (s * 2),
145 ctx.tiles[2]); // col 1, row 0
147 ctx.object.y_ + (s * 2) + 1,
148 ctx.tiles[3]); // col 1, row 1
149 }
150 }
151}
152
154 // Pattern: Vertical rail with corner/middle/end (object 0x69).
155 // ASM: RoomDraw_DownwardsHasEdge1x1_1to16_plus3 ($01:8EC3) loads A=2 then
156 // falls into RoomDraw_DownwardsHasEdge1x1_1to16, which calls
157 // RoomDraw_GetSize_1to16_timesA ($01:B0AF) to set $B2 = composite_size + A.
158 // For the _plus3 variant that yields count = size + 2 middle tiles, matching
159 // the horizontal counterpart RoomDraw_RightwardsHasEdge1x1_1to16_plus3
160 // ($01:8EF0) which uses the same A=2. Total span = 1 corner + (size+2)
161 // middles + 1 end = size + 4 tiles.
162 int size = ctx.object.size_ & 0x0F;
163 int count = size + 2;
164
165 if (ctx.tiles.size() < 3)
166 return;
167
168 int y = ctx.object.y_;
169 // USDASM $01:8EC9-$01:8ED4 suppresses the leading corner when the existing
170 // tile already contains the small vertical rail corner.
172 {0x00E3})) {
174 }
175 y++;
176 for (int s = 0; s < count; s++) {
178 y++;
179 }
181}
182
184 // Pattern: 1x1 edge tiles downward (objects 0x6A-0x6B)
185 int size = ctx.object.size_ & 0x0F;
186
187 // Assembly: GetSize_1to16, so count = size + 1
188 int count = size + 1;
189
190 for (int s = 0; s < count; s++) {
191 if (ctx.tiles.size() >= 1) {
192 // Use first 8x8 tile from span
194 ctx.object.y_ + s, ctx.tiles[0]);
195 }
196 }
197}
198
200 // Pattern: Left corner 2x1 tiles with +12 offset downward (object 0x6C)
201 const int size = ctx.object.size_ & 0x0F;
202 // USDASM $01:9045 - Object_Size_N_to_N_plus_15 with N=0x0A.
203 const int count = size + 10;
204 if (count <= 0 || ctx.tiles.empty()) {
205 return;
206 }
207
208 const int base_x = ctx.object.x_ + 12;
209 int current_y = ctx.object.y_;
210
211 const gfx::TileInfo& fill = ctx.tiles[0];
212 const gfx::TileInfo& start_top_left =
213 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
214 const gfx::TileInfo& start_bottom_left =
215 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
216 const gfx::TileInfo& body_left = ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
217 const gfx::TileInfo& end_top_left =
218 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_left;
219 const gfx::TileInfo& end_bottom_left =
220 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
221
223 current_y, {0x00E3})) {
224 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y,
225 start_top_left);
226 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
227 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
228 start_bottom_left);
229 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
230 fill);
231 current_y += 2;
232 }
233
234 for (int s = 0; s < count; ++s) {
235 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s,
236 body_left);
237 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
238 fill);
239 }
240
241 current_y += count;
242 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, end_top_left);
243 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
244 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
245 end_bottom_left);
246 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1, fill);
247}
248
250 // Pattern: Right corner 2x1 tiles with +12 offset downward (object 0x6D)
251 const int size = ctx.object.size_ & 0x0F;
252 // USDASM $01:908F - mirrored variant of the left-corner routine.
253 const int count = size + 10;
254 if (count <= 0 || ctx.tiles.empty()) {
255 return;
256 }
257
258 const int base_x = ctx.object.x_ + 12;
259 int current_y = ctx.object.y_;
260
261 const gfx::TileInfo& fill = ctx.tiles[0];
262 const gfx::TileInfo& start_top_right =
263 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
264 const gfx::TileInfo& start_bottom_right =
265 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
266 const gfx::TileInfo& body_right = ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
267 const gfx::TileInfo& end_top_right =
268 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_right;
269 const gfx::TileInfo& end_bottom_right =
270 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
271
273 current_y, {0x00E3})) {
274 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
275 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
276 start_top_right);
277 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
278 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
279 start_bottom_right);
280 current_y += 2;
281 }
282
283 for (int s = 0; s < count; ++s) {
284 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s, fill);
285 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
286 body_right);
287 }
288
289 current_y += count;
290 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
291 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
292 end_top_right);
293 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
294 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
295 end_bottom_right);
296}
297
299 const int size = ctx.object.size_ & 0x0F;
300 const int count = size + 1;
301 if (ctx.tiles.size() < 16) {
302 return;
303 }
304
305 for (int s = 0; s < count; ++s) {
306 const int base_y = ctx.object.y_ + (s * 4);
307 for (int x = 0; x < 4; ++x) {
308 for (int y = 0; y < 4; ++y) {
310 base_y + y, ctx.tiles[x * 4 + y]);
311 }
312 }
313 }
314}
315
317 const int size = ctx.object.size_ & 0x0F;
318 const int count = size + 4;
319 if (ctx.tiles.empty()) {
320 return;
321 }
322
323 for (int s = 0; s < count; ++s) {
325 ctx.object.y_ + s + 3, ctx.tiles[0]);
326 }
327}
328
330 const int size = ctx.object.size_ & 0x0F;
331 const int count = size + 1;
332 if (ctx.tiles.size() < 16) {
333 return;
334 }
335
336 for (int s = 0; s < count; ++s) {
337 const int base_y = ctx.object.y_ + (s * 6);
338 for (int x = 0; x < 4; ++x) {
339 for (int y = 0; y < 4; ++y) {
341 base_y + y, ctx.tiles[x * 4 + y]);
342 }
343 }
344 }
345}
346
348 const int size = ctx.object.size_ & 0x0F;
349 const int count = size + 1;
350 if (ctx.tiles.size() < 8) {
351 return;
352 }
353
354 for (int s = 0; s < count; ++s) {
355 const int base_y = ctx.object.y_ + (s * 6);
356 for (int x = 0; x < 2; ++x) {
357 for (int y = 0; y < 4; ++y) {
359 base_y + y, ctx.tiles[x * 4 + y]);
360 }
361 }
362 }
363}
364
366 const int size = ctx.object.size_ & 0x0F;
367 const int count = size + 1;
368 if (ctx.tiles.size() < 12) {
369 return;
370 }
371
372 for (int s = 0; s < count; ++s) {
373 const int base_y = ctx.object.y_ + (s * 8);
374 for (int x = 0; x < 3; ++x) {
375 for (int y = 0; y < 4; ++y) {
377 base_y + y, ctx.tiles[x * 4 + y]);
378 }
379 }
380 }
381}
382
384 const int size = ctx.object.size_ & 0x0F;
385 const int count = size + 1;
386 if (ctx.tiles.size() < 4) {
387 return;
388 }
389
390 for (int s = 0; s < count; ++s) {
391 const int base_y = ctx.object.y_ + (s * 14);
392 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
393 ctx.tiles[0]);
394 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
395 ctx.tiles[1]);
396 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
397 ctx.tiles[2]);
398 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
399 ctx.tiles[3]);
400 }
401}
402
404 const int size = ctx.object.size_ & 0x0F;
405 const int count = size + 2;
406 if (ctx.tiles.empty()) {
407 return;
408 }
409
410 for (int s = 0; s < count; ++s) {
412 ctx.object.y_ + s, ctx.tiles[0]);
413 }
414}
415
417 const int size = ctx.object.size_ & 0x0F;
418 const int count = size + 1;
419 if (ctx.tiles.size() < 8) {
420 return;
421 }
422
423 for (int s = 0; s < count; ++s) {
424 const int base_y = ctx.object.y_ + (s * 12);
425 for (int x = 0; x < 2; ++x) {
426 for (int y = 0; y < 4; ++y) {
428 base_y + y, ctx.tiles[x * 4 + y]);
429 }
430 }
431 }
432}
433
435 const int size = ctx.object.size_ & 0x0F;
436 const int count = size + 1;
437 if (ctx.tiles.size() < 12) {
438 return;
439 }
440
441 for (int s = 0; s < count; ++s) {
442 const int base_y = ctx.object.y_ + (s * 6);
443 for (int x = 0; x < 3; ++x) {
444 for (int y = 0; y < 4; ++y) {
446 base_y + y, ctx.tiles[x * 4 + y]);
447 }
448 }
449 }
450}
451
453 const int size = ctx.object.size_ & 0x0F;
454 const int middle_rows = size + 1;
455 const int total_rows = size + 6; // 2 top + (size+1) middle + 3 bottom.
456
457 if (ctx.tiles.size() >= 12) {
458 // USDASM $01:8F0C:
459 // - Top cap: 2x2 (tiles 0..3, column-major)
460 // - Middle: repeated 2x1 rows (tiles 4..5)
461 // - Bottom cap: 2 columns x 3 rows (tiles 6..11)
463 ctx.object.y_ + 0, ctx.tiles[0]);
465 ctx.object.y_ + 1, ctx.tiles[1]);
467 ctx.object.y_ + 0, ctx.tiles[2]);
469 ctx.object.y_ + 1, ctx.tiles[3]);
470
471 int base_y = ctx.object.y_ + 2;
472 for (int row = 0; row < middle_rows; ++row) {
474 base_y + row, ctx.tiles[4]);
476 base_y + row, ctx.tiles[5]);
477 }
478
479 const int cap_y = base_y + middle_rows;
480 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 0,
481 ctx.tiles[6]);
482 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 1,
483 ctx.tiles[7]);
484 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 2,
485 ctx.tiles[8]);
486 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 0,
487 ctx.tiles[9]);
488 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 1,
489 ctx.tiles[10]);
490 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 2,
491 ctx.tiles[11]);
492 return;
493 }
494
495 if (ctx.tiles.empty() || total_rows <= 0) {
496 return;
497 }
498 const gfx::TileInfo& left = ctx.tiles[0];
499 const gfx::TileInfo& right =
500 ctx.tiles.size() > 1 ? ctx.tiles[1] : ctx.tiles[0];
501 for (int row = 0; row < total_rows; ++row) {
503 ctx.object.y_ + row, left);
505 ctx.object.y_ + row, right);
506 }
507}
508
510 const int size = ctx.object.size_ & 0x0F;
511 const int count = size + 1;
512 if (ctx.tiles.size() < 4) {
513 return;
514 }
515
516 for (int s = 0; s < count; ++s) {
517 const int base_y = ctx.object.y_ + (s * 4);
518 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
519 ctx.tiles[0]);
520 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
521 ctx.tiles[1]);
522 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
523 ctx.tiles[2]);
524 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
525 ctx.tiles[3]);
526 }
527}
528
530 const int size = ctx.object.size_ & 0x0F;
531 const int repeat_count = size + 1;
532 if (ctx.tiles.size() < 12) {
533 return;
534 }
535
536 auto draw_segment = [&](int base_y, int tile_base) {
537 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
538 ctx.tiles[tile_base + 0]);
539 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
540 ctx.tiles[tile_base + 1]);
541 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 0,
542 ctx.tiles[tile_base + 2]);
543 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
544 ctx.tiles[tile_base + 3]);
545 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
546 ctx.tiles[tile_base + 4]);
547 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
548 ctx.tiles[tile_base + 5]);
549 };
550
551 // USDASM $01:9CEB:
552 // - Repeat the left 3x2 segment (tiles 0..5) size+1 times
553 // - Append one 3x2 edge segment (tiles 6..11)
554 for (int s = 0; s < repeat_count; ++s) {
555 draw_segment(ctx.object.y_ + (s * 2), /*tile_base=*/0);
556 }
557 draw_segment(ctx.object.y_ + (repeat_count * 2), /*tile_base=*/6);
558}
559
561 const int size = ctx.object.size_ & 0x0F;
562 const int middle_rows = (size + 2) * 2;
563 if (ctx.tiles.size() < 4) {
564 return;
565 }
566
567 // USDASM $01:97B5:
568 // - top row uses tiles 0..1
569 // - remaining rows use tiles 2..3, repeated 2*(size+2) times
571 ctx.object.y_ + 0, ctx.tiles[0]);
573 ctx.object.y_ + 0, ctx.tiles[1]);
574 for (int row = 0; row < middle_rows; ++row) {
576 ctx.object.y_ + 1 + row, ctx.tiles[2]);
578 ctx.object.y_ + 1 + row, ctx.tiles[3]);
579 }
580}
581
583 const int size = ctx.object.size_ & 0x0F;
584 const int count = size + 1;
585 if (ctx.tiles.size() < 4) {
586 return;
587 }
588
589 for (int s = 0; s < count; ++s) {
590 const int base_y = ctx.object.y_ + (s * 2);
591 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
592 ctx.tiles[0]);
593 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
594 ctx.tiles[1]);
595 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
596 ctx.tiles[2]);
597 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
598 ctx.tiles[3]);
599 }
600}
601
605
607 const int count = (ctx.object.size_ & 0x0F) + 8;
608 if (ctx.tiles.empty()) {
609 return;
610 }
611
612 for (int row = 0; row < count; ++row) {
614 ctx.object.y_ + row, ctx.tiles[0]);
615 }
616}
617
618void RegisterDownwardsRoutines(std::vector<DrawRoutineInfo>& registry) {
619 using Category = DrawRoutineInfo::Category;
620
621 registry.push_back(
622 DrawRoutineInfo{.id = 7, // RoomDraw_Downwards2x2_1to15or32
623 .name = "Downwards2x2_1to15or32",
624 .function = DrawDownwards2x2_1to15or32,
625 .draws_to_both_bgs = false,
626 .base_width = 2,
627 .base_height = 2,
628 .min_tiles = 4, // 2x2 block
629 .category = Category::Downwards});
630
631 registry.push_back(DrawRoutineInfo{
632 .id = 8, // RoomDraw_Downwards4x2_1to15or26
633 .name = "Downwards4x2_1to15or26",
634 .function = DrawDownwards4x2_1to15or26,
635 // USDASM: RoomDraw_Downwards4x2_1to15or26 ($01:8A89) jumps to
636 // RoomDraw_Downwards4x2VariableSpacing ($01:B220) which writes through
637 // the current tilemap pointers (single-layer).
638 .draws_to_both_bgs = false,
639 .base_width = 4,
640 .base_height = 2,
641 .min_tiles = 8, // 4x2 block
642 .category = Category::Downwards});
643
644 registry.push_back(
645 DrawRoutineInfo{.id = 9, // RoomDraw_Downwards4x2_1to16_BothBG
646 .name = "Downwards4x2_1to16_BothBG",
648 .draws_to_both_bgs = true,
649 .base_width = 4,
650 .base_height = 2,
651 .min_tiles = 8, // 4x2 block
652 .category = Category::Downwards});
653
654 registry.push_back(
655 DrawRoutineInfo{.id = 10, // RoomDraw_DownwardsDecor4x2spaced4_1to16
656 .name = "DownwardsDecor4x2spaced4_1to16",
658 .draws_to_both_bgs = false,
659 .base_width = 4,
660 .base_height = 2,
661 .min_tiles = 8, // 4x2 block
662 .category = Category::Downwards});
663
664 registry.push_back(DrawRoutineInfo{.id = 11, // RoomDraw_Downwards2x2_1to16
665 .name = "Downwards2x2_1to16",
666 .function = DrawDownwards2x2_1to16,
667 .draws_to_both_bgs = false,
668 .base_width = 2,
669 .base_height = 2,
670 .min_tiles = 4, // 2x2 block
671 .category = Category::Downwards});
672
673 registry.push_back(
674 DrawRoutineInfo{.id = 12, // RoomDraw_DownwardsHasEdge1x1_1to16_plus3
675 .name = "DownwardsHasEdge1x1_1to16_plus3",
677 .draws_to_both_bgs = false,
678 .base_width = 1,
679 // size=0 footprint = corner + 2 middles + end = 4 rows
680 // (mirrors horizontal kRightwardsHasEdge1x1_1to16_plus3
681 // base_width=4; both share ASM A=2 path).
682 .base_height = 4,
683 .min_tiles = 3, // top edge + middle + bottom edge
684 .category = Category::Downwards});
685
686 registry.push_back(
687 DrawRoutineInfo{.id = 13, // RoomDraw_DownwardsEdge1x1_1to16
688 .name = "DownwardsEdge1x1_1to16",
689 .function = DrawDownwardsEdge1x1_1to16,
690 .draws_to_both_bgs = false,
691 .base_width = 1,
692 .base_height = 1,
693 .min_tiles = 1, // single repeated tile
694 .category = Category::Downwards});
695
696 registry.push_back(DrawRoutineInfo{
697 .id = 14, // RoomDraw_DownwardsLeftCorners2x1_1to16_plus12
698 .name = "DownwardsLeftCorners2x1_1to16_plus12",
700 .draws_to_both_bgs = false,
701 .base_width = 2,
702 .base_height = 1,
703 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
704 .category = Category::Downwards});
705
706 registry.push_back(DrawRoutineInfo{
707 .id = 15, // RoomDraw_DownwardsRightCorners2x1_1to16_plus12
708 .name = "DownwardsRightCorners2x1_1to16_plus12",
710 .draws_to_both_bgs = false,
711 .base_width = 2,
712 .base_height = 1,
713 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
714 .category = Category::Downwards});
715
716 registry.push_back(
718 .name = "DownwardsFloor4x4_1to16",
719 .function = DrawDownwardsFloor4x4_1to16,
720 .draws_to_both_bgs = false,
721 .base_width = 4,
722 .base_height = 4,
723 .min_tiles = 16,
724 .category = Category::Downwards});
725
726 registry.push_back(
728 .name = "Downwards1x1Solid_1to16_plus3",
730 .draws_to_both_bgs = false,
731 .base_width = 1,
732 .base_height = 1,
733 .min_tiles = 1,
734 .category = Category::Downwards});
735
736 registry.push_back(
738 .name = "DownwardsDecor4x4spaced2_1to16",
740 .draws_to_both_bgs = false,
741 .base_width = 4,
742 .base_height = 4,
743 .min_tiles = 16,
744 .category = Category::Downwards});
745
746 registry.push_back(
748 .name = "DownwardsPillar2x4spaced2_1to16",
750 .draws_to_both_bgs = false,
751 .base_width = 2,
752 .base_height = 4,
753 .min_tiles = 8,
754 .category = Category::Downwards});
755
756 registry.push_back(
758 .name = "DownwardsDecor3x4spaced4_1to16",
760 .draws_to_both_bgs = false,
761 .base_width = 3,
762 .base_height = 4,
763 .min_tiles = 12,
764 .category = Category::Downwards});
765
766 registry.push_back(
768 .name = "DownwardsDecor2x2spaced12_1to16",
770 .draws_to_both_bgs = false,
771 .base_width = 2,
772 .base_height = 2,
773 .min_tiles = 4,
774 .category = Category::Downwards});
775
776 registry.push_back(
778 .name = "DownwardsLine1x1_1to16plus1",
780 .draws_to_both_bgs = false,
781 .base_width = 1,
782 .base_height = 1,
783 .min_tiles = 1,
784 .category = Category::Downwards});
785
786 registry.push_back(
788 .name = "DownwardsDecor2x4spaced8_1to16",
790 .draws_to_both_bgs = false,
791 .base_width = 2,
792 .base_height = 4,
793 .min_tiles = 8,
794 .category = Category::Downwards});
795
796 registry.push_back(
798 .name = "DownwardsDecor3x4spaced2_1to16",
800 .draws_to_both_bgs = false,
801 .base_width = 3,
802 .base_height = 4,
803 .min_tiles = 12,
804 .category = Category::Downwards});
805
806 registry.push_back(
808 .name = "DownwardsBigRail3x1_1to16plus5",
810 .draws_to_both_bgs = false,
811 .base_width = 2,
812 .base_height = 6,
813 .min_tiles = 12,
814 .category = Category::Downwards});
815
816 registry.push_back(
818 .name = "DownwardsBlock2x2spaced2_1to16",
820 .draws_to_both_bgs = false,
821 .base_width = 2,
822 .base_height = 2,
823 .min_tiles = 4,
824 .category = Category::Downwards});
825
826 registry.push_back(
828 .name = "DownwardsCannonHole3x4_1to16",
830 .draws_to_both_bgs = false,
831 .base_width = 3,
832 .base_height = 4,
833 .min_tiles = 12,
834 .category = Category::Downwards});
835
836 registry.push_back(
838 .name = "DownwardsBar2x5_1to16",
839 .function = DrawDownwardsBar2x5_1to16,
840 .draws_to_both_bgs = false,
841 .base_width = 2,
842 .base_height = 5,
843 .min_tiles = 4,
844 .category = Category::Downwards});
845
846 registry.push_back(
848 .name = "DownwardsPots2x2_1to16",
849 .function = DrawDownwardsPots2x2_1to16,
850 .draws_to_both_bgs = false,
851 .base_width = 2,
852 .base_height = 2,
853 .min_tiles = 4,
854 .category = Category::Downwards});
855
856 registry.push_back(
858 .name = "DownwardsHammerPegs2x2_1to16",
860 .draws_to_both_bgs = false,
861 .base_width = 2,
862 .base_height = 2,
863 .min_tiles = 4,
864 .category = Category::Downwards});
865
866 registry.push_back(
868 .name = "DownwardsEdge1x1_1to16plus7",
870 .draws_to_both_bgs = false,
871 .base_width = 1,
872 .base_height = 8,
873 .min_tiles = 1,
874 .category = Category::Downwards});
875}
876
877} // namespace draw_routines
878} // namespace zelda3
879} // 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.