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

This commit is contained in:
Andrew Alderwick 2021-11-04 16:38:32 +00:00
parent 18dddbacd6
commit 287bc67e1e
5 changed files with 218 additions and 211 deletions

View File

@ -30,11 +30,11 @@ See etc/mkuxn-fast.moon for instructions.
/* clang-format off */ /* clang-format off */
static void poke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; } static void poke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; }
static Uint8 peek8(Uint8 *m, Uint16 a) { return m[a]; } 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 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) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } 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); } 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); } 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 */ /* clang-format on */
@ -366,8 +366,7 @@ uxn_eval(Uxn *u, Uint16 vec)
case 0x17: /* DEO */ case 0x17: /* DEO */
{ {
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 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)) devw8(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 2, 0)) { if(__builtin_expect(u->wst.ptr < 2, 0)) {
u->wst.error = 1; u->wst.error = 1;
@ -828,8 +827,7 @@ uxn_eval(Uxn *u, Uint16 vec)
{ {
Uint8 a = u->wst.dat[u->wst.ptr - 1]; 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)); 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)) devw16(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 3, 0)) { if(__builtin_expect(u->wst.ptr < 3, 0)) {
u->wst.error = 1; u->wst.error = 1;
@ -1272,8 +1270,7 @@ uxn_eval(Uxn *u, Uint16 vec)
case 0x57: /* DEOr */ case 0x57: /* DEOr */
{ {
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 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)) devw8(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 2, 0)) { if(__builtin_expect(u->rst.ptr < 2, 0)) {
u->rst.error = 1; u->rst.error = 1;
@ -1734,8 +1731,7 @@ uxn_eval(Uxn *u, Uint16 vec)
{ {
Uint8 a = u->rst.dat[u->rst.ptr - 1]; 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)); 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)) devw16(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 3, 0)) { if(__builtin_expect(u->rst.ptr < 3, 0)) {
u->rst.error = 1; u->rst.error = 1;
@ -2235,8 +2231,7 @@ uxn_eval(Uxn *u, Uint16 vec)
case 0x97: /* DEOk */ case 0x97: /* DEOk */
{ {
Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2]; 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)) devw8(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 2, 0)) { if(__builtin_expect(u->wst.ptr < 2, 0)) {
u->wst.error = 1; u->wst.error = 1;
@ -2776,8 +2771,7 @@ uxn_eval(Uxn *u, Uint16 vec)
{ {
Uint8 a = u->wst.dat[u->wst.ptr - 1]; 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)); 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)) devw16(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->wst.ptr < 3, 0)) { if(__builtin_expect(u->wst.ptr < 3, 0)) {
u->wst.error = 1; u->wst.error = 1;
@ -3309,8 +3303,7 @@ uxn_eval(Uxn *u, Uint16 vec)
case 0xd7: /* DEOkr */ case 0xd7: /* DEOkr */
{ {
Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2]; 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)) devw8(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 2, 0)) { if(__builtin_expect(u->rst.ptr < 2, 0)) {
u->rst.error = 1; u->rst.error = 1;
@ -3850,8 +3843,7 @@ uxn_eval(Uxn *u, Uint16 vec)
{ {
Uint8 a = u->rst.dat[u->rst.ptr - 1]; 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)); 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)) devw16(&u->dev[a >> 4], a, b);
return 1;
#ifndef NO_STACK_CHECKS #ifndef NO_STACK_CHECKS
if(__builtin_expect(u->rst.ptr < 3, 0)) { if(__builtin_expect(u->rst.ptr < 3, 0)) {
u->rst.error = 1; u->rst.error = 1;
@ -4036,12 +4028,13 @@ uxn_boot(Uxn *u)
} }
Device * 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]; Device *d = &u->dev[id];
d->addr = id * 0x10; d->addr = id * 0x10;
d->u = u; d->u = u;
d->mem = u->ram.dat; d->mem = u->ram.dat;
d->talk = talkfn; d->dei = deifn;
d->deo = deofn;
return d; return d;
} }

View File

@ -26,7 +26,7 @@ static Uint16 (*pop8)(Stack *s);
static Uint16 (*pop)(Stack *s); static Uint16 (*pop)(Stack *s);
static void (*poke)(Uint8 *m, Uint16 a, Uint16 b); static void (*poke)(Uint8 *m, Uint16 a, Uint16 b);
static Uint16 (*peek)(Uint8 *m, Uint16 a); 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 Uint16 (*devr)(Device *d, Uint8 a);
static void (*warp)(Uxn *u, Uint16 a); static void (*warp)(Uxn *u, Uint16 a);
static void (*pull)(Uxn *u); 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 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 void poke8(Uint8 *m, Uint16 a, Uint16 b) { m[a] = b; }
static Uint16 peek8(Uint8 *m, Uint16 a) { return m[a]; } 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 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) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; } 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 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++)); } static void pull8(Uxn *u){ push8(u->src, peek8(u->ram.dat, u->ram.ptr++)); }
/* short mode */ /* 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); } 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); } 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); } 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 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 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++; } 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 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 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 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 */ /* Arithmetic */
case 0x18: /* ADD */ a = pop(u->src), b = pop(u->src); push(u->src, b + a); break; 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; 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 * 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]; Device *d = &u->dev[id];
d->addr = id * 0x10; d->addr = id * 0x10;
d->u = u; d->u = u;
d->mem = u->ram.dat; d->mem = u->ram.dat;
d->talk = talkfn; d->dei = deifn;
d->deo = deofn;
return d; return d;
} }

View File

@ -30,7 +30,8 @@ typedef struct Device {
struct Uxn *u; struct Uxn *u;
Uint8 addr, dat[16], *mem; Uint8 addr, dat[16], *mem;
Uint16 vector; Uint16 vector;
int (*talk)(struct Device *d, Uint8, Uint8); Uint8 (*dei)(struct Device *d, Uint8);
void (*deo)(struct Device *d, Uint8);
} Device; } Device;
typedef struct Uxn { typedef struct Uxn {
@ -47,4 +48,4 @@ Uint16 peek16(Uint8 *m, Uint16 a);
int uxn_boot(Uxn *c); int uxn_boot(Uxn *c);
int uxn_eval(Uxn *u, Uint16 vec); int uxn_eval(Uxn *u, Uint16 vec);
int uxn_halt(Uxn *u, Uint8 error, char *name, int id); 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));

View File

@ -43,43 +43,43 @@ inspect(Stack *s, char *name)
#pragma mark - Devices #pragma mark - Devices
static int static Uint8
system_talk(Device *d, Uint8 b0, Uint8 w) system_dei(Device *d, Uint8 b0)
{ {
if(!w) { /* read */ switch(b0) {
switch(b0) { case 0x2: return d->u->wst.ptr;
case 0x2: d->dat[0x2] = d->u->wst.ptr; break; case 0x3: return d->u->rst.ptr;
case 0x3: d->dat[0x3] = d->u->rst.ptr; break; default: return d->dat[b0];
}
} 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;
}
} }
return 1;
} }
static int static void
console_talk(Device *d, Uint8 b0, Uint8 w) 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) if(b0 == 0x1)
d->vector = peek16(d->dat, 0x0); d->vector = peek16(d->dat, 0x0);
if(w && b0 > 0x7) if(b0 > 0x7)
write(b0 - 0x7, (char *)&d->dat[b0], 1); write(b0 - 0x7, (char *)&d->dat[b0], 1);
return 1;
} }
static int static void
file_talk(Device *d, Uint8 b0, Uint8 w) file_deo(Device *d, Uint8 b0)
{ {
Uint8 read = b0 == 0xd; Uint8 read = b0 == 0xd;
if(w && (read || b0 == 0xf)) { if(read || b0 == 0xf) {
char *name = (char *)&d->mem[peek16(d->dat, 0x8)]; char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
Uint16 result = 0, length = peek16(d->dat, 0xa); Uint16 result = 0, length = peek16(d->dat, 0xa);
long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6); 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); poke16(d->dat, 0x2, result);
} }
return 1;
} }
static int static Uint8
datetime_talk(Device *d, Uint8 b0, Uint8 w) datetime_dei(Device *d, Uint8 b0)
{ {
time_t seconds = time(NULL); time_t seconds = time(NULL);
struct tm *t = localtime(&seconds); struct tm *t = localtime(&seconds);
t->tm_year += 1900; switch(b0) {
poke16(d->dat, 0x0, t->tm_year); case 0x0: return (t->tm_year + 1900) >> 8;
d->dat[0x2] = t->tm_mon; case 0x1: return (t->tm_year + 1900);
d->dat[0x3] = t->tm_mday; case 0x2: return t->tm_mon;
d->dat[0x4] = t->tm_hour; case 0x3: return t->tm_mday;
d->dat[0x5] = t->tm_min; case 0x4: return t->tm_hour;
d->dat[0x6] = t->tm_sec; case 0x5: return t->tm_min;
d->dat[0x7] = t->tm_wday; case 0x6: return t->tm_sec;
poke16(d->dat, 0x08, t->tm_yday); case 0x7: return t->tm_wday;
d->dat[0xa] = t->tm_isdst; case 0x8: return t->tm_yday >> 8;
(void)b0; case 0x9: return t->tm_yday;
(void)w; case 0xa: return t->tm_isdst;
return 1; default: return d->dat[b0];
}
} }
static int static Uint8
nil_talk(Device *d, Uint8 b0, Uint8 w) nil_dei(Device *d, Uint8 b0)
{ {
(void)d; return d->dat[b0];
(void)b0; }
(void)w;
return 1; static void
nil_deo(Device *d, Uint8 b0)
{
if(b0 == 0x1) d->vector = peek16(d->dat, 0x0);
} }
#pragma mark - Generics #pragma mark - Generics
@ -173,22 +176,22 @@ main(int argc, char **argv)
if(!uxn_boot(&u)) if(!uxn_boot(&u))
return error("Boot", "Failed"); return error("Boot", "Failed");
/* system */ devsystem = uxn_port(&u, 0x0, system_talk); /* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo);
/* console */ devconsole = uxn_port(&u, 0x1, console_talk); /* console */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo);
/* empty */ uxn_port(&u, 0x2, nil_talk); /* empty */ uxn_port(&u, 0x2, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x3, nil_talk); /* empty */ uxn_port(&u, 0x3, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x4, nil_talk); /* empty */ uxn_port(&u, 0x4, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x5, nil_talk); /* empty */ uxn_port(&u, 0x5, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x6, nil_talk); /* empty */ uxn_port(&u, 0x6, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x7, nil_talk); /* empty */ uxn_port(&u, 0x7, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x8, nil_talk); /* empty */ uxn_port(&u, 0x8, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x9, nil_talk); /* empty */ uxn_port(&u, 0x9, nil_dei, nil_deo);
/* file */ uxn_port(&u, 0xa, file_talk); /* file */ uxn_port(&u, 0xa, nil_dei, file_deo);
/* datetime */ uxn_port(&u, 0xb, datetime_talk); /* datetime */ uxn_port(&u, 0xb, datetime_dei, nil_deo);
/* empty */ uxn_port(&u, 0xc, nil_talk); /* empty */ uxn_port(&u, 0xc, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0xd, nil_talk); /* empty */ uxn_port(&u, 0xd, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0xe, nil_talk); /* empty */ uxn_port(&u, 0xe, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0xf, nil_talk); /* empty */ uxn_port(&u, 0xf, nil_dei, nil_deo);
for(i = 1; i < argc; ++i) { for(i = 1; i < argc; ++i) {
if(!loaded++) { if(!loaded++) {

View File

@ -289,87 +289,89 @@ doctrl(SDL_Event *event, int z)
#pragma mark - Devices #pragma mark - Devices
static int static Uint8
system_talk(Device *d, Uint8 b0, Uint8 w) system_dei(Device *d, Uint8 b0)
{ {
if(!w) { /* read */ switch(b0) {
switch(b0) { case 0x2: return d->u->wst.ptr;
case 0x2: d->dat[0x2] = d->u->wst.ptr; break; case 0x3: return d->u->rst.ptr;
case 0x3: d->dat[0x3] = d->u->rst.ptr; break; default: return d->dat[b0];
}
} 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]);
} }
return 1;
} }
static int static void
console_talk(Device *d, Uint8 b0, Uint8 w) system_deo(Device *d, Uint8 b0)
{ {
if(w) { switch(b0) {
if(b0 == 0x1) case 0x2: d->u->wst.ptr = d->dat[b0]; break;
d->vector = peek16(d->dat, 0x0); case 0x3: d->u->rst.ptr = d->dat[b0]; break;
if(b0 > 0x7)
write(b0 - 0x7, (char *)&d->dat[b0], 1);
} }
return 1; if(b0 > 0x7 && b0 < 0xe)
set_palette(&d->dat[0x8]);
} }
static int static void
screen_talk(Device *d, Uint8 b0, Uint8 w) console_deo(Device *d, Uint8 b0)
{ {
if(!w) switch(b0) { if(b0 == 0x1)
case 0x2: d->dat[0x2] = ppu.width >> 8; break; d->vector = peek16(d->dat, 0x0);
case 0x3: d->dat[0x3] = ppu.width; break; if(b0 > 0x7)
case 0x4: d->dat[0x4] = ppu.height >> 8; break; write(b0 - 0x7, (char *)&d->dat[b0], 1);
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;
}
}
return 1;
} }
static int static Uint8
file_talk(Device *d, Uint8 b0, Uint8 w) 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 */
}
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 void
file_deo(Device *d, Uint8 b0)
{ {
Uint8 read = b0 == 0xd; Uint8 read = b0 == 0xd;
if(w && (read || b0 == 0xf)) { if(read || b0 == 0xf) {
char *name = (char *)&d->mem[peek16(d->dat, 0x8)]; char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
Uint16 result = 0, length = peek16(d->dat, 0xa); Uint16 result = 0, length = peek16(d->dat, 0xa);
long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6); 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); poke16(d->dat, 0x2, result);
} }
return 1;
} }
static int static Uint8
audio_talk(Device *d, Uint8 b0, Uint8 w) audio_dei(Device *d, Uint8 b0)
{ {
Apu *c = &apu[d - devaudio0]; Apu *c = &apu[d - devaudio0];
if(!audio_id) return 1; if(!audio_id) return d->dat[b0];
if(!w) { switch(b0) {
if(b0 == 0x2) case 0x4: return apu_get_vu(c);
poke16(d->dat, 0x2, c->i); case 0x2: poke16(d->dat, 0x2, c->i); /* fall through */
else if(b0 == 0x4) default: return d->dat[b0];
d->dat[0x4] = apu_get_vu(c); }
} else if(b0 == 0xf) { }
static void
audio_deo(Device *d, Uint8 b0)
{
Apu *c = &apu[d - devaudio0];
if(!audio_id) return;
if(b0 == 0xf) {
SDL_LockAudioDevice(audio_id); SDL_LockAudioDevice(audio_id);
c->len = peek16(d->dat, 0xa); c->len = peek16(d->dat, 0xa);
c->addr = &d->mem[peek16(d->dat, 0xc)]; 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_UnlockAudioDevice(audio_id);
SDL_PauseAudioDevice(audio_id, 0); SDL_PauseAudioDevice(audio_id, 0);
} }
return 1;
} }
static int static Uint8
datetime_talk(Device *d, Uint8 b0, Uint8 w) datetime_dei(Device *d, Uint8 b0)
{ {
time_t seconds = time(NULL); time_t seconds = time(NULL);
struct tm *t = localtime(&seconds); struct tm *t = localtime(&seconds);
t->tm_year += 1900; switch(b0) {
poke16(d->dat, 0x0, t->tm_year); case 0x0: return (t->tm_year + 1900) >> 8;
d->dat[0x2] = t->tm_mon; case 0x1: return (t->tm_year + 1900);
d->dat[0x3] = t->tm_mday; case 0x2: return t->tm_mon;
d->dat[0x4] = t->tm_hour; case 0x3: return t->tm_mday;
d->dat[0x5] = t->tm_min; case 0x4: return t->tm_hour;
d->dat[0x6] = t->tm_sec; case 0x5: return t->tm_min;
d->dat[0x7] = t->tm_wday; case 0x6: return t->tm_sec;
poke16(d->dat, 0x08, t->tm_yday); case 0x7: return t->tm_wday;
d->dat[0xa] = t->tm_isdst; case 0x8: return t->tm_yday >> 8;
(void)b0; case 0x9: return t->tm_yday;
(void)w; case 0xa: return t->tm_isdst;
return 1; default: return d->dat[b0];
}
} }
static int static Uint8
nil_talk(Device *d, Uint8 b0, Uint8 w) nil_dei(Device *d, Uint8 b0)
{ {
if(w && b0 == 0x1) return d->dat[b0];
d->vector = peek16(d->dat, 0x0); }
(void)d;
(void)b0; static void
(void)w; nil_deo(Device *d, Uint8 b0)
return 1; {
if(b0 == 0x1) d->vector = peek16(d->dat, 0x0);
} }
static const char *errors[] = {"underflow", "overflow", "division by zero"}; static const char *errors[] = {"underflow", "overflow", "division by zero"};
@ -526,22 +535,22 @@ main(int argc, char **argv)
if(!uxn_boot(&u)) if(!uxn_boot(&u))
return error("Boot", "Failed to start uxn."); return error("Boot", "Failed to start uxn.");
/* system */ devsystem = uxn_port(&u, 0x0, system_talk); /* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo);
/* console */ devconsole = uxn_port(&u, 0x1, console_talk); /* console */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo);
/* screen */ devscreen = uxn_port(&u, 0x2, screen_talk); /* screen */ devscreen = uxn_port(&u, 0x2, screen_dei, screen_deo);
/* audio0 */ devaudio0 = uxn_port(&u, 0x3, audio_talk); /* audio0 */ devaudio0 = uxn_port(&u, 0x3, audio_dei, audio_deo);
/* audio1 */ uxn_port(&u, 0x4, audio_talk); /* audio1 */ uxn_port(&u, 0x4, audio_dei, audio_deo);
/* audio2 */ uxn_port(&u, 0x5, audio_talk); /* audio2 */ uxn_port(&u, 0x5, audio_dei, audio_deo);
/* audio3 */ uxn_port(&u, 0x6, audio_talk); /* audio3 */ uxn_port(&u, 0x6, audio_dei, audio_deo);
/* unused */ uxn_port(&u, 0x7, nil_talk); /* unused */ uxn_port(&u, 0x7, nil_dei, nil_deo);
/* control */ devctrl = uxn_port(&u, 0x8, nil_talk); /* control */ devctrl = uxn_port(&u, 0x8, nil_dei, nil_deo);
/* mouse */ devmouse = uxn_port(&u, 0x9, nil_talk); /* mouse */ devmouse = uxn_port(&u, 0x9, nil_dei, nil_deo);
/* file */ uxn_port(&u, 0xa, file_talk); /* file */ uxn_port(&u, 0xa, nil_dei, file_deo);
/* datetime */ uxn_port(&u, 0xb, datetime_talk); /* datetime */ uxn_port(&u, 0xb, datetime_dei, nil_deo);
/* unused */ uxn_port(&u, 0xc, nil_talk); /* unused */ uxn_port(&u, 0xc, nil_dei, nil_deo);
/* unused */ uxn_port(&u, 0xd, nil_talk); /* unused */ uxn_port(&u, 0xd, nil_dei, nil_deo);
/* unused */ uxn_port(&u, 0xe, nil_talk); /* unused */ uxn_port(&u, 0xe, nil_dei, nil_deo);
/* unused */ uxn_port(&u, 0xf, nil_talk); /* unused */ uxn_port(&u, 0xf, nil_dei, nil_deo);
/* set default zoom */ /* set default zoom */
if(SDL_GetCurrentDisplayMode(0, &DM) == 0) if(SDL_GetCurrentDisplayMode(0, &DM) == 0)