uxn

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

commit 27089a77e4720991821197825b8c2f24bbe8d676
parent bca73244f0574aec554e494008e4767388c6a50c
Author: Andrew Alderwick <andrew@alderwick.co.uk>
Date:   Thu, 17 Mar 2022 18:31:33 +0000

Prepare for more than one File device.

Diffstat:
Msrc/devices/file.c | 126+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/devices/file.h | 5++++-
Msrc/uxncli.c | 16+++++++++++++++-
Msrc/uxnemu.c | 16++++++++++++++--
4 files changed, 101 insertions(+), 62 deletions(-)

diff --git a/src/devices/file.c b/src/devices/file.c @@ -19,29 +19,32 @@ WITH REGARD TO THIS SOFTWARE. #include <sys/stat.h> #include <unistd.h> -static FILE *f; -static DIR *dir; -static char *current_filename = ""; -static struct dirent *de; - -static enum { IDLE, - FILE_READ, - FILE_WRITE, - DIR_READ } state; +typedef struct { + FILE *f; + DIR *dir; + char *current_filename; + struct dirent *de; + enum { IDLE, + FILE_READ, + FILE_WRITE, + DIR_READ } state; +} UxnFile; + +static UxnFile uxn_file[POLYFILEY]; static void -reset(void) +reset(UxnFile *c) { - if(f != NULL) { - fclose(f); - f = NULL; + if(c->f != NULL) { + fclose(c->f); + c->f = NULL; } - if(dir != NULL) { - closedir(dir); - dir = NULL; + if(c->dir != NULL) { + closedir(c->dir); + c->dir = NULL; } - de = NULL; - state = IDLE; + c->de = NULL; + c->state = IDLE; } static Uint16 @@ -61,20 +64,20 @@ get_entry(char *p, Uint16 len, const char *pathname, const char *basename, int f } static Uint16 -file_read_dir(char *dest, Uint16 len) +file_read_dir(UxnFile *c, char *dest, Uint16 len) { static char pathname[4096]; char *p = dest; - if(de == NULL) de = readdir(dir); - for(; de != NULL; de = readdir(dir)) { + if(c->de == NULL) c->de = readdir(c->dir); + for(; c->de != NULL; c->de = readdir(c->dir)) { Uint16 n; - if(de->d_name[0] == '.' && de->d_name[1] == '\0') + if(c->de->d_name[0] == '.' && c->de->d_name[1] == '\0') continue; - if(strlen(current_filename) + 1 + strlen(de->d_name) < sizeof(pathname)) - sprintf(pathname, "%s/%s", current_filename, de->d_name); + if(strlen(c->current_filename) + 1 + strlen(c->de->d_name) < sizeof(pathname)) + sprintf(pathname, "%s/%s", c->current_filename, c->de->d_name); else pathname[0] = '\0'; - n = get_entry(p, len, pathname, de->d_name, 1); + n = get_entry(p, len, pathname, c->de->d_name, 1); if(!n) break; p += n; len -= n; @@ -83,68 +86,69 @@ file_read_dir(char *dest, Uint16 len) } static Uint16 -file_init(void *filename) +file_init(UxnFile *c, void *filename) { - reset(); - current_filename = filename; + reset(c); + c->current_filename = filename; return 0; } static Uint16 -file_read(void *dest, Uint16 len) +file_read(UxnFile *c, void *dest, Uint16 len) { - if(state != FILE_READ && state != DIR_READ) { - reset(); - if((dir = opendir(current_filename)) != NULL) - state = DIR_READ; - else if((f = fopen(current_filename, "rb")) != NULL) - state = FILE_READ; + if(c->state != FILE_READ && c->state != DIR_READ) { + reset(c); + if((c->dir = opendir(c->current_filename)) != NULL) + c->state = DIR_READ; + else if((c->f = fopen(c->current_filename, "rb")) != NULL) + c->state = FILE_READ; } - if(state == FILE_READ) - return fread(dest, 1, len, f); - if(state == DIR_READ) - return file_read_dir(dest, len); + if(c->state == FILE_READ) + return fread(dest, 1, len, c->f); + if(c->state == DIR_READ) + return file_read_dir(c, dest, len); return 0; } static Uint16 -file_write(void *src, Uint16 len, Uint8 flags) +file_write(UxnFile *c, void *src, Uint16 len, Uint8 flags) { Uint16 ret = 0; - if(state != FILE_WRITE) { - reset(); - if((f = fopen(current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL) - state = FILE_WRITE; + if(c->state != FILE_WRITE) { + reset(c); + if((c->f = fopen(c->current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL) + c->state = FILE_WRITE; } - if(state == FILE_WRITE) { - if((ret = fwrite(src, 1, len, f)) > 0 && fflush(f) != 0) + if(c->state == FILE_WRITE) { + if((ret = fwrite(src, 1, len, c->f)) > 0 && fflush(c->f) != 0) ret = 0; } return ret; } static Uint16 -file_stat(void *dest, Uint16 len) +file_stat(UxnFile *c, void *dest, Uint16 len) { - char *basename = strrchr(current_filename, '/'); + char *basename = strrchr(c->current_filename, '/'); if(basename != NULL) basename++; else - basename = current_filename; - return get_entry(dest, len, current_filename, basename, 0); + basename = c->current_filename; + return get_entry(dest, len, c->current_filename, basename, 0); } static Uint16 -file_delete(void) +file_delete(UxnFile *c) { - return unlink(current_filename); + return unlink(c->current_filename); } /* IO */ void -file_deo(Device *d, Uint8 port) +file_i_deo(int instance, Device *d, Uint8 port) { + UxnFile *c = &uxn_file[instance]; Uint16 addr, len, res; switch(port) { case 0x5: @@ -152,16 +156,16 @@ file_deo(Device *d, Uint8 port) DEVPEEK16(len, 0xa); if(len > 0x10000 - addr) len = 0x10000 - addr; - res = file_stat(&d->u->ram[addr], len); + res = file_stat(c, &d->u->ram[addr], len); DEVPOKE16(0x2, res); break; case 0x6: - res = file_delete(); + res = file_delete(c); DEVPOKE16(0x2, res); break; case 0x9: DEVPEEK16(addr, 0x8); - res = file_init(&d->u->ram[addr]); + res = file_init(c, (char *)&d->u->ram[addr]); DEVPOKE16(0x2, res); break; case 0xd: @@ -169,7 +173,7 @@ file_deo(Device *d, Uint8 port) DEVPEEK16(len, 0xa); if(len > 0x10000 - addr) len = 0x10000 - addr; - res = file_read(&d->u->ram[addr], len); + res = file_read(c, &d->u->ram[addr], len); DEVPOKE16(0x2, res); break; case 0xf: @@ -177,8 +181,14 @@ file_deo(Device *d, Uint8 port) DEVPEEK16(len, 0xa); if(len > 0x10000 - addr) len = 0x10000 - addr; - res = file_write(&d->u->ram[addr], len, d->dat[0x7]); + res = file_write(c, &d->u->ram[addr], len, d->dat[0x7]); DEVPOKE16(0x2, res); break; } } + +Uint8 +file_i_dei(int instance, Device *d, Uint8 port) +{ + return d->dat[port]; +} diff --git a/src/devices/file.h b/src/devices/file.h @@ -10,4 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. */ -void file_deo(Device *d, Uint8 port); +#define POLYFILEY 1 + +void file_i_deo(int instance, Device *d, Uint8 port); +Uint8 file_i_dei(int instance, Device *d, Uint8 port); diff --git a/src/uxncli.c b/src/uxncli.c @@ -17,6 +17,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. */ +static Device *devfile0; + static int error(char *msg, const char *err) { @@ -42,6 +44,18 @@ console_deo(Device *d, Uint8 port) } } +static void +file_deo(Device *d, Uint8 port) +{ + file_i_deo(d - devfile0, d, port); +} + +static Uint8 +file_dei(Device *d, Uint8 port) +{ + return file_i_dei(d - devfile0, d, port); +} + static Uint8 nil_dei(Device *d, Uint8 port) { @@ -102,7 +116,7 @@ start(Uxn *u) /* 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); + /* file */ devfile0 = uxn_port(u, 0xa, file_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); diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -42,7 +42,7 @@ static SDL_Rect gRect; /* devices */ -static Device *devscreen, *devmouse, *devctrl, *devaudio0; +static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0; static Uint8 zoom = 1; static Uint32 stdin_event, audio0_event; @@ -207,6 +207,18 @@ audio_deo(Device *d, Uint8 port) } } +static void +file_deo(Device *d, Uint8 port) +{ + file_i_deo(d - devfile0, d, port); +} + +static Uint8 +file_dei(Device *d, Uint8 port) +{ + return file_i_dei(d - devfile0, d, port); +} + static Uint8 nil_dei(Device *d, Uint8 port) { @@ -253,7 +265,7 @@ start(Uxn *u, char *rom) /* 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); + /* file */ devfile0 = uxn_port(u, 0xa, file_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);