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;