aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-03-05 22:30:05 +0100
committerBad Diode <bd@badd10de.dev>2022-03-05 22:30:05 +0100
commit4aa83a8de5e5b131ddcabc920536d9b807b608ca (patch)
treeec21c58f04d3bea23fd2859e6733075e7d7b1ccc
parentc046d2a0a97c71035001a654b445de8c0f9dc933 (diff)
downloaduxnfb-4aa83a8de5e5b131ddcabc920536d9b807b608ca.tar.gz
uxnfb-4aa83a8de5e5b131ddcabc920536d9b807b608ca.zip
[WIP] Update core to current uxn version
-rw-r--r--src/main.c544
1 files changed, 260 insertions, 284 deletions
diff --git a/src/main.c b/src/main.c
index e0b3445..2c7fe03 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,7 +10,8 @@
10 10
11#include "shorthand.h" 11#include "shorthand.h"
12#include "ppu.c" 12#include "ppu.c"
13#include "uxn-fast.c" 13#include "uxn/src/devices/system.c"
14#include "uxn/src/uxn.c"
14 15
15#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) 16#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
16 17
@@ -18,7 +19,6 @@ static Uxn u;
18static Device *devscreen; 19static Device *devscreen;
19static Device *devctrl; 20static Device *devctrl;
20static Device *devmouse; 21static Device *devmouse;
21static Device *devaudio;
22 22
23typedef struct timespec Time; 23typedef struct timespec Time;
24 24
@@ -142,168 +142,168 @@ poll_input(void) {
142 142
143void 143void
144handle_keyboard(void) { 144handle_keyboard(void) {
145 // Find mod keys. 145 // // Find mod keys.
146 bool shift_mod = false; 146 // bool shift_mod = false;
147 // bool ctrl_mod = false; 147 // // bool ctrl_mod = false;
148 // bool alt_mod = false; 148 // // bool alt_mod = false;
149 // bool meta_mod = false; 149 // // bool meta_mod = false;
150 for (size_t i = 0; i < sizeof(in.map); i++) { 150 // for (size_t i = 0; i < sizeof(in.map); i++) {
151 for (size_t j = 0; j < 8; j++) { 151 // for (size_t j = 0; j < 8; j++) {
152 char key = in.map[i] & (1 << j); 152 // char key = in.map[i] & (1 << j);
153 if (key) { 153 // if (key) {
154 char key_code = i * 8 + j; 154 // char key_code = i * 8 + j;
155 switch (key_code) { 155 // switch (key_code) {
156 case KEY_LEFTSHIFT: 156 // case KEY_LEFTSHIFT:
157 case KEY_RIGHTSHIFT: { shift_mod = true; } break; 157 // case KEY_RIGHTSHIFT: { shift_mod = true; } break;
158 // case KEY_LEFTCTRL: 158 // // case KEY_LEFTCTRL:
159 // case KEY_RIGHTCTRL: { ctrl_mod = true; } break; 159 // // case KEY_RIGHTCTRL: { ctrl_mod = true; } break;
160 // case KEY_LEFTALT: 160 // // case KEY_LEFTALT:
161 // case KEY_RIGHTALT: { alt_mod = true; } break; 161 // // case KEY_RIGHTALT: { alt_mod = true; } break;
162 // case KEY_LEFTMETA: 162 // // case KEY_LEFTMETA:
163 // case KEY_RIGHTMETA: { meta_mod = true; } break; 163 // // case KEY_RIGHTMETA: { meta_mod = true; } break;
164 default: break; 164 // default: break;
165 } 165 // }
166 } 166 // }
167 } 167 // }
168 } 168 // }
169 169
170 // Handle normal keys. 170 // // Handle normal keys.
171 u8 controller_now = 0; 171 // u8 controller_now = 0;
172 for (size_t i = 0; i < sizeof(in.map); i++) { 172 // for (size_t i = 0; i < sizeof(in.map); i++) {
173 for (size_t j = 0; j < 8; j++) { 173 // for (size_t j = 0; j < 8; j++) {
174 char key = in.map[i] & (1 << j); 174 // char key = in.map[i] & (1 << j);
175 if (key) { 175 // if (key) {
176 char key_code = i * 8 + j; 176 // char key_code = i * 8 + j;
177 // Normal keys. 177 // // Normal keys.
178 u8 rune = '\0'; 178 // u8 rune = '\0';
179 switch (key_code) { 179 // switch (key_code) {
180 case KEY_KP1: 180 // case KEY_KP1:
181 case KEY_1: { rune = shift_mod ? '!' : '1'; } break; 181 // case KEY_1: { rune = shift_mod ? '!' : '1'; } break;
182 case KEY_KP2: 182 // case KEY_KP2:
183 case KEY_2: { rune = shift_mod ? '@' : '2'; } break; 183 // case KEY_2: { rune = shift_mod ? '@' : '2'; } break;
184 case KEY_KP3: 184 // case KEY_KP3:
185 case KEY_3: { rune = shift_mod ? '#' : '3'; } break; 185 // case KEY_3: { rune = shift_mod ? '#' : '3'; } break;
186 case KEY_KP4: 186 // case KEY_KP4:
187 case KEY_4: { rune = shift_mod ? '$' : '4'; } break; 187 // case KEY_4: { rune = shift_mod ? '$' : '4'; } break;
188 case KEY_KP5: 188 // case KEY_KP5:
189 case KEY_5: { rune = shift_mod ? '%' : '5'; } break; 189 // case KEY_5: { rune = shift_mod ? '%' : '5'; } break;
190 case KEY_KP6: 190 // case KEY_KP6:
191 case KEY_6: { rune = shift_mod ? '^' : '6'; } break; 191 // case KEY_6: { rune = shift_mod ? '^' : '6'; } break;
192 case KEY_KP7: 192 // case KEY_KP7:
193 case KEY_7: { rune = shift_mod ? '&' : '7'; } break; 193 // case KEY_7: { rune = shift_mod ? '&' : '7'; } break;
194 case KEY_KP8: 194 // case KEY_KP8:
195 case KEY_8: { rune = shift_mod ? '*' : '8'; } break; 195 // case KEY_8: { rune = shift_mod ? '*' : '8'; } break;
196 case KEY_KP9: 196 // case KEY_KP9:
197 case KEY_9: { rune = shift_mod ? '(' : '9'; } break; 197 // case KEY_9: { rune = shift_mod ? '(' : '9'; } break;
198 case KEY_KP0: 198 // case KEY_KP0:
199 case KEY_0: { rune = shift_mod ? ')' : '0'; } break; 199 // case KEY_0: { rune = shift_mod ? ')' : '0'; } break;
200 case KEY_KPMINUS: 200 // case KEY_KPMINUS:
201 case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break; 201 // case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break;
202 case KEY_KPEQUAL: 202 // case KEY_KPEQUAL:
203 case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break; 203 // case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break;
204 case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break; 204 // case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break;
205 case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break; 205 // case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break;
206 case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break; 206 // case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break;
207 case KEY_R: { rune = shift_mod ? 'T' : 't'; } break; 207 // case KEY_R: { rune = shift_mod ? 'T' : 't'; } break;
208 case KEY_T: { rune = shift_mod ? 'T' : 't'; } break; 208 // case KEY_T: { rune = shift_mod ? 'T' : 't'; } break;
209 case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break; 209 // case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break;
210 case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break; 210 // case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break;
211 case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break; 211 // case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break;
212 case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break; 212 // case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break;
213 case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break; 213 // case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break;
214 case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break; 214 // case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break;
215 case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break; 215 // case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break;
216 case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break; 216 // case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break;
217 case KEY_S: { rune = shift_mod ? 'S' : 's'; } break; 217 // case KEY_S: { rune = shift_mod ? 'S' : 's'; } break;
218 case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break; 218 // case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break;
219 case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break; 219 // case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break;
220 case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break; 220 // case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break;
221 case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break; 221 // case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break;
222 case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break; 222 // case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break;
223 case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break; 223 // case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break;
224 case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break; 224 // case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break;
225 case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break; 225 // case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break;
226 case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break; 226 // case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break;
227 case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break; 227 // case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break;
228 case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break; 228 // case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break;
229 case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break; 229 // case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break;
230 case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break; 230 // case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break;
231 case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break; 231 // case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break;
232 case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break; 232 // case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break;
233 case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break; 233 // case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break;
234 case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break; 234 // case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break;
235 case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break; 235 // case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break;
236 case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break; 236 // case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break;
237 case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break; 237 // case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break;
238 case KEY_KPSLASH: 238 // case KEY_KPSLASH:
239 case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break; 239 // case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break;
240 case KEY_KPASTERISK: { rune = '*'; } break; 240 // case KEY_KPASTERISK: { rune = '*'; } break;
241 case KEY_KPPLUS: { rune = '+'; } break; 241 // case KEY_KPPLUS: { rune = '+'; } break;
242 case KEY_KPCOMMA: { rune = '.'; } break; 242 // case KEY_KPCOMMA: { rune = '.'; } break;
243 case KEY_SPACE: { rune = ' '; } break; 243 // case KEY_SPACE: { rune = ' '; } break;
244 case KEY_TAB: { rune = '\t'; } break; 244 // case KEY_TAB: { rune = '\t'; } break;
245 case KEY_ESC: { rune = 0x1b; } break; 245 // case KEY_ESC: { rune = 0x1b; } break;
246 case KEY_BACKSPACE: { rune = 0x08; } break; 246 // case KEY_BACKSPACE: { rune = 0x08; } break;
247 case KEY_ENTER: 247 // case KEY_ENTER:
248 case KEY_KPENTER: { rune = 0x0d; } break; 248 // case KEY_KPENTER: { rune = 0x0d; } break;
249 default: break; 249 // default: break;
250 } 250 // }
251 if (rune) { 251 // if (rune) {
252 devctrl->dat[3] = rune; 252 // devctrl->dat[3] = rune;
253 uxn_eval(&u, mempeek16(devctrl->dat, 0)); 253 // uxn_eval(&u, mempeek16(devctrl->dat, 0));
254 devctrl->dat[3] = 0; 254 // devctrl->dat[3] = 0;
255 continue; 255 // continue;
256 } 256 // }
257 257
258 // Special keys. 258 // // Special keys.
259 switch (key_code) { 259 // switch (key_code) {
260 case KEY_LEFTCTRL: { rune = 0x01; } break; 260 // case KEY_LEFTCTRL: { rune = 0x01; } break;
261 case KEY_LEFTALT: { rune = 0x02; } break; 261 // case KEY_LEFTALT: { rune = 0x02; } break;
262 case KEY_LEFTSHIFT: { rune = 0x04; } break; 262 // case KEY_LEFTSHIFT: { rune = 0x04; } break;
263 case KEY_HOME: { rune = 0x08; } break; 263 // case KEY_HOME: { rune = 0x08; } break;
264 case KEY_UP: { rune = 0x10; } break; 264 // case KEY_UP: { rune = 0x10; } break;
265 case KEY_DOWN: { rune = 0x20; } break; 265 // case KEY_DOWN: { rune = 0x20; } break;
266 case KEY_LEFT: { rune = 0x40; } break; 266 // case KEY_LEFT: { rune = 0x40; } break;
267 case KEY_RIGHT: { rune = 0x80; } break; 267 // case KEY_RIGHT: { rune = 0x80; } break;
268 default: break; 268 // default: break;
269 } 269 // }
270 if (rune) { 270 // if (rune) {
271 controller_now |= rune; 271 // controller_now |= rune;
272 continue; 272 // continue;
273 } 273 // }
274 } 274 // }
275 } 275 // }
276 } 276 // }
277 277
278 if (controller_now != in.controller) { 278 // if (controller_now != in.controller) {
279 devctrl->dat[2] = controller_now; 279 // devctrl->dat[2] = controller_now;
280 uxn_eval(&u, mempeek16(devctrl->dat, 0)); 280 // uxn_eval(&u, mempeek16(devctrl->dat, 0));
281 in.controller = controller_now; 281 // in.controller = controller_now;
282 } 282 // }
283 283
284 // Reset input state. 284 // // Reset input state.
285 devctrl->dat[3] = 0; 285 // devctrl->dat[3] = 0;
286 memset(in.map, 0, sizeof(in.map)); 286 // memset(in.map, 0, sizeof(in.map));
287} 287}
288 288
289void 289void
290handle_mouse(void) { 290handle_mouse(void) {
291 if (in.mouse.update) { 291 // if (in.mouse.update) {
292 // Handle mouse keys. 292 // // Handle mouse keys.
293 devmouse->dat[6] = in.mouse.buttons; 293 // devmouse->dat[6] = in.mouse.buttons;
294 if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) { 294 // if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) {
295 devmouse->dat[7] = 0x01; 295 // devmouse->dat[7] = 0x01;
296 } 296 // }
297 if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) { 297 // if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) {
298 devmouse->dat[7] = 0x10; 298 // devmouse->dat[7] = 0x10;
299 } 299 // }
300 300
301 // Handle mouse location. 301 // // Handle mouse location.
302 mempoke16(devmouse->dat, 0x2, in.mouse.x); 302 // mempoke16(devmouse->dat, 0x2, in.mouse.x);
303 mempoke16(devmouse->dat, 0x4, in.mouse.y); 303 // mempoke16(devmouse->dat, 0x4, in.mouse.y);
304 uxn_eval(&u, mempeek16(devmouse->dat, 0)); 304 // uxn_eval(&u, mempeek16(devmouse->dat, 0));
305 in.mouse.update = false; 305 // in.mouse.update = false;
306 } 306 // }
307} 307}
308 308
309void 309void
@@ -312,11 +312,24 @@ handle_input(void) {
312 handle_mouse(); 312 handle_mouse();
313} 313}
314 314
315void 315static Uint8
316nil_talk(Device *d, u8 b0, u8 w) { 316nil_dei(Device *d, Uint8 port) {
317 return d->dat[port];
318}
319
320static void
321nil_deo(Device *d, Uint8 port) {
317 (void)d; 322 (void)d;
318 (void)b0; 323 (void)port;
319 (void)w; 324}
325
326static void
327console_deo(Device *d, Uint8 port) {
328 FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr : 0;
329 if(fd) {
330 fputc(d->dat[port], fd);
331 fflush(fd);
332 }
320} 333}
321 334
322void 335void
@@ -338,8 +351,58 @@ console_talk(Device *d, u8 b0, u8 w) {
338 // } 351 // }
339} 352}
340 353
354Uint8
355screen_dei(Device *d, Uint8 port) {
356 switch(port) {
357 case 0x2: return screen_width >> 8;
358 case 0x3: return screen_width;
359 case 0x4: return screen_height >> 8;
360 case 0x5: return screen_height;
361 default: return d->dat[port];
362 }
363}
364
365void
366screen_deo(Device *d, Uint8 port) {
367 switch(port) {
368 case 0xe: {
369 Uint16 x, y;
370 Uint8 layer = d->dat[0xe] & 0x40;
371 DEVPEEK16(x, 0x8);
372 DEVPEEK16(y, 0xa);
373 ppu_pixel(layer ? pixels_fg : pixels_bg, x, y, d->dat[0xe] & 0x3);
374 if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 1); /* auto x+1 */
375 if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 1); /* auto y+1 */
376 } break;
377 case 0xf: {
378 Uint16 x, y, addr;
379 Uint8 twobpp = !!(d->dat[0xf] & 0x80);
380 DEVPEEK16(x, 0x8);
381 DEVPEEK16(y, 0xa);
382 DEVPEEK16(addr, 0xc);
383 if(addr > 0xfff8 - twobpp * 8) {
384 return;
385 }
386 u8 *layer = (d->dat[0xf] & 0x40) ? pixels_fg : pixels_bg;
387 u8 color = d->dat[0xf] & 0xf;
388 u8 flipx = d->dat[0xf] & 0x10;
389 u8 flipy = d->dat[0xf] & 0x20;
390 u8 *sprite = &d->u->ram[addr];
391 if (twobpp) {
392 ppu_2bpp(layer, x, y, sprite, color, flipx, flipy);
393 } else {
394 ppu_1bpp(layer, x, y, sprite, color, flipx, flipy);
395 }
396 if(d->dat[0x6] & 0x04) DEVPOKE16(0xc, addr + 8 + twobpp * 8); /* auto addr+length */
397 if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 8); /* auto x+8 */
398 if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 8); /* auto y+8 */
399 } break;
400 }
401 reqdraw = 1;
402}
403
341static void 404static void
342docolors(Device *d) { 405screen_palette(Device *d) {
343 for(size_t i = 0; i < 4; ++i) { 406 for(size_t i = 0; i < 4; ++i) {
344 u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; 407 u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11;
345 u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; 408 u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11;
@@ -361,107 +424,13 @@ docolors(Device *d) {
361} 424}
362 425
363void 426void
364system_talk(Device *d, u8 b0, u8 w) { 427system_deo_special(Device *d, Uint8 port) {
365 if(!w) { /* read */ 428 if(port > 0x7 && port < 0xe) {
366 switch(b0) { 429 screen_palette(d);
367 case 0x2: d->dat[0x2] = d->u->wst.ptr; break;
368 case 0x3: d->dat[0x3] = d->u->rst.ptr; break;
369 }
370 } else { /* write */
371 switch(b0) {
372 case 0x2: d->u->wst.ptr = d->dat[0x2]; break;
373 case 0x3: d->u->rst.ptr = d->dat[0x3]; break;
374 case 0xf: d->u->ram.ptr = 0x0000; break;
375 }
376 if(b0 > 0x7 && b0 < 0xe) {
377 docolors(d);
378 }
379 } 430 }
380 (void)b0;
381} 431}
382 432
383void 433void
384screen_talk(Device *d, u8 b0, u8 w) {
385 if (w) {
386 switch (b0) {
387 case 0x1: {
388 d->vector = mempeek16(d->dat, 0x0);
389 } break;
390 case 0xe: {
391 u16 x = mempeek16(d->dat, 0x8);
392 u16 y = mempeek16(d->dat, 0xa);
393 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)];
394 u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg;
395 u8 mode = d->dat[0xe] >> 5;
396 u8 color = d->dat[0xf] & 0xf;
397 if(!mode) {
398 ppu_pixel(layer, x, y, d->dat[0xe] & 0x3);
399 } else if(mode-- & 0x1) {
400 u8 flipx = mode & 0x2;
401 u8 flipy = mode & 0x4;
402 ppu_1bpp(layer, x, y, addr, color, flipx, flipy);
403 } else {
404 u8 flipx = mode & 0x2;
405 u8 flipy = mode & 0x4;
406 ppu_2bpp(layer, x, y, addr, color, flipx, flipy);
407 }
408 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); }
409 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); }
410 } break;
411 case 0xf: {
412 u16 x = mempeek16(d->dat, 0x8);
413 u16 y = mempeek16(d->dat, 0xa);
414 u8 *addr = &d->mem[mempeek16(d->dat, 0xc)];
415 u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg;
416 u8 color = d->dat[0xf] & 0xf;
417 u8 flipx = (d->dat[0xf] >> 0x4) & 0x1;
418 u8 flipy = (d->dat[0xf] >> 0x5) & 0x1;
419 if(d->dat[0xf] >> 0x7 & 0x1) {
420 ppu_2bpp(layer, x, y, addr, color, flipx, flipy);
421 if(d->dat[0x6] & 0x04) {
422 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16);
423 }
424 } else {
425 ppu_1bpp(layer, x, y, addr, color, flipx, flipy);
426 if(d->dat[0x6] & 0x04) {
427 mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8);
428 }
429 }
430 if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); }
431 if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); }
432 } break;
433 default: break;
434 }
435 }
436 reqdraw = 1;
437}
438
439static void
440audio_talk(Device *d, u8 b0, u8 w) {
441 // TODO: Implement...
442 (void)d;
443 (void)b0;
444 (void)w;
445}
446
447void
448datetime_talk(Device *d, u8 b0, u8 w) {
449 // TODO: Implement...
450 (void)d;
451 (void)b0;
452 (void)w;
453}
454
455void
456file_talk(Device *d, u8 b0, u8 w) {
457 // TODO: Implement...
458 (void)d;
459 (void)b0;
460 (void)w;
461}
462
463
464void
465load_rom(char *file_name) { 434load_rom(char *file_name) {
466 FILE *file = fopen(file_name, "r"); 435 FILE *file = fopen(file_name, "r");
467 if (!file) { 436 if (!file) {
@@ -474,15 +443,16 @@ load_rom(char *file_name) {
474 fseek(file, 0, SEEK_SET); 443 fseek(file, 0, SEEK_SET);
475 char *uxn_rom = malloc(rom_size); 444 char *uxn_rom = malloc(rom_size);
476 fread(uxn_rom, 1, rom_size, file); 445 fread(uxn_rom, 1, rom_size, file);
477 memcpy(u.ram.dat + PAGE_PROGRAM, uxn_rom, rom_size); 446 memcpy(u.ram + PAGE_PROGRAM, uxn_rom, rom_size);
447
478 fclose(file); 448 fclose(file);
479 free(uxn_rom); 449 free(uxn_rom);
480} 450}
481 451
482void 452void
483init_uxn(char *file_name) { 453init_uxn(Uxn *u, char *file_name) {
484 // Clear UXN memory. 454 // Setup UXN memory.
485 memset(&u, 0, sizeof(Uxn)); 455 uxn_boot(u, calloc(0x10000, sizeof(Uint8)));
486 456
487 // Copy rom to VM. 457 // Copy rom to VM.
488 load_rom(file_name); 458 load_rom(file_name);
@@ -494,24 +464,30 @@ init_uxn(char *file_name) {
494 init_input(); 464 init_input();
495 465
496 // Prepare devices. 466 // Prepare devices.
497 uxn_port(&u, 0x0, "system", system_talk); 467 /* system */ uxn_port(u, 0x0, system_dei, system_deo);
498 uxn_port(&u, 0x1, "console", console_talk); 468 /* console */ uxn_port(u, 0x1, nil_dei, console_deo);
499 devscreen = uxn_port(&u, 0x2, "screen", screen_talk); 469 /* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo);
500 devaudio = uxn_port(&u, 0x3, "audio0", audio_talk); 470 // TODO:
501 uxn_port(&u, 0x4, "audio1", audio_talk); 471 // /* audio0 */ devaudio0 = uxn_port(u, 0x3, audio_dei, audio_deo);
502 uxn_port(&u, 0x5, "audio2", audio_talk); 472 // /* audio1 */ uxn_port(u, 0x4, audio_dei, audio_deo);
503 uxn_port(&u, 0x6, "audio3", audio_talk); 473 // /* audio2 */ uxn_port(u, 0x5, audio_dei, audio_deo);
504 uxn_port(&u, 0x7, "---", nil_talk); 474 // /* audio3 */ uxn_port(u, 0x6, audio_dei, audio_deo);
505 devctrl = uxn_port(&u, 0x8, "controller", nil_talk); 475 /* audio0 */ uxn_port(u, 0x3, nil_dei, nil_deo);
506 devmouse = uxn_port(&u, 0x9, "mouse", nil_talk); 476 /* audio1 */ uxn_port(u, 0x4, nil_dei, nil_deo);
507 uxn_port(&u, 0xa, "file", file_talk); 477 /* audio2 */ uxn_port(u, 0x5, nil_dei, nil_deo);
508 uxn_port(&u, 0xb, "datetime", datetime_talk); 478 /* audio3 */ uxn_port(u, 0x6, nil_dei, nil_deo);
509 uxn_port(&u, 0xc, "---", nil_talk); 479 /* unused */ uxn_port(u, 0x7, nil_dei, nil_deo);
510 uxn_port(&u, 0xd, "---", nil_talk); 480 /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
511 uxn_port(&u, 0xe, "---", nil_talk); 481 /* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo);
512 uxn_port(&u, 0xf, "---", nil_talk); 482 // TODO:
513 mempoke16(devscreen->dat, 2, screen_width); 483 // /* file */ uxn_port(u, 0xa, nil_dei, file_deo);
514 mempoke16(devscreen->dat, 4, screen_height); 484 // /* datetime */ uxn_port(u, 0xb, datetime_dei, nil_deo);
485 /* file */ uxn_port(u, 0xa, nil_dei, nil_deo);
486 /* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo);
487 /* unused */ uxn_port(u, 0xc, nil_dei, nil_deo);
488 /* unused */ uxn_port(u, 0xd, nil_dei, nil_deo);
489 /* unused */ uxn_port(u, 0xe, nil_dei, nil_deo);
490 /* unused */ uxn_port(u, 0xf, nil_dei, nil_deo);
515} 491}
516 492
517int 493int
@@ -521,10 +497,10 @@ main(int argc, char *argv[]) {
521 fprintf(stderr, "error: no rom selected\n"); 497 fprintf(stderr, "error: no rom selected\n");
522 exit(EXIT_FAILURE); 498 exit(EXIT_FAILURE);
523 } 499 }
524 init_uxn(argv[1]); 500 init_uxn(&u, argv[1]);
525 501
526 // Main loop. 502 // Main loop.
527 uxn_eval(&u, 0x0100); 503 uxn_eval(&u, PAGE_PROGRAM);
528 Time frame_time = time_now(); 504 Time frame_time = time_now();
529 while (true) { 505 while (true) {
530 poll_input(); 506 poll_input();
@@ -533,7 +509,7 @@ main(int argc, char *argv[]) {
533 handle_input(); 509 handle_input();
534 510
535 // Echo input to standard output. 511 // Echo input to standard output.
536 uxn_eval(&u, mempeek16(devscreen->dat, 0)); 512 uxn_eval(&u, GETVECTOR(devscreen));
537 513
538 // Blit ppu.pixels to the framebuffer. 514 // Blit ppu.pixels to the framebuffer.
539 blit_framebuffer(); 515 blit_framebuffer();