src/gba/renderers/software-mode0.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "gba/renderers/software-private.h"
7
8#include <mgba/internal/gba/gba.h>
9
10#define BACKGROUND_TEXT_SELECT_CHARACTER \
11 xBase = localX & 0xF8; \
12 if (background->size & 1) { \
13 xBase += (localX & 0x100) << 5; \
14 } \
15 screenBase = yBase + (xBase >> 3); \
16 LOAD_16(mapData, screenBase << 1, vram); \
17
18#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_16(BLEND, OBJWIN) \
19 paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
20 palette = &mainPalette[paletteData]; \
21 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
22 LOAD_32(tileData, charBase, vram); \
23 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
24 tileData >>= 4 * mod8; \
25 for (; outX < end; ++outX, ++pixel) { \
26 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
27 } \
28 } else { \
29 for (outX = end - 1; outX >= renderer->start; --outX) { \
30 uint32_t* pixel = &renderer->row[outX]; \
31 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
32 } \
33 }
34
35#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_16(BLEND, OBJWIN) \
36 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
37 LOAD_32(tileData, charBase, vram); \
38 paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
39 palette = &mainPalette[paletteData]; \
40 pixel = &renderer->row[outX]; \
41 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
42 if (outX < renderer->start) { \
43 tileData >>= 4 * (renderer->start - outX); \
44 outX = renderer->start; \
45 pixel = &renderer->row[outX]; \
46 } \
47 for (; outX < renderer->end; ++outX, ++pixel) { \
48 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
49 } \
50 } else { \
51 tileData >>= 4 * (0x8 - mod8); \
52 int end = renderer->end - 8; \
53 if (end < -1) { \
54 end = -1; \
55 } \
56 outX = renderer->end - 1; \
57 pixel = &renderer->row[outX]; \
58 for (; outX > end; --outX, --pixel) { \
59 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
60 } \
61 /* Needed for consistency checks */ \
62 if (VIDEO_CHECKS) { \
63 outX = renderer->end; \
64 pixel = &renderer->row[outX]; \
65 } \
66 }
67
68#define DRAW_BACKGROUND_MODE_0_MOSAIC_16(BLEND, OBJWIN) \
69 x = inX & 7; \
70 if (mosaicWait) { \
71 int baseX = x - (mosaicH - mosaicWait); \
72 if (baseX < 0) { \
73 int disturbX = (16 + baseX) >> 3; \
74 inX -= disturbX << 3; \
75 localX = tileX * 8 + inX; \
76 BACKGROUND_TEXT_SELECT_CHARACTER; \
77 localY = inY & 0x7; \
78 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
79 localY = 7 - localY; \
80 } \
81 baseX -= disturbX << 3; \
82 inX += disturbX << 3; \
83 } else { \
84 localX = tileX * 8 + inX; \
85 BACKGROUND_TEXT_SELECT_CHARACTER; \
86 localY = inY & 0x7; \
87 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
88 localY = 7 - localY; \
89 } \
90 } \
91 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
92 if (UNLIKELY(charBase >= 0x10000)) { \
93 carryData = 0; \
94 } else { \
95 paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
96 palette = &mainPalette[paletteData]; \
97 LOAD_32(tileData, charBase, vram); \
98 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
99 tileData >>= 4 * baseX; \
100 } else { \
101 tileData >>= 4 * (7 - baseX); \
102 } \
103 tileData &= 0xF; \
104 tileData |= tileData << 4; \
105 tileData |= tileData << 8; \
106 tileData |= tileData << 16; \
107 carryData = tileData; \
108 } \
109 } \
110 localX = tileX * 8 + inX; \
111 for (; length; ++tileX) { \
112 mapData = background->mapCache[(localX >> 3) & 0x3F]; \
113 localX += 8; \
114 localY = inY & 0x7; \
115 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
116 localY = 7 - localY; \
117 } \
118 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
119 tileData = carryData; \
120 for (; x < 8 && length; ++x, --length) { \
121 if (!mosaicWait) { \
122 if (UNLIKELY(charBase >= 0x10000)) { \
123 carryData = 0; \
124 } else { \
125 paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
126 palette = &mainPalette[paletteData]; \
127 LOAD_32(tileData, charBase, vram); \
128 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
129 tileData >>= x * 4; \
130 } else { \
131 tileData >>= (7 - x) * 4; \
132 } \
133 tileData &= 0xF; \
134 tileData |= tileData << 4; \
135 tileData |= tileData << 8; \
136 tileData |= tileData << 16; \
137 carryData = tileData; \
138 } \
139 mosaicWait = mosaicH; \
140 } \
141 --mosaicWait; \
142 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
143 ++pixel; \
144 } \
145 x = 0; \
146 }
147
148#define DRAW_BACKGROUND_MODE_0_TILES_16(BLEND, OBJWIN) \
149 for (; tileX < tileEnd; ++tileX) { \
150 mapData = background->mapCache[(localX >> 3) & 0x3F]; \
151 localX += 8; \
152 localY = inY & 0x7; \
153 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
154 localY = 7 - localY; \
155 } \
156 paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
157 palette = &mainPalette[paletteData]; \
158 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) + (localY << 2); \
159 if (UNLIKELY(charBase >= 0x10000)) { \
160 pixel += 8; \
161 continue; \
162 } \
163 LOAD_32(tileData, charBase, vram); \
164 if (tileData) { \
165 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
166 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
167 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 1); \
168 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 2); \
169 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 3); \
170 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 4); \
171 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 5); \
172 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 6); \
173 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 7); \
174 } else { \
175 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 7); \
176 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 6); \
177 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 5); \
178 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 4); \
179 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 3); \
180 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 2); \
181 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 1); \
182 BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, 0); \
183 } \
184 } \
185 pixel += 8; \
186 }
187
188#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256(BLEND, OBJWIN) \
189 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
190 int end2 = end - 4; \
191 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
192 int shift = inX & 0x3; \
193 if (LIKELY(charBase < 0x10000)) { \
194 if (end2 > outX) { \
195 LOAD_32(tileData, charBase, vram); \
196 tileData >>= 8 * shift; \
197 shift = 0; \
198 for (; outX < end2; ++outX, ++pixel) { \
199 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
200 } \
201 } \
202 } \
203 \
204 if (LIKELY(charBase < 0x10000)) { \
205 LOAD_32(tileData, charBase + 4, vram); \
206 tileData >>= 8 * shift; \
207 for (; outX < end; ++outX, ++pixel) { \
208 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
209 } \
210 } \
211 } else { \
212 int start = outX; \
213 outX = end - 1; \
214 pixel = &renderer->row[outX]; \
215 if (LIKELY(charBase < 0x10000)) { \
216 if (end2 > start) { \
217 LOAD_32(tileData, charBase, vram); \
218 for (; outX >= end2; --outX, --pixel) { \
219 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
220 } \
221 charBase += 4; \
222 } \
223 } \
224 \
225 if (LIKELY(charBase < 0x10000)) { \
226 LOAD_32(tileData, charBase, vram); \
227 for (; outX >= renderer->start; --outX, --pixel) { \
228 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
229 } \
230 } \
231 outX = end; \
232 pixel = &renderer->row[outX]; \
233 }
234
235#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \
236 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
237 if (UNLIKELY(charBase >= 0x10000)) { \
238 return; \
239 } \
240 int end = mod8 - 4; \
241 pixel = &renderer->row[outX]; \
242 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
243 if (end > 0) { \
244 LOAD_32(tileData, charBase, vram); \
245 for (; outX < renderer->end - end; ++outX, ++pixel) { \
246 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
247 } \
248 charBase += 4; \
249 } \
250 \
251 LOAD_32(tileData, charBase, vram); \
252 for (; outX < renderer->end; ++outX, ++pixel) { \
253 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
254 } \
255 } else { \
256 int shift = (8 - mod8) & 0x3; \
257 int start = outX; \
258 outX = renderer->end - 1; \
259 pixel = &renderer->row[outX]; \
260 if (end > 0) { \
261 LOAD_32(tileData, charBase, vram); \
262 tileData >>= 8 * shift; \
263 for (; outX >= start + 4; --outX, --pixel) { \
264 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
265 } \
266 shift = 0; \
267 } \
268 \
269 LOAD_32(tileData, charBase + 4, vram); \
270 tileData >>= 8 * shift; \
271 for (; outX >= start; --outX, --pixel) { \
272 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
273 } \
274 /* Needed for consistency checks */ \
275 if (VIDEO_CHECKS) { \
276 outX = renderer->end; \
277 pixel = &renderer->row[outX]; \
278 } \
279 }
280
281#define DRAW_BACKGROUND_MODE_0_TILES_256(BLEND, OBJWIN) \
282 for (; tileX < tileEnd; ++tileX) { \
283 mapData = background->mapCache[(localX >> 3) & 0x3F]; \
284 localX += 8; \
285 localY = inY & 0x7; \
286 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
287 localY = 7 - localY; \
288 } \
289 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
290 if (UNLIKELY(charBase >= 0x10000)) { \
291 pixel += 8; \
292 continue; \
293 } \
294 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
295 LOAD_32(tileData, charBase, vram); \
296 if (tileData) { \
297 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
298 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
299 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
300 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
301 } \
302 pixel += 4; \
303 LOAD_32(tileData, charBase + 4, vram); \
304 if (tileData) { \
305 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
306 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
307 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
308 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
309 } \
310 pixel += 4; \
311 } else { \
312 LOAD_32(tileData, charBase + 4, vram); \
313 if (tileData) { \
314 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
315 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
316 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
317 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
318 } \
319 pixel += 4; \
320 LOAD_32(tileData, charBase, vram); \
321 if (tileData) { \
322 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 3); \
323 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 2); \
324 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 1); \
325 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
326 } \
327 pixel += 4; \
328 } \
329 }
330
331#define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \
332 x = inX & 7; \
333 if (mosaicWait) { \
334 int baseX = x - (mosaicH - mosaicWait); \
335 if (baseX < 0) { \
336 int disturbX = (16 + baseX) >> 3; \
337 inX -= disturbX << 3; \
338 localX = tileX * 8 + inX; \
339 BACKGROUND_TEXT_SELECT_CHARACTER; \
340 localY = inY & 0x7; \
341 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
342 localY = 7 - localY; \
343 } \
344 baseX -= disturbX << 3; \
345 inX += disturbX << 3; \
346 } else { \
347 localX = tileX * 8 + inX; \
348 BACKGROUND_TEXT_SELECT_CHARACTER; \
349 localY = inY & 0x7; \
350 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
351 localY = 7 - localY; \
352 } \
353 } \
354 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
355 if (UNLIKELY(charBase >= 0x10000)) { \
356 carryData = 0; \
357 } else { \
358 LOAD_32(tileData, charBase, vram); \
359 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
360 if (x >= 4) { \
361 LOAD_32(tileData, charBase + 4, vram); \
362 tileData >>= (x - 4) * 8; \
363 } else { \
364 LOAD_32(tileData, charBase, vram); \
365 tileData >>= x * 8; \
366 } \
367 } else { \
368 if (x >= 4) { \
369 LOAD_32(tileData, charBase, vram); \
370 tileData >>= (7 - x) * 8; \
371 } else { \
372 LOAD_32(tileData, charBase + 4, vram); \
373 tileData >>= (3 - x) * 8; \
374 } \
375 } \
376 tileData &= 0xFF; \
377 carryData = tileData; \
378 } \
379 } \
380 localX = tileX * 8 + inX; \
381 for (; length; ++tileX) { \
382 mapData = background->mapCache[(localX >> 3) & 0x3F]; \
383 localX += 8; \
384 localY = inY & 0x7; \
385 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
386 localY = 7 - localY; \
387 } \
388 charBase = (background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) + (localY << 3); \
389 tileData = carryData; \
390 for (; x < 8 && length; ++x, --length) { \
391 if (!mosaicWait) { \
392 if (UNLIKELY(charBase >= 0x10000)) { \
393 carryData = 0; \
394 } else { \
395 if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
396 if (x >= 4) { \
397 LOAD_32(tileData, charBase + 4, vram); \
398 tileData >>= (x - 4) * 8; \
399 } else { \
400 LOAD_32(tileData, charBase, vram); \
401 tileData >>= x * 8; \
402 } \
403 } else { \
404 if (x >= 4) { \
405 LOAD_32(tileData, charBase, vram); \
406 tileData >>= (7 - x) * 8; \
407 } else { \
408 LOAD_32(tileData, charBase + 4, vram); \
409 tileData >>= (3 - x) * 8; \
410 } \
411 } \
412 tileData &= 0xFF; \
413 carryData = tileData; \
414 } \
415 mosaicWait = mosaicH; \
416 } \
417 tileData |= tileData << 8; \
418 --mosaicWait; \
419 BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, 0); \
420 ++pixel; \
421 } \
422 x = 0; \
423 }
424
425#define DRAW_BACKGROUND_MODE_0(BPP, BLEND, OBJWIN) \
426 uint32_t* pixel = &renderer->row[outX]; \
427 if (background->mosaic && GBAMosaicControlGetBgH(renderer->mosaic)) { \
428 int mosaicH = GBAMosaicControlGetBgH(renderer->mosaic) + 1; \
429 int x; \
430 int mosaicWait = (mosaicH - outX + GBA_VIDEO_HORIZONTAL_PIXELS * mosaicH) % mosaicH; \
431 int carryData = 0; \
432 paletteData = 0; /* Quiets compiler warning */ \
433 DRAW_BACKGROUND_MODE_0_MOSAIC_ ## BPP (BLEND, OBJWIN) \
434 return; \
435 } \
436 \
437 if (inX & 0x7) { \
438 localX = tileX * 8 + inX; \
439 BACKGROUND_TEXT_SELECT_CHARACTER; \
440 localY = inY & 0x7; \
441 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
442 localY = 7 - localY; \
443 } \
444 int mod8 = inX & 0x7; \
445 int end = outX + 0x8 - mod8; \
446 if (end > renderer->end) { \
447 end = renderer->end; \
448 } \
449 if (UNLIKELY(end == outX)) { \
450 return; \
451 } \
452 if (UNLIKELY(end < outX)) { \
453 mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw!"); \
454 return; \
455 } \
456 DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_ ## BPP (BLEND, OBJWIN) \
457 outX = end; \
458 if (tileX < tileEnd) { \
459 ++tileX; \
460 } else if (VIDEO_CHECKS && UNLIKELY(tileX > tileEnd)) { \
461 mLOG(GBA_VIDEO, FATAL, "Invariant doesn't hold in background draw! tileX (%u) > tileEnd (%u)", tileX, tileEnd); \
462 return; \
463 } \
464 length -= end - renderer->start; \
465 } \
466 /*! TODO: Make sure these lines can be removed */ \
467 /*!*/ pixel = &renderer->row[outX]; \
468 outX += (tileEnd - tileX) * 8; \
469 /*!*/ if (VIDEO_CHECKS && UNLIKELY(outX > GBA_VIDEO_HORIZONTAL_PIXELS)) { \
470 /*!*/ mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw would occur!"); \
471 /*!*/ return; \
472 /*!*/ } \
473 localX = (tileX * 8 + inX) & 0x1FF; \
474 DRAW_BACKGROUND_MODE_0_TILES_ ## BPP (BLEND, OBJWIN) \
475 if (length & 0x7) { \
476 localX = tileX * 8 + inX; \
477 BACKGROUND_TEXT_SELECT_CHARACTER; \
478 localY = inY & 0x7; \
479 if (GBA_TEXT_MAP_VFLIP(mapData)) { \
480 localY = 7 - localY; \
481 } \
482 int mod8 = length & 0x7; \
483 if (VIDEO_CHECKS && UNLIKELY(outX + mod8 != renderer->end)) { \
484 mLOG(GBA_VIDEO, FATAL, "Invariant doesn't hold in background draw!"); \
485 return; \
486 } \
487 DRAW_BACKGROUND_MODE_0_TILE_PREFIX_ ## BPP (BLEND, OBJWIN) \
488 } \
489 if (VIDEO_CHECKS && UNLIKELY(&renderer->row[outX] != pixel)) { \
490 mLOG(GBA_VIDEO, FATAL, "Background draw ended in the wrong place! Diff: %" PRIXPTR, &renderer->row[outX] - pixel); \
491 } \
492 if (VIDEO_CHECKS && UNLIKELY(outX > GBA_VIDEO_HORIZONTAL_PIXELS)) { \
493 mLOG(GBA_VIDEO, FATAL, "Out of bounds background draw occurred!"); \
494 return; \
495 }
496
497void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {
498 int inX = (renderer->start + background->x - background->offsetX) & 0x1FF;
499 int length = renderer->end - renderer->start;
500 if (background->mosaic) {
501 int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1;
502 y -= y % mosaicV;
503 }
504 int inY = y + background->y - background->offsetY;
505 uint16_t mapData;
506
507 unsigned yBase = inY & 0xF8;
508 if (background->size == 2) {
509 yBase += inY & 0x100;
510 } else if (background->size == 3) {
511 yBase += (inY & 0x100) << 1;
512 }
513 yBase = (background->screenBase >> 1) + (yBase << 2);
514
515 int localX;
516 int localY;
517
518 unsigned xBase;
519
520 uint32_t flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND;
521 flags |= FLAG_TARGET_2 * background->target2;
522 int objwinFlags = FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && GBAWindowControlIsBlendEnable(renderer->objwin.packed));
523 objwinFlags |= flags;
524 flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed));
525 if (renderer->blendEffect == BLEND_ALPHA && renderer->blda == 0x10 && renderer->bldb == 0) {
526 flags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2);
527 objwinFlags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2);
528 }
529
530 uint32_t screenBase;
531 uint32_t charBase;
532 int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN);
533 color_t* mainPalette = renderer->normalPalette;
534 if (renderer->d.highlightAmount && background->highlight) {
535 mainPalette = renderer->highlightPalette;
536 }
537 if (variant) {
538 mainPalette = renderer->variantPalette;
539 if (renderer->d.highlightAmount && background->highlight) {
540 mainPalette = renderer->highlightVariantPalette;
541 }
542 }
543 color_t* palette = mainPalette;
544 PREPARE_OBJWIN;
545
546 int outX = renderer->start;
547
548 uint32_t tileData;
549 uint32_t current;
550 int pixelData;
551 int paletteData;
552 int tileX;
553 int tileEnd = ((length + inX) >> 3) - (inX >> 3);
554 uint16_t* vram = renderer->d.vram;
555
556 if (background->yCache != inY >> 3) {
557 localX = 0;
558 for (tileX = 0; tileX < 64; ++tileX, localX += 8) {
559 BACKGROUND_TEXT_SELECT_CHARACTER;
560 background->mapCache[tileX] = mapData;
561 }
562 background->yCache = inY >> 3;
563 }
564
565 tileX = 0;
566 if (!objwinSlowPath) {
567 if (!(flags & FLAG_TARGET_2)) {
568 if (!background->multipalette) {
569 DRAW_BACKGROUND_MODE_0(16, NoBlend, NO_OBJWIN);
570 } else {
571 DRAW_BACKGROUND_MODE_0(256, NoBlend, NO_OBJWIN);
572 }
573 } else {
574 if (!background->multipalette) {
575 DRAW_BACKGROUND_MODE_0(16, Blend, NO_OBJWIN);
576 } else {
577 DRAW_BACKGROUND_MODE_0(256, Blend, NO_OBJWIN);
578 }
579 }
580 } else {
581 if (!(flags & FLAG_TARGET_2)) {
582 if (!background->multipalette) {
583 DRAW_BACKGROUND_MODE_0(16, NoBlend, OBJWIN);
584 } else {
585 DRAW_BACKGROUND_MODE_0(256, NoBlend, OBJWIN);
586 }
587 } else {
588 if (!background->multipalette) {
589 DRAW_BACKGROUND_MODE_0(16, Blend, OBJWIN);
590 } else {
591 DRAW_BACKGROUND_MODE_0(256, Blend, OBJWIN);
592 }
593 }
594 }
595}