all repos — mgba @ 270ce0cba344a65f0e73d7071e3d07193491bf58

mGBA Game Boy Advance Emulator

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}