diff --git a/Makefile b/Makefile index cfdf43f..203e1d3 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ BASE_UXN := src/uxn/src SRC_DIR ?= src BUILD_DIR ?= build SRC_MAIN ?= $(SRC_DIR)/main.c -EXE_NAME ?= fbtest +EXE_NAME ?= uxnfb BIN := $(BUILD_DIR)/$(EXE_NAME) UXN_HEAD := $(BASE_UXN)/uxn.h diff --git a/src/main.c b/src/main.c index 73a74e1..7d77051 100644 --- a/src/main.c +++ b/src/main.c @@ -89,22 +89,56 @@ system_talk(Device *d, u8 b0, u8 w) { void screen_talk(Device *d, u8 b0, u8 w) { - if(w && b0 == 0xe) { - Uint16 x = mempeek16(d->dat, 0x8); - Uint16 y = mempeek16(d->dat, 0xa); - Uint8 layer = d->dat[0xe] >> 4 & 0x1; - ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); - reqdraw = 1; - } else if(w && b0 == 0xf) { - Uint16 x = mempeek16(d->dat, 0x8); - Uint16 y = mempeek16(d->dat, 0xa); - Uint8 layer = d->dat[0xf] >> 0x6 & 0x1; - Uint8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; - if(d->dat[0xf] >> 0x7 & 0x1) - ppu_2bpp(layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); - else - ppu_1bpp(layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); - reqdraw = 1; + if (w) { + switch (b0) { + case 0x1: { + d->vector = mempeek16(d->dat, 0x0); + } break; + case 0xe: { + u16 x = mempeek16(d->dat, 0x8); + u16 y = mempeek16(d->dat, 0xa); + u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; + u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg; + u8 mode = d->dat[0xe] >> 5; + u8 color = d->dat[0xf] & 0xf; + if(!mode) { + ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); + } else if(mode-- & 0x1) { + u8 flipx = mode & 0x2; + u8 flipy = mode & 0x4; + ppu_1bpp(layer, x, y, addr, color, flipx, flipy); + } else { + u8 flipx = mode & 0x2; + u8 flipy = mode & 0x4; + ppu_2bpp(layer, x, y, addr, color, flipx, flipy); + } + if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); } + if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); } + } break; + case 0xf: { + u16 x = mempeek16(d->dat, 0x8); + u16 y = mempeek16(d->dat, 0xa); + u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; + u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg; + u8 color = d->dat[0xf] & 0xf; + u8 flipx = (d->dat[0xf] >> 0x4) & 0x1; + u8 flipy = (d->dat[0xf] >> 0x5) & 0x1; + if(d->dat[0xf] >> 0x7 & 0x1) { + ppu_2bpp(layer, x, y, addr, color, flipx, flipy); + if(d->dat[0x6] & 0x04) { + mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16); + } + } else { + ppu_1bpp(layer, x, y, addr, color, flipx, flipy); + if(d->dat[0x6] & 0x04) { + mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8); + } + } + if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); } + if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); } + } break; + default: break; + } } } diff --git a/src/ppu.c b/src/ppu.c index 19e530b..a8d7dc6 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -21,7 +21,8 @@ static size_t screen_height = 0; static u32 *framebuffer = 0; static u32 palette[16]; -static u8 *pixels_buf; +static u8 *pixels_fg; +static u8 *pixels_bg; static u8 *dirty_lines; static u8 reqdraw = 0; // TODO: Probably should consider this @@ -35,17 +36,18 @@ static u8 blending[5][16] = { {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; void -ppu_pixel(u8 layer, u16 x, u16 y, u8 color) { - size_t idx = y * screen_width + x; - u8 *pixel = &pixels_buf[idx], shift = layer * 2; - if(x < screen_width && y < screen_height) { - *pixel = (*pixel & ~(0x3 << shift)) | (color << shift); - } +ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { + if(x < screen_width && y < screen_height) { + Uint32 i = x + y *screen_width; + if(color != layer[i]) { + layer[i] = color; + } + } dirty_lines[y] |= 1; } void -ppu_1bpp(u8 layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { +ppu_1bpp(u8 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { u16 v, h; for(v = 0; v < 8; v++) for(h = 0; h < 8; h++) { @@ -59,7 +61,7 @@ ppu_1bpp(u8 layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { } void -ppu_2bpp(u8 layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { +ppu_2bpp(u8 *layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) { u16 v, h; for(v = 0; v < 8; v++) for(h = 0; h < 8; h++) { @@ -106,7 +108,8 @@ ppu_init(void) { } // Allocate intermediate buffers. - pixels_buf = malloc(screen_width * screen_height); + pixels_fg = malloc(screen_width * screen_height); + pixels_bg = malloc(screen_width * screen_height); dirty_lines = malloc(screen_height); // Initialize default palette. @@ -116,7 +119,8 @@ ppu_init(void) { palette[3] = 0xff7777; // Clear pixel buffer memory. - memset(pixels_buf, 0, screen_width * screen_height); + memset(pixels_fg, 0, screen_width * screen_height); + memset(pixels_bg, 0, screen_width * screen_height); memset(dirty_lines, 1, screen_height); // Make sure we perform an initial screen drawing. @@ -135,7 +139,7 @@ blit_framebuffer(void) { if (dirty_lines[j] != 0) { for (size_t i = 0; i < screen_width; i++) { size_t idx = i + j * screen_width; - framebuffer[idx] = palette[pixels_buf[idx] % 16]; + framebuffer[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; } } dirty_lines[j] = 0; diff --git a/src/ppu.h b/src/ppu.h index 852c207..1c427c3 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -15,6 +15,6 @@ typedef unsigned short Uint16; typedef unsigned int Uint32; int ppu_init(void); -void ppu_pixel(Uint8 layer, Uint16 x, Uint16 y, Uint8 color); -void ppu_1bpp(Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); -void ppu_2bpp(Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); +void ppu_pixel(Uint8 *layer, Uint16 x, Uint16 y, Uint8 color); +void ppu_1bpp(Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); +void ppu_2bpp(Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); diff --git a/src/uxn.h b/src/uxn.h index e904e24..94dda0b 100644 --- a/src/uxn.h +++ b/src/uxn.h @@ -29,6 +29,7 @@ typedef struct { typedef struct Device { struct Uxn *u; Uint8 addr, dat[16], *mem; + u16 vector; void (*talk)(struct Device *d, Uint8, Uint8); } Device;