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}