uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

commit 763b0ce442247f56bba5018733e28d7108158cd5
parent fac4acb717a65437515fa1d6ea16d098818b7511
Author: Devine Lu Linvega <aliceffekt@gmail.com>
Date:   Wed, 27 Nov 2024 10:49:28 -0800

Using new system and screen device

Diffstat:
Msrc/devices/audio.c | 2+-
Msrc/devices/console.c | 4++--
Msrc/devices/console.h | 4++--
Msrc/devices/controller.c | 6+++---
Msrc/devices/file.c | 14+++++++-------
Msrc/devices/mouse.c | 8++++----
Msrc/devices/screen.c | 193+++++++++++++++++++++++++++----------------------------------------------------
Msrc/devices/screen.h | 7+++----
Msrc/devices/system.c | 2429+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/devices/system.h | 9+++++----
Msrc/uxn.c | 108++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/uxn.h | 14+++++---------
Msrc/uxncli.c | 54++++++++++++++++++++++++++++--------------------------
Msrc/uxnemu.c | 44+++++++++++++++++++++++---------------------
14 files changed, 2583 insertions(+), 313 deletions(-)

diff --git a/src/devices/audio.c b/src/devices/audio.c @@ -250,7 +250,7 @@ audio_handler(void *ctx, Uint8 *out_stream, int len) Uxn *u = (Uxn *)ctx; Uint8 *addr = &u->dev[device]; if(channel[n].duration <= 0 && PEEK2(addr)) { - uxn_eval(PEEK2(addr)); + uxn_eval(&uxn, PEEK2(addr)); } channel[n].duration -= SOUND_TIMER; int x = 0; diff --git a/src/devices/console.c b/src/devices/console.c @@ -20,7 +20,7 @@ console_input(Uint8 c, int type) { uxn.dev[0x12] = c; uxn.dev[0x17] = type; - return uxn_eval(PEEK2(&uxn.dev[0x10])); + return uxn_eval(&uxn, PEEK2(&uxn.dev[0x10])); } void @@ -34,7 +34,7 @@ console_listen(int i, int argc, char **argv) } void -console_deo(Uint8 addr) +console_deo(Uxn *u, Uint8 addr) { FILE *fd; switch(addr) { diff --git a/src/devices/console.h b/src/devices/console.h @@ -16,5 +16,5 @@ WITH REGARD TO THIS SOFTWARE. int console_input(Uint8 c, int type); void console_listen(int i, int argc, char **argv); -Uint8 console_dei(Uint8 addr); -void console_deo(Uint8 addr); +Uint8 console_dei(Uxn *u, Uint8 addr); +void console_deo(Uxn *u, Uint8 addr); diff --git a/src/devices/controller.c b/src/devices/controller.c @@ -17,7 +17,7 @@ controller_down(Uint8 mask) { if(mask) { uxn.dev[0x82] |= mask; - uxn_eval(PEEK2(&uxn.dev[0x80])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x80])); } } @@ -26,7 +26,7 @@ controller_up(Uint8 mask) { if(mask) { uxn.dev[0x82] &= (~mask); - uxn_eval(PEEK2(&uxn.dev[0x80])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x80])); } } @@ -35,7 +35,7 @@ controller_key(Uint8 key) { if(key) { uxn.dev[0x83] = key; - uxn_eval(PEEK2(&uxn.dev[0x80])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x80])); uxn.dev[0x83] = 0; } } diff --git a/src/devices/file.c b/src/devices/file.c @@ -217,7 +217,7 @@ is_dir_path(char *p) { char c; int saw_slash = 0; - while ((c = *p++)) + while((c = *p++)) saw_slash = c == DIR_SEP_CHAR; return saw_slash; } @@ -235,7 +235,7 @@ ensure_parent_dirs(char *p) int ok = 1; char c, *s = p; for(; ok && (c = *p); p++) { - if (c == DIR_SEP_CHAR) { + if(c == DIR_SEP_CHAR) { *p = '\0'; ok = dir_exists(s) || mkdir(s); *p = c; @@ -252,7 +252,7 @@ file_write(UxnFile *c, void *src, Uint16 len, Uint8 flags) ensure_parent_dirs(c->current_filename); if(c->state != FILE_WRITE && c->state != DIR_WRITE) { reset(c); - if (is_dir_path(c->current_filename)) + if(is_dir_path(c->current_filename)) c->state = DIR_WRITE; else if((c->f = fopen(c->current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL) c->state = FILE_WRITE; @@ -261,7 +261,7 @@ file_write(UxnFile *c, void *src, Uint16 len, Uint8 flags) if((ret = fwrite(src, 1, len, c->f)) > 0 && fflush(c->f) != 0) ret = 0; } - if (c->state == DIR_WRITE) { + if(c->state == DIR_WRITE) { ret = dir_exists(c->current_filename); } return ret; @@ -271,7 +271,7 @@ static Uint16 stat_fill(Uint8 *dest, Uint16 len, char c) { Uint16 i; - for (i = 0; i < len; i++) + for(i = 0; i < len; i++) *(dest++) = c; return len; } @@ -281,9 +281,9 @@ stat_size(Uint8 *dest, Uint16 len, off_t size) { Uint16 i; dest += len - 1; - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { char c = '0' + (Uint8)(size & 0xf); - if (c > '9') c += 39; + if(c > '9') c += 39; *(dest--) = c; size = size >> 4; } diff --git a/src/devices/mouse.c b/src/devices/mouse.c @@ -16,14 +16,14 @@ void mouse_down(Uint8 mask) { uxn.dev[0x96] |= mask; - uxn_eval(PEEK2(&uxn.dev[0x90])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x90])); } void mouse_up(Uint8 mask) { uxn.dev[0x96] &= (~mask); - uxn_eval(PEEK2(&uxn.dev[0x90])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x90])); } void @@ -31,7 +31,7 @@ mouse_pos(Uint16 x, Uint16 y) { uxn.dev[0x92] = x >> 8, uxn.dev[0x93] = x; uxn.dev[0x94] = y >> 8, uxn.dev[0x95] = y; - uxn_eval(PEEK2(&uxn.dev[0x90])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x90])); } void @@ -39,7 +39,7 @@ mouse_scroll(Uint16 x, Uint16 y) { uxn.dev[0x9a] = x >> 8, uxn.dev[0x9b] = x; uxn.dev[0x9c] = -y >> 8, uxn.dev[0x9d] = -y; - uxn_eval(PEEK2(&uxn.dev[0x90])); + uxn_eval(&uxn, PEEK2(&uxn.dev[0x90])); uxn.dev[0x9a] = 0, uxn.dev[0x9b] = 0; uxn.dev[0x9c] = 0, uxn.dev[0x9d] = 0; } diff --git a/src/devices/screen.c b/src/devices/screen.c @@ -1,11 +1,10 @@ #include <stdlib.h> -#include <stdio.h> #include "../uxn.h" #include "screen.h" /* -Copyright (c) 2021-2023 Devine Lu Linvega, Andrew Alderwick +Copyright (c) 2021-2024 Devine Lu Linvega, Andrew Alderwick Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -17,6 +16,9 @@ WITH REGARD TO THIS SOFTWARE. UxnScreen uxn_screen; +#define MAR(x) (x + 0x08) +#define MAR2(x) (x + 0x10) + /* c = !ch ? (color % 5 ? color >> 2 : 0) : color % 4 + ch == 1 ? 0 : (ch - 2 + (color & 3)) % 3 + 1; */ static Uint8 blending[4][16] = { @@ -25,40 +27,6 @@ static Uint8 blending[4][16] = { {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1}, {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}}; -static void -screen_2bpp(Uint8 *layer, Uint8 *addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy) -{ - int row, w = uxn_screen.width, h = uxn_screen.height, opaque = (color % 5); - Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8; - Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8; - for(y = y1 + ymod; y != ymax; y += fy, addr++) { - int c = (addr[8] << 8) | addr[0]; - if(y < h) - for(x = x1 + xmod, row = y * w; x != xmax; x -= fx, c >>= 1) { - Uint8 ch = (c & 1) | ((c >> 7) & 2); - if((opaque || ch) && x < w) - layer[x + row] = blending[ch][color]; - } - } -} - -static void -screen_1bpp(Uint8 *layer, Uint8 *addr, Uint16 x1, Uint16 y1, Uint16 color, int fx, int fy) -{ - int row, w = uxn_screen.width, h = uxn_screen.height, opaque = (color % 5); - Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8; - Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8; - for(y = y1 + ymod; y != ymax; y += fy) { - int c = *addr++; - if(y < h) - for(x = x1 + xmod, row = y * w; x != xmax; x -= fx, c >>= 1) { - Uint8 ch = c & 1; - if((opaque || ch) && x < w) - layer[x + row] = blending[ch][color]; - } - } -} - int screen_changed(void) { @@ -90,72 +58,15 @@ screen_change(int x1, int y1, int x2, int y2) if(y2 > uxn_screen.y2) uxn_screen.y2 = y2; } -/* clang-format off */ - -static Uint8 icons[] = { - 0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x00, 0x7c, 0x82, 0x02, 0x7c, 0x80, 0x80, 0xfe, 0x00, 0x7c, 0x82, 0x02, 0x1c, 0x02, - 0x82, 0x7c, 0x00, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04, 0x00, 0xfe, 0x80, 0x80, 0x7c, - 0x02, 0x82, 0x7c, 0x00, 0x7c, 0x82, 0x80, 0xfc, 0x82, 0x82, 0x7c, 0x00, 0x7c, 0x82, 0x02, - 0x1e, 0x02, 0x02, 0x02, 0x00, 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c, 0x00, 0x7c, 0x82, - 0x82, 0x7e, 0x02, 0x82, 0x7c, 0x00, 0x7c, 0x82, 0x02, 0x7e, 0x82, 0x82, 0x7e, 0x00, 0xfc, - 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc, 0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c, 0x00, - 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c, - 0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80 }; -static Uint8 arrow[] = { - 0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00 }; - -/* clang-format on */ - -static void -draw_byte(Uint8 b, Uint16 x, Uint16 y, Uint8 color) -{ - screen_1bpp(uxn_screen.fg, &icons[(b >> 4) << 3], x, y, color, 1, 1); - screen_1bpp(uxn_screen.fg, &icons[(b & 0xf) << 3], x + 8, y, color, 1, 1); - screen_change(x, y, x + 0x10, y + 0x8); -} - -static void -screen_debugger(void) -{ - int i; - for(i = 0; i < 0x08; i++) { - Uint8 pos = uxn.wst.ptr - 4 + i; - Uint8 color = i > 4 ? 0x01 : !pos ? 0xc - : i == 4 ? 0x8 - : 0x2; - draw_byte(uxn.wst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x18, color); - } - for(i = 0; i < 0x08; i++) { - Uint8 pos = uxn.rst.ptr - 4 + i; - Uint8 color = i > 4 ? 0x01 : !pos ? 0xc - : i == 4 ? 0x8 - : 0x2; - draw_byte(uxn.rst.dat[pos], i * 0x18 + 0x8, uxn_screen.height - 0x10, color); - } - screen_1bpp(uxn_screen.fg, &arrow[0], 0x68, uxn_screen.height - 0x20, 3, 1, 1); - for(i = 0; i < 0x20; i++) - draw_byte(uxn.ram[i], (i & 0x7) * 0x18 + 0x8, ((i >> 3) << 3) + 0x8, 1 + !!uxn.ram[i]); -} - void screen_fill(Uint8 *layer, int color) { - int i, length = uxn_screen.width * uxn_screen.height; - for(i = 0; i < length; i++) + int i, len = MAR2(uxn_screen.width) * uxn_screen.height; + for(i = 0; i < len; i++) layer[i] = color; } void -screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color) -{ - int row, x, y, w = uxn_screen.width, h = uxn_screen.height; - for(y = y1; y < y2 && y < h; y++) - for(x = x1, row = y * w; x < x2 && x < w; x++) - layer[x + row] = color; -} - -void screen_palette(void) { int i, shift; @@ -181,7 +92,8 @@ screen_resize(Uint16 width, Uint16 height, int scale) if(uxn_screen.width == width && uxn_screen.height == height && uxn_screen.scale == scale) return; if(dim_change) { - bg = malloc(width * height), fg = malloc(width * height); + int wmar = MAR2(width), hmar = MAR2(height); + bg = malloc(wmar * hmar), fg = malloc(wmar * hmar); if(bg && fg) pixels = realloc(uxn_screen.pixels, width * height * sizeof(Uint32) * scale * scale); if(!bg || !fg || !pixels) { @@ -215,14 +127,11 @@ screen_redraw(void) Uint32 palette[16], *pixels = uxn_screen.pixels; uxn_screen.x1 = uxn_screen.y1 = 9000; uxn_screen.x2 = uxn_screen.y2 = 0; - if(uxn.dev[0x0e]) - screen_debugger(); for(i = 0; i < 16; i++) palette[i] = uxn_screen.palette[(i >> 2) ? (i >> 2) : (i & 3)]; for(y = y1; y < y2; y++) { int ys = y * s; - int o = y * w; - for(x = x1, i = x1 + o; x < x2; x++, i++) { + for(x = x1, i = MAR(x) + MAR(y) * MAR2(w); x < x2; x++, i++) { int c = palette[fg[i] << 2 | bg[i]]; for(k = 0; k < s; k++) { int oo = ((ys + k) * w + x) * s; @@ -238,7 +147,7 @@ screen_redraw(void) static int rX, rY, rA, rMX, rMY, rMA, rML, rDX, rDY; Uint8 -screen_dei(Uint8 addr) +screen_dei(Uxn *u, Uint8 addr) { switch(addr) { case 0x22: return uxn_screen.width >> 8; @@ -251,46 +160,49 @@ screen_dei(Uint8 addr) case 0x2b: return rY; case 0x2c: return rA >> 8; case 0x2d: return rA; - default: return uxn.dev[addr]; + default: return u->dev[addr]; } } void -screen_deo(Uint8 addr) +screen_deo(Uxn *u, Uint8 addr) { switch(addr) { case 0x23: screen_resize(PEEK2(&uxn.dev[0x22]), uxn_screen.height, uxn_screen.scale); return; case 0x25: screen_resize(uxn_screen.width, PEEK2(&uxn.dev[0x24]), uxn_screen.scale); return; - case 0x26: rMX = uxn.dev[0x26] & 0x1, rMY = uxn.dev[0x26] & 0x2, rMA = uxn.dev[0x26] & 0x4, rML = uxn.dev[0x26] >> 4, rDX = rMX << 3, rDY = rMY << 2; return; + case 0x26: rMX = u->dev[0x26] & 0x1, rMY = u->dev[0x26] & 0x2, rMA = u->dev[0x26] & 0x4, rML = u->dev[0x26] >> 4, rDX = rMX << 3, rDY = rMY << 2; return; case 0x28: - case 0x29: rX = (uxn.dev[0x28] << 8) | uxn.dev[0x29], rX = twos(rX); return; + case 0x29: rX = (u->dev[0x28] << 8) | u->dev[0x29], rX = twos(rX); return; case 0x2a: - case 0x2b: rY = (uxn.dev[0x2a] << 8) | uxn.dev[0x2b], rY = twos(rY); return; + case 0x2b: rY = (u->dev[0x2a] << 8) | u->dev[0x2b], rY = twos(rY); return; case 0x2c: - case 0x2d: rA = (uxn.dev[0x2c] << 8) | uxn.dev[0x2d]; return; + case 0x2d: rA = (u->dev[0x2c] << 8) | u->dev[0x2d]; return; case 0x2e: { - Uint8 ctrl = uxn.dev[0x2e]; - Uint8 color = ctrl & 0x3; + int ctrl = u->dev[0x2e]; + int color = ctrl & 0x3; + int len = MAR2(uxn_screen.width); Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg; /* fill mode */ if(ctrl & 0x80) { - Uint16 x1, y1, x2, y2; + int x1, y1, x2, y2, ax, bx, ay, by, hor, ver; if(ctrl & 0x10) - x1 = 0, x2 = rX; + x1 = MAR(0), x2 = MAR(rX); else - x1 = rX, x2 = uxn_screen.width; + x1 = MAR(rX), x2 = MAR(uxn_screen.width); if(ctrl & 0x20) - y1 = 0, y2 = rY; + y1 = MAR(0), y2 = MAR(rY); else - y1 = rY, y2 = uxn_screen.height; - screen_rect(layer, x1, y1, x2, y2, color); + y1 = MAR(rY), y2 = MAR(uxn_screen.height); + hor = x2 - x1, ver = y2 - y1; + for(ay = y1 * len, by = ay + ver * len; ay < by; ay += len) + for(ax = ay + x1, bx = ax + hor; ax < bx; ax++) + layer[ax] = color; screen_change(x1, y1, x2, y2); } /* pixel mode */ else { - Uint16 w = uxn_screen.width; - if(rX >= 0 && rY >= 0 && rX < w && rY < uxn_screen.height) - layer[rX + rY * w] = color; + if(rX >= 0 && rY >= 0 && rX < len && rY < uxn_screen.height) + layer[MAR(rX) + MAR(rY) * len] = color; screen_change(rX, rY, rX + 1, rY + 1); if(rMX) rX++; if(rMY) rY++; @@ -298,20 +210,45 @@ screen_deo(Uint8 addr) return; } case 0x2f: { - Uint8 i; - Uint8 ctrl = uxn.dev[0x2f]; - Uint8 twobpp = !!(ctrl & 0x80); - Uint8 color = ctrl & 0xf; - Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg; + int i; + int ctrl = u->dev[0x2f]; + int twobpp = !!(ctrl & 0x80); + int blend = ctrl & 0xf; int fx = ctrl & 0x10 ? -1 : 1, fy = ctrl & 0x20 ? -1 : 1; - int x1, x2, y1, y2, x = rX, y = rY; + int x1, x2, y1, y2, ax, ay, qx, qy, x = rX, y = rY; int dxy = rDX * fy, dyx = rDY * fx, addr_incr = rMA << (1 + twobpp); + int len = MAR2(uxn_screen.width); + Uint8 *layer = ctrl & 0x40 ? uxn_screen.fg : uxn_screen.bg; if(twobpp) - for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) - screen_2bpp(layer, &uxn.ram[rA], x, y, color, fx, fy); + for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) { + Uint16 xx = MAR(x), yy = MAR(y); + if(xx < MAR(uxn_screen.width) && MAR(yy) < MAR2(uxn_screen.height)) { + Uint8 *sprite = &u->ram[rA]; + int opaque = blend % 5, by = (yy + 8) * len; + for(ay = yy * len, qy = fy < 0 ? 7 : 0; ay < by; ay += len, qy += fy) { + int ch1 = sprite[qy], ch2 = sprite[qy + 8] << 1, bx = xx + 8 + ay; + for(ax = xx + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { + int color = ((ch1 >> qx) & 1) | ((ch2 >> qx) & 2); + if(opaque || color) layer[ax] = blending[color][blend]; + } + } + } + } else - for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) - screen_1bpp(layer, &uxn.ram[rA], x, y, color, fx, fy); + for(i = 0; i <= rML; i++, x += dyx, y += dxy, rA += addr_incr) { + Uint16 xx = MAR(x), yy = MAR(y); + if(xx < MAR(uxn_screen.width) && MAR(yy) < MAR2(uxn_screen.height)) { + Uint8 *sprite = &u->ram[rA]; + int opaque = blend % 5, by = (yy + 8) * len; + for(ay = yy * len, qy = fy < 0 ? 7 : 0; ay < by; ay += len, qy += fy) { + int ch1 = sprite[qy], bx = xx + 8 + ay; + for(ax = xx + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { + int color = (ch1 >> qx) & 1; + if(opaque || color) layer[ax] = blending[color][blend]; + } + } + } + } if(fx < 0) x1 = x, x2 = rX; else diff --git a/src/devices/screen.h b/src/devices/screen.h @@ -20,12 +20,11 @@ extern int emu_resize(int width, int height); int screen_changed(void); void screen_change(int x1, int y1, int x2, int y2); void screen_fill(Uint8 *layer, int color); -void screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color); void screen_palette(void); void screen_resize(Uint16 width, Uint16 height, int scale); -void screen_redraw(void); +void screen_redraw(); -Uint8 screen_dei(Uint8 addr); -void screen_deo(Uint8 addr); +Uint8 screen_dei(Uxn *u, Uint8 addr); +void screen_deo(Uxn *u, Uint8 addr); #define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v) diff --git a/src/devices/system.c b/src/devices/system.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include "../uxn.h" + #include "system.h" /* @@ -15,27 +16,2348 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. */ +Uxn bios; char *boot_rom; +static unsigned char bios_rom[] = { + 0xa0, + 0x01, + 0x14, + 0x80, + 0x20, + 0x37, + 0x80, + 0x24, + 0x36, + 0xa0, + 0x00, + 0x30, + 0x39, + 0x80, + 0x17, + 0x33, + 0x60, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x80, + 0xfb, + 0x13, + 0x80, + 0x07, + 0x1c, + 0x20, + 0x00, + 0x72, + 0xa0, + 0x00, + 0x08, + 0x80, + 0x28, + 0x37, + 0xa0, + 0x00, + 0x00, + 0x80, + 0x2a, + 0x37, + 0xa0, + 0x80, + 0x00, + 0x80, + 0x04, + 0x16, + 0xa0, + 0x03, + 0x35, + 0x60, + 0x00, + 0xed, + 0xa0, + 0x00, + 0x08, + 0x80, + 0x28, + 0x37, + 0x80, + 0x2a, + 0xb6, + 0xa0, + 0x00, + 0x19, + 0x38, + 0x05, + 0x37, + 0xa0, + 0x81, + 0x00, + 0x80, + 0x05, + 0x16, + 0xa0, + 0x03, + 0x39, + 0x60, + 0x00, + 0xd2, + 0x80, + 0x01, + 0x20, + 0x00, + 0x3a, + 0xa0, + 0x00, + 0x28, + 0x80, + 0x28, + 0x37, + 0xa0, + 0x00, + 0x08, + 0x80, + 0x2a, + 0x37, + 0x80, + 0x01, + 0xa0, + 0x03, + 0x0e, + 0x15, + 0xa0, + 0x0a, + 0x0e, + 0x60, + 0x01, + 0x49, + 0xa0, + 0x00, + 0x00, + 0x1d, + 0x20, + 0x00, + 0x01, + 0x00, + 0xa0, + 0x26, + 0x26, + 0x17, + 0xa0, + 0x00, + 0x08, + 0x26, + 0x80, + 0x28, + 0x37, + 0x80, + 0x2a, + 0x37, + 0xa0, + 0x09, + 0x7d, + 0x80, + 0x2c, + 0x37, + 0xa0, + 0xc5, + 0x2f, + 0x97, + 0x97, + 0x17, + 0x00, + 0xa0, + 0x02, + 0x04, + 0x80, + 0x02, + 0x37, + 0x80, + 0x65, + 0x32, + 0xa0, + 0x80, + 0x06, + 0x28, + 0x80, + 0x60, + 0x12, + 0x80, + 0x37, + 0x08, + 0x1c, + 0x20, + 0x00, + 0x01, + 0x6c, + 0x80, + 0x51, + 0x32, + 0xa0, + 0x02, + 0x14, + 0x35, + 0xa0, + 0x02, + 0x0f, + 0x80, + 0x02, + 0x37, + 0x80, + 0x00, + 0xa0, + 0x01, + 0x54, + 0x15, + 0xa0, + 0x0a, + 0x0e, + 0x60, + 0x01, + 0x4e, + 0x21, + 0x94, + 0x20, + 0x00, + 0x02, + 0x22, + 0x6c, + 0x94, + 0x0f, + 0x21, + 0x26, + 0x80, + 0x00, + 0x4f, + 0x80, + 0x03, + 0x1a, + 0x38, + 0x24, + 0x94, + 0x80, + 0x83, + 0x08, + 0x20, + 0x00, + 0x0b, + 0xa0, + 0x00, + 0x03, + 0x38, + 0xaa, + 0x20, + 0xff, + 0xf1, + 0x22, + 0x22, + 0x6c, + 0x21, + 0x34, + 0xa0, + 0x02, + 0x1f, + 0x35, + 0xa0, + 0x02, + 0x1a, + 0x80, + 0x02, + 0x37, + 0xa0, + 0x09, + 0x7d, + 0xa0, + 0x01, + 0x71, + 0x35, + 0x22, + 0x6c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x06, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x01, + 0xfe, + 0x01, + 0x00, + 0x80, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x0d, + 0x01, + 0x00, + 0x90, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x09, + 0x7d, + 0x60, + 0x00, + 0x91, + 0x80, + 0x28, + 0xb6, + 0xa0, + 0x00, + 0x08, + 0x38, + 0x05, + 0x37, + 0x80, + 0x03, + 0xa0, + 0x03, + 0x0e, + 0x15, + 0x06, + 0x60, + 0x00, + 0xac, + 0x80, + 0x28, + 0xb6, + 0xa0, + 0x00, + 0x08, + 0x38, + 0x05, + 0x37, + 0x80, + 0x01, + 0xa0, + 0x03, + 0x0e, + 0x15, + 0x80, + 0x08, + 0x19, + 0x80, + 0x00, + 0x04, + 0x38, + 0x26, + 0xa0, + 0x00, + 0x08, + 0x38, + 0x24, + 0x8f, + 0xcf, + 0x80, + 0x80, + 0x0b, + 0x80, + 0x02, + 0x04, + 0x19, + 0xa0, + 0x03, + 0x0e, + 0x15, + 0x94, + 0x60, + 0x00, + 0x7f, + 0xcf, + 0x80, + 0xff, + 0x09, + 0x20, + 0x00, + 0x29, + 0xa0, + 0x25, + 0x26, + 0x17, + 0xa0, + 0x03, + 0x65, + 0x80, + 0x2c, + 0x37, + 0x80, + 0x2a, + 0xb6, + 0xa0, + 0x00, + 0x04, + 0x39, + 0x05, + 0x37, + 0xa0, + 0x03, + 0x2f, + 0x17, + 0x80, + 0x28, + 0xb6, + 0xa0, + 0x00, + 0x08, + 0x39, + 0x05, + 0x37, + 0x80, + 0x2a, + 0xb6, + 0xa0, + 0x00, + 0x04, + 0x38, + 0x05, + 0x37, + 0x80, + 0x28, + 0xb6, + 0xa0, + 0x00, + 0x08, + 0x38, + 0x05, + 0x37, + 0x41, + 0x21, + 0xaa, + 0x20, + 0xff, + 0xb1, + 0x22, + 0x22, + 0x42, + 0xa0, + 0x15, + 0x26, + 0x17, + 0xa0, + 0x03, + 0x7d, + 0x80, + 0x2c, + 0x37, + 0xa0, + 0x01, + 0x2f, + 0x17, + 0x6c, + 0x80, + 0x28, + 0x36, + 0x80, + 0x0c, + 0x33, + 0xa0, + 0x15, + 0x26, + 0x17, + 0x94, + 0x80, + 0x0a, + 0x09, + 0x20, + 0x00, + 0x12, + 0xa0, + 0x00, + 0x00, + 0x80, + 0x28, + 0x37, + 0x80, + 0x2a, + 0xb6, + 0xa0, + 0x00, + 0x10, + 0x38, + 0x05, + 0x37, + 0x40, + 0x00, + 0x04, + 0x94, + 0x60, + 0x00, + 0x1d, + 0x21, + 0x94, + 0x20, + 0xff, + 0xde, + 0x22, + 0x6c, + 0xa0, + 0x15, + 0x26, + 0x17, + 0x06, + 0x80, + 0x04, + 0x1f, + 0x60, + 0x00, + 0x00, + 0x80, + 0x0f, + 0x1c, + 0x80, + 0x00, + 0x04, + 0xa0, + 0x03, + 0x3d, + 0x38, + 0x14, + 0x80, + 0x20, + 0x19, + 0x80, + 0x00, + 0x04, + 0x80, + 0x40, + 0x3f, + 0xa0, + 0x03, + 0x8d, + 0x38, + 0x80, + 0x2c, + 0x37, + 0xa0, + 0x01, + 0x2f, + 0x17, + 0x6c, + 0x21, + 0x94, + 0x20, + 0xff, + 0xfb, + 0x6c, + 0x04, + 0x60, + 0x00, + 0x00, + 0x06, + 0x80, + 0x04, + 0x1f, + 0x60, + 0x00, + 0x00, + 0x80, + 0x0f, + 0x1c, + 0x06, + 0x80, + 0x09, + 0x0a, + 0x80, + 0x27, + 0x1a, + 0x18, + 0x80, + 0x30, + 0x18, + 0x80, + 0x19, + 0x17, + 0x6c, + 0x57, + 0x53, + 0x54, + 0x00, + 0x52, + 0x53, + 0x54, + 0x00, + 0x30, + 0x31, + 0x32, + 0x33, + 0x34, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x61, + 0x62, + 0x63, + 0x64, + 0x65, + 0x66, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x40, + 0x80, + 0x40, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x38, + 0x38, + 0x38, + 0x38, + 0x10, + 0x10, + 0x10, + 0x10, + 0x00, + 0x00, + 0x10, + 0x38, + 0x10, + 0x6c, + 0x6c, + 0x24, + 0x24, + 0x48, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x12, + 0x12, + 0x12, + 0x7f, + 0x24, + 0x24, + 0x24, + 0x24, + 0x24, + 0xfe, + 0x48, + 0x48, + 0x48, + 0x48, + 0x00, + 0x10, + 0x38, + 0x54, + 0x92, + 0x96, + 0x90, + 0x50, + 0x38, + 0x14, + 0x12, + 0xd2, + 0x92, + 0x94, + 0x78, + 0x10, + 0x10, + 0x02, + 0x62, + 0x94, + 0x94, + 0x94, + 0x98, + 0x68, + 0x10, + 0x10, + 0x2c, + 0x32, + 0x52, + 0x52, + 0x52, + 0x8c, + 0x80, + 0x00, + 0x30, + 0x48, + 0x48, + 0x48, + 0x50, + 0x20, + 0x2e, + 0x54, + 0x54, + 0x94, + 0x88, + 0x8c, + 0x72, + 0x00, + 0x00, + 0xe0, + 0xe0, + 0x20, + 0x20, + 0xc0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x04, + 0x08, + 0x08, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x08, + 0x08, + 0x04, + 0x02, + 0x80, + 0x40, + 0x20, + 0x20, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x20, + 0x20, + 0x40, + 0x80, + 0x00, + 0x00, + 0x00, + 0x10, + 0x38, + 0x92, + 0xd6, + 0x38, + 0xd6, + 0x92, + 0x38, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x10, + 0x10, + 0x10, + 0xfe, + 0x10, + 0x10, + 0x10, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe0, + 0xe0, + 0x20, + 0x20, + 0xc0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + 0xe0, + 0xe0, + 0x40, + 0x00, + 0x02, + 0x02, + 0x04, + 0x04, + 0x08, + 0x08, + 0x08, + 0x10, + 0x10, + 0x10, + 0x20, + 0x20, + 0x40, + 0x40, + 0x80, + 0x80, + 0x00, + 0x18, + 0x24, + 0x24, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x24, + 0x24, + 0x18, + 0x00, + 0x00, + 0x10, + 0x70, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x7c, + 0x00, + 0x00, + 0x00, + 0x18, + 0x24, + 0x42, + 0x62, + 0x02, + 0x04, + 0x08, + 0x08, + 0x10, + 0x20, + 0x22, + 0x42, + 0x7e, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0x82, + 0x02, + 0x04, + 0x38, + 0x04, + 0x02, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0x08, + 0x18, + 0x28, + 0x28, + 0x48, + 0x48, + 0x88, + 0x88, + 0xfe, + 0x08, + 0x08, + 0x08, + 0x3c, + 0x00, + 0x00, + 0x00, + 0xfc, + 0x80, + 0x80, + 0x80, + 0xb8, + 0xc4, + 0x82, + 0x02, + 0x02, + 0xc2, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x46, + 0x80, + 0x80, + 0xb8, + 0xc4, + 0x82, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x82, + 0x82, + 0x04, + 0x04, + 0x04, + 0x08, + 0x08, + 0x08, + 0x08, + 0x10, + 0x10, + 0x10, + 0x10, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x44, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0x82, + 0x82, + 0x82, + 0x46, + 0x3a, + 0x02, + 0x02, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x18, + 0x10, + 0x30, + 0x02, + 0x04, + 0x04, + 0x08, + 0x08, + 0x10, + 0x10, + 0x20, + 0x20, + 0x10, + 0x10, + 0x08, + 0x08, + 0x04, + 0x04, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x40, + 0x40, + 0x20, + 0x20, + 0x10, + 0x10, + 0x08, + 0x08, + 0x10, + 0x10, + 0x20, + 0x20, + 0x40, + 0x40, + 0x80, + 0x00, + 0x38, + 0x44, + 0x82, + 0xc2, + 0x02, + 0x04, + 0x04, + 0x08, + 0x10, + 0x10, + 0x00, + 0x00, + 0x10, + 0x38, + 0x10, + 0x00, + 0x3c, + 0x42, + 0x82, + 0x9a, + 0xa6, + 0xa2, + 0xa2, + 0xa2, + 0xa6, + 0x9a, + 0x80, + 0x42, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x10, + 0x28, + 0x28, + 0x28, + 0x44, + 0x44, + 0x44, + 0x44, + 0x7c, + 0x82, + 0x82, + 0x82, + 0xc6, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x44, + 0x42, + 0x42, + 0x42, + 0x44, + 0x78, + 0x44, + 0x42, + 0x42, + 0x42, + 0x42, + 0xfc, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x46, + 0x42, + 0x80, + 0x80, + 0x80, + 0x80, + 0x80, + 0x80, + 0x82, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x44, + 0x44, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x44, + 0x44, + 0xf8, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x42, + 0x42, + 0x40, + 0x48, + 0x48, + 0x78, + 0x48, + 0x48, + 0x42, + 0x42, + 0x42, + 0xfe, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x42, + 0x42, + 0x40, + 0x48, + 0x48, + 0x78, + 0x48, + 0x48, + 0x40, + 0x40, + 0x40, + 0xf0, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x26, + 0x42, + 0x40, + 0x80, + 0x80, + 0x8f, + 0x82, + 0x82, + 0x82, + 0x42, + 0x66, + 0x1a, + 0x00, + 0x00, + 0x00, + 0xe7, + 0x42, + 0x42, + 0x42, + 0x42, + 0x7e, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0xe7, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0xfe, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0xe6, + 0x44, + 0x44, + 0x48, + 0x48, + 0x70, + 0x50, + 0x48, + 0x48, + 0x44, + 0x44, + 0x42, + 0xe3, + 0x00, + 0x00, + 0x00, + 0xf0, + 0x40, + 0x40, + 0x40, + 0x40, + 0x40, + 0x40, + 0x40, + 0x40, + 0x42, + 0x42, + 0x42, + 0xfe, + 0x00, + 0x00, + 0x00, + 0x82, + 0xc6, + 0xaa, + 0xaa, + 0xaa, + 0x92, + 0x92, + 0x92, + 0x82, + 0x82, + 0x82, + 0x82, + 0xc6, + 0x00, + 0x00, + 0x00, + 0x87, + 0xc2, + 0xa2, + 0xa2, + 0xa2, + 0x92, + 0x92, + 0x92, + 0x8a, + 0x8a, + 0x8a, + 0x86, + 0xc2, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x44, + 0x42, + 0x42, + 0x42, + 0x42, + 0x44, + 0x78, + 0x40, + 0x40, + 0x40, + 0x40, + 0xf0, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x44, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0xba, + 0x44, + 0x44, + 0x38, + 0x08, + 0x06, + 0x00, + 0xf8, + 0x44, + 0x42, + 0x42, + 0x42, + 0x44, + 0x78, + 0x48, + 0x44, + 0x44, + 0x44, + 0x42, + 0xe3, + 0x00, + 0x00, + 0x00, + 0x34, + 0x4c, + 0x84, + 0x80, + 0x80, + 0x60, + 0x18, + 0x04, + 0x82, + 0x82, + 0x82, + 0xc4, + 0xb8, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x92, + 0x92, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x7c, + 0x00, + 0x00, + 0x00, + 0xe7, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x3c, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x82, + 0x82, + 0x82, + 0x82, + 0x44, + 0x44, + 0x44, + 0x44, + 0x28, + 0x28, + 0x10, + 0x10, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x82, + 0x82, + 0x82, + 0x92, + 0x92, + 0x92, + 0xaa, + 0xaa, + 0xaa, + 0x44, + 0x44, + 0x44, + 0x00, + 0x00, + 0x00, + 0xee, + 0x44, + 0x44, + 0x28, + 0x28, + 0x10, + 0x28, + 0x28, + 0x28, + 0x44, + 0x44, + 0x82, + 0xc6, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x82, + 0x44, + 0x44, + 0x44, + 0x28, + 0x28, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x7c, + 0x00, + 0x00, + 0x00, + 0xfe, + 0x84, + 0x88, + 0x08, + 0x10, + 0x10, + 0x10, + 0x20, + 0x20, + 0x42, + 0x42, + 0x82, + 0xfe, + 0x00, + 0x00, + 0x1e, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x1e, + 0x00, + 0x80, + 0x80, + 0x40, + 0x40, + 0x20, + 0x20, + 0x10, + 0x10, + 0x08, + 0x08, + 0x04, + 0x04, + 0x02, + 0x02, + 0x00, + 0xf0, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0xf0, + 0x10, + 0x28, + 0x44, + 0x82, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x30, + 0x30, + 0x20, + 0x20, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x42, + 0x02, + 0x3e, + 0x42, + 0x82, + 0x82, + 0x86, + 0x7b, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x40, + 0x40, + 0x40, + 0x78, + 0x44, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x44, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x46, + 0x82, + 0x80, + 0x80, + 0x80, + 0x82, + 0x42, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x06, + 0x04, + 0x04, + 0x04, + 0x3c, + 0x44, + 0x84, + 0x84, + 0x84, + 0x84, + 0x84, + 0x44, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0xfe, + 0x80, + 0x80, + 0x82, + 0x42, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x11, + 0x10, + 0x10, + 0xfe, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x7c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x44, + 0x44, + 0x44, + 0x38, + 0x40, + 0x78, + 0x84, + 0x82, + 0x82, + 0x7c, + 0x00, + 0xc0, + 0x40, + 0x40, + 0x40, + 0x5c, + 0x62, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0xe7, + 0x00, + 0x00, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x78, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0xff, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0xc0, + 0x40, + 0x40, + 0x40, + 0x42, + 0x44, + 0x48, + 0x58, + 0x64, + 0x44, + 0x42, + 0x42, + 0xe3, + 0x00, + 0x00, + 0x00, + 0x78, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x92, + 0x92, + 0x92, + 0x92, + 0x92, + 0x92, + 0x92, + 0xdb, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x62, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0xe7, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x44, + 0x82, + 0x82, + 0x82, + 0x82, + 0x82, + 0x44, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0x44, + 0x42, + 0x42, + 0x42, + 0x42, + 0x44, + 0x78, + 0x40, + 0x40, + 0xf0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x44, + 0x84, + 0x84, + 0x84, + 0x84, + 0x44, + 0x3c, + 0x04, + 0x04, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x32, + 0x22, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0xfc, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x46, + 0x42, + 0x40, + 0x3c, + 0x02, + 0x82, + 0xc2, + 0xbc, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x20, + 0x20, + 0xfc, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x22, + 0x22, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x46, + 0x39, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc6, + 0x82, + 0x82, + 0x44, + 0x44, + 0x44, + 0x28, + 0x28, + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x92, + 0x92, + 0x92, + 0x92, + 0xaa, + 0xaa, + 0x44, + 0x44, + 0x44, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xee, + 0x44, + 0x28, + 0x28, + 0x10, + 0x28, + 0x28, + 0x44, + 0xee, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe7, + 0x42, + 0x22, + 0x24, + 0x14, + 0x08, + 0x08, + 0x10, + 0x90, + 0xa0, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x44, + 0x08, + 0x08, + 0x10, + 0x10, + 0x22, + 0x42, + 0xfe, + 0x00, + 0x00, + 0x06, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x10, + 0x20, + 0x10, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x06, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0xc0, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x10, + 0x08, + 0x10, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0x20, + 0xc0, + 0x60, + 0x92, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, +}; + static void -system_zero(int soft) +system_zero(Uxn *u, int soft) { int i; for(i = soft ? 0x100 : 0; i < 0x10000; i++) - uxn.ram[i] = 0; + u->ram[i] = 0; for(i = 0x0; i < 0x100; i++) - uxn.dev[i] = 0; - uxn.wst.ptr = uxn.rst.ptr = 0; + u->dev[i] = 0; + u->wst.ptr = u->rst.ptr = 0; } static int -system_load(char *filename) +system_load(Uint8 *ram, char *filename) { FILE *f = fopen(filename, "rb"); if(f) { - int i = 0, l = fread(&uxn.ram[PAGE_PROGRAM], 0x10000 - PAGE_PROGRAM, 1, f); + int i = 0, l = fread(ram, 0x10000 - PAGE_PROGRAM, 1, f); while(l && ++i < RAM_PAGES) - l = fread(uxn.ram + 0x10000 * i, 0x10000, 1, f); + l = fread(ram + 0x10000 * i - PAGE_PROGRAM, 0x10000, 1, f); fclose(f); } return !!f; @@ -60,73 +2382,84 @@ system_inspect(void) int system_error(char *msg, const char *err) { - fprintf(stderr, "%s: %s\n", msg, err); - fflush(stderr); + fprintf(stderr, "%s: %s\n", msg, err), fflush(stderr); return 0; } void -system_reboot(char *rom, int soft) +system_reboot(int soft) { - system_zero(soft); - if(system_load(boot_rom)) - if(uxn_eval(PAGE_PROGRAM)) - boot_rom = rom; + system_zero(&uxn, soft); + if(system_load(&uxn.ram[PAGE_PROGRAM], boot_rom)) + uxn_eval(&uxn, PAGE_PROGRAM); } int -system_boot(Uint8 *ram, char *rom) +system_boot(Uint8 *ram, char *boot) { - uxn.ram = ram; - system_zero(0); - if(!system_load(rom)) - if(!system_load("boot.rom")) - return system_error("Could not load rom", rom); - boot_rom = rom; - return 1; + /* Load rom(bios) */ + bios.ram = ram; + bios.dev = bios.ram + 0x8300; + bios.wst.dat = bios.ram + 0x8400; + bios.rst.dat = bios.ram + 0x8500; + bios.dev[0xe] = 0xff; + if(!system_load(bios.ram + PAGE_PROGRAM, "bios.rom")) { + size_t i, bios_len = sizeof(bios_rom) / sizeof(bios_rom[0]); + for(i = 0; i < bios_len; i++) + bios.ram[PAGE_PROGRAM + i] = bios_rom[i]; + } + /* Load rom(main) */ + uxn.ram = ram + 0x10000; + uxn.dev = bios.ram + 0x8000; + uxn.wst.dat = bios.ram + 0x8100; + uxn.rst.dat = bios.ram + 0x8200; + boot_rom = boot; + return system_load(uxn.ram + PAGE_PROGRAM, boot); } /* IO */ Uint8 -system_dei(Uint8 addr) +system_dei(Uxn *u, Uint8 addr) { switch(addr) { case 0x4: return uxn.wst.ptr; case 0x5: return uxn.rst.ptr; - default: return uxn.dev[addr]; + default: return u->dev[addr]; } } void -system_deo(Uint8 port) +system_deo(Uxn *u, Uint8 port) { switch(port) { case 0x3: { - Uint16 addr = PEEK2(uxn.dev + 2); - if(uxn.ram[addr] == 0x0) { - Uint8 value = uxn.ram[addr + 7]; - Uint16 i, length = PEEK2(uxn.ram + addr + 1); - Uint16 dst_page = PEEK2(uxn.ram + addr + 3), dst_addr = PEEK2(uxn.ram + addr + 5); - int dst = (dst_page % RAM_PAGES) * 0x10000; - for(i = 0; i < length; i++) - uxn.ram[dst + (Uint16)(dst_addr + i)] = value; - } else if(uxn.ram[addr] == 0x1) { - Uint16 i, length = PEEK2(uxn.ram + addr + 1); - Uint16 a_page = PEEK2(uxn.ram + addr + 3), a_addr = PEEK2(uxn.ram + addr + 5); - Uint16 b_page = PEEK2(uxn.ram + addr + 7), b_addr = PEEK2(uxn.ram + addr + 9); - int src = (a_page % RAM_PAGES) * 0x10000, dst = (b_page % RAM_PAGES) * 0x10000; - for(i = 0; i < length; i++) - uxn.ram[dst + (Uint16)(b_addr + i)] = uxn.ram[src + (Uint16)(a_addr + i)]; - } else if(uxn.ram[addr] == 0x2) { - Uint16 i, length = PEEK2(uxn.ram + addr + 1); - Uint16 a_page = PEEK2(uxn.ram + addr + 3), a_addr = PEEK2(uxn.ram + addr + 5); - Uint16 b_page = PEEK2(uxn.ram + addr + 7), b_addr = PEEK2(uxn.ram + addr + 9); - int src = (a_page % RAM_PAGES) * 0x10000, dst = (b_page % RAM_PAGES) * 0x10000; - for(i = length - 1; i != 0xffff; i--) - uxn.ram[dst + (Uint16)(b_addr + i)] = uxn.ram[src + (Uint16)(a_addr + i)]; + Uint16 addr = PEEK2(u->dev + 2); + if(u->ram[addr] == 0x0) { + Uint16 i, value = u->ram[addr + 7], length = PEEK2(u->ram + addr + 1); + unsigned int dst_page = PEEK2(u->ram + addr + 3), dst_addr = PEEK2(u->ram + addr + 5); + unsigned int dst = dst_page * 0x10000; + if(dst_page < RAM_PAGES) + for(i = 0; i < length; i++) + u->ram[dst + (Uint16)(dst_addr + i)] = value; + } else if(u->ram[addr] == 0x1) { + Uint16 i, length = PEEK2(u->ram + addr + 1); + unsigned int a_page = PEEK2(u->ram + addr + 3), a_addr = PEEK2(u->ram + addr + 5); + unsigned int b_page = PEEK2(u->ram + addr + 7), b_addr = PEEK2(u->ram + addr + 9); + unsigned int src = a_page * 0x10000, dst = b_page * 0x10000; + if(a_page < RAM_PAGES && b_page < RAM_PAGES) + for(i = 0; i < length; i++) + u->ram[dst + (Uint16)(b_addr + i)] = u->ram[src + (Uint16)(a_addr + i)]; + } else if(u->ram[addr] == 0x2) { + Uint16 i, length = PEEK2(u->ram + addr + 1); + unsigned int a_page = PEEK2(u->ram + addr + 3), a_addr = PEEK2(u->ram + addr + 5); + unsigned int b_page = PEEK2(u->ram + addr + 7), b_addr = PEEK2(u->ram + addr + 9); + unsigned int src = a_page * 0x10000, dst = b_page * 0x10000; + if(a_page < RAM_PAGES && b_page < RAM_PAGES) + for(i = length - 1; i != 0xffff; i--) + u->ram[dst + (Uint16)(b_addr + i)] = u->ram[src + (Uint16)(a_addr + i)]; } else - fprintf(stderr, "Unknown Expansion Command 0x%02x\n", uxn.ram[addr]); + fprintf(stderr, "Unknown Expansion Command 0x%02x\n", u->ram[addr]); break; } case 0x4: diff --git a/src/devices/system.h b/src/devices/system.h @@ -11,12 +11,12 @@ WITH REGARD TO THIS SOFTWARE. #define RAM_PAGES 0x10 -void system_reboot(char *rom, int soft); +void system_reboot(int soft); void system_inspect(void); int system_error(char *msg, const char *err); int system_boot(Uint8 *ram, char *rom); -Uint8 system_dei(Uint8 addr); -void system_deo(Uint8 addr); +Uint8 system_dei(Uxn *u, Uint8 addr); +void system_deo(Uxn *u, Uint8 addr); -extern char *boot_rom; +extern Uxn bios; +\ No newline at end of file diff --git a/src/uxn.c b/src/uxn.c @@ -16,78 +16,78 @@ WITH REGARD TO THIS SOFTWARE. case 0x20|opc: {const int _2=1,_r=0;init body;} break;\ case 0x40|opc: {const int _2=0,_r=1;init body;} break;\ case 0x60|opc: {const int _2=1,_r=1;init body;} break;\ - case 0x80|opc: {const int _2=0,_r=0;int k=uxn.wst.ptr;init uxn.wst.ptr= k;body;} break;\ - case 0xa0|opc: {const int _2=1,_r=0;int k=uxn.wst.ptr;init uxn.wst.ptr= k;body;} break;\ - case 0xc0|opc: {const int _2=0,_r=1;int k=uxn.rst.ptr;init uxn.rst.ptr= k;body;} break;\ - case 0xe0|opc: {const int _2=1,_r=1;int k=uxn.rst.ptr;init uxn.rst.ptr= k;body;} break;\ + case 0x80|opc: {const int _2=0,_r=0,k=u->wst.ptr;init u->wst.ptr=k;body;} break;\ + case 0xa0|opc: {const int _2=1,_r=0,k=u->wst.ptr;init u->wst.ptr=k;body;} break;\ + case 0xc0|opc: {const int _2=0,_r=1,k=u->rst.ptr;init u->rst.ptr=k;body;} break;\ + case 0xe0|opc: {const int _2=1,_r=1,k=u->rst.ptr;init u->rst.ptr=k;body;} break;\ } /* Microcode */ -#define JMI a = uxn.ram[pc] << 8 | uxn.ram[pc + 1], pc += a + 2; -#define REM if(_r) uxn.rst.ptr -= 1 + _2; else uxn.wst.ptr -= 1 + _2; -#define INC(s) uxn.s.dat[uxn.s.ptr++] -#define DEC(s) uxn.s.dat[--uxn.s.ptr] -#define JMP(i) { if(_2) pc = i; else pc += (Sint8)i; } -#define PO1(o) { o = _r ? DEC(rst) : DEC(wst); } -#define PO2(o) { PO1(o) o |= (_r ? DEC(rst) : DEC(wst)) << 8; } -#define POx(o) { if(_2) { PO2(o) } else PO1(o) } +#define JMI a = u->ram[pc] << 8 | u->ram[pc + 1], pc += a + 2; +#define REM if(_r) u->rst.ptr -= 1 + _2; else u->wst.ptr -= 1 + _2; +#define INC(s) u->s.dat[u->s.ptr++] +#define DEC(s) u->s.dat[--u->s.ptr] +#define JMP(i) pc = _2 ? i : pc + (Sint8)i; +#define PO1(o) o = _r ? DEC(rst) : DEC(wst); +#define PO2(o) o = _r ? DEC(rst) | DEC(rst) << 8 : DEC(wst) | DEC(wst) << 8; +#define POx(o) { if(_2) PO2(o) else PO1(o) } #define PU1(i) { if(_r) INC(rst) = i; else INC(wst) = i; } #define RP1(i) { if(_r) INC(wst) = i; else INC(rst) = i; } #define PUx(i) { if(_2) { c = (i); PU1(c >> 8) PU1(c) } else PU1(i) } #define GET(o) { if(_2) PO1(o[1]) PO1(o[0]) } #define PUT(i) { PU1(i[0]) if(_2) PU1(i[1]) } -#define DEI(i,o) o[0] = emu_dei(i); if(_2) o[1] = emu_dei(i + 1); PUT(o) -#define DEO(i,j) emu_deo(i, j[0]); if(_2) emu_deo(i + 1, j[1]); -#define PEK(i,o,m) o[0] = uxn.ram[i]; if(_2) o[1] = uxn.ram[(i + 1) & m]; PUT(o) -#define POK(i,j,m) uxn.ram[i] = j[0]; if(_2) uxn.ram[(i + 1) & m] = j[1]; +#define DEI(i,o) o[0] = emu_dei(u, i); if(_2) o[1] = emu_dei(u, i + 1); PUT(o) +#define DEO(i,j) emu_deo(u, i, j[0]); if(_2) emu_deo(u, i + 1, j[1]); +#define PEK(i,o,m) o[0] = u->ram[i]; if(_2) o[1] = u->ram[(i + 1) & m]; PUT(o) +#define POK(i,j,m) u->ram[i] = j[0]; if(_2) u->ram[(i + 1) & m] = j[1]; int -uxn_eval(Uint16 pc) +uxn_eval(Uxn *u, Uint16 pc) { unsigned int a, b, c, x[2], y[2], z[2], step; - if(!pc || uxn.dev[0x0f]) return 0; + if(!pc || u->dev[0x0f]) return 0; for(step = STEP_MAX; step; step--) { - switch(uxn.ram[pc++]) { + switch(u->ram[pc++]) { /* BRK */ case 0x00: return 1; /* JCI */ case 0x20: if(DEC(wst)) { JMI break; } pc += 2; break; /* JMI */ case 0x40: JMI break; /* JSI */ case 0x60: c = pc + 2; INC(rst) = c >> 8; INC(rst) = c; JMI break; - /* LI2 */ case 0xa0: INC(wst) = uxn.ram[pc++]; /* fall-through */ - /* LIT */ case 0x80: INC(wst) = uxn.ram[pc++]; break; - /* L2r */ case 0xe0: INC(rst) = uxn.ram[pc++]; /* fall-through */ - /* LIr */ case 0xc0: INC(rst) = uxn.ram[pc++]; break; - /* INC */ OPC(0x01, POx(a), PUx(a + 1)) - /* POP */ OPC(0x02, REM, {}) - /* NIP */ OPC(0x03, GET(x) REM,PUT(x)) - /* SWP */ OPC(0x04, GET(x) GET(y),PUT(x) PUT(y)) - /* ROT */ OPC(0x05, GET(x) GET(y) GET(z),PUT(y) PUT(x) PUT(z)) - /* DUP */ OPC(0x06, GET(x),PUT(x) PUT(x)) - /* OVR */ OPC(0x07, GET(x) GET(y),PUT(y) PUT(x) PUT(y)) - /* EQU */ OPC(0x08, POx(a) POx(b),PU1(b == a)) - /* NEQ */ OPC(0x09, POx(a) POx(b),PU1(b != a)) - /* GTH */ OPC(0x0a, POx(a) POx(b),PU1(b > a)) - /* LTH */ OPC(0x0b, POx(a) POx(b),PU1(b < a)) - /* JMP */ OPC(0x0c, POx(a),JMP(a)) - /* JCN */ OPC(0x0d, POx(a) PO1(b), if(b) JMP(a)) - /* JSR */ OPC(0x0e, POx(a),RP1(pc >> 8) RP1(pc) JMP(a)) - /* STH */ OPC(0x0f, GET(x),RP1(x[0]) if(_2) RP1(x[1])) - /* LDZ */ OPC(0x10, PO1(a),PEK(a, x, 0xff)) - /* STZ */ OPC(0x11, PO1(a) GET(y),POK(a, y, 0xff)) - /* LDR */ OPC(0x12, PO1(a),PEK(pc + (Sint8)a, x, 0xffff)) - /* STR */ OPC(0x13, PO1(a) GET(y),POK(pc + (Sint8)a, y, 0xffff)) - /* LDA */ OPC(0x14, PO2(a),PEK(a, x, 0xffff)) - /* STA */ OPC(0x15, PO2(a) GET(y),POK(a, y, 0xffff)) - /* DEI */ OPC(0x16, PO1(a),DEI(a, x)) - /* DEO */ OPC(0x17, PO1(a) GET(y),DEO(a, y)) - /* ADD */ OPC(0x18, POx(a) POx(b),PUx(b + a)) - /* SUB */ OPC(0x19, POx(a) POx(b),PUx(b - a)) - /* MUL */ OPC(0x1a, POx(a) POx(b),PUx(b * a)) - /* DIV */ OPC(0x1b, POx(a) POx(b),PUx(a ? b / a : 0)) - /* AND */ OPC(0x1c, POx(a) POx(b),PUx(b & a)) - /* ORA */ OPC(0x1d, POx(a) POx(b),PUx(b | a)) - /* EOR */ OPC(0x1e, POx(a) POx(b),PUx(b ^ a)) - /* SFT */ OPC(0x1f, PO1(a) POx(b),PUx(b >> (a & 0xf) << (a >> 4))) + /* LI2 */ case 0xa0: INC(wst) = u->ram[pc++]; /* fall-through */ + /* LIT */ case 0x80: INC(wst) = u->ram[pc++]; break; + /* L2r */ case 0xe0: INC(rst) = u->ram[pc++]; /* fall-through */ + /* LIr */ case 0xc0: INC(rst) = u->ram[pc++]; break; + /* INC */ OPC(0x01,POx(a),PUx(a + 1)) + /* POP */ OPC(0x02,REM ,{}) + /* NIP */ OPC(0x03,GET(x) REM ,PUT(x)) + /* SWP */ OPC(0x04,GET(x) GET(y),PUT(x) PUT(y)) + /* ROT */ OPC(0x05,GET(x) GET(y) GET(z),PUT(y) PUT(x) PUT(z)) + /* DUP */ OPC(0x06,GET(x),PUT(x) PUT(x)) + /* OVR */ OPC(0x07,GET(x) GET(y),PUT(y) PUT(x) PUT(y)) + /* EQU */ OPC(0x08,POx(a) POx(b),PU1(b == a)) + /* NEQ */ OPC(0x09,POx(a) POx(b),PU1(b != a)) + /* GTH */ OPC(0x0a,POx(a) POx(b),PU1(b > a)) + /* LTH */ OPC(0x0b,POx(a) POx(b),PU1(b < a)) + /* JMP */ OPC(0x0c,POx(a),JMP(a)) + /* JCN */ OPC(0x0d,POx(a) PO1(b),if(b) JMP(a)) + /* JSR */ OPC(0x0e,POx(a),RP1(pc >> 8) RP1(pc) JMP(a)) + /* STH */ OPC(0x0f,GET(x),RP1(x[0]) if(_2) RP1(x[1])) + /* LDZ */ OPC(0x10,PO1(a),PEK(a, x, 0xff)) + /* STZ */ OPC(0x11,PO1(a) GET(y),POK(a, y, 0xff)) + /* LDR */ OPC(0x12,PO1(a),PEK(pc + (Sint8)a, x, 0xffff)) + /* STR */ OPC(0x13,PO1(a) GET(y),POK(pc + (Sint8)a, y, 0xffff)) + /* LDA */ OPC(0x14,PO2(a),PEK(a, x, 0xffff)) + /* STA */ OPC(0x15,PO2(a) GET(y),POK(a, y, 0xffff)) + /* DEI */ OPC(0x16,PO1(a),DEI(a, x)) + /* DEO */ OPC(0x17,PO1(a) GET(y),DEO(a, y)) + /* ADD */ OPC(0x18,POx(a) POx(b),PUx(b + a)) + /* SUB */ OPC(0x19,POx(a) POx(b),PUx(b - a)) + /* MUL */ OPC(0x1a,POx(a) POx(b),PUx(b * a)) + /* DIV */ OPC(0x1b,POx(a) POx(b),PUx(a ? b / a : 0)) + /* AND */ OPC(0x1c,POx(a) POx(b),PUx(b & a)) + /* ORA */ OPC(0x1d,POx(a) POx(b),PUx(b | a)) + /* EOR */ OPC(0x1e,POx(a) POx(b),PUx(b ^ a)) + /* SFT */ OPC(0x1f,PO1(a) POx(b),PUx(b >> (a & 0xf) << (a >> 4))) } } return 0; diff --git a/src/uxn.h b/src/uxn.h @@ -26,20 +26,16 @@ typedef signed short Sint16; typedef unsigned int Uint32; typedef struct { - Uint8 dat[0x100], ptr; + Uint8 *dat, ptr; } Stack; typedef struct Uxn { - Uint8 *ram, dev[0x100]; + Uint8 *ram, *dev; Stack wst, rst; } Uxn; -/* required functions */ - -extern Uint8 emu_dei(Uint8 addr); -extern void emu_deo(Uint8 addr, Uint8 value); +extern Uint8 emu_dei(Uxn *u, Uint8 addr); +extern void emu_deo(Uxn *u, Uint8 addr, Uint8 value); extern Uxn uxn; -/* built-ins */ - -int uxn_eval(Uint16 pc); +int uxn_eval(Uxn *u, Uint16 pc); diff --git a/src/uxncli.c b/src/uxncli.c @@ -19,54 +19,56 @@ WITH REGARD TO THIS SOFTWARE. */ Uxn uxn; -Uint8 ram[0x10000 * RAM_PAGES]; Uint8 -emu_dei(Uint8 addr) +emu_dei(Uxn *u, Uint8 addr) { switch(addr & 0xf0) { - case 0x00: return system_dei(addr); + case 0x00: return system_dei(u, addr); case 0xc0: return datetime_dei(addr); } return uxn.dev[addr]; } void -emu_deo(Uint8 addr, Uint8 value) +emu_deo(Uxn *u, Uint8 addr, Uint8 value) { uxn.dev[addr] = value; switch(addr & 0xf0) { - case 0x00: system_deo(addr); break; - case 0x10: console_deo(addr); break; + case 0x00: system_deo(u, addr); break; + case 0x10: console_deo(u, addr); break; case 0xa0: file_deo(addr); break; case 0xb0: file_deo(addr); break; } } -static void -emu_run(void) -{ - while(!uxn.dev[0x0f]) { - int c = fgetc(stdin); - if(c == EOF) { - console_input(0x00, CONSOLE_END); - break; - } - console_input(c, CONSOLE_STD); - } -} - int main(int argc, char **argv) { - if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'v') - fprintf(stdout, "Uxncli - Varvara Emulator, 12 Nov 2024.\n"); - else if(argc == 1 || !system_boot(ram, argv[1])) + int i = 1; + if(argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') + return !fprintf(stdout, "Uxn11(cli) - Varvara Emulator, 27 Nov 2024.\n"); + else if(argc == 1) return !fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]); - else { - uxn.dev[0x17] = argc - 2; - if(uxn_eval(PAGE_PROGRAM) && PEEK2(uxn.dev + 0x10)) - console_listen(2, argc, argv), emu_run(); + else if(!system_boot((Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), argv[i++])) + return !fprintf(stdout, "Could not load %s.\n", argv[i - 1]); + uxn.dev[0x17] = argc - 2; + if(uxn_eval(&uxn, PAGE_PROGRAM) && uxn.dev[0x10]) { + /* arguments input */ + for(; i < argc; i++) { + char *p = argv[i]; + while(*p) console_input(*p++, CONSOLE_ARG); + console_input('\n', i == argc - 1 ? CONSOLE_END : CONSOLE_EOA); + } + /* console input */ + while(!uxn.dev[0x0f]) { + int c = fgetc(stdin); + if(c == EOF) { + console_input(0x00, CONSOLE_END); + break; + } + console_input(c, CONSOLE_STD); + } } return uxn.dev[0x0f] & 0x7f; } diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -80,12 +80,12 @@ audio_deo(int instance, Uint8 *d, Uint8 port) } Uint8 -emu_dei(Uint8 addr) +emu_dei(Uxn *u, Uint8 addr) { Uint8 p = addr & 0x0f, d = addr & 0xf0; switch(d) { - case 0x00: return system_dei(addr); - case 0x20: return screen_dei(addr); + case 0x00: return system_dei(u, addr); + case 0x20: return screen_dei(u, addr); case 0x30: return audio_dei(0, &uxn.dev[d], p); case 0x40: return audio_dei(1, &uxn.dev[d], p); case 0x50: return audio_dei(2, &uxn.dev[d], p); @@ -96,17 +96,17 @@ emu_dei(Uint8 addr) } void -emu_deo(Uint8 addr, Uint8 value) +emu_deo(Uxn *u, Uint8 addr, Uint8 value) { Uint8 p = addr & 0x0f, d = addr & 0xf0; uxn.dev[addr] = value; switch(d) { case 0x00: - system_deo(addr); + system_deo(u, addr); if(p > 0x7 && p < 0xe) screen_palette(); break; - case 0x10: console_deo(addr); break; - case 0x20: screen_deo(addr); break; + case 0x10: console_deo(u, addr); break; + case 0x20: screen_deo(u, addr); break; case 0x30: audio_deo(0, &uxn.dev[d], p); break; case 0x40: audio_deo(1, &uxn.dev[d], p); break; case 0x50: audio_deo(2, &uxn.dev[d], p); break; @@ -255,19 +255,19 @@ emu_init(void) ms_interval = SDL_GetPerformanceFrequency() / 1000; deadline_interval = ms_interval * TIMEOUT_MS; exec_deadline = SDL_GetPerformanceCounter() + deadline_interval; - screen_change(0, 0, WIDTH,HEIGHT), screen_resize(WIDTH, HEIGHT, 1); + screen_change(0, 0, WIDTH, HEIGHT), screen_resize(WIDTH, HEIGHT, 1); SDL_PauseAudioDevice(audio_id, 1); return 1; } static void -emu_restart(char *rom, int soft) +emu_restart(char *drop, int soft) { - screen_change(0, 0, WIDTH,HEIGHT), screen_resize(WIDTH, HEIGHT, 1); + screen_change(0, 0, WIDTH, HEIGHT), screen_resize(WIDTH, HEIGHT, 1); screen_fill(uxn_screen.bg, 0); screen_fill(uxn_screen.fg, 0); - system_reboot(rom, soft); - SDL_SetWindowTitle(emu_window, boot_rom); + system_reboot(soft); + SDL_SetWindowTitle(emu_window, "Varvara"); } static Uint8 @@ -359,9 +359,9 @@ handle_events(void) else if(event.key.keysym.sym == SDLK_F3) uxn.dev[0x0f] = 0xff; else if(event.key.keysym.sym == SDLK_F4) - emu_restart(boot_rom, 0); + emu_restart(NULL, 0); else if(event.key.keysym.sym == SDLK_F5) - emu_restart(boot_rom, 1); + emu_restart(NULL, 1); else if(event.key.keysym.sym == SDLK_F11) set_fullscreen(!fullscreen, 1); else if(event.key.keysym.sym == SDLK_F12) @@ -437,7 +437,7 @@ emu_run(char *rom) if(now >= next_refresh) { now = SDL_GetPerformanceCounter(); next_refresh = now + frame_interval; - uxn_eval(screen_vector); + uxn_eval(&uxn, screen_vector); if(screen_changed()) emu_redraw(); } @@ -452,6 +452,7 @@ emu_run(char *rom) static int emu_end(void) { + int exitcode = uxn.dev[0x0f] & 0x7f; SDL_CloseAudioDevice(audio_id); #ifdef _WIN32 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" @@ -460,8 +461,8 @@ emu_end(void) close(0); /* make stdin thread exit */ #endif SDL_Quit(); - free(uxn.ram); - return uxn.dev[0x0f] & 0x7f; + free(bios.ram); + return exitcode; } int @@ -472,7 +473,7 @@ main(int argc, char **argv) /* flags */ if(argc > 1 && argv[i][0] == '-') { if(!strcmp(argv[i], "-v")) - return system_error("Uxnemu - Varvara Emulator", "12 Nov 2024."); + return system_error("Uxnemu - Varvara Emulator", "27 Nov 2024."); else if(!strcmp(argv[i], "-2x")) set_zoom(2, 0); else if(!strcmp(argv[i], "-3x")) @@ -483,15 +484,16 @@ main(int argc, char **argv) } /* start */ rom = i == argc ? "boot.rom" : argv[i++]; - if(!system_boot((Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), rom)) + if(!system_boot((Uint8 *)calloc(0x10000 * RAM_PAGES + 1, sizeof(Uint8)), rom)) return system_error("usage:", "uxnemu [-v | -f | -2x | -3x] file.rom [args...]"); if(!emu_init()) return system_error("Init", "Failed to initialize varvara."); /* loop */ uxn.dev[0x17] = argc - i; - if(uxn_eval(PAGE_PROGRAM)) { + if(uxn_eval(&uxn, PAGE_PROGRAM)) { + /* uxn_eval(&bios, PAGE_PROGRAM); */ console_listen(i, argc, argv); - emu_run(boot_rom); + emu_run(rom); } return emu_end(); }