all repos — mgba @ 92849dee1a9704a34f75b6cf0de0bb0443b5dfc2

mGBA Game Boy Advance Emulator

src/gba/renderers/software-bg.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 DRAW_BACKGROUND_MODE_2(BLEND, OBJWIN) \
 11	for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) { \
 12		x += background->dx; \
 13		y += background->dy; \
 14		\
 15		if (!mosaicWait) { \
 16			if (background->overflow) { \
 17				localX = x & (sizeAdjusted - 1); \
 18				localY = y & (sizeAdjusted - 1); \
 19			} else if ((x | y) & ~(sizeAdjusted - 1)) { \
 20				continue; \
 21			} else { \
 22				localX = x; \
 23				localY = y; \
 24			} \
 25			mapData = ((uint8_t*)renderer->d.vram)[screenBase + (localX >> 11) + (((localY >> 7) & 0x7F0) << background->size)]; \
 26			pixelData = ((uint8_t*)renderer->d.vram)[charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)]; \
 27			\
 28			mosaicWait = mosaicH; \
 29		} else { \
 30			--mosaicWait; \
 31		} \
 32		\
 33		uint32_t current = *pixel; \
 34		if (pixelData && IS_WRITABLE(current)) {	\
 35			COMPOSITE_256_ ## OBJWIN (BLEND); \
 36		} \
 37	}
 38
 39void GBAVideoSoftwareRendererDrawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
 40	int sizeAdjusted = 0x8000 << background->size;
 41
 42	BACKGROUND_BITMAP_INIT;
 43
 44	uint32_t screenBase = background->screenBase;
 45	uint32_t charBase = background->charBase;
 46	uint8_t mapData;
 47	uint8_t pixelData = 0;
 48
 49	int outX;
 50	uint32_t* pixel;
 51
 52	if (!objwinSlowPath) {
 53		if (!(flags & FLAG_TARGET_2) && renderer->blendEffect != BLEND_ALPHA) {
 54			DRAW_BACKGROUND_MODE_2(NoBlend, NO_OBJWIN);
 55		} else {
 56			DRAW_BACKGROUND_MODE_2(Blend, NO_OBJWIN);
 57		}
 58	} else {
 59		if (!(flags & FLAG_TARGET_2) && renderer->blendEffect != BLEND_ALPHA) {
 60			DRAW_BACKGROUND_MODE_2(NoBlend, OBJWIN);
 61		} else {
 62			DRAW_BACKGROUND_MODE_2(Blend, OBJWIN);
 63		}
 64	}
 65}
 66
 67void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
 68	BACKGROUND_BITMAP_INIT;
 69
 70	uint32_t color = renderer->normalPalette[0];
 71
 72	int outX;
 73	uint32_t* pixel;
 74	for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
 75		BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
 76
 77		if (!mosaicWait) {
 78			LOAD_16(color, ((localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS) << 1, renderer->d.vram);
 79#ifndef COLOR_16_BIT
 80			unsigned color32;
 81			color32 = 0;
 82			color32 |= (color << 3) & 0xF8;
 83			color32 |= (color << 6) & 0xF800;
 84			color32 |= (color << 9) & 0xF80000;
 85			color = color32;
 86#elif COLOR_5_6_5
 87			uint16_t color16 = 0;
 88			color16 |= (color & 0x001F) << 11;
 89			color16 |= (color & 0x03E0) << 1;
 90			color16 |= (color & 0x7C00) >> 10;
 91			color = color16;
 92#endif
 93			mosaicWait = mosaicH;
 94		} else {
 95			--mosaicWait;
 96		}
 97
 98		uint32_t current = *pixel;
 99		if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
100			unsigned mergedFlags = flags;
101			if (current & FLAG_OBJWIN) {
102				mergedFlags = objwinFlags;
103			}
104			if (!variant) {
105				_compositeBlendObjwin(renderer, pixel, color | mergedFlags, current);
106			} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
107				_compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | mergedFlags, current);
108			} else if (renderer->blendEffect == BLEND_DARKEN) {
109				_compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | mergedFlags, current);
110			}
111		}
112	}
113}
114
115void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
116	BACKGROUND_BITMAP_INIT;
117
118	uint16_t color = renderer->normalPalette[0];
119	uint32_t offset = 0;
120	if (GBARegisterDISPCNTIsFrameSelect(renderer->dispcnt)) {
121		offset = 0xA000;
122	}
123
124	int outX;
125	uint32_t* pixel;
126	for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
127		BACKGROUND_BITMAP_ITERATE(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
128
129		if (!mosaicWait) {
130			color = ((uint8_t*)renderer->d.vram)[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS];
131
132			mosaicWait = mosaicH;
133		} else {
134			--mosaicWait;
135		}
136
137		uint32_t current = *pixel;
138		if (color && IS_WRITABLE(current)) {
139			if (!objwinSlowPath) {
140				_compositeBlendNoObjwin(renderer, pixel, palette[color] | flags, current);
141			} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) {
142				color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette;
143				unsigned mergedFlags = flags;
144				if (current & FLAG_OBJWIN) {
145					mergedFlags = objwinFlags;
146				}
147				_compositeBlendObjwin(renderer, pixel, currentPalette[color] | mergedFlags, current);
148			}
149		}
150	}
151}
152
153void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) {
154	BACKGROUND_BITMAP_INIT;
155
156	uint32_t color = renderer->normalPalette[0];
157	uint32_t offset = 0;
158	if (GBARegisterDISPCNTIsFrameSelect(renderer->dispcnt)) {
159		offset = 0xA000;
160	}
161
162	int outX;
163	uint32_t* pixel;
164	for (outX = renderer->start, pixel = &renderer->row[outX]; outX < renderer->end; ++outX, ++pixel) {
165		BACKGROUND_BITMAP_ITERATE(160, 128);
166
167		if (!mosaicWait) {
168			LOAD_16(color, offset + (localX >> 8) * 2 + (localY >> 8) * 320, renderer->d.vram);
169#ifndef COLOR_16_BIT
170			unsigned color32 = 0;
171			color32 |= (color << 9) & 0xF80000;
172			color32 |= (color << 3) & 0xF8;
173			color32 |= (color << 6) & 0xF800;
174			color = color32;
175#elif COLOR_5_6_5
176			uint16_t color16 = 0;
177			color16 |= (color & 0x001F) << 11;
178			color16 |= (color & 0x03E0) << 1;
179			color16 |= (color & 0x7C00) >> 10;
180			color = color16;
181#endif
182			mosaicWait = mosaicH;
183		} else {
184			--mosaicWait;
185		}
186
187		uint32_t current = *pixel;
188		if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
189			unsigned mergedFlags = flags;
190			if (current & FLAG_OBJWIN) {
191				mergedFlags = objwinFlags;
192			}
193			if (!variant) {
194				_compositeBlendObjwin(renderer, pixel, color | mergedFlags, current);
195			} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
196				_compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | mergedFlags, current);
197			} else if (renderer->blendEffect == BLEND_DARKEN) {
198				_compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | mergedFlags, current);
199			}
200		}
201	}
202}