uxn

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

commit 287bc67e1e8a537e6e9cb8af5e0f8919970f7a32
parent 18dddbacd6bf253619045b06ab0c31f4e52545e3
Author: Andrew Alderwick <andrew@alderwick.co.uk>
Date:   Thu,  4 Nov 2021 16:38:32 +0000

Split talk functions into dei and deo; make deo functions void

Diffstat:
Msrc/uxn-fast.c | 35++++++++++++++---------------------
Msrc/uxn.c | 15++++++++-------
Msrc/uxn.h | 5+++--
Msrc/uxncli.c | 129++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/uxnemu.c | 243+++++++++++++++++++++++++++++++++++++++++--------------------------------------
5 files changed, 217 insertions(+), 210 deletions(-)

diff --git a/src/uxn-fast.c b/src/uxn-fast.c @@ -30,11 +30,11 @@ See etc/mkuxn-fast.moon for instructions. /* clang-format off */ static void poke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; } static Uint8 peek8(Uint8 *m, Uint16 a) { return m[a]; } -static int devw8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; return d->talk(d, a & 0x0f, 1); } -static Uint8 devr8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } +static void devw8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; d->deo(d, a & 0x0f); } +static Uint8 devr8(Device *d, Uint8 a) { return d->dei(d, a & 0x0f); } void poke16(Uint8 *m, Uint16 a, Uint16 b) { poke8(m, a, b >> 8); poke8(m, a + 1, b); } Uint16 peek16(Uint8 *m, Uint16 a) { return (peek8(m, a) << 8) + peek8(m, a + 1); } -static int devw16(Device *d, Uint8 a, Uint16 b) { return devw8(d, a, b >> 8) && devw8(d, a + 1, b); } +static void devw16(Device *d, Uint8 a, Uint16 b) { devw8(d, a, b >> 8); devw8(d, a + 1, b); } /* clang-format on */ @@ -366,8 +366,7 @@ uxn_eval(Uxn *u, Uint16 vec) case 0x17: /* DEO */ { Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; - if(!devw8(&u->dev[a >> 4], a, b)) - return 1; + devw8(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->wst.ptr < 2, 0)) { u->wst.error = 1; @@ -828,8 +827,7 @@ uxn_eval(Uxn *u, Uint16 vec) { Uint8 a = u->wst.dat[u->wst.ptr - 1]; Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); - if(!devw16(&u->dev[a >> 4], a, b)) - return 1; + devw16(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->wst.ptr < 3, 0)) { u->wst.error = 1; @@ -1272,8 +1270,7 @@ uxn_eval(Uxn *u, Uint16 vec) case 0x57: /* DEOr */ { Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; - if(!devw8(&u->dev[a >> 4], a, b)) - return 1; + devw8(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->rst.ptr < 2, 0)) { u->rst.error = 1; @@ -1734,8 +1731,7 @@ uxn_eval(Uxn *u, Uint16 vec) { Uint8 a = u->rst.dat[u->rst.ptr - 1]; Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); - if(!devw16(&u->dev[a >> 4], a, b)) - return 1; + devw16(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->rst.ptr < 3, 0)) { u->rst.error = 1; @@ -2235,8 +2231,7 @@ uxn_eval(Uxn *u, Uint16 vec) case 0x97: /* DEOk */ { Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; - if(!devw8(&u->dev[a >> 4], a, b)) - return 1; + devw8(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->wst.ptr < 2, 0)) { u->wst.error = 1; @@ -2776,8 +2771,7 @@ uxn_eval(Uxn *u, Uint16 vec) { Uint8 a = u->wst.dat[u->wst.ptr - 1]; Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8)); - if(!devw16(&u->dev[a >> 4], a, b)) - return 1; + devw16(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->wst.ptr < 3, 0)) { u->wst.error = 1; @@ -3309,8 +3303,7 @@ uxn_eval(Uxn *u, Uint16 vec) case 0xd7: /* DEOkr */ { Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; - if(!devw8(&u->dev[a >> 4], a, b)) - return 1; + devw8(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->rst.ptr < 2, 0)) { u->rst.error = 1; @@ -3850,8 +3843,7 @@ uxn_eval(Uxn *u, Uint16 vec) { Uint8 a = u->rst.dat[u->rst.ptr - 1]; Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8)); - if(!devw16(&u->dev[a >> 4], a, b)) - return 1; + devw16(&u->dev[a >> 4], a, b); #ifndef NO_STACK_CHECKS if(__builtin_expect(u->rst.ptr < 3, 0)) { u->rst.error = 1; @@ -4036,12 +4028,13 @@ uxn_boot(Uxn *u) } Device * -uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *d, Uint8 b0, Uint8 w)) +uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *d, Uint8 b0), void (*deofn)(Device *d, Uint8 b0)) { Device *d = &u->dev[id]; d->addr = id * 0x10; d->u = u; d->mem = u->ram.dat; - d->talk = talkfn; + d->dei = deifn; + d->deo = deofn; return d; } diff --git a/src/uxn.c b/src/uxn.c @@ -26,7 +26,7 @@ static Uint16 (*pop8)(Stack *s); static Uint16 (*pop)(Stack *s); static void (*poke)(Uint8 *m, Uint16 a, Uint16 b); static Uint16 (*peek)(Uint8 *m, Uint16 a); -static int (*devw)(Device *d, Uint8 a, Uint16 b); +static void (*devw)(Device *d, Uint8 a, Uint16 b); static Uint16 (*devr)(Device *d, Uint8 a); static void (*warp)(Uxn *u, Uint16 a); static void (*pull)(Uxn *u); @@ -36,8 +36,8 @@ static Uint16 pop8k(Stack *s) { if(s->kptr == 0) { s->error = 1; return 0; } ret static Uint16 pop8d(Stack *s) { if(s->ptr == 0) { s->error = 1; return 0; } return s->dat[--s->ptr]; } static void poke8(Uint8 *m, Uint16 a, Uint16 b) { m[a] = b; } static Uint16 peek8(Uint8 *m, Uint16 a) { return m[a]; } -static int devw8(Device *d, Uint8 a, Uint16 b) { d->dat[a & 0xf] = b; return d->talk(d, a & 0x0f, 1); } -static Uint16 devr8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } +static void devw8(Device *d, Uint8 a, Uint16 b) { d->dat[a & 0xf] = b; d->deo(d, a & 0x0f); } +static Uint16 devr8(Device *d, Uint8 a) { return d->dei(d, a & 0x0f); } static void warp8(Uxn *u, Uint16 a){ u->ram.ptr += (Sint8)a; } static void pull8(Uxn *u){ push8(u->src, peek8(u->ram.dat, u->ram.ptr++)); } /* short mode */ @@ -45,7 +45,7 @@ static void push16(Stack *s, Uint16 a) { push8(s, a >> 8); push8(s, a); } static Uint16 pop16(Stack *s) { Uint8 a = pop8(s), b = pop8(s); return a + (b << 8); } void poke16(Uint8 *m, Uint16 a, Uint16 b) { poke8(m, a, b >> 8); poke8(m, a + 1, b); } Uint16 peek16(Uint8 *m, Uint16 a) { return (peek8(m, a) << 8) + peek8(m, a + 1); } -static int devw16(Device *d, Uint8 a, Uint16 b) { return devw8(d, a, b >> 8) && devw8(d, a + 1, b); } +static void devw16(Device *d, Uint8 a, Uint16 b) { devw8(d, a, b >> 8); devw8(d, a + 1, b); } static Uint16 devr16(Device *d, Uint8 a) { return (devr8(d, a) << 8) + devr8(d, a + 1); } static void warp16(Uxn *u, Uint16 a){ u->ram.ptr = a; } static void pull16(Uxn *u){ push16(u->src, peek16(u->ram.dat, u->ram.ptr++)); u->ram.ptr++; } @@ -116,7 +116,7 @@ uxn_eval(Uxn *u, Uint16 vec) case 0x14: /* LDA */ a = pop16(u->src); push(u->src, peek(u->ram.dat, a)); break; case 0x15: /* STA */ a = pop16(u->src); b = pop(u->src); poke(u->ram.dat, a, b); break; case 0x16: /* DEI */ a = pop8(u->src); push(u->src, devr(&u->dev[a >> 4], a)); break; - case 0x17: /* DEO */ a = pop8(u->src); b = pop(u->src); if (!devw(&u->dev[a >> 4], a, b)) return 1; break; + case 0x17: /* DEO */ a = pop8(u->src); b = pop(u->src); devw(&u->dev[a >> 4], a, b); break; /* Arithmetic */ case 0x18: /* ADD */ a = pop(u->src), b = pop(u->src); push(u->src, b + a); break; case 0x19: /* SUB */ a = pop(u->src), b = pop(u->src); push(u->src, b - a); break; @@ -146,12 +146,13 @@ uxn_boot(Uxn *u) } Device * -uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *d, Uint8 b0, Uint8 w)) +uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *d, Uint8 b0), void (*deofn)(Device *d, Uint8 b0)) { Device *d = &u->dev[id]; d->addr = id * 0x10; d->u = u; d->mem = u->ram.dat; - d->talk = talkfn; + d->dei = deifn; + d->deo = deofn; return d; } diff --git a/src/uxn.h b/src/uxn.h @@ -30,7 +30,8 @@ typedef struct Device { struct Uxn *u; Uint8 addr, dat[16], *mem; Uint16 vector; - int (*talk)(struct Device *d, Uint8, Uint8); + Uint8 (*dei)(struct Device *d, Uint8); + void (*deo)(struct Device *d, Uint8); } Device; typedef struct Uxn { @@ -47,4 +48,4 @@ Uint16 peek16(Uint8 *m, Uint16 a); int uxn_boot(Uxn *c); int uxn_eval(Uxn *u, Uint16 vec); int uxn_halt(Uxn *u, Uint8 error, char *name, int id); -Device *uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *, Uint8, Uint8)); +Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8)); diff --git a/src/uxncli.c b/src/uxncli.c @@ -43,43 +43,43 @@ inspect(Stack *s, char *name) #pragma mark - Devices -static int -system_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +system_dei(Device *d, Uint8 b0) { - if(!w) { /* read */ - switch(b0) { - 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 0xe: - inspect(&d->u->wst, "Working-stack"); - inspect(&d->u->rst, "Return-stack"); - break; - case 0xf: return 0; - } + switch(b0) { + case 0x2: return d->u->wst.ptr; + case 0x3: return d->u->rst.ptr; + default: return d->dat[b0]; } - return 1; } -static int -console_talk(Device *d, Uint8 b0, Uint8 w) +static void +system_deo(Device *d, Uint8 b0) +{ + switch(b0) { + case 0x2: d->u->wst.ptr = d->dat[b0]; break; + case 0x3: d->u->rst.ptr = d->dat[b0]; break; + case 0xe: + inspect(&d->u->wst, "Working-stack"); + inspect(&d->u->rst, "Return-stack"); + break; + } +} + +static void +console_deo(Device *d, Uint8 b0) { if(b0 == 0x1) d->vector = peek16(d->dat, 0x0); - if(w && b0 > 0x7) + if(b0 > 0x7) write(b0 - 0x7, (char *)&d->dat[b0], 1); - return 1; } -static int -file_talk(Device *d, Uint8 b0, Uint8 w) +static void +file_deo(Device *d, Uint8 b0) { Uint8 read = b0 == 0xd; - if(w && (read || b0 == 0xf)) { + if(read || b0 == 0xf) { char *name = (char *)&d->mem[peek16(d->dat, 0x8)]; Uint16 result = 0, length = peek16(d->dat, 0xa); long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6); @@ -92,36 +92,39 @@ file_talk(Device *d, Uint8 b0, Uint8 w) } poke16(d->dat, 0x2, result); } - return 1; } -static int -datetime_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +datetime_dei(Device *d, Uint8 b0) { time_t seconds = time(NULL); struct tm *t = localtime(&seconds); - t->tm_year += 1900; - poke16(d->dat, 0x0, t->tm_year); - d->dat[0x2] = t->tm_mon; - d->dat[0x3] = t->tm_mday; - d->dat[0x4] = t->tm_hour; - d->dat[0x5] = t->tm_min; - d->dat[0x6] = t->tm_sec; - d->dat[0x7] = t->tm_wday; - poke16(d->dat, 0x08, t->tm_yday); - d->dat[0xa] = t->tm_isdst; - (void)b0; - (void)w; - return 1; + switch(b0) { + case 0x0: return (t->tm_year + 1900) >> 8; + case 0x1: return (t->tm_year + 1900); + case 0x2: return t->tm_mon; + case 0x3: return t->tm_mday; + case 0x4: return t->tm_hour; + case 0x5: return t->tm_min; + case 0x6: return t->tm_sec; + case 0x7: return t->tm_wday; + case 0x8: return t->tm_yday >> 8; + case 0x9: return t->tm_yday; + case 0xa: return t->tm_isdst; + default: return d->dat[b0]; + } } -static int -nil_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +nil_dei(Device *d, Uint8 b0) { - (void)d; - (void)b0; - (void)w; - return 1; + return d->dat[b0]; +} + +static void +nil_deo(Device *d, Uint8 b0) +{ + if(b0 == 0x1) d->vector = peek16(d->dat, 0x0); } #pragma mark - Generics @@ -173,22 +176,22 @@ main(int argc, char **argv) if(!uxn_boot(&u)) return error("Boot", "Failed"); - /* system */ devsystem = uxn_port(&u, 0x0, system_talk); - /* console */ devconsole = uxn_port(&u, 0x1, console_talk); - /* empty */ uxn_port(&u, 0x2, nil_talk); - /* empty */ uxn_port(&u, 0x3, nil_talk); - /* empty */ uxn_port(&u, 0x4, nil_talk); - /* empty */ uxn_port(&u, 0x5, nil_talk); - /* empty */ uxn_port(&u, 0x6, nil_talk); - /* empty */ uxn_port(&u, 0x7, nil_talk); - /* empty */ uxn_port(&u, 0x8, nil_talk); - /* empty */ uxn_port(&u, 0x9, nil_talk); - /* file */ uxn_port(&u, 0xa, file_talk); - /* datetime */ uxn_port(&u, 0xb, datetime_talk); - /* empty */ uxn_port(&u, 0xc, nil_talk); - /* empty */ uxn_port(&u, 0xd, nil_talk); - /* empty */ uxn_port(&u, 0xe, nil_talk); - /* empty */ uxn_port(&u, 0xf, nil_talk); + /* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo); + /* console */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo); + /* empty */ uxn_port(&u, 0x2, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x3, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x4, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x5, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x6, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x7, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x8, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0x9, nil_dei, nil_deo); + /* file */ uxn_port(&u, 0xa, nil_dei, file_deo); + /* datetime */ uxn_port(&u, 0xb, datetime_dei, nil_deo); + /* empty */ uxn_port(&u, 0xc, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0xd, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0xe, nil_dei, nil_deo); + /* empty */ uxn_port(&u, 0xf, nil_dei, nil_deo); for(i = 1; i < argc; ++i) { if(!loaded++) { diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -289,87 +289,89 @@ doctrl(SDL_Event *event, int z) #pragma mark - Devices -static int -system_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +system_dei(Device *d, Uint8 b0) { - if(!w) { /* read */ - switch(b0) { - 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: return 0; - } - if(b0 > 0x7 && b0 < 0xe) - set_palette(&d->dat[0x8]); + switch(b0) { + case 0x2: return d->u->wst.ptr; + case 0x3: return d->u->rst.ptr; + default: return d->dat[b0]; } - return 1; } -static int -console_talk(Device *d, Uint8 b0, Uint8 w) +static void +system_deo(Device *d, Uint8 b0) { - if(w) { - if(b0 == 0x1) - d->vector = peek16(d->dat, 0x0); - if(b0 > 0x7) - write(b0 - 0x7, (char *)&d->dat[b0], 1); + switch(b0) { + case 0x2: d->u->wst.ptr = d->dat[b0]; break; + case 0x3: d->u->rst.ptr = d->dat[b0]; break; } - return 1; + if(b0 > 0x7 && b0 < 0xe) + set_palette(&d->dat[0x8]); } -static int -screen_talk(Device *d, Uint8 b0, Uint8 w) +static void +console_deo(Device *d, Uint8 b0) { - if(!w) switch(b0) { - case 0x2: d->dat[0x2] = ppu.width >> 8; break; - case 0x3: d->dat[0x3] = ppu.width; break; - case 0x4: d->dat[0x4] = ppu.height >> 8; break; - case 0x5: d->dat[0x5] = ppu.height; break; - } - else - switch(b0) { - case 0x1: d->vector = peek16(d->dat, 0x0); break; - case 0x5: - if(!FIXED_SIZE) return set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1); - break; - case 0xe: { - Uint16 x = peek16(d->dat, 0x8); - Uint16 y = peek16(d->dat, 0xa); - Uint8 layer = d->dat[0xe] & 0x40; - ppu_write(&ppu, !!layer, x, y, d->dat[0xe] & 0x3); - if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */ - if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */ - break; - } - case 0xf: { - Uint16 x = peek16(d->dat, 0x8); - Uint16 y = peek16(d->dat, 0xa); - Uint8 layer = d->dat[0xf] & 0x40; - Uint8 *addr = &d->mem[peek16(d->dat, 0xc)]; - if(d->dat[0xf] & 0x80) { - ppu_2bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); - if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */ - } else { - ppu_1bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); - if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */ - } - if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */ - if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */ - break; - } + if(b0 == 0x1) + d->vector = peek16(d->dat, 0x0); + if(b0 > 0x7) + write(b0 - 0x7, (char *)&d->dat[b0], 1); +} + +static Uint8 +screen_dei(Device *d, Uint8 b0) +{ + switch(b0) { + case 0x2: return ppu.width >> 8; + case 0x3: return ppu.width; + case 0x4: return ppu.height >> 8; + case 0x5: return ppu.height; + default: return d->dat[b0]; + } +} + +static void +screen_deo(Device *d, Uint8 b0) +{ + switch(b0) { + case 0x1: d->vector = peek16(d->dat, 0x0); break; + case 0x5: + if(!FIXED_SIZE) set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1); + break; + case 0xe: { + Uint16 x = peek16(d->dat, 0x8); + Uint16 y = peek16(d->dat, 0xa); + Uint8 layer = d->dat[0xe] & 0x40; + ppu_write(&ppu, !!layer, x, y, d->dat[0xe] & 0x3); + if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */ + if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */ + break; + } + case 0xf: { + Uint16 x = peek16(d->dat, 0x8); + Uint16 y = peek16(d->dat, 0xa); + Uint8 layer = d->dat[0xf] & 0x40; + Uint8 *addr = &d->mem[peek16(d->dat, 0xc)]; + if(d->dat[0xf] & 0x80) { + ppu_2bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); + if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */ + } else { + ppu_1bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); + if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */ } - return 1; + if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */ + if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */ + break; + } + } } -static int -file_talk(Device *d, Uint8 b0, Uint8 w) +static void +file_deo(Device *d, Uint8 b0) { Uint8 read = b0 == 0xd; - if(w && (read || b0 == 0xf)) { + if(read || b0 == 0xf) { char *name = (char *)&d->mem[peek16(d->dat, 0x8)]; Uint16 result = 0, length = peek16(d->dat, 0xa); long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6); @@ -382,20 +384,26 @@ file_talk(Device *d, Uint8 b0, Uint8 w) } poke16(d->dat, 0x2, result); } - return 1; } -static int -audio_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +audio_dei(Device *d, Uint8 b0) { Apu *c = &apu[d - devaudio0]; - if(!audio_id) return 1; - if(!w) { - if(b0 == 0x2) - poke16(d->dat, 0x2, c->i); - else if(b0 == 0x4) - d->dat[0x4] = apu_get_vu(c); - } else if(b0 == 0xf) { + if(!audio_id) return d->dat[b0]; + switch(b0) { + case 0x4: return apu_get_vu(c); + case 0x2: poke16(d->dat, 0x2, c->i); /* fall through */ + default: return d->dat[b0]; + } +} + +static void +audio_deo(Device *d, Uint8 b0) +{ + Apu *c = &apu[d - devaudio0]; + if(!audio_id) return; + if(b0 == 0xf) { SDL_LockAudioDevice(audio_id); c->len = peek16(d->dat, 0xa); c->addr = &d->mem[peek16(d->dat, 0xc)]; @@ -406,38 +414,39 @@ audio_talk(Device *d, Uint8 b0, Uint8 w) SDL_UnlockAudioDevice(audio_id); SDL_PauseAudioDevice(audio_id, 0); } - return 1; } -static int -datetime_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +datetime_dei(Device *d, Uint8 b0) { time_t seconds = time(NULL); struct tm *t = localtime(&seconds); - t->tm_year += 1900; - poke16(d->dat, 0x0, t->tm_year); - d->dat[0x2] = t->tm_mon; - d->dat[0x3] = t->tm_mday; - d->dat[0x4] = t->tm_hour; - d->dat[0x5] = t->tm_min; - d->dat[0x6] = t->tm_sec; - d->dat[0x7] = t->tm_wday; - poke16(d->dat, 0x08, t->tm_yday); - d->dat[0xa] = t->tm_isdst; - (void)b0; - (void)w; - return 1; + switch(b0) { + case 0x0: return (t->tm_year + 1900) >> 8; + case 0x1: return (t->tm_year + 1900); + case 0x2: return t->tm_mon; + case 0x3: return t->tm_mday; + case 0x4: return t->tm_hour; + case 0x5: return t->tm_min; + case 0x6: return t->tm_sec; + case 0x7: return t->tm_wday; + case 0x8: return t->tm_yday >> 8; + case 0x9: return t->tm_yday; + case 0xa: return t->tm_isdst; + default: return d->dat[b0]; + } } -static int -nil_talk(Device *d, Uint8 b0, Uint8 w) +static Uint8 +nil_dei(Device *d, Uint8 b0) { - if(w && b0 == 0x1) - d->vector = peek16(d->dat, 0x0); - (void)d; - (void)b0; - (void)w; - return 1; + return d->dat[b0]; +} + +static void +nil_deo(Device *d, Uint8 b0) +{ + if(b0 == 0x1) d->vector = peek16(d->dat, 0x0); } static const char *errors[] = {"underflow", "overflow", "division by zero"}; @@ -526,22 +535,22 @@ main(int argc, char **argv) if(!uxn_boot(&u)) return error("Boot", "Failed to start uxn."); - /* system */ devsystem = uxn_port(&u, 0x0, system_talk); - /* console */ devconsole = uxn_port(&u, 0x1, console_talk); - /* screen */ devscreen = uxn_port(&u, 0x2, screen_talk); - /* audio0 */ devaudio0 = uxn_port(&u, 0x3, audio_talk); - /* audio1 */ uxn_port(&u, 0x4, audio_talk); - /* audio2 */ uxn_port(&u, 0x5, audio_talk); - /* audio3 */ uxn_port(&u, 0x6, audio_talk); - /* unused */ uxn_port(&u, 0x7, nil_talk); - /* control */ devctrl = uxn_port(&u, 0x8, nil_talk); - /* mouse */ devmouse = uxn_port(&u, 0x9, nil_talk); - /* file */ uxn_port(&u, 0xa, file_talk); - /* datetime */ uxn_port(&u, 0xb, datetime_talk); - /* unused */ uxn_port(&u, 0xc, nil_talk); - /* unused */ uxn_port(&u, 0xd, nil_talk); - /* unused */ uxn_port(&u, 0xe, nil_talk); - /* unused */ uxn_port(&u, 0xf, nil_talk); + /* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo); + /* console */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo); + /* screen */ devscreen = uxn_port(&u, 0x2, screen_dei, screen_deo); + /* audio0 */ devaudio0 = uxn_port(&u, 0x3, audio_dei, audio_deo); + /* audio1 */ uxn_port(&u, 0x4, audio_dei, audio_deo); + /* audio2 */ uxn_port(&u, 0x5, audio_dei, audio_deo); + /* audio3 */ uxn_port(&u, 0x6, audio_dei, audio_deo); + /* unused */ uxn_port(&u, 0x7, nil_dei, nil_deo); + /* control */ devctrl = uxn_port(&u, 0x8, nil_dei, nil_deo); + /* mouse */ devmouse = uxn_port(&u, 0x9, nil_dei, nil_deo); + /* file */ uxn_port(&u, 0xa, nil_dei, file_deo); + /* datetime */ uxn_port(&u, 0xb, datetime_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); /* set default zoom */ if(SDL_GetCurrentDisplayMode(0, &DM) == 0)