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