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 int size = ctx.object.size_ & 0x0F;
156 int count = size + 1;
157
158 if (ctx.tiles.size() < 3)
159 return;
160
161 int y = ctx.object.y_;
162 // USDASM $01:8EC9-$01:8ED4 suppresses the leading corner when the existing
163 // tile already contains the small vertical rail corner.
165 {0x00E3})) {
167 }
168 y++;
169 for (int s = 0; s < count; s++) {
171 y++;
172 }
174}
175
177 // Pattern: 1x1 edge tiles downward (objects 0x6A-0x6B)
178 int size = ctx.object.size_ & 0x0F;
179
180 // Assembly: GetSize_1to16, so count = size + 1
181 int count = size + 1;
182
183 for (int s = 0; s < count; s++) {
184 if (ctx.tiles.size() >= 1) {
185 // Use first 8x8 tile from span
187 ctx.object.y_ + s, ctx.tiles[0]);
188 }
189 }
190}
191
193 // Pattern: Left corner 2x1 tiles with +12 offset downward (object 0x6C)
194 const int size = ctx.object.size_ & 0x0F;
195 // USDASM $01:9045 - Object_Size_N_to_N_plus_15 with N=0x0A.
196 const int count = size + 10;
197 if (count <= 0 || ctx.tiles.empty()) {
198 return;
199 }
200
201 const int base_x = ctx.object.x_ + 12;
202 int current_y = ctx.object.y_;
203
204 const gfx::TileInfo& fill = ctx.tiles[0];
205 const gfx::TileInfo& start_top_left =
206 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
207 const gfx::TileInfo& start_bottom_left =
208 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
209 const gfx::TileInfo& body_left =
210 ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
211 const gfx::TileInfo& end_top_left =
212 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_left;
213 const gfx::TileInfo& end_bottom_left =
214 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
215
216 if (!DrawRoutineUtils::ExistingTileMatchesAny(ctx.target_bg, base_x, current_y,
217 {0x00E3})) {
218 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y,
219 start_top_left);
220 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
221 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
222 start_bottom_left);
223 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
224 fill);
225 current_y += 2;
226 }
227
228 for (int s = 0; s < count; ++s) {
229 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s,
230 body_left);
231 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
232 fill);
233 }
234
235 current_y += count;
236 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, end_top_left);
237 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y, fill);
238 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1,
239 end_bottom_left);
240 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1, fill);
241}
242
244 // Pattern: Right corner 2x1 tiles with +12 offset downward (object 0x6D)
245 const int size = ctx.object.size_ & 0x0F;
246 // USDASM $01:908F - mirrored variant of the left-corner routine.
247 const int count = size + 10;
248 if (count <= 0 || ctx.tiles.empty()) {
249 return;
250 }
251
252 const int base_x = ctx.object.x_ + 12;
253 int current_y = ctx.object.y_;
254
255 const gfx::TileInfo& fill = ctx.tiles[0];
256 const gfx::TileInfo& start_top_right =
257 ctx.tiles.size() > 1 ? ctx.tiles[1] : fill;
258 const gfx::TileInfo& start_bottom_right =
259 ctx.tiles.size() > 2 ? ctx.tiles[2] : fill;
260 const gfx::TileInfo& body_right =
261 ctx.tiles.size() > 3 ? ctx.tiles[3] : fill;
262 const gfx::TileInfo& end_top_right =
263 ctx.tiles.size() > 4 ? ctx.tiles[4] : body_right;
264 const gfx::TileInfo& end_bottom_right =
265 ctx.tiles.size() > 5 ? ctx.tiles[5] : fill;
266
268 current_y, {0x00E3})) {
269 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
270 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
271 start_top_right);
272 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
273 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
274 start_bottom_right);
275 current_y += 2;
276 }
277
278 for (int s = 0; s < count; ++s) {
279 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + s, fill);
280 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + s,
281 body_right);
282 }
283
284 current_y += count;
285 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y, fill);
286 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y,
287 end_top_right);
288 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x, current_y + 1, fill);
289 DrawRoutineUtils::WriteTile8(ctx.target_bg, base_x + 1, current_y + 1,
290 end_bottom_right);
291}
292
294 const int size = ctx.object.size_ & 0x0F;
295 const int count = size + 1;
296 if (ctx.tiles.size() < 16) {
297 return;
298 }
299
300 for (int s = 0; s < count; ++s) {
301 const int base_y = ctx.object.y_ + (s * 4);
302 for (int x = 0; x < 4; ++x) {
303 for (int y = 0; y < 4; ++y) {
305 base_y + y, ctx.tiles[x * 4 + y]);
306 }
307 }
308 }
309}
310
312 const int size = ctx.object.size_ & 0x0F;
313 const int count = size + 4;
314 if (ctx.tiles.empty()) {
315 return;
316 }
317
318 for (int s = 0; s < count; ++s) {
320 ctx.object.y_ + s + 3, ctx.tiles[0]);
321 }
322}
323
325 const int size = ctx.object.size_ & 0x0F;
326 const int count = size + 1;
327 if (ctx.tiles.size() < 16) {
328 return;
329 }
330
331 for (int s = 0; s < count; ++s) {
332 const int base_y = ctx.object.y_ + (s * 6);
333 for (int x = 0; x < 4; ++x) {
334 for (int y = 0; y < 4; ++y) {
336 base_y + y, ctx.tiles[x * 4 + y]);
337 }
338 }
339 }
340}
341
343 const int size = ctx.object.size_ & 0x0F;
344 const int count = size + 1;
345 if (ctx.tiles.size() < 8) {
346 return;
347 }
348
349 for (int s = 0; s < count; ++s) {
350 const int base_y = ctx.object.y_ + (s * 6);
351 for (int x = 0; x < 2; ++x) {
352 for (int y = 0; y < 4; ++y) {
354 base_y + y, ctx.tiles[x * 4 + y]);
355 }
356 }
357 }
358}
359
361 const int size = ctx.object.size_ & 0x0F;
362 const int count = size + 1;
363 if (ctx.tiles.size() < 12) {
364 return;
365 }
366
367 for (int s = 0; s < count; ++s) {
368 const int base_y = ctx.object.y_ + (s * 8);
369 for (int x = 0; x < 3; ++x) {
370 for (int y = 0; y < 4; ++y) {
372 base_y + y, ctx.tiles[x * 4 + y]);
373 }
374 }
375 }
376}
377
379 const int size = ctx.object.size_ & 0x0F;
380 const int count = size + 1;
381 if (ctx.tiles.size() < 4) {
382 return;
383 }
384
385 for (int s = 0; s < count; ++s) {
386 const int base_y = ctx.object.y_ + (s * 14);
387 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
388 ctx.tiles[0]);
389 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
390 ctx.tiles[1]);
391 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
392 ctx.tiles[2]);
393 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
394 ctx.tiles[3]);
395 }
396}
397
399 const int size = ctx.object.size_ & 0x0F;
400 const int count = size + 2;
401 if (ctx.tiles.empty()) {
402 return;
403 }
404
405 for (int s = 0; s < count; ++s) {
407 ctx.object.y_ + s, ctx.tiles[0]);
408 }
409}
410
412 const int size = ctx.object.size_ & 0x0F;
413 const int count = size + 1;
414 if (ctx.tiles.size() < 8) {
415 return;
416 }
417
418 for (int s = 0; s < count; ++s) {
419 const int base_y = ctx.object.y_ + (s * 12);
420 for (int x = 0; x < 2; ++x) {
421 for (int y = 0; y < 4; ++y) {
423 base_y + y, ctx.tiles[x * 4 + y]);
424 }
425 }
426 }
427}
428
430 const int size = ctx.object.size_ & 0x0F;
431 const int count = size + 1;
432 if (ctx.tiles.size() < 12) {
433 return;
434 }
435
436 for (int s = 0; s < count; ++s) {
437 const int base_y = ctx.object.y_ + (s * 6);
438 for (int x = 0; x < 3; ++x) {
439 for (int y = 0; y < 4; ++y) {
441 base_y + y, ctx.tiles[x * 4 + y]);
442 }
443 }
444 }
445}
446
448 const int size = ctx.object.size_ & 0x0F;
449 const int middle_rows = size + 1;
450 const int total_rows = size + 6; // 2 top + (size+1) middle + 3 bottom.
451
452 if (ctx.tiles.size() >= 12) {
453 // USDASM $01:8F0C:
454 // - Top cap: 2x2 (tiles 0..3, column-major)
455 // - Middle: repeated 2x1 rows (tiles 4..5)
456 // - Bottom cap: 2 columns x 3 rows (tiles 6..11)
458 ctx.object.y_ + 0, ctx.tiles[0]);
460 ctx.object.y_ + 1, ctx.tiles[1]);
462 ctx.object.y_ + 0, ctx.tiles[2]);
464 ctx.object.y_ + 1, ctx.tiles[3]);
465
466 int base_y = ctx.object.y_ + 2;
467 for (int row = 0; row < middle_rows; ++row) {
469 base_y + row, ctx.tiles[4]);
471 base_y + row, ctx.tiles[5]);
472 }
473
474 const int cap_y = base_y + middle_rows;
475 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 0,
476 ctx.tiles[6]);
477 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 1,
478 ctx.tiles[7]);
479 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, cap_y + 2,
480 ctx.tiles[8]);
481 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 0,
482 ctx.tiles[9]);
483 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 1,
484 ctx.tiles[10]);
485 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, cap_y + 2,
486 ctx.tiles[11]);
487 return;
488 }
489
490 if (ctx.tiles.empty() || total_rows <= 0) {
491 return;
492 }
493 const gfx::TileInfo& left = ctx.tiles[0];
494 const gfx::TileInfo& right =
495 ctx.tiles.size() > 1 ? ctx.tiles[1] : ctx.tiles[0];
496 for (int row = 0; row < total_rows; ++row) {
498 ctx.object.y_ + row, left);
500 ctx.object.y_ + row, right);
501 }
502}
503
505 const int size = ctx.object.size_ & 0x0F;
506 const int count = size + 1;
507 if (ctx.tiles.size() < 4) {
508 return;
509 }
510
511 for (int s = 0; s < count; ++s) {
512 const int base_y = ctx.object.y_ + (s * 4);
513 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
514 ctx.tiles[0]);
515 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
516 ctx.tiles[1]);
517 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
518 ctx.tiles[2]);
519 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
520 ctx.tiles[3]);
521 }
522}
523
525 const int size = ctx.object.size_ & 0x0F;
526 const int repeat_count = size + 1;
527 if (ctx.tiles.size() < 12) {
528 return;
529 }
530
531 auto draw_segment = [&](int base_y, int tile_base) {
532 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
533 ctx.tiles[tile_base + 0]);
534 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
535 ctx.tiles[tile_base + 1]);
536 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 0,
537 ctx.tiles[tile_base + 2]);
538 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
539 ctx.tiles[tile_base + 3]);
540 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
541 ctx.tiles[tile_base + 4]);
542 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 2, base_y + 1,
543 ctx.tiles[tile_base + 5]);
544 };
545
546 // USDASM $01:9CEB:
547 // - Repeat the left 3x2 segment (tiles 0..5) size+1 times
548 // - Append one 3x2 edge segment (tiles 6..11)
549 for (int s = 0; s < repeat_count; ++s) {
550 draw_segment(ctx.object.y_ + (s * 2), /*tile_base=*/0);
551 }
552 draw_segment(ctx.object.y_ + (repeat_count * 2), /*tile_base=*/6);
553}
554
556 const int size = ctx.object.size_ & 0x0F;
557 const int middle_rows = (size + 2) * 2;
558 if (ctx.tiles.size() < 4) {
559 return;
560 }
561
562 // USDASM $01:97B5:
563 // - top row uses tiles 0..1
564 // - remaining rows use tiles 2..3, repeated 2*(size+2) times
566 ctx.object.y_ + 0, ctx.tiles[0]);
568 ctx.object.y_ + 0, ctx.tiles[1]);
569 for (int row = 0; row < middle_rows; ++row) {
571 ctx.object.y_ + 1 + row, ctx.tiles[2]);
573 ctx.object.y_ + 1 + row, ctx.tiles[3]);
574 }
575}
576
578 const int size = ctx.object.size_ & 0x0F;
579 const int count = size + 1;
580 if (ctx.tiles.size() < 4) {
581 return;
582 }
583
584 for (int s = 0; s < count; ++s) {
585 const int base_y = ctx.object.y_ + (s * 2);
586 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 0,
587 ctx.tiles[0]);
588 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 0, base_y + 1,
589 ctx.tiles[1]);
590 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 0,
591 ctx.tiles[2]);
592 DrawRoutineUtils::WriteTile8(ctx.target_bg, ctx.object.x_ + 1, base_y + 1,
593 ctx.tiles[3]);
594 }
595}
596
600
601void RegisterDownwardsRoutines(std::vector<DrawRoutineInfo>& registry) {
602 using Category = DrawRoutineInfo::Category;
603
604 registry.push_back(
605 DrawRoutineInfo{.id = 7, // RoomDraw_Downwards2x2_1to15or32
606 .name = "Downwards2x2_1to15or32",
607 .function = DrawDownwards2x2_1to15or32,
608 .draws_to_both_bgs = false,
609 .base_width = 2,
610 .base_height = 2,
611 .min_tiles = 4, // 2x2 block
612 .category = Category::Downwards});
613
614 registry.push_back(DrawRoutineInfo{
615 .id = 8, // RoomDraw_Downwards4x2_1to15or26
616 .name = "Downwards4x2_1to15or26",
617 .function = DrawDownwards4x2_1to15or26,
618 // USDASM: RoomDraw_Downwards4x2_1to15or26 ($01:8A89) jumps to
619 // RoomDraw_Downwards4x2VariableSpacing ($01:B220) which writes through
620 // the current tilemap pointers (single-layer).
621 .draws_to_both_bgs = false,
622 .base_width = 4,
623 .base_height = 2,
624 .min_tiles = 8, // 4x2 block
625 .category = Category::Downwards});
626
627 registry.push_back(
628 DrawRoutineInfo{.id = 9, // RoomDraw_Downwards4x2_1to16_BothBG
629 .name = "Downwards4x2_1to16_BothBG",
631 .draws_to_both_bgs = true,
632 .base_width = 4,
633 .base_height = 2,
634 .min_tiles = 8, // 4x2 block
635 .category = Category::Downwards});
636
637 registry.push_back(
638 DrawRoutineInfo{.id = 10, // RoomDraw_DownwardsDecor4x2spaced4_1to16
639 .name = "DownwardsDecor4x2spaced4_1to16",
641 .draws_to_both_bgs = false,
642 .base_width = 4,
643 .base_height = 2,
644 .min_tiles = 8, // 4x2 block
645 .category = Category::Downwards});
646
647 registry.push_back(DrawRoutineInfo{.id = 11, // RoomDraw_Downwards2x2_1to16
648 .name = "Downwards2x2_1to16",
649 .function = DrawDownwards2x2_1to16,
650 .draws_to_both_bgs = false,
651 .base_width = 2,
652 .base_height = 2,
653 .min_tiles = 4, // 2x2 block
654 .category = Category::Downwards});
655
656 registry.push_back(
657 DrawRoutineInfo{.id = 12, // RoomDraw_DownwardsHasEdge1x1_1to16_plus3
658 .name = "DownwardsHasEdge1x1_1to16_plus3",
660 .draws_to_both_bgs = false,
661 .base_width = 1,
662 .base_height = 3,
663 .min_tiles = 3, // top edge + middle + bottom edge
664 .category = Category::Downwards});
665
666 registry.push_back(
667 DrawRoutineInfo{.id = 13, // RoomDraw_DownwardsEdge1x1_1to16
668 .name = "DownwardsEdge1x1_1to16",
669 .function = DrawDownwardsEdge1x1_1to16,
670 .draws_to_both_bgs = false,
671 .base_width = 1,
672 .base_height = 1,
673 .min_tiles = 1, // single repeated tile
674 .category = Category::Downwards});
675
676 registry.push_back(DrawRoutineInfo{
677 .id = 14, // RoomDraw_DownwardsLeftCorners2x1_1to16_plus12
678 .name = "DownwardsLeftCorners2x1_1to16_plus12",
680 .draws_to_both_bgs = false,
681 .base_width = 2,
682 .base_height = 1,
683 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
684 .category = Category::Downwards});
685
686 registry.push_back(DrawRoutineInfo{
687 .id = 15, // RoomDraw_DownwardsRightCorners2x1_1to16_plus12
688 .name = "DownwardsRightCorners2x1_1to16_plus12",
690 .draws_to_both_bgs = false,
691 .base_width = 2,
692 .base_height = 1,
693 .min_tiles = 6, // cap + body + endpoint tile spans from subtype-1 table
694 .category = Category::Downwards});
695
696 registry.push_back(
698 .name = "DownwardsFloor4x4_1to16",
699 .function = DrawDownwardsFloor4x4_1to16,
700 .draws_to_both_bgs = false,
701 .base_width = 4,
702 .base_height = 4,
703 .min_tiles = 16,
704 .category = Category::Downwards});
705
706 registry.push_back(
708 .name = "Downwards1x1Solid_1to16_plus3",
710 .draws_to_both_bgs = false,
711 .base_width = 1,
712 .base_height = 1,
713 .min_tiles = 1,
714 .category = Category::Downwards});
715
716 registry.push_back(
718 .name = "DownwardsDecor4x4spaced2_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 = "DownwardsPillar2x4spaced2_1to16",
730 .draws_to_both_bgs = false,
731 .base_width = 2,
732 .base_height = 4,
733 .min_tiles = 8,
734 .category = Category::Downwards});
735
736 registry.push_back(
738 .name = "DownwardsDecor3x4spaced4_1to16",
740 .draws_to_both_bgs = false,
741 .base_width = 3,
742 .base_height = 4,
743 .min_tiles = 12,
744 .category = Category::Downwards});
745
746 registry.push_back(
748 .name = "DownwardsDecor2x2spaced12_1to16",
750 .draws_to_both_bgs = false,
751 .base_width = 2,
752 .base_height = 2,
753 .min_tiles = 4,
754 .category = Category::Downwards});
755
756 registry.push_back(
758 .name = "DownwardsLine1x1_1to16plus1",
760 .draws_to_both_bgs = false,
761 .base_width = 1,
762 .base_height = 1,
763 .min_tiles = 1,
764 .category = Category::Downwards});
765
766 registry.push_back(
768 .name = "DownwardsDecor2x4spaced8_1to16",
770 .draws_to_both_bgs = false,
771 .base_width = 2,
772 .base_height = 4,
773 .min_tiles = 8,
774 .category = Category::Downwards});
775
776 registry.push_back(
778 .name = "DownwardsDecor3x4spaced2_1to16",
780 .draws_to_both_bgs = false,
781 .base_width = 3,
782 .base_height = 4,
783 .min_tiles = 12,
784 .category = Category::Downwards});
785
786 registry.push_back(
788 .name = "DownwardsBigRail3x1_1to16plus5",
790 .draws_to_both_bgs = false,
791 .base_width = 2,
792 .base_height = 6,
793 .min_tiles = 12,
794 .category = Category::Downwards});
795
796 registry.push_back(
798 .name = "DownwardsBlock2x2spaced2_1to16",
800 .draws_to_both_bgs = false,
801 .base_width = 2,
802 .base_height = 2,
803 .min_tiles = 4,
804 .category = Category::Downwards});
805
806 registry.push_back(
808 .name = "DownwardsCannonHole3x4_1to16",
810 .draws_to_both_bgs = false,
811 .base_width = 3,
812 .base_height = 4,
813 .min_tiles = 12,
814 .category = Category::Downwards});
815
816 registry.push_back(
818 .name = "DownwardsBar2x5_1to16",
819 .function = DrawDownwardsBar2x5_1to16,
820 .draws_to_both_bgs = false,
821 .base_width = 2,
822 .base_height = 5,
823 .min_tiles = 4,
824 .category = Category::Downwards});
825
826 registry.push_back(
828 .name = "DownwardsPots2x2_1to16",
829 .function = DrawDownwardsPots2x2_1to16,
830 .draws_to_both_bgs = false,
831 .base_width = 2,
832 .base_height = 2,
833 .min_tiles = 4,
834 .category = Category::Downwards});
835
836 registry.push_back(
838 .name = "DownwardsHammerPegs2x2_1to16",
840 .draws_to_both_bgs = false,
841 .base_width = 2,
842 .base_height = 2,
843 .min_tiles = 4,
844 .category = Category::Downwards});
845}
846
847} // namespace draw_routines
848} // namespace zelda3
849} // 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 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.