[WIP] Update core to current uxn version

This commit is contained in:
Bad Diode 2022-03-05 22:30:05 +01:00
parent c046d2a0a9
commit 4aa83a8de5
1 changed files with 258 additions and 282 deletions

View File

@ -10,7 +10,8 @@
#include "shorthand.h" #include "shorthand.h"
#include "ppu.c" #include "ppu.c"
#include "uxn-fast.c" #include "uxn/src/devices/system.c"
#include "uxn/src/uxn.c"
#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
@ -18,7 +19,6 @@ static Uxn u;
static Device *devscreen; static Device *devscreen;
static Device *devctrl; static Device *devctrl;
static Device *devmouse; static Device *devmouse;
static Device *devaudio;
typedef struct timespec Time; typedef struct timespec Time;
@ -142,168 +142,168 @@ poll_input(void) {
void void
handle_keyboard(void) { handle_keyboard(void) {
// Find mod keys. // // Find mod keys.
bool shift_mod = false; // bool shift_mod = false;
// bool ctrl_mod = false; // // bool ctrl_mod = false;
// bool alt_mod = false; // // bool alt_mod = false;
// bool meta_mod = false; // // bool meta_mod = false;
for (size_t i = 0; i < sizeof(in.map); i++) { // for (size_t i = 0; i < sizeof(in.map); i++) {
for (size_t j = 0; j < 8; j++) { // for (size_t j = 0; j < 8; j++) {
char key = in.map[i] & (1 << j); // char key = in.map[i] & (1 << j);
if (key) { // if (key) {
char key_code = i * 8 + j; // char key_code = i * 8 + j;
switch (key_code) { // switch (key_code) {
case KEY_LEFTSHIFT: // case KEY_LEFTSHIFT:
case KEY_RIGHTSHIFT: { shift_mod = true; } break; // case KEY_RIGHTSHIFT: { shift_mod = true; } break;
// case KEY_LEFTCTRL: // // case KEY_LEFTCTRL:
// case KEY_RIGHTCTRL: { ctrl_mod = true; } break; // // case KEY_RIGHTCTRL: { ctrl_mod = true; } break;
// case KEY_LEFTALT: // // case KEY_LEFTALT:
// case KEY_RIGHTALT: { alt_mod = true; } break; // // case KEY_RIGHTALT: { alt_mod = true; } break;
// case KEY_LEFTMETA: // // case KEY_LEFTMETA:
// case KEY_RIGHTMETA: { meta_mod = true; } break; // // case KEY_RIGHTMETA: { meta_mod = true; } break;
default: break; // default: break;
} // }
} // }
} // }
} // }
// Handle normal keys. // // Handle normal keys.
u8 controller_now = 0; // u8 controller_now = 0;
for (size_t i = 0; i < sizeof(in.map); i++) { // for (size_t i = 0; i < sizeof(in.map); i++) {
for (size_t j = 0; j < 8; j++) { // for (size_t j = 0; j < 8; j++) {
char key = in.map[i] & (1 << j); // char key = in.map[i] & (1 << j);
if (key) { // if (key) {
char key_code = i * 8 + j; // char key_code = i * 8 + j;
// Normal keys. // // Normal keys.
u8 rune = '\0'; // u8 rune = '\0';
switch (key_code) { // switch (key_code) {
case KEY_KP1: // case KEY_KP1:
case KEY_1: { rune = shift_mod ? '!' : '1'; } break; // case KEY_1: { rune = shift_mod ? '!' : '1'; } break;
case KEY_KP2: // case KEY_KP2:
case KEY_2: { rune = shift_mod ? '@' : '2'; } break; // case KEY_2: { rune = shift_mod ? '@' : '2'; } break;
case KEY_KP3: // case KEY_KP3:
case KEY_3: { rune = shift_mod ? '#' : '3'; } break; // case KEY_3: { rune = shift_mod ? '#' : '3'; } break;
case KEY_KP4: // case KEY_KP4:
case KEY_4: { rune = shift_mod ? '$' : '4'; } break; // case KEY_4: { rune = shift_mod ? '$' : '4'; } break;
case KEY_KP5: // case KEY_KP5:
case KEY_5: { rune = shift_mod ? '%' : '5'; } break; // case KEY_5: { rune = shift_mod ? '%' : '5'; } break;
case KEY_KP6: // case KEY_KP6:
case KEY_6: { rune = shift_mod ? '^' : '6'; } break; // case KEY_6: { rune = shift_mod ? '^' : '6'; } break;
case KEY_KP7: // case KEY_KP7:
case KEY_7: { rune = shift_mod ? '&' : '7'; } break; // case KEY_7: { rune = shift_mod ? '&' : '7'; } break;
case KEY_KP8: // case KEY_KP8:
case KEY_8: { rune = shift_mod ? '*' : '8'; } break; // case KEY_8: { rune = shift_mod ? '*' : '8'; } break;
case KEY_KP9: // case KEY_KP9:
case KEY_9: { rune = shift_mod ? '(' : '9'; } break; // case KEY_9: { rune = shift_mod ? '(' : '9'; } break;
case KEY_KP0: // case KEY_KP0:
case KEY_0: { rune = shift_mod ? ')' : '0'; } break; // case KEY_0: { rune = shift_mod ? ')' : '0'; } break;
case KEY_KPMINUS: // case KEY_KPMINUS:
case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break; // case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break;
case KEY_KPEQUAL: // case KEY_KPEQUAL:
case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break; // case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break;
case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break; // case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break;
case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break; // case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break;
case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break; // case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break;
case KEY_R: { rune = shift_mod ? 'T' : 't'; } break; // case KEY_R: { rune = shift_mod ? 'T' : 't'; } break;
case KEY_T: { rune = shift_mod ? 'T' : 't'; } break; // case KEY_T: { rune = shift_mod ? 'T' : 't'; } break;
case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break; // case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break;
case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break; // case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break;
case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break; // case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break;
case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break; // case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break;
case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break; // case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break;
case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break; // case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break;
case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break; // case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break;
case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break; // case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break;
case KEY_S: { rune = shift_mod ? 'S' : 's'; } break; // case KEY_S: { rune = shift_mod ? 'S' : 's'; } break;
case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break; // case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break;
case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break; // case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break;
case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break; // case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break;
case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break; // case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break;
case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break; // case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break;
case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break; // case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break;
case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break; // case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break;
case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break; // case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break;
case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break; // case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break;
case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break; // case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break;
case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break; // case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break;
case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break; // case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break;
case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break; // case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break;
case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break; // case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break;
case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break; // case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break;
case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break; // case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break;
case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break; // case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break;
case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break; // case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break;
case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break; // case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break;
case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break; // case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break;
case KEY_KPSLASH: // case KEY_KPSLASH:
case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break; // case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break;
case KEY_KPASTERISK: { rune = '*'; } break; // case KEY_KPASTERISK: { rune = '*'; } break;
case KEY_KPPLUS: { rune = '+'; } break; // case KEY_KPPLUS: { rune = '+'; } break;
case KEY_KPCOMMA: { rune = '.'; } break; // case KEY_KPCOMMA: { rune = '.'; } break;
case KEY_SPACE: { rune = ' '; } break; // case KEY_SPACE: { rune = ' '; } break;
case KEY_TAB: { rune = '\t'; } break; // case KEY_TAB: { rune = '\t'; } break;
case KEY_ESC: { rune = 0x1b; } break; // case KEY_ESC: { rune = 0x1b; } break;
case KEY_BACKSPACE: { rune = 0x08; } break; // case KEY_BACKSPACE: { rune = 0x08; } break;
case KEY_ENTER: // case KEY_ENTER:
case KEY_KPENTER: { rune = 0x0d; } break; // case KEY_KPENTER: { rune = 0x0d; } break;
default: break; // default: break;
} // }
if (rune) { // if (rune) {
devctrl->dat[3] = rune; // devctrl->dat[3] = rune;
uxn_eval(&u, mempeek16(devctrl->dat, 0)); // uxn_eval(&u, mempeek16(devctrl->dat, 0));
devctrl->dat[3] = 0; // devctrl->dat[3] = 0;
continue; // continue;
} // }
// Special keys. // // Special keys.
switch (key_code) { // switch (key_code) {
case KEY_LEFTCTRL: { rune = 0x01; } break; // case KEY_LEFTCTRL: { rune = 0x01; } break;
case KEY_LEFTALT: { rune = 0x02; } break; // case KEY_LEFTALT: { rune = 0x02; } break;
case KEY_LEFTSHIFT: { rune = 0x04; } break; // case KEY_LEFTSHIFT: { rune = 0x04; } break;
case KEY_HOME: { rune = 0x08; } break; // case KEY_HOME: { rune = 0x08; } break;
case KEY_UP: { rune = 0x10; } break; // case KEY_UP: { rune = 0x10; } break;
case KEY_DOWN: { rune = 0x20; } break; // case KEY_DOWN: { rune = 0x20; } break;
case KEY_LEFT: { rune = 0x40; } break; // case KEY_LEFT: { rune = 0x40; } break;
case KEY_RIGHT: { rune = 0x80; } break; // case KEY_RIGHT: { rune = 0x80; } break;
default: break; // default: break;
} // }
if (rune) { // if (rune) {
controller_now |= rune; // controller_now |= rune;
continue; // continue;
} // }
} // }
} // }
} // }
if (controller_now != in.controller) { // if (controller_now != in.controller) {
devctrl->dat[2] = controller_now; // devctrl->dat[2] = controller_now;
uxn_eval(&u, mempeek16(devctrl->dat, 0)); // uxn_eval(&u, mempeek16(devctrl->dat, 0));
in.controller = controller_now; // in.controller = controller_now;
} // }
// Reset input state. // // Reset input state.
devctrl->dat[3] = 0; // devctrl->dat[3] = 0;
memset(in.map, 0, sizeof(in.map)); // memset(in.map, 0, sizeof(in.map));
} }
void void
handle_mouse(void) { handle_mouse(void) {
if (in.mouse.update) { // if (in.mouse.update) {
// Handle mouse keys. // // Handle mouse keys.
devmouse->dat[6] = in.mouse.buttons; // devmouse->dat[6] = in.mouse.buttons;
if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) { // if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) {
devmouse->dat[7] = 0x01; // devmouse->dat[7] = 0x01;
} // }
if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) { // if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) {
devmouse->dat[7] = 0x10; // devmouse->dat[7] = 0x10;
} // }
// Handle mouse location. // // Handle mouse location.
mempoke16(devmouse->dat, 0x2, in.mouse.x); // mempoke16(devmouse->dat, 0x2, in.mouse.x);
mempoke16(devmouse->dat, 0x4, in.mouse.y); // mempoke16(devmouse->dat, 0x4, in.mouse.y);
uxn_eval(&u, mempeek16(devmouse->dat, 0)); // uxn_eval(&u, mempeek16(devmouse->dat, 0));
in.mouse.update = false; // in.mouse.update = false;
} // }
} }
void void
@ -312,11 +312,24 @@ handle_input(void) {
handle_mouse(); handle_mouse();
} }
void static Uint8
nil_talk(Device *d, u8 b0, u8 w) { nil_dei(Device *d, Uint8 port) {
return d->dat[port];
}
static void
nil_deo(Device *d, Uint8 port) {
(void)d; (void)d;
(void)b0; (void)port;
(void)w; }
static void
console_deo(Device *d, Uint8 port) {
FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr : 0;
if(fd) {
fputc(d->dat[port], fd);
fflush(fd);
}
} }
void void
@ -338,8 +351,58 @@ console_talk(Device *d, u8 b0, u8 w) {
// } // }
} }
Uint8
screen_dei(Device *d, Uint8 port) {
switch(port) {
case 0x2: return screen_width >> 8;
case 0x3: return screen_width;
case 0x4: return screen_height >> 8;
case 0x5: return screen_height;
default: return d->dat[port];
}
}
void
screen_deo(Device *d, Uint8 port) {
switch(port) {
case 0xe: {
Uint16 x, y;
Uint8 layer = d->dat[0xe] & 0x40;
DEVPEEK16(x, 0x8);
DEVPEEK16(y, 0xa);
ppu_pixel(layer ? pixels_fg : pixels_bg, x, y, d->dat[0xe] & 0x3);
if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 1); /* auto x+1 */
if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 1); /* auto y+1 */
} break;
case 0xf: {
Uint16 x, y, addr;
Uint8 twobpp = !!(d->dat[0xf] & 0x80);
DEVPEEK16(x, 0x8);
DEVPEEK16(y, 0xa);
DEVPEEK16(addr, 0xc);
if(addr > 0xfff8 - twobpp * 8) {
return;
}
u8 *layer = (d->dat[0xf] & 0x40) ? pixels_fg : pixels_bg;
u8 color = d->dat[0xf] & 0xf;
u8 flipx = d->dat[0xf] & 0x10;
u8 flipy = d->dat[0xf] & 0x20;
u8 *sprite = &d->u->ram[addr];
if (twobpp) {
ppu_2bpp(layer, x, y, sprite, color, flipx, flipy);
} else {
ppu_1bpp(layer, x, y, sprite, color, flipx, flipy);
}
if(d->dat[0x6] & 0x04) DEVPOKE16(0xc, addr + 8 + twobpp * 8); /* auto addr+length */
if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 8); /* auto x+8 */
if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 8); /* auto y+8 */
} break;
}
reqdraw = 1;
}
static void static void
docolors(Device *d) { screen_palette(Device *d) {
for(size_t i = 0; i < 4; ++i) { for(size_t i = 0; i < 4; ++i) {
u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; 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 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11;
@ -361,105 +424,11 @@ docolors(Device *d) {
} }
void void
system_talk(Device *d, u8 b0, u8 w) { system_deo_special(Device *d, Uint8 port) {
if(!w) { /* read */ if(port > 0x7 && port < 0xe) {
switch(b0) { screen_palette(d);
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) {
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;
}
}
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 void
load_rom(char *file_name) { load_rom(char *file_name) {
@ -474,15 +443,16 @@ load_rom(char *file_name) {
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
char *uxn_rom = malloc(rom_size); char *uxn_rom = malloc(rom_size);
fread(uxn_rom, 1, rom_size, file); fread(uxn_rom, 1, rom_size, file);
memcpy(u.ram.dat + PAGE_PROGRAM, uxn_rom, rom_size); memcpy(u.ram + PAGE_PROGRAM, uxn_rom, rom_size);
fclose(file); fclose(file);
free(uxn_rom); free(uxn_rom);
} }
void void
init_uxn(char *file_name) { init_uxn(Uxn *u, char *file_name) {
// Clear UXN memory. // Setup UXN memory.
memset(&u, 0, sizeof(Uxn)); uxn_boot(u, calloc(0x10000, sizeof(Uint8)));
// Copy rom to VM. // Copy rom to VM.
load_rom(file_name); load_rom(file_name);
@ -494,24 +464,30 @@ init_uxn(char *file_name) {
init_input(); init_input();
// Prepare devices. // Prepare devices.
uxn_port(&u, 0x0, "system", system_talk); /* system */ uxn_port(u, 0x0, system_dei, system_deo);
uxn_port(&u, 0x1, "console", console_talk); /* console */ uxn_port(u, 0x1, nil_dei, console_deo);
devscreen = uxn_port(&u, 0x2, "screen", screen_talk); /* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo);
devaudio = uxn_port(&u, 0x3, "audio0", audio_talk); // TODO:
uxn_port(&u, 0x4, "audio1", audio_talk); // /* audio0 */ devaudio0 = uxn_port(u, 0x3, audio_dei, audio_deo);
uxn_port(&u, 0x5, "audio2", audio_talk); // /* audio1 */ uxn_port(u, 0x4, audio_dei, audio_deo);
uxn_port(&u, 0x6, "audio3", audio_talk); // /* audio2 */ uxn_port(u, 0x5, audio_dei, audio_deo);
uxn_port(&u, 0x7, "---", nil_talk); // /* audio3 */ uxn_port(u, 0x6, audio_dei, audio_deo);
devctrl = uxn_port(&u, 0x8, "controller", nil_talk); /* audio0 */ uxn_port(u, 0x3, nil_dei, nil_deo);
devmouse = uxn_port(&u, 0x9, "mouse", nil_talk); /* audio1 */ uxn_port(u, 0x4, nil_dei, nil_deo);
uxn_port(&u, 0xa, "file", file_talk); /* audio2 */ uxn_port(u, 0x5, nil_dei, nil_deo);
uxn_port(&u, 0xb, "datetime", datetime_talk); /* audio3 */ uxn_port(u, 0x6, nil_dei, nil_deo);
uxn_port(&u, 0xc, "---", nil_talk); /* unused */ uxn_port(u, 0x7, nil_dei, nil_deo);
uxn_port(&u, 0xd, "---", nil_talk); /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
uxn_port(&u, 0xe, "---", nil_talk); /* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo);
uxn_port(&u, 0xf, "---", nil_talk); // TODO:
mempoke16(devscreen->dat, 2, screen_width); // /* file */ uxn_port(u, 0xa, nil_dei, file_deo);
mempoke16(devscreen->dat, 4, screen_height); // /* datetime */ uxn_port(u, 0xb, datetime_dei, nil_deo);
/* file */ uxn_port(u, 0xa, nil_dei, nil_deo);
/* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo);
/* unused */ uxn_port(u, 0xc, nil_dei, nil_deo);
/* unused */ uxn_port(u, 0xd, nil_dei, nil_deo);
/* unused */ uxn_port(u, 0xe, nil_dei, nil_deo);
/* unused */ uxn_port(u, 0xf, nil_dei, nil_deo);
} }
int int
@ -521,10 +497,10 @@ main(int argc, char *argv[]) {
fprintf(stderr, "error: no rom selected\n"); fprintf(stderr, "error: no rom selected\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
init_uxn(argv[1]); init_uxn(&u, argv[1]);
// Main loop. // Main loop.
uxn_eval(&u, 0x0100); uxn_eval(&u, PAGE_PROGRAM);
Time frame_time = time_now(); Time frame_time = time_now();
while (true) { while (true) {
poll_input(); poll_input();
@ -533,7 +509,7 @@ main(int argc, char *argv[]) {
handle_input(); handle_input();
// Echo input to standard output. // Echo input to standard output.
uxn_eval(&u, mempeek16(devscreen->dat, 0)); uxn_eval(&u, GETVECTOR(devscreen));
// Blit ppu.pixels to the framebuffer. // Blit ppu.pixels to the framebuffer.
blit_framebuffer(); blit_framebuffer();