[WIP] Update core to current uxn version
This commit is contained in:
parent
c046d2a0a9
commit
4aa83a8de5
540
src/main.c
540
src/main.c
|
@ -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,106 +424,12 @@ 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) {
|
||||||
FILE *file = fopen(file_name, "r");
|
FILE *file = fopen(file_name, "r");
|
||||||
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue