Compare commits

...

4 Commits

Author SHA1 Message Date
Nico fcb04138fa Merge commit 'ee638b70e5' into varvara 2021-11-17 09:38:13 +00:00
Nico ee638b70e5 cleanup, fix devices 2021-11-17 09:37:48 +00:00
Nico 1416893720 make file device build on hardwar 2021-11-16 19:43:56 +00:00
Nico ee3fa037d2 update to newer uxn core 2021-11-16 18:46:24 +00:00
6 changed files with 236 additions and 4138 deletions

View File

@ -1,17 +0,0 @@
( dev/console )
|10 @Console $8 &write
( init )
|0100 ( -> )
;hello-word
&while
( send ) LDAk .Console/write DEO
INC2 LDAk ,&while JCN
POP2
BRK
@hello-word "Hello 20 "Uxn!

View File

@ -49,14 +49,14 @@ file_cleanup(void)
static Uint16
get_entry(char *p, Uint16 len, const char *basename, struct dirinfo info)
{
if(len < strlen(basename) + 7)
if(len < rb->strlen(basename) + 7)
return 0;
else if(info.attribute & ATTR_DIRECTORY)
return snprintf(p, len, "---- %s\n", basename);
return rb->snprintf(p, len, "---- %s\n", basename);
else if(info.size < 0x10000)
return snprintf(p, len, "%04x %s\n", (Uint16)info.size, basename);
return rb->snprintf(p, len, "%04x %s\n", (Uint16)info.size, basename);
else
return snprintf(p, len, "???? %s\n", basename);
return rb->snprintf(p, len, "???? %s\n", basename);
}
static Uint16
@ -80,7 +80,7 @@ Uint16
file_init(const char *filename)
{
file_cleanup();
snprintf(current_filename, sizeof(current_filename), "/%s", (filename[0] == '/') ? &filename[1] : filename);
rb->snprintf(current_filename, sizeof(current_filename), "/%s", (filename[0] == '/') ? &filename[1] : filename);
return 0;
}
@ -122,7 +122,7 @@ file_stat(void *dest, Uint16 len)
{
DIR *sd;
struct dirent *sde;
char *basename = strrchr(current_filename, '/');
char *basename = rb->strrchr(current_filename, '/');
if(basename != current_filename) {
*basename = '\0';
sd = rb->opendir(current_filename);
@ -133,7 +133,7 @@ file_stat(void *dest, Uint16 len)
}
if(sd == NULL) return 0;
while((sde = rb->readdir(sd)) != NULL) {
if(!strcmp(sde->d_name, basename)) {
if(!rb->strcmp(sde->d_name, basename)) {
Uint16 ret = get_entry(dest, len, basename, rb->dir_get_info(sd, sde));
rb->closedir(sd);
return ret;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#include "uxn.h"
#include <stdio.h>
/*
Copyright (u) 2021 Devine Lu Linvega
Copyright (u) 2021 Andrew Alderwick
@ -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 port), void (*deofn)(Device *d, Uint8 port))
{
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;
}

View File

@ -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));

View File

@ -11,8 +11,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
TODO optimise support for greyscale/1-bit displays
TODO rom loading
TODO other varvara devices
TODO audio device
TODO clean up
*/
@ -85,89 +84,86 @@ set_palette(Uint8 *addr)
}
/* taken from uxncli */
static int
system_talk(Device *d, Uint8 b0, Uint8 w)
static void
system_deo(Device *d, Uint8 port)
{
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) {
switch(port) {
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;
}
if(b0 > 0x7 && b0 < 0xe)
if(port > 0x7 && port < 0xe)
set_palette(&d->dat[0x8]);
}
static Uint8 system_dei(Device *d, Uint8 port) {
switch(port) {
case 0x2: return d->u->wst.ptr; break;
case 0x3: return d->u->rst.ptr; break;
}
}
/* taken from uxncli */
static void
console_deo(Device *d, Uint8 port)
{
if(port == 0x1)
d->vector = peek16(d->dat, 0x0);
if(port > 0x7)
DEBUGF("%c",(char *)&d->dat[port]);
}
/* taken from uxnemu */
static Uint8
screen_dei(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return ppu.width >> 8; break;
case 0x3: return ppu.width; break;
case 0x4: return ppu.height >> 8; break;
case 0x5: return ppu.height; break;
default: return d->dat[port];
}
return 1;
}
/* taken from uxncli */
static int
console_talk(Device *d, Uint8 b0, Uint8 w)
{
if(b0 == 0x1)
d->vector = peek16(d->dat, 0x0);
if(w && b0 > 0x7)
DEBUGF("%c",(char *)&d->dat[b0]);
return 1;
static void
screen_deo(Device *d, Uint8 port) {
switch(port) {
case 0x1: d->vector = peek16(d->dat, 0x0); break;
case 0x5:
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;
}
}
}
/* taken from uxnemu */
static int
screen_talk(Device *d, Uint8 b0, Uint8 w)
static void
file_deo(Device *d, Uint8 port)
{
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:
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
file_talk(Device *d, Uint8 b0, Uint8 w)
{
if(w) switch(b0) {
switch(port) {
case 0x1: d->vector = peek16(d->dat, 0x0); break;
case 0x9: poke16(d->dat, 0x2, file_init(&d->mem[peek16(d->dat, 0x8)])); break;
case 0xd: poke16(d->dat, 0x2, file_read(&d->mem[peek16(d->dat, 0xc)], peek16(d->dat, 0xa))); break;
@ -175,35 +171,42 @@ file_talk(Device *d, Uint8 b0, Uint8 w)
case 0x5: poke16(d->dat, 0x2, file_stat(&d->mem[peek16(d->dat, 0x4)], peek16(d->dat, 0xa))); break;
case 0x6: poke16(d->dat, 0x2, file_delete()); break;
}
return 1;
}
static int
nil_talk(Device *d, Uint8 b0, Uint8 w)
static void
nil_deo(Device *d, Uint8 port)
{
(void)d;
(void)b0;
(void)w;
return 1;
(void)port;
}
static int
datetime_talk(Device *d, Uint8 b0, Uint8 w)
static Uint8
nil_dei(Device *d, Uint8 port)
{
(void)d;
(void)port;
return 1;
}
static Uint8
datetime_dei(Device *d, Uint8 port)
{
struct tm* t = rb->get_time();
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(port) {
case 0x0: return t->tm_year >> 8;
case 0x1: return t->tm_year;
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[port];
}
}
// TODO mono and greyscale that don't suck
@ -257,8 +260,8 @@ static void run() {
// TODO allow scrolls (that don't have a button release) to be mapped as buttons
if(b == VARVARA_MENU)
return;
if(b == VARVARA_A)
devctrl->dat[2] += 0x01;
if(b == VARVARA_A)
devctrl->dat[2] += 0x01;
if(b == (VARVARA_A | BUTTON_REL))
devctrl->dat[2] -= 0x01;
if(b == VARVARA_B)
@ -333,22 +336,22 @@ enum plugin_status plugin_start(const void* parameter)
ppu_init(&ppu, LCD_WIDTH, LCD_HEIGHT, framebuffer);
// Register ports
/* 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 */ uxn_port(&u, 0x3, nil_talk);
/* audio1 */ uxn_port(&u, 0x4, nil_talk);
/* audio2 */ uxn_port(&u, 0x5, nil_talk);
/* audio3 */ uxn_port(&u, 0x6, nil_talk);
/* empty */ uxn_port(&u, 0x7, nil_talk);
/* control */ devctrl = uxn_port(&u, 0x8, nil_talk);
/* mouse */ 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);
/* screen */ devscreen = uxn_port(&u, 0x2, screen_dei, screen_deo);
/* audio0 */ uxn_port(&u, 0x3, nil_dei, nil_deo);
/* audio1 */ uxn_port(&u, 0x4, nil_dei, nil_deo);
/* audio2 */ uxn_port(&u, 0x5, nil_dei, nil_deo);
/* audio3 */ uxn_port(&u, 0x6, nil_dei, nil_deo);
/* empty */ uxn_port(&u, 0x7, nil_dei, nil_deo);
/* control */ devctrl = uxn_port(&u, 0x8, nil_dei, nil_deo);
/* mouse */ 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);
uxn_eval(&u, 0x0100);
run();
file_cleanup();