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) size = 32; // Special case for object 0x60
15
16 for (int s = 0; s < size; s++) {
17 if (ctx.tiles.size() >= 4) {
18 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
19 // Assembly uses indirect pointers: $BF, $CB, $C2, $CE
20 // tiles[0] → $BF → (col 0, row 0) = top-left
21 // tiles[1] → $CB → (col 0, row 1) = bottom-left
22 // tiles[2] → $C2 → (col 1, row 0) = top-right
23 // tiles[3] → $CE → (col 1, row 1) = bottom-right
25 ctx.object.y_ + (s * 2),
26 ctx.tiles[0]); // col 0, row 0
28 ctx.object.y_ + (s * 2) + 1,
29 ctx.tiles[1]); // col 0, row 1
31 ctx.object.y_ + (s * 2),
32 ctx.tiles[2]); // col 1, row 0
34 ctx.object.y_ + (s * 2) + 1,
35 ctx.tiles[3]); // col 1, row 1
36 }
37 }
38}
39
41 // Pattern: Draws 4x2 tiles downward (objects 0x61-0x62)
42 // This is 4 columns × 2 rows = 8 tiles in ROW-MAJOR order (per ZScream)
43 int size = ctx.object.size_;
44 if (size == 0) size = 26; // Special case
45
46 for (int s = 0; s < size; s++) {
47 if (ctx.tiles.size() >= 8) {
48 // Draw 4x2 pattern in ROW-MAJOR order (matching ZScream)
49 // Row 0: tiles 0, 1, 2, 3 at x+0, x+1, x+2, x+3
51 ctx.object.y_ + (s * 2), ctx.tiles[0]);
53 ctx.object.y_ + (s * 2), ctx.tiles[1]);
55 ctx.object.y_ + (s * 2), ctx.tiles[2]);
57 ctx.object.y_ + (s * 2), ctx.tiles[3]);
58 // Row 1: tiles 4, 5, 6, 7 at x+0, x+1, x+2, x+3
60 ctx.object.y_ + (s * 2) + 1, ctx.tiles[4]);
62 ctx.object.y_ + (s * 2) + 1, ctx.tiles[5]);
64 ctx.object.y_ + (s * 2) + 1, ctx.tiles[6]);
66 ctx.object.y_ + (s * 2) + 1, ctx.tiles[7]);
67 } else if (ctx.tiles.size() >= 4) {
68 // Fallback: with 4 tiles draw 4x1 row pattern
70 ctx.object.y_ + (s * 2), ctx.tiles[0]);
72 ctx.object.y_ + (s * 2), ctx.tiles[1]);
74 ctx.object.y_ + (s * 2), ctx.tiles[2]);
76 ctx.object.y_ + (s * 2), ctx.tiles[3]);
77 }
78 }
79}
80
82 // Pattern: Same as above but draws to both BG1 and BG2 (objects 0x63-0x64)
84 // Note: BothBG would require access to both buffers - simplified for now
85}
86
88 // Pattern: Draws 4x2 decoration downward with spacing (objects 0x65-0x66)
89 // This is 4 columns × 2 rows = 8 tiles in COLUMN-MAJOR order with 6-tile Y
90 // spacing
91 int size = ctx.object.size_ & 0x0F;
92
93 // Assembly: GetSize_1to16, so count = size + 1
94 int count = size + 1;
95
96 for (int s = 0; s < count; s++) {
97 if (ctx.tiles.size() >= 8) {
98 // Draw 4x2 pattern in COLUMN-MAJOR order
99 // Column 0 (tiles 0-1)
101 ctx.object.y_ + (s * 6),
102 ctx.tiles[0]); // col 0, row 0
104 ctx.object.y_ + (s * 6) + 1,
105 ctx.tiles[1]); // col 0, row 1
106 // Column 1 (tiles 2-3)
108 ctx.object.y_ + (s * 6),
109 ctx.tiles[2]); // col 1, row 0
111 ctx.object.y_ + (s * 6) + 1,
112 ctx.tiles[3]); // col 1, row 1
113 // Column 2 (tiles 4-5)
115 ctx.object.y_ + (s * 6),
116 ctx.tiles[4]); // col 2, row 0
118 ctx.object.y_ + (s * 6) + 1,
119 ctx.tiles[5]); // col 2, row 1
120 // Column 3 (tiles 6-7)
122 ctx.object.y_ + (s * 6),
123 ctx.tiles[6]); // col 3, row 0
125 ctx.object.y_ + (s * 6) + 1,
126 ctx.tiles[7]); // col 3, row 1
127 }
128 }
129}
130
132 // Pattern: Draws 2x2 tiles downward (objects 0x67-0x68)
133 int size = ctx.object.size_ & 0x0F;
134
135 // Assembly: GetSize_1to16, so count = size + 1
136 int count = size + 1;
137
138 for (int s = 0; s < count; s++) {
139 if (ctx.tiles.size() >= 4) {
140 // Draw 2x2 pattern in COLUMN-MAJOR order (matching assembly)
141 // tiles[0] → col 0, row 0 = top-left
142 // tiles[1] → col 0, row 1 = bottom-left
143 // tiles[2] → col 1, row 0 = top-right
144 // tiles[3] → col 1, row 1 = bottom-right
146 ctx.object.y_ + (s * 2),
147 ctx.tiles[0]); // col 0, row 0
149 ctx.object.y_ + (s * 2) + 1,
150 ctx.tiles[1]); // col 0, row 1
152 ctx.object.y_ + (s * 2),
153 ctx.tiles[2]); // col 1, row 0
155 ctx.object.y_ + (s * 2) + 1,
156 ctx.tiles[3]); // col 1, row 1
157 }
158 }
159}
160
162 // Pattern: 1x1 tiles with edge detection +3 offset downward (object 0x69)
163 int size = ctx.object.size_ & 0x0F;
164
165 // Assembly: GetSize_1to16_timesA(2), so count = size + 2
166 int count = size + 2;
167
168 for (int s = 0; s < count; s++) {
169 if (ctx.tiles.size() >= 1) {
170 // Use first 8x8 tile from span
172 ctx.object.y_ + s, ctx.tiles[0]);
173 }
174 }
175}
176
178 // Pattern: 1x1 edge tiles downward (objects 0x6A-0x6B)
179 int size = ctx.object.size_ & 0x0F;
180
181 // Assembly: GetSize_1to16, so count = size + 1
182 int count = size + 1;
183
184 for (int s = 0; s < count; s++) {
185 if (ctx.tiles.size() >= 1) {
186 // Use first 8x8 tile from span
188 ctx.object.y_ + s, ctx.tiles[0]);
189 }
190 }
191}
192
194 // Pattern: Left corner 2x1 tiles with +12 offset downward (object 0x6C)
195 int size = ctx.object.size_ & 0x0F;
196
197 // Assembly: GetSize_1to16_timesA(0x0A), so count = size + 10
198 int count = size + 10;
199
200 for (int s = 0; s < count; s++) {
201 if (ctx.tiles.size() >= 2) {
202 // Use first tile span for 2x1 pattern
204 ctx.object.y_ + s, ctx.tiles[0]);
206 ctx.object.y_ + s, ctx.tiles[1]);
207 }
208 }
209}
210
212 // Pattern: Right corner 2x1 tiles with +12 offset downward (object 0x6D)
213 int size = ctx.object.size_ & 0x0F;
214
215 // Assembly: GetSize_1to16_timesA(0x0A), so count = size + 10
216 int count = size + 10;
217
218 for (int s = 0; s < count; s++) {
219 if (ctx.tiles.size() >= 2) {
220 // Use first tile span for 2x1 pattern
222 ctx.object.y_ + s, ctx.tiles[0]);
224 ctx.object.y_ + s, ctx.tiles[1]);
225 }
226 }
227}
228
229void RegisterDownwardsRoutines(std::vector<DrawRoutineInfo>& registry) {
230 using Category = DrawRoutineInfo::Category;
231
232 registry.push_back(DrawRoutineInfo{
233 .id = 7, // RoomDraw_Downwards2x2_1to15or32
234 .name = "Downwards2x2_1to15or32",
235 .function = DrawDownwards2x2_1to15or32,
236 .draws_to_both_bgs = false,
237 .base_width = 2,
238 .base_height = 2,
239 .category = Category::Downwards});
240
241 registry.push_back(DrawRoutineInfo{
242 .id = 8, // RoomDraw_Downwards4x2_1to15or26
243 .name = "Downwards4x2_1to15or26",
244 .function = DrawDownwards4x2_1to15or26,
245 .draws_to_both_bgs = false,
246 .base_width = 4,
247 .base_height = 2,
248 .category = Category::Downwards});
249
250 registry.push_back(DrawRoutineInfo{
251 .id = 9, // RoomDraw_Downwards4x2_1to16_BothBG
252 .name = "Downwards4x2_1to16_BothBG",
254 .draws_to_both_bgs = true,
255 .base_width = 4,
256 .base_height = 2,
257 .category = Category::Downwards});
258
259 registry.push_back(DrawRoutineInfo{
260 .id = 10, // RoomDraw_DownwardsDecor4x2spaced4_1to16
261 .name = "DownwardsDecor4x2spaced4_1to16",
263 .draws_to_both_bgs = false,
264 .base_width = 4,
265 .base_height = 2,
266 .category = Category::Downwards});
267
268 registry.push_back(DrawRoutineInfo{
269 .id = 11, // RoomDraw_Downwards2x2_1to16
270 .name = "Downwards2x2_1to16",
271 .function = DrawDownwards2x2_1to16,
272 .draws_to_both_bgs = false,
273 .base_width = 2,
274 .base_height = 2,
275 .category = Category::Downwards});
276
277 registry.push_back(DrawRoutineInfo{
278 .id = 12, // RoomDraw_DownwardsHasEdge1x1_1to16_plus3
279 .name = "DownwardsHasEdge1x1_1to16_plus3",
281 .draws_to_both_bgs = false,
282 .base_width = 1,
283 .base_height = 1,
284 .category = Category::Downwards});
285
286 registry.push_back(DrawRoutineInfo{
287 .id = 13, // RoomDraw_DownwardsEdge1x1_1to16
288 .name = "DownwardsEdge1x1_1to16",
289 .function = DrawDownwardsEdge1x1_1to16,
290 .draws_to_both_bgs = false,
291 .base_width = 1,
292 .base_height = 1,
293 .category = Category::Downwards});
294
295 registry.push_back(DrawRoutineInfo{
296 .id = 14, // RoomDraw_DownwardsLeftCorners2x1_1to16_plus12
297 .name = "DownwardsLeftCorners2x1_1to16_plus12",
299 .draws_to_both_bgs = false,
300 .base_width = 2,
301 .base_height = 1,
302 .category = Category::Downwards});
303
304 registry.push_back(DrawRoutineInfo{
305 .id = 15, // RoomDraw_DownwardsRightCorners2x1_1to16_plus12
306 .name = "DownwardsRightCorners2x1_1to16_plus12",
308 .draws_to_both_bgs = false,
309 .base_width = 2,
310 .base_height = 1,
311 .category = Category::Downwards});
312}
313
314} // namespace draw_routines
315} // namespace zelda3
316} // namespace yaze
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 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 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 DrawDownwardsHasEdge1x1_1to16_plus3(const DrawContext &ctx)
Draw 1x1 tiles with edge detection +3 offset downward.
void DrawDownwardsLeftCorners2x1_1to16_plus12(const DrawContext &ctx)
Draw left corner 2x1 tiles with +12 offset downward.
void DrawDownwardsRightCorners2x1_1to16_plus12(const DrawContext &ctx)
Draw right corner 2x1 tiles with +12 offset downward.
void DrawDownwardsDecor4x2spaced4_1to16(const DrawContext &ctx)
Draw 4x2 decoration downward with spacing (1-16 iterations)
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.