| ... | ... |
@@ -19,29 +19,32 @@ WITH REGARD TO THIS SOFTWARE. |
| 19 | 19 |
#include <sys/stat.h> |
| 20 | 20 |
#include <unistd.h> |
| 21 | 21 |
|
| 22 |
-static FILE *f; |
|
| 23 |
-static DIR *dir; |
|
| 24 |
-static char *current_filename = ""; |
|
| 25 |
-static struct dirent *de; |
|
| 26 |
- |
|
| 27 |
-static enum { IDLE,
|
|
| 28 |
- FILE_READ, |
|
| 29 |
- FILE_WRITE, |
|
| 30 |
- DIR_READ } state; |
|
| 22 |
+typedef struct {
|
|
| 23 |
+ FILE *f; |
|
| 24 |
+ DIR *dir; |
|
| 25 |
+ char *current_filename; |
|
| 26 |
+ struct dirent *de; |
|
| 27 |
+ enum { IDLE,
|
|
| 28 |
+ FILE_READ, |
|
| 29 |
+ FILE_WRITE, |
|
| 30 |
+ DIR_READ } state; |
|
| 31 |
+} UxnFile; |
|
| 32 |
+ |
|
| 33 |
+static UxnFile uxn_file[POLYFILEY]; |
|
| 31 | 34 |
|
| 32 | 35 |
static void |
| 33 |
-reset(void) |
|
| 36 |
+reset(UxnFile *c) |
|
| 34 | 37 |
{
|
| 35 |
- if(f != NULL) {
|
|
| 36 |
- fclose(f); |
|
| 37 |
- f = NULL; |
|
| 38 |
+ if(c->f != NULL) {
|
|
| 39 |
+ fclose(c->f); |
|
| 40 |
+ c->f = NULL; |
|
| 38 | 41 |
} |
| 39 |
- if(dir != NULL) {
|
|
| 40 |
- closedir(dir); |
|
| 41 |
- dir = NULL; |
|
| 42 |
+ if(c->dir != NULL) {
|
|
| 43 |
+ closedir(c->dir); |
|
| 44 |
+ c->dir = NULL; |
|
| 42 | 45 |
} |
| 43 |
- de = NULL; |
|
| 44 |
- state = IDLE; |
|
| 46 |
+ c->de = NULL; |
|
| 47 |
+ c->state = IDLE; |
|
| 45 | 48 |
} |
| 46 | 49 |
|
| 47 | 50 |
static Uint16 |
| ... | ... |
@@ -61,20 +64,20 @@ get_entry(char *p, Uint16 len, const char *pathname, const char *basename, int f |
| 61 | 64 |
} |
| 62 | 65 |
|
| 63 | 66 |
static Uint16 |
| 64 |
-file_read_dir(char *dest, Uint16 len) |
|
| 67 |
+file_read_dir(UxnFile *c, char *dest, Uint16 len) |
|
| 65 | 68 |
{
|
| 66 | 69 |
static char pathname[4096]; |
| 67 | 70 |
char *p = dest; |
| 68 |
- if(de == NULL) de = readdir(dir); |
|
| 69 |
- for(; de != NULL; de = readdir(dir)) {
|
|
| 71 |
+ if(c->de == NULL) c->de = readdir(c->dir); |
|
| 72 |
+ for(; c->de != NULL; c->de = readdir(c->dir)) {
|
|
| 70 | 73 |
Uint16 n; |
| 71 |
- if(de->d_name[0] == '.' && de->d_name[1] == '\0') |
|
| 74 |
+ if(c->de->d_name[0] == '.' && c->de->d_name[1] == '\0') |
|
| 72 | 75 |
continue; |
| 73 |
- if(strlen(current_filename) + 1 + strlen(de->d_name) < sizeof(pathname)) |
|
| 74 |
- sprintf(pathname, "%s/%s", current_filename, de->d_name); |
|
| 76 |
+ if(strlen(c->current_filename) + 1 + strlen(c->de->d_name) < sizeof(pathname)) |
|
| 77 |
+ sprintf(pathname, "%s/%s", c->current_filename, c->de->d_name); |
|
| 75 | 78 |
else |
| 76 | 79 |
pathname[0] = '\0'; |
| 77 |
- n = get_entry(p, len, pathname, de->d_name, 1); |
|
| 80 |
+ n = get_entry(p, len, pathname, c->de->d_name, 1); |
|
| 78 | 81 |
if(!n) break; |
| 79 | 82 |
p += n; |
| 80 | 83 |
len -= n; |
| ... | ... |
@@ -83,68 +86,69 @@ file_read_dir(char *dest, Uint16 len) |
| 83 | 86 |
} |
| 84 | 87 |
|
| 85 | 88 |
static Uint16 |
| 86 |
-file_init(void *filename) |
|
| 89 |
+file_init(UxnFile *c, void *filename) |
|
| 87 | 90 |
{
|
| 88 |
- reset(); |
|
| 89 |
- current_filename = filename; |
|
| 91 |
+ reset(c); |
|
| 92 |
+ c->current_filename = filename; |
|
| 90 | 93 |
return 0; |
| 91 | 94 |
} |
| 92 | 95 |
|
| 93 | 96 |
static Uint16 |
| 94 |
-file_read(void *dest, Uint16 len) |
|
| 97 |
+file_read(UxnFile *c, void *dest, Uint16 len) |
|
| 95 | 98 |
{
|
| 96 |
- if(state != FILE_READ && state != DIR_READ) {
|
|
| 97 |
- reset(); |
|
| 98 |
- if((dir = opendir(current_filename)) != NULL) |
|
| 99 |
- state = DIR_READ; |
|
| 100 |
- else if((f = fopen(current_filename, "rb")) != NULL) |
|
| 101 |
- state = FILE_READ; |
|
| 99 |
+ if(c->state != FILE_READ && c->state != DIR_READ) {
|
|
| 100 |
+ reset(c); |
|
| 101 |
+ if((c->dir = opendir(c->current_filename)) != NULL) |
|
| 102 |
+ c->state = DIR_READ; |
|
| 103 |
+ else if((c->f = fopen(c->current_filename, "rb")) != NULL) |
|
| 104 |
+ c->state = FILE_READ; |
|
| 102 | 105 |
} |
| 103 |
- if(state == FILE_READ) |
|
| 104 |
- return fread(dest, 1, len, f); |
|
| 105 |
- if(state == DIR_READ) |
|
| 106 |
- return file_read_dir(dest, len); |
|
| 106 |
+ if(c->state == FILE_READ) |
|
| 107 |
+ return fread(dest, 1, len, c->f); |
|
| 108 |
+ if(c->state == DIR_READ) |
|
| 109 |
+ return file_read_dir(c, dest, len); |
|
| 107 | 110 |
return 0; |
| 108 | 111 |
} |
| 109 | 112 |
|
| 110 | 113 |
static Uint16 |
| 111 |
-file_write(void *src, Uint16 len, Uint8 flags) |
|
| 114 |
+file_write(UxnFile *c, void *src, Uint16 len, Uint8 flags) |
|
| 112 | 115 |
{
|
| 113 | 116 |
Uint16 ret = 0; |
| 114 |
- if(state != FILE_WRITE) {
|
|
| 115 |
- reset(); |
|
| 116 |
- if((f = fopen(current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL) |
|
| 117 |
- state = FILE_WRITE; |
|
| 117 |
+ if(c->state != FILE_WRITE) {
|
|
| 118 |
+ reset(c); |
|
| 119 |
+ if((c->f = fopen(c->current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL) |
|
| 120 |
+ c->state = FILE_WRITE; |
|
| 118 | 121 |
} |
| 119 |
- if(state == FILE_WRITE) {
|
|
| 120 |
- if((ret = fwrite(src, 1, len, f)) > 0 && fflush(f) != 0) |
|
| 122 |
+ if(c->state == FILE_WRITE) {
|
|
| 123 |
+ if((ret = fwrite(src, 1, len, c->f)) > 0 && fflush(c->f) != 0) |
|
| 121 | 124 |
ret = 0; |
| 122 | 125 |
} |
| 123 | 126 |
return ret; |
| 124 | 127 |
} |
| 125 | 128 |
|
| 126 | 129 |
static Uint16 |
| 127 |
-file_stat(void *dest, Uint16 len) |
|
| 130 |
+file_stat(UxnFile *c, void *dest, Uint16 len) |
|
| 128 | 131 |
{
|
| 129 |
- char *basename = strrchr(current_filename, '/'); |
|
| 132 |
+ char *basename = strrchr(c->current_filename, '/'); |
|
| 130 | 133 |
if(basename != NULL) |
| 131 | 134 |
basename++; |
| 132 | 135 |
else |
| 133 |
- basename = current_filename; |
|
| 134 |
- return get_entry(dest, len, current_filename, basename, 0); |
|
| 136 |
+ basename = c->current_filename; |
|
| 137 |
+ return get_entry(dest, len, c->current_filename, basename, 0); |
|
| 135 | 138 |
} |
| 136 | 139 |
|
| 137 | 140 |
static Uint16 |
| 138 |
-file_delete(void) |
|
| 141 |
+file_delete(UxnFile *c) |
|
| 139 | 142 |
{
|
| 140 |
- return unlink(current_filename); |
|
| 143 |
+ return unlink(c->current_filename); |
|
| 141 | 144 |
} |
| 142 | 145 |
|
| 143 | 146 |
/* IO */ |
| 144 | 147 |
|
| 145 | 148 |
void |
| 146 |
-file_deo(Device *d, Uint8 port) |
|
| 149 |
+file_i_deo(int instance, Device *d, Uint8 port) |
|
| 147 | 150 |
{
|
| 151 |
+ UxnFile *c = &uxn_file[instance]; |
|
| 148 | 152 |
Uint16 addr, len, res; |
| 149 | 153 |
switch(port) {
|
| 150 | 154 |
case 0x5: |
| ... | ... |
@@ -152,16 +156,16 @@ file_deo(Device *d, Uint8 port) |
| 152 | 156 |
DEVPEEK16(len, 0xa); |
| 153 | 157 |
if(len > 0x10000 - addr) |
| 154 | 158 |
len = 0x10000 - addr; |
| 155 |
- res = file_stat(&d->u->ram[addr], len); |
|
| 159 |
+ res = file_stat(c, &d->u->ram[addr], len); |
|
| 156 | 160 |
DEVPOKE16(0x2, res); |
| 157 | 161 |
break; |
| 158 | 162 |
case 0x6: |
| 159 |
- res = file_delete(); |
|
| 163 |
+ res = file_delete(c); |
|
| 160 | 164 |
DEVPOKE16(0x2, res); |
| 161 | 165 |
break; |
| 162 | 166 |
case 0x9: |
| 163 | 167 |
DEVPEEK16(addr, 0x8); |
| 164 |
- res = file_init(&d->u->ram[addr]); |
|
| 168 |
+ res = file_init(c, (char *)&d->u->ram[addr]); |
|
| 165 | 169 |
DEVPOKE16(0x2, res); |
| 166 | 170 |
break; |
| 167 | 171 |
case 0xd: |
| ... | ... |
@@ -169,7 +173,7 @@ file_deo(Device *d, Uint8 port) |
| 169 | 173 |
DEVPEEK16(len, 0xa); |
| 170 | 174 |
if(len > 0x10000 - addr) |
| 171 | 175 |
len = 0x10000 - addr; |
| 172 |
- res = file_read(&d->u->ram[addr], len); |
|
| 176 |
+ res = file_read(c, &d->u->ram[addr], len); |
|
| 173 | 177 |
DEVPOKE16(0x2, res); |
| 174 | 178 |
break; |
| 175 | 179 |
case 0xf: |
| ... | ... |
@@ -177,8 +181,14 @@ file_deo(Device *d, Uint8 port) |
| 177 | 181 |
DEVPEEK16(len, 0xa); |
| 178 | 182 |
if(len > 0x10000 - addr) |
| 179 | 183 |
len = 0x10000 - addr; |
| 180 |
- res = file_write(&d->u->ram[addr], len, d->dat[0x7]); |
|
| 184 |
+ res = file_write(c, &d->u->ram[addr], len, d->dat[0x7]); |
|
| 181 | 185 |
DEVPOKE16(0x2, res); |
| 182 | 186 |
break; |
| 183 | 187 |
} |
| 184 | 188 |
} |
| 189 |
+ |
|
| 190 |
+Uint8 |
|
| 191 |
+file_i_dei(int instance, Device *d, Uint8 port) |
|
| 192 |
+{
|
|
| 193 |
+ return d->dat[port]; |
|
| 194 |
+} |
| ... | ... |
@@ -10,4 +10,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 10 | 10 |
WITH REGARD TO THIS SOFTWARE. |
| 11 | 11 |
*/ |
| 12 | 12 |
|
| 13 |
-void file_deo(Device *d, Uint8 port); |
|
| 13 |
+#define POLYFILEY 1 |
|
| 14 |
+ |
|
| 15 |
+void file_i_deo(int instance, Device *d, Uint8 port); |
|
| 16 |
+Uint8 file_i_dei(int instance, Device *d, Uint8 port); |
| ... | ... |
@@ -17,6 +17,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 17 | 17 |
WITH REGARD TO THIS SOFTWARE. |
| 18 | 18 |
*/ |
| 19 | 19 |
|
| 20 |
+static Device *devfile0; |
|
| 21 |
+ |
|
| 20 | 22 |
static int |
| 21 | 23 |
error(char *msg, const char *err) |
| 22 | 24 |
{
|
| ... | ... |
@@ -42,6 +44,18 @@ console_deo(Device *d, Uint8 port) |
| 42 | 44 |
} |
| 43 | 45 |
} |
| 44 | 46 |
|
| 47 |
+static void |
|
| 48 |
+file_deo(Device *d, Uint8 port) |
|
| 49 |
+{
|
|
| 50 |
+ file_i_deo(d - devfile0, d, port); |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+static Uint8 |
|
| 54 |
+file_dei(Device *d, Uint8 port) |
|
| 55 |
+{
|
|
| 56 |
+ return file_i_dei(d - devfile0, d, port); |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 45 | 59 |
static Uint8 |
| 46 | 60 |
nil_dei(Device *d, Uint8 port) |
| 47 | 61 |
{
|
| ... | ... |
@@ -102,7 +116,7 @@ start(Uxn *u) |
| 102 | 116 |
/* empty */ uxn_port(u, 0x7, nil_dei, nil_deo); |
| 103 | 117 |
/* empty */ uxn_port(u, 0x8, nil_dei, nil_deo); |
| 104 | 118 |
/* empty */ uxn_port(u, 0x9, nil_dei, nil_deo); |
| 105 |
- /* file */ uxn_port(u, 0xa, nil_dei, file_deo); |
|
| 119 |
+ /* file */ devfile0 = uxn_port(u, 0xa, file_dei, file_deo); |
|
| 106 | 120 |
/* datetime */ uxn_port(u, 0xb, datetime_dei, nil_deo); |
| 107 | 121 |
/* empty */ uxn_port(u, 0xc, nil_dei, nil_deo); |
| 108 | 122 |
/* empty */ uxn_port(u, 0xd, nil_dei, nil_deo); |
| ... | ... |
@@ -42,7 +42,7 @@ static SDL_Rect gRect; |
| 42 | 42 |
|
| 43 | 43 |
/* devices */ |
| 44 | 44 |
|
| 45 |
-static Device *devscreen, *devmouse, *devctrl, *devaudio0; |
|
| 45 |
+static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0; |
|
| 46 | 46 |
static Uint8 zoom = 1; |
| 47 | 47 |
static Uint32 stdin_event, audio0_event; |
| 48 | 48 |
|
| ... | ... |
@@ -207,6 +207,18 @@ audio_deo(Device *d, Uint8 port) |
| 207 | 207 |
} |
| 208 | 208 |
} |
| 209 | 209 |
|
| 210 |
+static void |
|
| 211 |
+file_deo(Device *d, Uint8 port) |
|
| 212 |
+{
|
|
| 213 |
+ file_i_deo(d - devfile0, d, port); |
|
| 214 |
+} |
|
| 215 |
+ |
|
| 216 |
+static Uint8 |
|
| 217 |
+file_dei(Device *d, Uint8 port) |
|
| 218 |
+{
|
|
| 219 |
+ return file_i_dei(d - devfile0, d, port); |
|
| 220 |
+} |
|
| 221 |
+ |
|
| 210 | 222 |
static Uint8 |
| 211 | 223 |
nil_dei(Device *d, Uint8 port) |
| 212 | 224 |
{
|
| ... | ... |
@@ -253,7 +265,7 @@ start(Uxn *u, char *rom) |
| 253 | 265 |
/* unused */ uxn_port(u, 0x7, nil_dei, nil_deo); |
| 254 | 266 |
/* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo); |
| 255 | 267 |
/* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo); |
| 256 |
- /* file */ uxn_port(u, 0xa, nil_dei, file_deo); |
|
| 268 |
+ /* file */ devfile0 = uxn_port(u, 0xa, file_dei, file_deo); |
|
| 257 | 269 |
/* datetime */ uxn_port(u, 0xb, datetime_dei, nil_deo); |
| 258 | 270 |
/* unused */ uxn_port(u, 0xc, nil_dei, nil_deo); |
| 259 | 271 |
/* unused */ uxn_port(u, 0xd, nil_dei, nil_deo); |