commit 852b7da
zzo38
·
2023-04-20 02:09:24 +0000 UTC
parent 48733a3
Implement some nonstandard features having to do with files. (The append port can close a file, and also expansion commands for seeking)
2 files changed,
+68,
-23
M
main.c
+27,
-0
1@@ -223,6 +223,28 @@ emulator to the program), ? for parameters that may be input and/or output,
2 (if it is unknown or unused, then the emulator MUST ignore it and not
3 make changes to that data).
4
5+a0 offset%
6+ Given a 32-bit offset, seek the currently opened file to the specified
7+ absolute offset. (You must open the file first, by attempting to read
8+ from or write to it; you can read/write zero bytes to open it without
9+ reading/writing anything.) (The effect of seeking (absolute or relative)
10+ when a file is opened in append mode is unspecified.)
11+
12+a1 offset%
13+ Given a signed 32-bit offset, seek the currently opened file to the
14+ specified offset relative to the current file position.
15+
16+a2 offset%
17+ Given a signed 32-bit offset, seek the currently opened file to the
18+ specified offset relative to the end of the file.
19+
20+a3 >offset%
21+ Tell the current offset of the currently opened file; the 32-bit offset
22+ will be stored in the expansion command buffer.
23+
24+b_ offset%
25+ Same as a_ but for the second file.
26+
27 Nonstandard ports of devices are:
28
29 17
30@@ -230,3 +252,8 @@ Nonstandard ports of devices are:
31 EOF; the value of input will be zero and the value of this port will
32 be 0x80. (The high bit will be preserved by the emulator.)
33
34+a7/b7
35+ In addition to the usual effect (sets the append mode), writing anything
36+ to this port (whether or not it is the same value that was previously
37+ written) will close the file.
38+
M
main.c
+41,
-23
1@@ -82,6 +82,7 @@ typedef struct Device {
2 Uint8 d[16];
3 Uint8(*in)(struct Device*,Uint8);
4 void(*out)(struct Device*,Uint8);
5+ void(*exp)(struct Device*,Uint16);
6 void*aux;
7 } Device;
8
9@@ -221,7 +222,6 @@ static volatile Uint8 timer_expired=0;
10 static SDL_Surface*screen;
11 static Uint8 layers;
12 static Uint8 palet=7;
13-static SDL_Thread*in_thread;
14
15 static Sint32*audio_option;
16 static SDL_AudioSpec audiospec;
17@@ -368,13 +368,14 @@ static void load_rom(void) {
18
19 static Uint8 default_in(Device*misc1,Uint8 misc2) { return misc1->d[misc2&15]; }
20 static void default_out(Device*misc1,Uint8 misc2) {}
21-
22-static void expansion_command(Uint16 addr);
23+static void default_exp(Device*misc1,Uint16 misc2) {}
24
25 static void system_out(Device*dev,Uint8 id) {
26+ Uint16 x;
27 switch(id) {
28 case 3:
29- expansion_command(GET16(dev->d+2));
30+ x=GET16(dev->d+2);
31+ device[mem[x]>>4].exp(device+(mem[x]>>4),x);
32 break;
33 case 8 ... 13:
34 colors[070].r=colors[074].r=(dev->d[8]>>4)*0x11;
35@@ -415,27 +416,22 @@ static Uint16 files_stat(int fd,char*name,Uint16 len,Uint8*out) {
36 return 0;
37 }
38
39-static void files_seek(UxnFile*uf,Uint8 mode,Uint32 len) {
40- switch(mode&3) {
41- case 0: len=0; break;
42- case 1: /* do nothing */ break;
43- case 2: len<<=16; break;
44- case 3: return;
45- }
46+static Uint32 files_seek(UxnFile*uf,Uint8 mode,Uint32 len) {
47 switch(uf->mode) {
48 case 1: case 2: case 4:
49- switch((mode>>2)&3) {
50- case 0: fseek(uf->file,len,SEEK_CUR); break;
51- case 1: fseek(uf->file,-len,SEEK_CUR); break;
52- case 2: fseek(uf->file,len,SEEK_SET); break;
53- case 3: fseek(uf->file,-len,SEEK_END); break;
54+ switch(mode) {
55+ case 0: fseek(uf->file,len,SEEK_SET); break;
56+ case 1: fseek(uf->file,(Sint32)len,SEEK_CUR); break;
57+ case 2: fseek(uf->file,(Sint32)len,SEEK_END); break;
58+ case 3: return ftell(uf->file);
59 }
60 break;
61 case 3:
62- if(((mode>>2)&3)==2) rewinddir(uf->dir);
63+ if(!mode && !len) rewinddir(uf->dir);
64 uf->de=0;
65 break;
66 }
67+ return 0;
68 }
69
70 static int files_set(Device*dev,int rw) {
71@@ -485,6 +481,9 @@ static void files_out(Device*dev,Uint8 id) {
72 y=files_stat(AT_FDCWD,uf->name,len,mem+addr);
73 if(y<=len) PUT16(dev->d+2,y);
74 break;
75+ case 7:
76+ if(use_extension) files_set(dev,0);
77+ break;
78 case 9:
79 addr=GET16(dev->d+8);
80 files_set(dev,0);
81@@ -576,6 +575,23 @@ static Uint8 files_in(Device*dev,Uint8 id) {
82 }
83 }
84
85+static void files_exp(Device*dev,Uint16 addr) {
86+ UxnFile*uf=dev->aux;
87+ Uint32 x;
88+ if(use_extension) switch(mem[addr]&15) {
89+ case 0 ... 2:
90+ x=GET16(mem+addr+1)<<16;
91+ x|=GET16(mem+addr+3);
92+ files_seek(uf,mem[addr]&15,x);
93+ break;
94+ case 3:
95+ x=files_seek(uf,3,0);
96+ PUT16(mem+addr+1,x>>16);
97+ PUT16(mem+addr+3,x);
98+ break;
99+ }
100+}
101+
102 static Uint8 datetime_in(Device*dev,Uint8 id) {
103 time_t t=time(0);
104 struct tm r;
105@@ -835,7 +851,7 @@ static void run_audio(void) {
106 }
107 }
108
109-static void expansion_command(Uint16 addr) {
110+static void system_exp(Device*dev,Uint16 addr) {
111 Uint32 src,dst;
112 Uint16 len;
113 switch(mem[addr]) {
114@@ -1034,8 +1050,8 @@ static void debug_screen(Uint8*s,Uint8 k) {
115 case 5:
116 if(k=='c') files_set(device+10,0);
117 if(k=='C') files_set(device+11,0);
118- if(k=='r') files_seek(&uxnfile0,8,0);
119- if(k=='R') files_seek(&uxnfile1,8,0);
120+ if(k=='r') files_seek(&uxnfile0,0,0);
121+ if(k=='R') files_seek(&uxnfile1,0,0);
122 break;
123 case 6:
124 if(k==8 || k==11) --break_pc;
125@@ -1410,8 +1426,10 @@ int main(int argc,char**argv) {
126 for(i=0;i<16;i++) {
127 device[i].in=default_in;
128 device[i].out=default_out;
129+ device[i].exp=default_exp;
130 }
131 device[0].out=system_out;
132+ device[0].exp=system_exp;
133 device[10].aux=&uxnfile0;
134 device[11].aux=&uxnfile1;
135 device[12].in=datetime_in;
136@@ -1424,7 +1442,7 @@ int main(int argc,char**argv) {
137 case 'Q': use_mouse=0; break;
138 case 'S': disallow_size_change=1; break;
139 case 'T': device[12].in=default_in; set_datetime(optarg); break;
140- case 'Y': allow_write=1; device[10].out=device[11].out=files_out; device[10].in=device[11].in=files_in; break;
141+ case 'Y': allow_write=1; device[10].out=device[11].out=files_out; device[10].in=device[11].in=files_in; device[10].exp=device[11].exp=files_exp; break;
142 case 'Z': use_utc=1; break;
143 case 'a': set_audio(optarg); break;
144 case 'd': use_debug=1; break;
145@@ -1438,7 +1456,7 @@ int main(int argc,char**argv) {
146 case 't': timer_rate=strtol(optarg,0,10); break;
147 case 'w': default_width=strtol(optarg,0,10); break;
148 case 'x': use_extension=1; break;
149- case 'y': allow_write=0; device[10].out=device[11].out=files_out; device[10].in=device[11].in=files_in; break;
150+ case 'y': allow_write=0; device[10].out=device[11].out=files_out; device[10].in=device[11].in=files_in; device[10].exp=device[11].exp=files_exp; break;
151 case 'z': zoom=strtol(optarg,0,10); break;
152 default: return 1;
153 }
154@@ -1485,7 +1503,7 @@ int main(int argc,char**argv) {
155 }
156 if(use_screen) {
157 if(size_changed) set_screen_mode(scr_w,scr_h);
158- if(use_thread) in_thread=SDL_CreateThread(stdin_thread_fn,0);
159+ if(use_thread) SDL_CreateThread(stdin_thread_fn,0);
160 while(run_screen()) {
161 for(i=0;i<15;i++) for(j=0;j<16;j++) device[i].d[j]=0;
162 load_rom();