commit b883c4e

zzo38  ·  2022-10-29 07:18:27 +0000 UTC
parent 95d5c37
Implement the "bicycle mode"
2 files changed,  +43, -12
M main.c
+3, -0
 1@@ -1,6 +1,9 @@
 2 
 3 === Command-line switches ===
 4 
 5+-B
 6+  Bicycle mode; affects the meaning of some ports of the system device.
 7+
 8 -D
 9   Use double buffering for the display.
10 
M main.c
+40, -12
  1@@ -20,7 +20,7 @@ exit
  2 
  3 typedef struct {
  4   Uint8 p;
  5-  Uint8 d[255];
  6+  Uint8 d[256];
  7 } Stack;
  8 
  9 typedef struct Device {
 10@@ -149,6 +149,7 @@ static volatile Uint8 timer_expired=0;
 11 static SDL_Surface*screen;
 12 static Uint8 layers;
 13 static Uint8 palet=7;
 14+static Uint8 bicycle=0;
 15 
 16 static void debug(int i) {
 17   if(i) fprintf(stderr,"Debug(%02X)\n",i);
 18@@ -167,11 +168,11 @@ static void uxnerr(int n,int pc) {
 19   errx(2,"Uxn error %d at 0x%04X",n,pc);
 20 }
 21 
 22-#define Push8(z) ({ if(s->p>254) uxnerr(2,pc); s->d[s->p++]=(z); })
 23-#define Push16(z) ({ if(s->p>253) uxnerr(2,pc); s->d[s->p++]=(z)>>8; s->d[s->p++]=(z); })
 24-#define Push(z) ({ if(s->p>(v&0x20?253:254)) uxnerr(2,pc); if(v&0x20) s->d[s->p++]=(z)>>8; s->d[s->p++]=(z); })
 25-#define Pop8(z) ({ if(!k) uxnerr(1,pc); z=s->d[--k]; if(v<0x80) s->p=k; })
 26-#define Pop16(z) ({ if(k<2) uxnerr(1,pc); z=s->d[--k]; z|=s->d[--k]<<8; if(v<0x80) s->p=k; })
 27+#define Push8(z) ({ if(s->p>254) {v=2; goto error;} s->d[s->p++]=(z); })
 28+#define Push16(z) ({ if(s->p>253) {v=2; goto error;} s->d[s->p++]=(z)>>8; s->d[s->p++]=(z); })
 29+#define Push(z) ({ if(s->p>(v&0x20?253:254)) {v=2; goto error;} if(v&0x20) s->d[s->p++]=(z)>>8; s->d[s->p++]=(z); })
 30+#define Pop8(z) ({ if(!k) {v=1; goto error;} z=s->d[--k]; if(v<0x80) s->p=k; })
 31+#define Pop16(z) ({ if(k<2) {v=1; goto error;} z=s->d[--k]; z|=s->d[--k]<<8; if(v<0x80) s->p=k; })
 32 #define Pop(z) ({ if(v&0x20) Pop16(z); else Pop8(z); })
 33 
 34 static void run(Uint16 pc) {
 35@@ -179,6 +180,7 @@ static void run(Uint16 pc) {
 36   Uint8 k,v;
 37   Uint16 x,y,z;
 38   if(!pc) return;
 39+  start:
 40   while(v=mem[pc++]) {
 41     // if(use_debug) printf("! pc=%04X v=%02X ds=%02X rs=%02X\n",pc-1,v,ds.p,rs.p);
 42     s=(v&0x40?&rs:&ds);
 43@@ -229,7 +231,7 @@ static void run(Uint16 pc) {
 44       case 0x18: Pop(x); Pop(y); Push(y+x); break;
 45       case 0x19: Pop(x); Pop(y); Push(y-x); break;
 46       case 0x1A: Pop(x); Pop(y); Push(y*x); break;
 47-      case 0x1B: Pop(x); Pop(y); if(!x) uxnerr(3,pc); Push(y/x); break;
 48+      case 0x1B: Pop(x); Pop(y); if(!x) {v=3; goto error;} Push(y/x); break;
 49       case 0x1C: Pop(x); Pop(y); Push(y&x); break;
 50       case 0x1D: Pop(x); Pop(y); Push(y|x); break;
 51       case 0x1E: Pop(x); Pop(y); Push(y^x); break;
 52@@ -246,6 +248,20 @@ static void run(Uint16 pc) {
 53     }
 54   }
 55   fflush(stdout);
 56+  if(bicycle && (k=device[0].d[2])) {
 57+    memcpy(mem+(k<<8),ds.d,254);
 58+    mem[(k<<8)+0xFF]=ds.p;
 59+  }
 60+  return;
 61+  error:
 62+  if(bicycle && (device[0].d[0] || device[0].d[1])) {
 63+    if(device[0].d[2]) mem[(device[0].d[2]<<8)+0xFE]=v; else fprintf(stderr,"Uxn error %d at 0x%04X\n",v,pc);
 64+    pc=GET16(device[0].d);
 65+    ds.p=rs.p=0;
 66+    goto start;
 67+  } else {
 68+    uxnerr(v,pc);
 69+  }
 70 }
 71 
 72 static void load_rom(void) {
 73@@ -262,16 +278,27 @@ static void default_out(Device*misc1,Uint8 misc2) {}
 74 
 75 static Uint8 system_in(Device*dev,Uint8 id) {
 76   switch(id) {
 77-    case 2: return rs.p;
 78-    case 3: return ds.p;
 79+    case 2: return ds.p;
 80+    case 3: return rs.p;
 81     default: return dev->d[id];
 82   }
 83 }
 84 
 85 static void system_out(Device*dev,Uint8 id) {
 86   switch(id) {
 87-    case 2: rs.p=dev->d[2]; break;
 88-    case 3: ds.p=dev->d[3]; break;
 89+    case 2:
 90+      if(bicycle) {
 91+        if(dev->d[2]) {
 92+          memcpy(ds.d,mem+(dev->d[2]<<8),256);
 93+          ds.p=mem[(dev->d[2]<<8)+0xFF];
 94+        } else {
 95+          ds.p=0;
 96+        }
 97+      } else {
 98+        ds.p=dev->d[2];
 99+      }
100+      break;
101+    case 3: if(!bicycle) rs.p=dev->d[3]; break;
102     case 8 ... 13:
103       if(!screen) break;
104       colors[070].r=colors[074].r=(dev->d[8]>>4)*0x11;
105@@ -686,7 +713,8 @@ int main(int argc,char**argv) {
106   device[10].aux=&uxnfile0;
107   device[11].aux=&uxnfile1;
108   device[12].in=datetime_in;
109-  while((i=getopt(argc,argv,"+ADFNQT:YZdh:inp:qt:w:xyz:"))>0) switch(i) {
110+  while((i=getopt(argc,argv,"+ABDFNQT:YZdh:inp:qt:w:xyz:"))>0) switch(i) {
111+    case 'B': bicycle=1; device[0].in=default_in; break;
112     case 'D': scrflags|=SDL_DOUBLEBUF; break;
113     case 'F': scrflags|=SDL_FULLSCREEN; break;
114     case 'N': scrflags|=SDL_NOFRAME; break;