diff --git a/Makefile b/Makefile index 8de6bb0..3d41a4a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ EXE_NAME ?= uxnfb BIN := $(BUILD_DIR)/$(EXE_NAME) UXN_HEAD := $(BASE_UXN)/src/uxn.h TAL_SRC ?= $(BASE_UXN)/projects/examples/devices/screen.tal -UXN_ROM ?= $(BUILD_DIR)/screen.rom +UXN_ROM ?= $(BUILD_DIR)/rom.rom UXN_ASM ?= $(BUILD_DIR)/uxnasm CC ?= cc diff --git a/src/main.c b/src/main.c index 1a4d6f6..e213bbb 100644 --- a/src/main.c +++ b/src/main.c @@ -1,9 +1,11 @@ +#include +#include +#include #include #include -#include -#include +#include #include -#include + #include #include #include @@ -18,6 +20,21 @@ static Device *devctrl; static Device *devmouse; static Device *devaudio; +typedef struct timespec Time; + +Time +time_now(){ + struct timespec t; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); + return t; +} + +size_t +time_elapsed(Time since){ + struct timespec now = time_now(); + return (now.tv_sec - since.tv_sec) * 1e9 + (now.tv_nsec - since.tv_nsec); +} + void nil_talk(Device *d, u8 b0, u8 w) { (void)d; @@ -36,11 +53,11 @@ console_talk(Device *d, u8 b0, u8 w) { // } // 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; + // 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; // } } @@ -70,14 +87,14 @@ 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; + 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; + 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); @@ -91,51 +108,51 @@ screen_talk(Device *d, u8 b0, u8 w) { if (w) { switch (b0) { case 0x1: { - d->vector = mempeek16(d->dat, 0x0); - } break; + 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; + 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; + 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; } } @@ -226,22 +243,20 @@ main(int argc, char *argv[]) { } init_uxn(argv[1]); - // Main loop. + // Main loop. uxn_eval(&u, 0x0100); - // u64 current_ticks = timer_get_ticks(); + Time frame_time = time_now(); while (true) { - // Echo input to standard output. - uxn_eval(&u, mempeek16(devscreen->dat, 0)); + size_t elapsed = time_elapsed(frame_time); + if (elapsed >= 16666666) { + // 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(); + // Blit ppu.pixels to the framebuffer. + blit_framebuffer(); + frame_time = time_now(); + } } - return 0; + return 0; }