diff options
author | Bad Diode <bd@badd10de.dev> | 2021-08-08 11:07:05 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-08-08 11:07:05 +0200 |
commit | de1ee4b04838fd41663f41dfca0532e5a1dc3648 (patch) | |
tree | b665a7efdf507fef52b5aa3b386a013a0fb4e7d4 | |
parent | fb100fe1abef4f61ad6aaca8e501ab13f1ca4b09 (diff) | |
download | uxngba-de1ee4b04838fd41663f41dfca0532e5a1dc3648.tar.gz uxngba-de1ee4b04838fd41663f41dfca0532e5a1dc3648.zip |
Port PPU changes from uxnds
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/ppu.c | 239 | ||||
-rw-r--r-- | src/ppu.h | 6 |
3 files changed, 169 insertions, 82 deletions
@@ -136,11 +136,11 @@ screen_talk(Device *d, u8 b0, u8 w) { | |||
136 | u8 *layer = d->dat[0xe] >> 4 & 0x1 ? ppu.fg : ppu.bg; | 136 | u8 *layer = d->dat[0xe] >> 4 & 0x1 ? ppu.fg : ppu.bg; |
137 | u8 mode = d->dat[0xe] >> 5; | 137 | u8 mode = d->dat[0xe] >> 5; |
138 | if(!mode) { | 138 | if(!mode) { |
139 | putpixel(layer, x, y, d->dat[0xe] & 0x3); | 139 | ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); |
140 | } else if(mode-- & 0x1) { | 140 | } else if(mode-- & 0x1) { |
141 | puticn(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); | 141 | ppu_1bpp(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); |
142 | } else { | 142 | } else { |
143 | putchr(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); | 143 | ppu_2bpp(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); |
144 | } | 144 | } |
145 | } | 145 | } |
146 | } | 146 | } |
@@ -25,7 +25,7 @@ WITH REGARD TO THIS SOFTWARE. | |||
25 | // Keyboard. | 25 | // Keyboard. |
26 | #define SPRITE_START_IDX 640 | 26 | #define SPRITE_START_IDX 640 |
27 | 27 | ||
28 | static u32 unpack_icon_lut[256] = { | 28 | static u32 lut_2bpp[256] = { |
29 | 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, | 29 | 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, |
30 | 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001, | 30 | 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001, |
31 | 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, | 31 | 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, |
@@ -80,7 +80,7 @@ static u32 unpack_icon_lut[256] = { | |||
80 | 0x11111111 | 80 | 0x11111111 |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static u32 unpack_icon_lut_flipx[256] = { | 83 | static u32 lut2bpp_flipx[256] = { |
84 | 0x00000000, 0x10000000, 0x01000000, 0x11000000, 0x00100000, | 84 | 0x00000000, 0x10000000, 0x01000000, 0x11000000, 0x00100000, |
85 | 0x10100000, 0x01100000, 0x11100000, 0x00010000, 0x10010000, | 85 | 0x10100000, 0x01100000, 0x11100000, 0x00010000, 0x10010000, |
86 | 0x01010000, 0x11010000, 0x00110000, 0x10110000, 0x01110000, | 86 | 0x01010000, 0x11010000, 0x00110000, 0x10110000, 0x01110000, |
@@ -135,6 +135,14 @@ static u32 unpack_icon_lut_flipx[256] = { | |||
135 | 0x11111111 | 135 | 0x11111111 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static u8 blending[5][16] = { | ||
139 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, | ||
140 | {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, | ||
141 | {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, | ||
142 | {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, | ||
143 | {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0} | ||
144 | }; | ||
145 | |||
138 | static u32 dirty_tiles[21] = {0}; | 146 | static u32 dirty_tiles[21] = {0}; |
139 | 147 | ||
140 | void | 148 | void |
@@ -160,7 +168,7 @@ putcolors(u8 *addr) { | |||
160 | 168 | ||
161 | IWRAM_CODE | 169 | IWRAM_CODE |
162 | void | 170 | void |
163 | putpixel(u32 *layer, u16 x, u16 y, u8 color) { | 171 | ppu_pixel(u32 *layer, u16 x, u16 y, u8 color) { |
164 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; | 172 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; |
165 | size_t tile_x = x / 8; | 173 | size_t tile_x = x / 8; |
166 | size_t tile_y = y / 8; | 174 | size_t tile_y = y / 8; |
@@ -174,106 +182,185 @@ putpixel(u32 *layer, u16 x, u16 y, u8 color) { | |||
174 | 182 | ||
175 | IWRAM_CODE | 183 | IWRAM_CODE |
176 | void | 184 | void |
177 | puticn(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { | 185 | ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { |
178 | u8 sprline; | 186 | u8 sprline; |
179 | u16 v; | 187 | u16 v; |
180 | u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); | 188 | u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); |
181 | |||
182 | u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); | ||
183 | u32 *layerptr = &layer[layerpos]; | ||
184 | u32 shift = (x & 7) << 2; | ||
185 | u32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx; | ||
186 | 189 | ||
187 | if (flipy) flipy = 7; | 190 | u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); |
191 | u32 *layerptr = &layer[layerpos]; | ||
192 | u32 shift = (x & 7) << 2; | ||
193 | u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; | ||
188 | 194 | ||
189 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; | 195 | if (flipy) flipy = 7; |
190 | 196 | ||
191 | if (color != 0x05 && color != 0x0a && color != 0x0f) { | 197 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; |
192 | u64 mask = ~((u64)0xFFFFFFFF << shift); | ||
193 | 198 | ||
194 | for (v = 0; v < 8; v++, layerptr++) { | 199 | if (blending[4][color]) { |
195 | if ((y + v) >= SCREEN_HEIGHT) break; | 200 | u64 mask = ~((u64)0xFFFFFFFF << shift); |
196 | 201 | ||
197 | sprline = sprite[v ^ flipy]; | 202 | for (v = 0; v < 8; v++, layerptr++) { |
198 | u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; | 203 | if ((y + v) >= SCREEN_HEIGHT) break; |
199 | data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift; | ||
200 | 204 | ||
201 | layerptr[0] = (layerptr[0] & mask) | data; | 205 | sprline = sprite[v ^ flipy]; |
202 | layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | 206 | u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; |
207 | data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift; | ||
203 | 208 | ||
204 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | 209 | layerptr[0] = (layerptr[0] & mask) | data; |
205 | } | 210 | layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); |
206 | } else { | ||
207 | for (v = 0; v < 8; v++, layerptr++) { | ||
208 | if ((y + v) >= SCREEN_HEIGHT) break; | ||
209 | 211 | ||
210 | sprline = sprite[v ^ flipy]; | 212 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; |
211 | u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift); | 213 | } |
212 | u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; | 214 | } else { |
215 | for (v = 0; v < 8; v++, layerptr++) { | ||
216 | if ((y + v) >= SCREEN_HEIGHT) break; | ||
213 | 217 | ||
214 | layerptr[0] = (layerptr[0] & mask) | data; | 218 | sprline = sprite[v ^ flipy]; |
215 | layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | 219 | u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift); |
220 | u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; | ||
216 | 221 | ||
217 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | 222 | layerptr[0] = (layerptr[0] & mask) | data; |
218 | } | 223 | layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); |
219 | } | ||
220 | 224 | ||
221 | dirty_tiles[y >> 3] |= dirtyflag; | 225 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; |
222 | dirty_tiles[(y + 7) >> 3] |= dirtyflag; | 226 | } |
223 | } | 227 | } |
224 | 228 | ||
225 | IWRAM_CODE | 229 | dirty_tiles[y >> 3] |= dirtyflag; |
226 | void | 230 | dirty_tiles[(y + 7) >> 3] |= dirtyflag; |
227 | putfontchar(u32 *layer, u16 tile_x, u16 tile_y, u8 ch, u8 color) { | ||
228 | u32 pos = (tile_x + tile_y * 32) * 8; | ||
229 | u32 *tile_data = &layer[pos]; | ||
230 | u32 *font_data = &FONT_DATA[8 * ch]; | ||
231 | for (size_t i = 0; i < 8; ++i) { | ||
232 | tile_data[i] = font_data[i] * color; | ||
233 | } | ||
234 | dirty_tiles[tile_y] |= 1 << tile_x; | ||
235 | } | 231 | } |
236 | 232 | ||
237 | IWRAM_CODE | 233 | IWRAM_CODE |
238 | void | 234 | void |
239 | putchr(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, | 235 | ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, |
240 | u8 flipx, u8 flipy) { | 236 | u8 flipx, u8 flipy) { |
241 | u8 sprline1, sprline2; | 237 | u8 sprline1, sprline2; |
242 | u16 v; | 238 | u8 xrightedge = x < ((32 - 1) * 8); |
243 | u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); | 239 | u16 v, h; |
240 | u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); | ||
241 | |||
242 | u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); | ||
243 | u32 *layerptr = &layer[layerpos]; | ||
244 | u32 shift = (x & 7) << 2; | ||
245 | |||
246 | if (flipy) flipy = 7; | ||
247 | |||
248 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; | ||
249 | |||
250 | if (color == 1) { | ||
251 | u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; | ||
252 | u64 mask = ~((u64)0xFFFFFFFF << shift); | ||
253 | |||
254 | for (v = 0; v < 8; v++, layerptr++) { | ||
255 | if ((y + v) >= (24 * 8)) break; | ||
244 | 256 | ||
245 | u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); | 257 | sprline1 = sprite[v ^ flipy]; |
246 | u32 *layerptr = &layer[layerpos]; | 258 | sprline2 = sprite[(v ^ flipy) | 8]; |
247 | u32 shift = (x & 7) << 2; | ||
248 | u32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx; | ||
249 | 259 | ||
250 | if (flipy) flipy = 7; | 260 | u32 data32 = (lut_expand[sprline1]) | (lut_expand[sprline2] << 1); |
261 | u64 data = ((u64) (data32 & 0x33333333)) << shift; | ||
251 | 262 | ||
252 | if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; | 263 | layerptr[0] = (layerptr[0] & mask) | data; |
264 | if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | ||
265 | |||
266 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | ||
267 | } | ||
268 | } else if (blending[4][color]) { | ||
269 | u64 mask = ~((u64)0xFFFFFFFF << shift); | ||
253 | 270 | ||
254 | u64 mask = ~((u64)0xFFFFFFFF << shift); | 271 | for (v = 0; v < 8; v++, layerptr++) { |
255 | u32 colconst = (color >> 2) * 0x11111111; | 272 | if ((y + v) >= (24 * 8)) break; |
256 | 273 | ||
257 | for (v = 0; v < 8; v++, layerptr++) { | 274 | u8 ch1 = sprite[v ^ flipy]; |
258 | if ((y + v) >= SCREEN_HEIGHT) break; | 275 | u8 ch2 = sprite[(v ^ flipy) | 8]; |
276 | u32 data32 = 0; | ||
259 | 277 | ||
260 | sprline1 = sprite[v ^ flipy]; | 278 | if (!flipx) { |
261 | sprline2 = sprite[(v ^ flipy) | 8]; | 279 | for (h = 0; h < 8; h++) { |
280 | data32 <<= 4; | ||
262 | 281 | ||
263 | u32 data32 = | 282 | u8 ch = (ch1 & 1) | ((ch2 & 1) << 1); |
264 | (lut_expand[sprline1] * (color & 3)) | 283 | data32 |= blending[ch][color]; |
265 | + (lut_expand[sprline2] * ((color & 1) << 1)) | ||
266 | + colconst; | ||
267 | u64 data = ((u64) (data32 & 0x33333333)) << shift; | ||
268 | 284 | ||
269 | layerptr[0] = (layerptr[0] & mask) | data; | 285 | ch1 >>= 1; ch2 >>= 1; |
270 | layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | 286 | } |
287 | } else { | ||
288 | for (h = 0; h < 8; h++) { | ||
289 | data32 <<= 4; | ||
271 | 290 | ||
272 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | 291 | u8 ch = (ch1 >> 7) | ((ch2 >> 7) << 1); |
273 | } | 292 | data32 |= blending[ch][color]; |
274 | 293 | ||
275 | dirty_tiles[y >> 3] |= dirtyflag; | 294 | ch1 <<= 1; ch2 <<= 1; |
276 | dirty_tiles[(y + 7) >> 3] |= dirtyflag; | 295 | } |
296 | } | ||
297 | |||
298 | u64 data = ((u64) (data32 & 0x33333333)) << shift; | ||
299 | |||
300 | layerptr[0] = (layerptr[0] & mask) | data; | ||
301 | if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | ||
302 | |||
303 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | ||
304 | } | ||
305 | } else { | ||
306 | for (v = 0; v < 8; v++, layerptr++) { | ||
307 | if ((y + v) >= (24 * 8)) break; | ||
308 | |||
309 | u8 ch1 = sprite[v ^ flipy]; | ||
310 | u8 ch2 = sprite[(v ^ flipy) | 8]; | ||
311 | u32 data32 = 0; | ||
312 | u32 mask32 = 0; | ||
313 | |||
314 | if (!flipx) { | ||
315 | for (h = 0; h < 8; h++) { | ||
316 | data32 <<= 4; mask32 <<= 4; | ||
317 | |||
318 | if ((ch1 | ch2) & 1) { | ||
319 | u8 ch = (ch1 & 1) | ((ch2 & 1) << 1); | ||
320 | data32 |= blending[ch][color]; | ||
321 | mask32 |= 0xF; | ||
322 | } | ||
323 | |||
324 | ch1 >>= 1; ch2 >>= 1; | ||
325 | } | ||
326 | } else { | ||
327 | for (h = 0; h < 8; h++) { | ||
328 | data32 <<= 4; mask32 <<= 4; | ||
329 | |||
330 | if ((ch1 | ch2) & 128) { | ||
331 | u8 ch = (ch1 >> 7) | ((ch2 >> 7) << 1); | ||
332 | data32 |= blending[ch][color]; | ||
333 | mask32 |= 0xF; | ||
334 | } | ||
335 | |||
336 | ch1 <<= 1; ch2 <<= 1; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | u64 data = ((u64) (data32 & 0x33333333)) << shift; | ||
341 | u64 mask = ~(((u64) (mask32 & 0x33333333)) << shift); | ||
342 | |||
343 | layerptr[0] = (layerptr[0] & mask) | data; | ||
344 | if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); | ||
345 | |||
346 | if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | dirty_tiles[y >> 3] |= dirtyflag; | ||
351 | dirty_tiles[(y + 7) >> 3] |= dirtyflag; | ||
352 | } | ||
353 | |||
354 | IWRAM_CODE | ||
355 | void | ||
356 | putfontchar(u32 *layer, u16 tile_x, u16 tile_y, u8 ch, u8 color) { | ||
357 | u32 pos = (tile_x + tile_y * 32) * 8; | ||
358 | u32 *tile_data = &layer[pos]; | ||
359 | u32 *font_data = &FONT_DATA[8 * ch]; | ||
360 | for (size_t i = 0; i < 8; ++i) { | ||
361 | tile_data[i] = font_data[i] * color; | ||
362 | } | ||
363 | dirty_tiles[tile_y] |= 1 << tile_x; | ||
277 | } | 364 | } |
278 | 365 | ||
279 | IWRAM_CODE | 366 | IWRAM_CODE |
@@ -24,7 +24,7 @@ typedef struct Ppu { | |||
24 | 24 | ||
25 | int initppu(Ppu *p, u8 hor, u8 ver, u8 pad); | 25 | int initppu(Ppu *p, u8 hor, u8 ver, u8 pad); |
26 | void putcolors(u8 *addr); | 26 | void putcolors(u8 *addr); |
27 | void putpixel(u32 *layer, u16 x, u16 y, u8 color); | 27 | void ppu_pixel(u32 *layer, u16 x, u16 y, u8 color); |
28 | void puticn(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); | 28 | void ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); |
29 | void putchr(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); | 29 | void ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); |
30 | #endif // UXNGBA_PPU_H | 30 | #endif // UXNGBA_PPU_H |