From 232f303cf139ec7aa0b3af1c89003c3f01a9f25b Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 4 Mar 2022 15:16:29 +0100 Subject: [PATCH] Port uxnrpi main function --- src/main.c | 191 +++++++++++++++++++++++++++++++++++++++++++++-------- src/ppu.c | 2 +- 2 files changed, 166 insertions(+), 27 deletions(-) diff --git a/src/main.c b/src/main.c index aabf79f..73a74e1 100644 --- a/src/main.c +++ b/src/main.c @@ -13,37 +13,176 @@ #include "uxn-fast.c" #include "rom.c" -// static Uxn u; -// static Device *devscreen; -// static Device *devctrl; -// static Device *devmouse; -// static Device *devaudio; +static Uxn u; +static Device *devscreen; +static Device *devctrl; +static Device *devmouse; +static Device *devaudio; + +void +nil_talk(Device *d, u8 b0, u8 w) { + (void)d; + (void)b0; + (void)w; +} + +void +console_talk(Device *d, u8 b0, u8 w) { + (void)d; + (void)b0; + (void)w; + // char stmp[2]; + // if(!w) { + // return; + // } + // switch(b0) { + // case 0x8: stmp[0] = d->dat[0x8]; stmp[1] = 0; uart_puts(stmp); break; + // TODO: implement printf for the uart to be able to format + // numbers. + // case 0x9: txt_printf("0x%02x", d->dat[0x9]); break; + // case 0xb: txt_printf("0x%04x", mempeek16(d->dat, 0xa)); break; + // case 0xd: txt_printf("%s", &d->mem[mempeek16(d->dat, 0xc)]); break; + // } +} + +static void +docolors(Device *d) { + for(size_t i = 0; i < 4; ++i) { + u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; + u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; + u8 b = ((d->dat[0xc + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; + + if (rgb_order) { + palette[i] = (b << 16) | (g << 8) | r; + } else { + palette[i] = (r << 16) | (g << 8) | b; + } + } + for(size_t i = 4; i < 16; ++i) { + palette[i] = palette[i / 4]; + } + + // Redraw the screen if we change the color palette. + reqdraw = 1; + redraw_screen(); +} + +void +system_talk(Device *d, u8 b0, u8 w) { + if(!w) { /* read */ + switch(b0) { + case 0x2: d->dat[0x2] = d->u->wst.ptr; break; + case 0x3: d->dat[0x3] = d->u->rst.ptr; break; + } + } else { /* write */ + switch(b0) { + case 0x2: d->u->wst.ptr = d->dat[0x2]; break; + case 0x3: d->u->rst.ptr = d->dat[0x3]; break; + case 0xf: d->u->ram.ptr = 0x0000; break; + } + if(b0 > 0x7 && b0 < 0xe) { + docolors(d); + } + } + (void)b0; +} + +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; + } +} + +static void +audio_talk(Device *d, u8 b0, u8 w) { + // TODO: Implement... + (void)d; + (void)b0; + (void)w; +} + +void +datetime_talk(Device *d, u8 b0, u8 w) { + // TODO: Implement... + (void)d; + (void)b0; + (void)w; +} + +void +file_talk(Device *d, u8 b0, u8 w) { + // TODO: Implement... + (void)d; + (void)b0; + (void)w; +} + +void +init_uxn() { + // Clear UXN memory. + memset(&u, 0, sizeof(Uxn)); + + ppu_init(); + + // Copy rom to VM. + memcpy(u.ram.dat + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); + + // Prepare devices. + uxn_port(&u, 0x0, "system", system_talk); + uxn_port(&u, 0x1, "console", console_talk); + devscreen = uxn_port(&u, 0x2, "screen", screen_talk); + devaudio = uxn_port(&u, 0x3, "audio0", audio_talk); + uxn_port(&u, 0x4, "audio1", audio_talk); + uxn_port(&u, 0x5, "audio2", audio_talk); + uxn_port(&u, 0x6, "audio3", audio_talk); + uxn_port(&u, 0x7, "---", nil_talk); + devctrl = uxn_port(&u, 0x8, "controller", nil_talk); + devmouse = uxn_port(&u, 0x9, "mouse", nil_talk); + uxn_port(&u, 0xa, "file", file_talk); + uxn_port(&u, 0xb, "datetime", datetime_talk); + uxn_port(&u, 0xc, "---", nil_talk); + uxn_port(&u, 0xd, "---", nil_talk); + uxn_port(&u, 0xe, "---", nil_talk); + uxn_port(&u, 0xf, "---", nil_talk); + mempoke16(devscreen->dat, 2, screen_width); + mempoke16(devscreen->dat, 4, screen_height); +} int main(void) { - ppu_init(); + init_uxn(); // Main loop. - uint8_t shade = 0; - size_t counter = 0; - size_t direction = 1; - while (true) { - for (size_t j = 0; j < screen_height; j++) { - for (size_t i = 0; i < screen_width; i++) { - framebuffer[j * screen_width + i] = shade; - } - } - counter++; - if (counter > 10) { - shade += direction; - counter = 0; - } - if (shade == 0xFF) { - direction = -1; - } else if (shade == 0x00) { - direction = 1; - } - } + uxn_eval(&u, 0x0100); + // u64 current_ticks = timer_get_ticks(); + while (true) { + // Echo input to standard output. + uxn_eval(&u, mempeek16(devscreen->dat, 0)); + + // Blit ppu.pixels to the framebuffer. + blit_framebuffer(); + + // TODO: Sync at 60 Hz. + // if ((timer_get_ticks() - current_ticks) < 16666) { + // wait(16666 - (timer_get_ticks() - current_ticks)); + // } + // current_ticks = timer_get_ticks(); + } return 0; } diff --git a/src/ppu.c b/src/ppu.c index 6c38ab6..19e530b 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -25,7 +25,7 @@ static u8 *pixels_buf; static u8 *dirty_lines; static u8 reqdraw = 0; // TODO: Probably should consider this -// static u32 rgb_order; +static u32 rgb_order = 0; static u8 blending[5][16] = { {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},