From de1ee4b04838fd41663f41dfca0532e5a1dc3648 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 8 Aug 2021 11:07:05 +0200 Subject: Port PPU changes from uxnds --- src/main.c | 6 +- src/ppu.c | 239 +++++++++++++++++++++++++++++++++++++++++-------------------- src/ppu.h | 6 +- 3 files changed, 169 insertions(+), 82 deletions(-) diff --git a/src/main.c b/src/main.c index 4b2b2d6..0e56897 100644 --- a/src/main.c +++ b/src/main.c @@ -136,11 +136,11 @@ screen_talk(Device *d, u8 b0, u8 w) { u8 *layer = d->dat[0xe] >> 4 & 0x1 ? ppu.fg : ppu.bg; u8 mode = d->dat[0xe] >> 5; if(!mode) { - putpixel(layer, x, y, d->dat[0xe] & 0x3); + ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); } else if(mode-- & 0x1) { - puticn(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); + ppu_1bpp(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); } else { - putchr(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); + ppu_2bpp(layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); } } } diff --git a/src/ppu.c b/src/ppu.c index f626604..018555f 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -25,7 +25,7 @@ WITH REGARD TO THIS SOFTWARE. // Keyboard. #define SPRITE_START_IDX 640 -static u32 unpack_icon_lut[256] = { +static u32 lut_2bpp[256] = { 0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111, 0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, @@ -80,7 +80,7 @@ static u32 unpack_icon_lut[256] = { 0x11111111 }; -static u32 unpack_icon_lut_flipx[256] = { +static u32 lut2bpp_flipx[256] = { 0x00000000, 0x10000000, 0x01000000, 0x11000000, 0x00100000, 0x10100000, 0x01100000, 0x11100000, 0x00010000, 0x10010000, 0x01010000, 0x11010000, 0x00110000, 0x10110000, 0x01110000, @@ -135,6 +135,14 @@ static u32 unpack_icon_lut_flipx[256] = { 0x11111111 }; +static u8 blending[5][16] = { + {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, + {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, + {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, + {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, + {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0} +}; + static u32 dirty_tiles[21] = {0}; void @@ -160,7 +168,7 @@ putcolors(u8 *addr) { IWRAM_CODE void -putpixel(u32 *layer, u16 x, u16 y, u8 color) { +ppu_pixel(u32 *layer, u16 x, u16 y, u8 color) { if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; size_t tile_x = x / 8; size_t tile_y = y / 8; @@ -174,106 +182,185 @@ putpixel(u32 *layer, u16 x, u16 y, u8 color) { IWRAM_CODE void -puticn(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { - u8 sprline; - u16 v; - u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); - - u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); - u32 *layerptr = &layer[layerpos]; - u32 shift = (x & 7) << 2; - u32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx; +ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { + u8 sprline; + u16 v; + u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); - if (flipy) flipy = 7; + u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); + u32 *layerptr = &layer[layerpos]; + u32 shift = (x & 7) << 2; + u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; - if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; + if (flipy) flipy = 7; - if (color != 0x05 && color != 0x0a && color != 0x0f) { - u64 mask = ~((u64)0xFFFFFFFF << shift); + if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; - for (v = 0; v < 8; v++, layerptr++) { - if ((y + v) >= SCREEN_HEIGHT) break; + if (blending[4][color]) { + u64 mask = ~((u64)0xFFFFFFFF << shift); - sprline = sprite[v ^ flipy]; - u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; - data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift; + for (v = 0; v < 8; v++, layerptr++) { + if ((y + v) >= SCREEN_HEIGHT) break; - layerptr[0] = (layerptr[0] & mask) | data; - layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + sprline = sprite[v ^ flipy]; + u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; + data |= (u64)(lut_expand[sprline ^ 0xFF] * (color >> 2)) << shift; - if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; - } - } else { - for (v = 0; v < 8; v++, layerptr++) { - if ((y + v) >= SCREEN_HEIGHT) break; + layerptr[0] = (layerptr[0] & mask) | data; + layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); - sprline = sprite[v ^ flipy]; - u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift); - u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; + if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; + } + } else { + for (v = 0; v < 8; v++, layerptr++) { + if ((y + v) >= SCREEN_HEIGHT) break; - layerptr[0] = (layerptr[0] & mask) | data; - layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + sprline = sprite[v ^ flipy]; + u64 mask = ~((u64)(lut_expand[sprline] * 0xF) << shift); + u64 data = (u64)(lut_expand[sprline] * (color & 3)) << shift; - if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; - } - } + layerptr[0] = (layerptr[0] & mask) | data; + layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); - dirty_tiles[y >> 3] |= dirtyflag; - dirty_tiles[(y + 7) >> 3] |= dirtyflag; -} + if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; + } + } -IWRAM_CODE -void -putfontchar(u32 *layer, u16 tile_x, u16 tile_y, u8 ch, u8 color) { - u32 pos = (tile_x + tile_y * 32) * 8; - u32 *tile_data = &layer[pos]; - u32 *font_data = &FONT_DATA[8 * ch]; - for (size_t i = 0; i < 8; ++i) { - tile_data[i] = font_data[i] * color; - } - dirty_tiles[tile_y] |= 1 << tile_x; + dirty_tiles[y >> 3] |= dirtyflag; + dirty_tiles[(y + 7) >> 3] |= dirtyflag; } IWRAM_CODE void -putchr(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, +ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { - u8 sprline1, sprline2; - u16 v; - u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); + u8 sprline1, sprline2; + u8 xrightedge = x < ((32 - 1) * 8); + u16 v, h; + u32 dirtyflag = (1 << (x >> 3)) | (1 << ((x + 7) >> 3)); + + u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); + u32 *layerptr = &layer[layerpos]; + u32 shift = (x & 7) << 2; + + if (flipy) flipy = 7; + + if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; + + if (color == 1) { + u32 *lut_expand = flipx ? lut_2bpp : lut2bpp_flipx; + u64 mask = ~((u64)0xFFFFFFFF << shift); + + for (v = 0; v < 8; v++, layerptr++) { + if ((y + v) >= (24 * 8)) break; - u32 layerpos = ((y & 7) + (((x >> 3) + (y >> 3) * 32) * 8)); - u32 *layerptr = &layer[layerpos]; - u32 shift = (x & 7) << 2; - u32 *lut_expand = flipx ? unpack_icon_lut : unpack_icon_lut_flipx; + sprline1 = sprite[v ^ flipy]; + sprline2 = sprite[(v ^ flipy) | 8]; - if (flipy) flipy = 7; + u32 data32 = (lut_expand[sprline1]) | (lut_expand[sprline2] << 1); + u64 data = ((u64) (data32 & 0x33333333)) << shift; - if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; + layerptr[0] = (layerptr[0] & mask) | data; + if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + + if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; + } + } else if (blending[4][color]) { + u64 mask = ~((u64)0xFFFFFFFF << shift); - u64 mask = ~((u64)0xFFFFFFFF << shift); - u32 colconst = (color >> 2) * 0x11111111; + for (v = 0; v < 8; v++, layerptr++) { + if ((y + v) >= (24 * 8)) break; - for (v = 0; v < 8; v++, layerptr++) { - if ((y + v) >= SCREEN_HEIGHT) break; + u8 ch1 = sprite[v ^ flipy]; + u8 ch2 = sprite[(v ^ flipy) | 8]; + u32 data32 = 0; - sprline1 = sprite[v ^ flipy]; - sprline2 = sprite[(v ^ flipy) | 8]; + if (!flipx) { + for (h = 0; h < 8; h++) { + data32 <<= 4; - u32 data32 = - (lut_expand[sprline1] * (color & 3)) - + (lut_expand[sprline2] * ((color & 1) << 1)) - + colconst; - u64 data = ((u64) (data32 & 0x33333333)) << shift; + u8 ch = (ch1 & 1) | ((ch2 & 1) << 1); + data32 |= blending[ch][color]; - layerptr[0] = (layerptr[0] & mask) | data; - layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + ch1 >>= 1; ch2 >>= 1; + } + } else { + for (h = 0; h < 8; h++) { + data32 <<= 4; - if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; - } + u8 ch = (ch1 >> 7) | ((ch2 >> 7) << 1); + data32 |= blending[ch][color]; - dirty_tiles[y >> 3] |= dirtyflag; - dirty_tiles[(y + 7) >> 3] |= dirtyflag; + ch1 <<= 1; ch2 <<= 1; + } + } + + u64 data = ((u64) (data32 & 0x33333333)) << shift; + + layerptr[0] = (layerptr[0] & mask) | data; + if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + + if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; + } + } else { + for (v = 0; v < 8; v++, layerptr++) { + if ((y + v) >= (24 * 8)) break; + + u8 ch1 = sprite[v ^ flipy]; + u8 ch2 = sprite[(v ^ flipy) | 8]; + u32 data32 = 0; + u32 mask32 = 0; + + if (!flipx) { + for (h = 0; h < 8; h++) { + data32 <<= 4; mask32 <<= 4; + + if ((ch1 | ch2) & 1) { + u8 ch = (ch1 & 1) | ((ch2 & 1) << 1); + data32 |= blending[ch][color]; + mask32 |= 0xF; + } + + ch1 >>= 1; ch2 >>= 1; + } + } else { + for (h = 0; h < 8; h++) { + data32 <<= 4; mask32 <<= 4; + + if ((ch1 | ch2) & 128) { + u8 ch = (ch1 >> 7) | ((ch2 >> 7) << 1); + data32 |= blending[ch][color]; + mask32 |= 0xF; + } + + ch1 <<= 1; ch2 <<= 1; + } + } + + u64 data = ((u64) (data32 & 0x33333333)) << shift; + u64 mask = ~(((u64) (mask32 & 0x33333333)) << shift); + + layerptr[0] = (layerptr[0] & mask) | data; + if (xrightedge) layerptr[8] = (layerptr[8] & (mask >> 32)) | (data >> 32); + + if (((y + v) & 7) == 7) layerptr += (32 - 1) * 8; + } + } + + dirty_tiles[y >> 3] |= dirtyflag; + dirty_tiles[(y + 7) >> 3] |= dirtyflag; +} + +IWRAM_CODE +void +putfontchar(u32 *layer, u16 tile_x, u16 tile_y, u8 ch, u8 color) { + u32 pos = (tile_x + tile_y * 32) * 8; + u32 *tile_data = &layer[pos]; + u32 *font_data = &FONT_DATA[8 * ch]; + for (size_t i = 0; i < 8; ++i) { + tile_data[i] = font_data[i] * color; + } + dirty_tiles[tile_y] |= 1 << tile_x; } IWRAM_CODE diff --git a/src/ppu.h b/src/ppu.h index 0356b63..b5eb250 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -24,7 +24,7 @@ typedef struct Ppu { int initppu(Ppu *p, u8 hor, u8 ver, u8 pad); void putcolors(u8 *addr); -void putpixel(u32 *layer, u16 x, u16 y, u8 color); -void puticn(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); -void putchr(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); +void ppu_pixel(u32 *layer, u16 x, u16 y, u8 color); +void ppu_1bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); +void ppu_2bpp(u32 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy); #endif // UXNGBA_PPU_H -- cgit v1.2.1