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