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