all repos — mgba @ 0b0a70d9b725c294034f2f2d9fdbaa4a3a6b5729

mGBA Game Boy Advance Emulator

src/gba/renderers/software-private.h (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#ifndef SOFTWARE_PRIVATE_H
  7#define SOFTWARE_PRIVATE_H
  8
  9#include <mgba/internal/arm/macros.h>
 10#include <mgba/internal/gba/renderers/video-software.h>
 11
 12#ifdef NDEBUG
 13#define VIDEO_CHECKS false
 14#else
 15#define VIDEO_CHECKS true
 16#endif
 17
 18void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer,
 19                                                 struct GBAVideoSoftwareBackground* background, int y);
 20void GBAVideoSoftwareRendererDrawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer,
 21                                                 struct GBAVideoSoftwareBackground* background, int y);
 22void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer,
 23                                                 struct GBAVideoSoftwareBackground* background, int y);
 24void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer,
 25                                                 struct GBAVideoSoftwareBackground* background, int y);
 26void GBAVideoSoftwareRendererDrawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer,
 27                                                 struct GBAVideoSoftwareBackground* background, int y);
 28
 29int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct GBAObj* sprite, int index, int y);
 30void GBAVideoSoftwareRendererPostprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority);
 31
 32static inline unsigned _brighten(unsigned color, int y);
 33static inline unsigned _darken(unsigned color, int y);
 34
 35// We stash the priority on the top bits so we can do a one-operator comparison
 36// The lower the number, the higher the priority, and sprites take precedence over backgrounds
 37// We want to do special processing if the color pixel is target 1, however
 38
 39static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
 40	if (color >= current) {
 41		if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
 42			color = mColorMix5Bit(renderer->blda, current, renderer->bldb, color);
 43		} else {
 44			color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN);
 45		}
 46	} else {
 47		color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN);
 48	}
 49	*pixel = color;
 50}
 51
 52static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
 53	if (color >= current) {
 54		if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
 55			color = mColorMix5Bit(renderer->blda, current, renderer->bldb, color);
 56		} else {
 57			color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN);
 58		}
 59	} else {
 60		color = color & ~FLAG_TARGET_2;
 61	}
 62	*pixel = color;
 63}
 64
 65static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color,
 66                                           uint32_t current) {
 67	UNUSED(renderer);
 68	if (color < current) {
 69		color |= (current & FLAG_OBJWIN);
 70	} else {
 71		color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN);
 72	}
 73	*pixel = color;
 74}
 75
 76static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color,
 77                                             uint32_t current) {
 78	UNUSED(renderer);
 79	if (color >= current) {
 80		color = current & (0x00FFFFFF | FLAG_REBLEND | FLAG_OBJWIN);
 81	}
 82	*pixel = color;
 83}
 84
 85#define COMPOSITE_16_OBJWIN(BLEND, IDX)  \
 86	if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) {                                          \
 87		unsigned color = (current & FLAG_OBJWIN) ? objwinPalette[paletteData | pixelData] : palette[pixelData]; \
 88		unsigned mergedFlags = flags; \
 89		if (current & FLAG_OBJWIN) { \
 90			mergedFlags = objwinFlags; \
 91		} \
 92		_composite ## BLEND ## Objwin(renderer, &pixel[IDX], color | mergedFlags, current); \
 93	}
 94
 95#define COMPOSITE_16_NO_OBJWIN(BLEND, IDX) \
 96	_composite ## BLEND ## NoObjwin(renderer, &pixel[IDX], palette[pixelData] | flags, current);
 97
 98#define COMPOSITE_256_OBJWIN(BLEND, IDX) \
 99	if (objwinForceEnable || (!(current & FLAG_OBJWIN)) == objwinOnly) { \
100		unsigned color = (current & FLAG_OBJWIN) ? objwinPalette[pixelData] : palette[pixelData]; \
101		unsigned mergedFlags = flags; \
102		if (current & FLAG_OBJWIN) { \
103			mergedFlags = objwinFlags; \
104		} \
105		_composite ## BLEND ## Objwin(renderer, &pixel[IDX], color | mergedFlags, current); \
106	}
107
108#define COMPOSITE_256_NO_OBJWIN COMPOSITE_16_NO_OBJWIN
109
110#define BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN, IDX) \
111	pixelData = tileData & 0xF; \
112	current = pixel[IDX]; \
113	if (pixelData && IS_WRITABLE(current)) { \
114		COMPOSITE_16_ ## OBJWIN (BLEND, IDX); \
115	} \
116	tileData >>= 4;
117
118#define BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN, IDX) \
119	pixelData = tileData & 0xFF; \
120	current = pixel[IDX]; \
121	if (pixelData && IS_WRITABLE(current)) { \
122		COMPOSITE_256_ ## OBJWIN (BLEND, IDX); \
123	} \
124	tileData >>= 8;
125
126// TODO: Remove UNUSEDs after implementing OBJWIN for modes 3 - 5
127#define PREPARE_OBJWIN                                                                            \
128	int objwinSlowPath = GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt);                     \
129	int objwinOnly = 0;                                                                           \
130	int objwinForceEnable = 0;                                                                    \
131	UNUSED(objwinForceEnable);                                                                    \
132	color_t* objwinPalette = renderer->normalPalette;                                             \
133	if (renderer->d.highlightAmount && background->highlight) {                                   \
134		objwinPalette = renderer->highlightPalette;                                               \
135	}                                                                                             \
136	UNUSED(objwinPalette);                                                                        \
137	if (objwinSlowPath) {                                                                         \
138		if (background->target1 && GBAWindowControlIsBlendEnable(renderer->objwin.packed) &&      \
139		    (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN)) { \
140			objwinPalette = renderer->variantPalette;                                             \
141			if (renderer->d.highlightAmount && background->highlight) {                           \
142				palette = renderer->highlightVariantPalette;                                      \
143			}                                                                                     \
144		}                                                                                         \
145		switch (background->index) {                                                              \
146		case 0:                                                                                   \
147			objwinForceEnable = GBAWindowControlIsBg0Enable(renderer->objwin.packed) &&           \
148			    GBAWindowControlIsBg0Enable(renderer->currentWindow.packed);                      \
149			objwinOnly = !GBAWindowControlIsBg0Enable(renderer->objwin.packed);                   \
150			break;                                                                                \
151		case 1:                                                                                   \
152			objwinForceEnable = GBAWindowControlIsBg1Enable(renderer->objwin.packed) &&           \
153			    GBAWindowControlIsBg1Enable(renderer->currentWindow.packed);                      \
154			objwinOnly = !GBAWindowControlIsBg1Enable(renderer->objwin.packed);                   \
155			break;                                                                                \
156		case 2:                                                                                   \
157			objwinForceEnable = GBAWindowControlIsBg2Enable(renderer->objwin.packed) &&           \
158			    GBAWindowControlIsBg2Enable(renderer->currentWindow.packed);                      \
159			objwinOnly = !GBAWindowControlIsBg2Enable(renderer->objwin.packed);                   \
160			break;                                                                                \
161		case 3:                                                                                   \
162			objwinForceEnable = GBAWindowControlIsBg3Enable(renderer->objwin.packed) &&           \
163			    GBAWindowControlIsBg3Enable(renderer->currentWindow.packed);                      \
164			objwinOnly = !GBAWindowControlIsBg3Enable(renderer->objwin.packed);                   \
165			break;                                                                                \
166		}                                                                                         \
167	}
168
169static inline unsigned _brighten(unsigned color, int y) {
170	unsigned c = 0;
171	unsigned a;
172#ifdef COLOR_16_BIT
173	a = color & 0x1F;
174	c |= (a + ((0x1F - a) * y) / 16) & 0x1F;
175
176#ifdef COLOR_5_6_5
177	a = color & 0x7C0;
178	c |= (a + ((0x7C0 - a) * y) / 16) & 0x7C0;
179
180	a = color & 0xF800;
181	c |= (a + ((0xF800 - a) * y) / 16) & 0xF800;
182#else
183	a = color & 0x3E0;
184	c |= (a + ((0x3E0 - a) * y) / 16) & 0x3E0;
185
186	a = color & 0x7C00;
187	c |= (a + ((0x7C00 - a) * y) / 16) & 0x7C00;
188#endif
189#else
190	a = color & 0xFF;
191	c |= (a + ((0xFF - a) * y) / 16) & 0xFF;
192
193	a = color & 0xFF00;
194	c |= (a + ((0xFF00 - a) * y) / 16) & 0xFF00;
195
196	a = color & 0xFF0000;
197	c |= (a + ((0xFF0000 - a) * y) / 16) & 0xFF0000;
198#endif
199	return c;
200}
201
202static inline unsigned _darken(unsigned color, int y) {
203	unsigned c = 0;
204	unsigned a;
205#ifdef COLOR_16_BIT
206	a = color & 0x1F;
207	c |= (a - (a * y) / 16) & 0x1F;
208
209#ifdef COLOR_5_6_5
210	a = color & 0x7C0;
211	c |= (a - (a * y) / 16) & 0x7C0;
212
213	a = color & 0xF800;
214	c |= (a - (a * y) / 16) & 0xF800;
215#else
216	a = color & 0x3E0;
217	c |= (a - (a * y) / 16) & 0x3E0;
218
219	a = color & 0x7C00;
220	c |= (a - (a * y) / 16) & 0x7C00;
221#endif
222#else
223	a = color & 0xFF;
224	c |= (a - (a * y) / 16) & 0xFF;
225
226	a = color & 0xFF00;
227	c |= (a - (a * y) / 16) & 0xFF00;
228
229	a = color & 0xFF0000;
230	c |= (a - (a * y) / 16) & 0xFF0000;
231#endif
232	return c;
233}
234
235#endif