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