Browse code

Prepare for more than one File device.

Andrew Alderwick authored on 17/03/2022 18:31:33
Showing 4 changed files
... ...
@@ -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);