diff options
author | Bad Diode <bd@badd10de.dev> | 2022-03-04 18:43:38 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-03-04 18:43:38 +0100 |
commit | 6b29a0cb080aa7e8fad9de8943d2637437cad53d (patch) | |
tree | f0d107f88f0af53cf145039ea172e0921977a110 | |
parent | 87ce7bbb4b5812e672b4912cc0c981a8037c2cd6 (diff) | |
download | uxnfb-6b29a0cb080aa7e8fad9de8943d2637437cad53d.tar.gz uxnfb-6b29a0cb080aa7e8fad9de8943d2637437cad53d.zip |
Sync updates at 60hz
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/main.c | 153 |
2 files changed, 85 insertions, 70 deletions
@@ -6,7 +6,7 @@ EXE_NAME ?= uxnfb | |||
6 | BIN := $(BUILD_DIR)/$(EXE_NAME) | 6 | BIN := $(BUILD_DIR)/$(EXE_NAME) |
7 | UXN_HEAD := $(BASE_UXN)/src/uxn.h | 7 | UXN_HEAD := $(BASE_UXN)/src/uxn.h |
8 | TAL_SRC ?= $(BASE_UXN)/projects/examples/devices/screen.tal | 8 | TAL_SRC ?= $(BASE_UXN)/projects/examples/devices/screen.tal |
9 | UXN_ROM ?= $(BUILD_DIR)/screen.rom | 9 | UXN_ROM ?= $(BUILD_DIR)/rom.rom |
10 | UXN_ASM ?= $(BUILD_DIR)/uxnasm | 10 | UXN_ASM ?= $(BUILD_DIR)/uxnasm |
11 | 11 | ||
12 | CC ?= cc | 12 | CC ?= cc |
@@ -1,9 +1,11 @@ | |||
1 | #include <fcntl.h> | ||
2 | #include <stdbool.h> | ||
3 | #include <stdint.h> | ||
1 | #include <stdio.h> | 4 | #include <stdio.h> |
2 | #include <stdlib.h> | 5 | #include <stdlib.h> |
3 | #include <stdint.h> | 6 | #include <time.h> |
4 | #include <stdbool.h> | ||
5 | #include <unistd.h> | 7 | #include <unistd.h> |
6 | #include <fcntl.h> | 8 | |
7 | #include <linux/fb.h> | 9 | #include <linux/fb.h> |
8 | #include <sys/ioctl.h> | 10 | #include <sys/ioctl.h> |
9 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
@@ -18,6 +20,21 @@ static Device *devctrl; | |||
18 | static Device *devmouse; | 20 | static Device *devmouse; |
19 | static Device *devaudio; | 21 | static Device *devaudio; |
20 | 22 | ||
23 | typedef struct timespec Time; | ||
24 | |||
25 | Time | ||
26 | time_now(){ | ||
27 | struct timespec t; | ||
28 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); | ||
29 | return t; | ||
30 | } | ||
31 | |||
32 | size_t | ||
33 | time_elapsed(Time since){ | ||
34 | struct timespec now = time_now(); | ||
35 | return (now.tv_sec - since.tv_sec) * 1e9 + (now.tv_nsec - since.tv_nsec); | ||
36 | } | ||
37 | |||
21 | void | 38 | void |
22 | nil_talk(Device *d, u8 b0, u8 w) { | 39 | nil_talk(Device *d, u8 b0, u8 w) { |
23 | (void)d; | 40 | (void)d; |
@@ -36,11 +53,11 @@ console_talk(Device *d, u8 b0, u8 w) { | |||
36 | // } | 53 | // } |
37 | // switch(b0) { | 54 | // switch(b0) { |
38 | // case 0x8: stmp[0] = d->dat[0x8]; stmp[1] = 0; uart_puts(stmp); break; | 55 | // case 0x8: stmp[0] = d->dat[0x8]; stmp[1] = 0; uart_puts(stmp); break; |
39 | // TODO: implement printf for the uart to be able to format | 56 | // TODO: implement printf for the uart to be able to format |
40 | // numbers. | 57 | // numbers. |
41 | // case 0x9: txt_printf("0x%02x", d->dat[0x9]); break; | 58 | // case 0x9: txt_printf("0x%02x", d->dat[0x9]); break; |
42 | // case 0xb: txt_printf("0x%04x", mempeek16(d->dat, 0xa)); break; | 59 | // case 0xb: txt_printf("0x%04x", mempeek16(d->dat, 0xa)); break; |
43 | // case 0xd: txt_printf("%s", &d->mem[mempeek16(d->dat, 0xc)]); break; | 60 | // case 0xd: txt_printf("%s", &d->mem[mempeek16(d->dat, 0xc)]); break; |
44 | // } | 61 | // } |
45 | } | 62 | } |
46 | 63 | ||
@@ -70,14 +87,14 @@ void | |||
70 | system_talk(Device *d, u8 b0, u8 w) { | 87 | system_talk(Device *d, u8 b0, u8 w) { |
71 | if(!w) { /* read */ | 88 | if(!w) { /* read */ |
72 | switch(b0) { | 89 | switch(b0) { |
73 | case 0x2: d->dat[0x2] = d->u->wst.ptr; break; | 90 | case 0x2: d->dat[0x2] = d->u->wst.ptr; break; |
74 | case 0x3: d->dat[0x3] = d->u->rst.ptr; break; | 91 | case 0x3: d->dat[0x3] = d->u->rst.ptr; break; |
75 | } | 92 | } |
76 | } else { /* write */ | 93 | } else { /* write */ |
77 | switch(b0) { | 94 | switch(b0) { |
78 | case 0x2: d->u->wst.ptr = d->dat[0x2]; break; | 95 | case 0x2: d->u->wst.ptr = d->dat[0x2]; break; |
79 | case 0x3: d->u->rst.ptr = d->dat[0x3]; break; | 96 | case 0x3: d->u->rst.ptr = d->dat[0x3]; break; |
80 | case 0xf: d->u->ram.ptr = 0x0000; break; | 97 | case 0xf: d->u->ram.ptr = 0x0000; break; |
81 | } | 98 | } |
82 | if(b0 > 0x7 && b0 < 0xe) { | 99 | if(b0 > 0x7 && b0 < 0xe) { |
83 | docolors(d); | 100 | docolors(d); |
@@ -91,51 +108,51 @@ screen_talk(Device *d, u8 b0, u8 w) { | |||
91 | if (w) { | 108 | if (w) { |
92 | switch (b0) { | 109 | switch (b0) { |
93 | case 0x1: { | 110 | case 0x1: { |
94 | d->vector = mempeek16(d->dat, 0x0); | 111 | d->vector = mempeek16(d->dat, 0x0); |
95 | } break; | 112 | } break; |
96 | case 0xe: { | 113 | case 0xe: { |
97 | u16 x = mempeek16(d->dat, 0x8); | 114 | u16 x = mempeek16(d->dat, 0x8); |
98 | u16 y = mempeek16(d->dat, 0xa); | 115 | u16 y = mempeek16(d->dat, 0xa); |
99 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; | 116 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; |
100 | u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg; | 117 | u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg; |
101 | u8 mode = d->dat[0xe] >> 5; | 118 | u8 mode = d->dat[0xe] >> 5; |
102 | u8 color = d->dat[0xf] & 0xf; | 119 | u8 color = d->dat[0xf] & 0xf; |
103 | if(!mode) { | 120 | if(!mode) { |
104 | ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); | 121 | ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); |
105 | } else if(mode-- & 0x1) { | 122 | } else if(mode-- & 0x1) { |
106 | u8 flipx = mode & 0x2; | 123 | u8 flipx = mode & 0x2; |
107 | u8 flipy = mode & 0x4; | 124 | u8 flipy = mode & 0x4; |
108 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); | 125 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); |
109 | } else { | 126 | } else { |
110 | u8 flipx = mode & 0x2; | 127 | u8 flipx = mode & 0x2; |
111 | u8 flipy = mode & 0x4; | 128 | u8 flipy = mode & 0x4; |
112 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); | 129 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); |
113 | } | 130 | } |
114 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); } | 131 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); } |
115 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); } | 132 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); } |
116 | } break; | 133 | } break; |
117 | case 0xf: { | 134 | case 0xf: { |
118 | u16 x = mempeek16(d->dat, 0x8); | 135 | u16 x = mempeek16(d->dat, 0x8); |
119 | u16 y = mempeek16(d->dat, 0xa); | 136 | u16 y = mempeek16(d->dat, 0xa); |
120 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; | 137 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; |
121 | u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg; | 138 | u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg; |
122 | u8 color = d->dat[0xf] & 0xf; | 139 | u8 color = d->dat[0xf] & 0xf; |
123 | u8 flipx = (d->dat[0xf] >> 0x4) & 0x1; | 140 | u8 flipx = (d->dat[0xf] >> 0x4) & 0x1; |
124 | u8 flipy = (d->dat[0xf] >> 0x5) & 0x1; | 141 | u8 flipy = (d->dat[0xf] >> 0x5) & 0x1; |
125 | if(d->dat[0xf] >> 0x7 & 0x1) { | 142 | if(d->dat[0xf] >> 0x7 & 0x1) { |
126 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); | 143 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); |
127 | if(d->dat[0x6] & 0x04) { | 144 | if(d->dat[0x6] & 0x04) { |
128 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16); | 145 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16); |
129 | } | 146 | } |
130 | } else { | 147 | } else { |
131 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); | 148 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); |
132 | if(d->dat[0x6] & 0x04) { | 149 | if(d->dat[0x6] & 0x04) { |
133 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8); | 150 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8); |
134 | } | 151 | } |
135 | } | 152 | } |
136 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); } | 153 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); } |
137 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); } | 154 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); } |
138 | } break; | 155 | } break; |
139 | default: break; | 156 | default: break; |
140 | } | 157 | } |
141 | } | 158 | } |
@@ -226,22 +243,20 @@ main(int argc, char *argv[]) { | |||
226 | } | 243 | } |
227 | init_uxn(argv[1]); | 244 | init_uxn(argv[1]); |
228 | 245 | ||
229 | // Main loop. | 246 | // Main loop. |
230 | uxn_eval(&u, 0x0100); | 247 | uxn_eval(&u, 0x0100); |
231 | // u64 current_ticks = timer_get_ticks(); | 248 | Time frame_time = time_now(); |
232 | while (true) { | 249 | while (true) { |
233 | // Echo input to standard output. | 250 | size_t elapsed = time_elapsed(frame_time); |
234 | uxn_eval(&u, mempeek16(devscreen->dat, 0)); | 251 | if (elapsed >= 16666666) { |
235 | 252 | // Echo input to standard output. | |
236 | // Blit ppu.pixels to the framebuffer. | 253 | uxn_eval(&u, mempeek16(devscreen->dat, 0)); |
237 | blit_framebuffer(); | ||
238 | 254 | ||
239 | // TODO: Sync at 60 Hz. | 255 | // Blit ppu.pixels to the framebuffer. |
240 | // if ((timer_get_ticks() - current_ticks) < 16666) { | 256 | blit_framebuffer(); |
241 | // wait(16666 - (timer_get_ticks() - current_ticks)); | 257 | frame_time = time_now(); |
242 | // } | 258 | } |
243 | // current_ticks = timer_get_ticks(); | ||
244 | } | 259 | } |
245 | 260 | ||
246 | return 0; | 261 | return 0; |
247 | } | 262 | } |