]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/md/mem.c
devcons: fix permissions for reboot and sysstat
[plan9front.git] / sys / src / games / md / mem.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "../eui.h"
5 #include "dat.h"
6 #include "fns.h"
7
8 u16int ram[32768], vram[32768];
9 u16int cram[64], vsram[40];
10 u32int cramc[64];
11 u8int zram[8192];
12 u8int reg[32];
13 u8int ctl[15];
14
15 u8int dma;
16 u8int vdplatch;
17 u16int vdpaddr, vdpdata;
18
19 u8int yma1, yma2;
20
21 u8int z80bus = RESET;
22 u16int z80bank;
23
24 //#define vramdebug(a, s, a1, a2, a3) if((a & ~1) == 0xe7a0) print(s, a1, a2, a3);
25 #define vramdebug(a, s, a1, a2, a3)
26
27 u8int
28 regread(u16int a)
29 {
30         u16int v;
31
32         switch(a | 1){
33         case 0x0001: return 0xa0;
34         case 0x0003:
35                 v = ~(keys & 0xffff);
36                 if((ctl[0] & 0x40) == 0)
37                         v >>= 8;
38                 return ctl[0] & 0xc0 | v & 0x3f;
39         case 0x0005:
40         case 0x0007:
41                 return ctl[a-3>>1] & 0xc0 | 0x3f;
42         case 0x0009: case 0x000b: case 0x000d:
43                 return ctl[a-3>>1];
44         case 0x1101:
45                 return (~z80bus & BUSACK) >> 1;
46         }
47         sysfatal("read from 0xa1%.4ux (pc=%#.6ux)", a, curpc);
48         return 0;
49 }
50
51 void
52 regwrite(u16int a, u16int v)
53 {
54         switch(a | 1){
55         case 0x0003: case 0x0005: case 0x0007:
56         case 0x0009: case 0x000b: case 0x000d:
57                 ctl[a-3>>1] = v;
58                 return;
59         case 0x1101:
60                 z80bus = z80bus & ~BUSREQ | v & BUSREQ;
61                 return;
62         case 0x1201:
63                 if((v & 1) == 0){
64                         z80bus |= RESET;
65                         z80bus &= ~BUSACK;
66                 }else
67                         z80bus &= ~RESET;
68                 return;
69         case 0x30f1:
70                 if((v & 1) != 0)
71                         sramctl |= SRAMEN;
72                 else
73                         sramctl &= ~SRAMEN;
74                 return;
75         case 0x30f3: case 0x30f5: case 0x30f7: case 0x30f9: case 0x30fb:
76                 return;
77         }
78         sysfatal("write to 0xa1%.4x (pc=%#.6ux)", a, curpc);
79 }
80
81 void
82 vdpwrite(u16int v)
83 {
84         u8int a;
85
86         if((vdplatch & 0x80) == 0){
87                 if((v & 0xc000) == 0x8000){
88                         a = v >> 8 & 0x1f;
89                         reg[a] = v & 0xff;
90                         if(a == 0x0c)
91                                 vdpmode();
92                         vdplatch = 0;
93                         return;
94                 }
95                 vdplatch = vdplatch & 0xfc | v >> 14 | 0x80;
96                 vdpaddr = vdpaddr & 0xc000 | v & 0x3fff;
97         }else{
98                 vdplatch = vdplatch & 0x03 | v >> 2 & 0x1c;
99                 vdpaddr = vdpaddr & 0x3fff | v << 14 & 0xc000;
100                 if((v & 0x80) != 0 && (reg[MODE2] & DMAEN) != 0){
101                         dma = reg[23] >> 6 & 3;
102                         if(dma == 0)
103                                 dma++;
104                 }
105         }
106 }
107
108 void
109 cramwrite(u16int a, u16int v)
110 {
111         u32int w;
112
113         cram[a/2] = v;
114         w = v << 12 & 0xe00000 | v << 8 & 0xe000 | v << 4 & 0xe0;
115         cramc[a/2] = w;
116 }
117
118 u16int
119 memread(u32int a)
120 {
121         u16int v;
122
123         switch(a >> 21 & 7){
124         case 0: case 1:
125                 if((sramctl & SRAMEN) != 0 && a >= sram0 && a <= sram1)
126                         switch(sramctl & ADDRMASK){
127                         case ADDREVEN: return sram[(a - sram0) >> 1] << 8;
128                         case ADDRODD: return sram[(a - sram0) >> 1];
129                         case ADDRBOTH: return sram[a - sram0] << 8 | sram[a - sram0 + 1];
130                         }
131                 return prg[(a % nprg) / 2];
132         case 5:
133                 switch(a >> 16 & 0xff){
134                 case 0xa0:
135                         if((z80bus & BUSACK) != 0)
136                                 v = z80read(a & 0x7fff);
137                         else
138                                 v = 0;
139                         return v << 8 | v;
140                 case 0xa1:
141                         v = regread(a);
142                         return v << 8 | v;
143                 }
144                 goto invalid;
145         case 6:
146                 if((a & 0xe700e0) != 0xc00000)
147                         goto invalid;
148                 switch(a & 30){
149                 case 0: case 2:
150                         vdplatch &= 0x7f;
151                         switch(vdplatch & 0xf){
152                         case 0:
153                                 v = vram[vdpaddr/2];
154                                 vdpaddr += reg[AUTOINC];
155                                 break;
156                         case 4:
157                                 v = vdpaddr & 0x7f;
158                                 if(v < 80)
159                                         v = vsram[v / 2];
160                                 else
161                                         v = 0;
162                                 vdpaddr = (vdpaddr + reg[AUTOINC]) & 0x7f;
163                                 break;
164                         case 8:
165                                 v = cram[(vdpaddr & 0x7f) / 2];
166                                 vdpaddr = (vdpaddr + reg[AUTOINC]) & 0x7f;
167                                 break;
168                         default: v = 0;
169                         }
170                         return v;
171                 case 4: case 6:
172                         vdplatch &= 0x7f;
173                         v = vdpstat;
174                         if(dma != 0 && dma != 2)
175                                 v |= STATDMA;
176                         if(vdpx >= 0xe4 || vdpx < 0x08)
177                                 v |= STATHBL;
178                         return v;
179                 case 8: case 10: case 12: case 14:
180                         if((reg[MODE4] & WIDE) != 0)
181                                 v = vdpx - (vdpx >= 360 ? 406 : 0);
182                         else
183                                 v = vdpx - (vdpx >= 296 ? 342 : 0);
184                         if(intla)
185                                 return vdpy - (vdpy >= 234 ? 5 : 0) << 8 & 0xfe00 | frame << 8 | v >> 1 & 0xff;
186                         return vdpy - (vdpy >= 234 ? 5 : 0) << 8 | v >> 1 & 0xff;
187                 default:
188                         goto invalid;
189                 }
190         case 7: return ram[((u16int)a) / 2];
191         default:
192         invalid:
193                 sysfatal("read from %#.6ux (pc=%#.6ux)", a, curpc);
194                 return 0;
195         }
196 }
197
198 void
199 memwrite(u32int a, u16int v, u16int m)
200 {
201         u16int *p;
202         u16int w;
203
204         if(0 && (a & 0xe0fffe) == 0xe0df46)
205                 print("%x %x %x\n", curpc, v, m);
206         switch((a >> 21) & 7){
207         case 0: case 1:
208                 if((sramctl & SRAMEN) != 0 && a >= sram0 && a <= sram1){
209                         switch(sramctl & ADDRMASK){
210                         case ADDREVEN: sram[(a - sram0) >> 1] = v >> 8; break;
211                         case ADDRODD: sram[(a - sram0) >> 1] = v; break;
212                         case ADDRBOTH:
213                                 if((m & 0xff00) == 0xff00)
214                                         sram[a - sram0] = v >> 8;
215                                 if((m & 0xff) == 0xff)
216                                         sram[a + 1 - sram0] = v;
217                                 break;
218                         }
219                         if(saveclock == 0)
220                                 saveclock = SAVEFREQ;
221                         return;
222                 }
223                 goto invalid;
224         case 5:
225                 switch(a >> 16 & 0xff){
226                 case 0xa0:
227                         if((z80bus & BUSACK) != 0)
228                                 z80write(a & 0xffff, v >> 8);
229                         return;
230                 case 0xa1:
231                         regwrite(a, v >> 8);
232                         return;
233                 default:
234                         goto invalid;
235                 }
236         case 6:
237                 if((a & 0xe700e0) != 0xc00000)
238                         goto invalid;
239                 switch(a & 30){
240                 case 0: case 2:
241                         if(dma == 2){
242                                 dma = 4;
243                                 vdpdata = v >> 8;
244                                 vramdebug(vdpaddr, "vdp fill write val %x (pc = %x) %d\n", v & 0xff, curpc, 0);
245                                 p = &vram[vdpaddr / 2];
246                                 if((vdpaddr & 1) == 0)
247                                         *p = *p & 0xff | v << 8;
248                                 else
249                                         *p = *p & 0xff00 | v & 0xff;
250                                 return;
251                         }
252                         vdplatch &= 0x7f;
253                         switch(vdplatch & 0xf){
254                         case 1:
255                                 if((vdpaddr & 1) != 0)
256                                         v = v << 8 | v >> 8;
257                                 p = &vram[vdpaddr / 2];
258                                 vramdebug(vdpaddr, "vdp write val %x mask %x (pc = %x)\n", v, m, curpc);
259                                 *p = *p & ~m | v & m;
260                                 vdpaddr += reg[AUTOINC];
261                                 return;
262                         case 3:
263                                 cramwrite(vdpaddr & 0x7f, v);
264                                 vdpaddr = (vdpaddr + reg[AUTOINC]) & 0x7f;
265                                 return;
266                         case 5:
267                                 w = vdpaddr & 0x7f;
268                                 if(w < 80)
269                                         vsram[w / 2] = v;
270                                 vdpaddr = (vdpaddr + reg[AUTOINC]) & 0x7f;
271                                 return;
272                         default:
273                                 return;
274                         }
275                 case 4: case 6:
276                         vdpwrite(v);
277                         return;
278                 case 16: case 18: case 20: case 22:
279                         return;
280                 default:
281                         goto invalid;
282                 }
283         case 7:
284                 p = &ram[((u16int)a) / 2];
285                 *p = *p & ~m | v & m;
286                 break;
287         default:
288         invalid:
289                 sysfatal("write to %#.6x (pc=%#.6x)", a, curpc);
290         }
291 }
292
293 void
294 dmastep(void)
295 {
296         u16int v, *p;
297         u32int a;
298         
299         switch(dma){
300         case 1:
301                 a = reg[DMASRC0] << 1 | reg[DMASRC1] << 9 | reg[DMASRC2] << 17;
302                 v = memread(a);
303                 if(++reg[DMASRC0] == 0)
304                         reg[DMASRC1]++;
305                 switch(vdplatch & 0x7){
306                 case 1:
307                         if((vdpaddr & 1) != 0)
308                                 v = v >> 8 | v << 8;
309                         vramdebug(vdpaddr, "dma from 68K %x val %x (%d)\n", a, v, 0);
310                         vram[vdpaddr / 2] = v;
311                         break;
312                 case 3:
313                         if(vdpaddr > 0x7f)
314                                 dma = 0;
315                         else
316                                 cramwrite(vdpaddr, v);
317                         break;
318                 case 5:
319                         if(vdpaddr < 80)
320                                 vsram[vdpaddr / 2] = v;
321                         break;
322                 }
323                 break;
324         case 2:
325                 return;
326         case 3:
327                 a = reg[DMASRC0] | reg[DMASRC1] << 8;
328                 v = vram[a / 2];
329                 if((a & 1) == 0)
330                         v = v >> 8;
331                 if(++reg[DMASRC0] == 0)
332                         reg[DMASRC1]++;
333                 vramdebug(vdpaddr, "dma copy from %x val %x (%d)\n", a, v, 0);
334                 p = &vram[vdpaddr / 2];
335                 if((vdpaddr & 1) != 0)
336                         *p = *p & 0xff00 | v & 0xff;
337                 else
338                         *p = *p & 0xff | v << 8;
339                 break;
340         case 4:
341                 p = &vram[vdpaddr / 2];
342                 vramdebug(vdpaddr, "dma fill val %x (%d%d)\n", vdpdata, 0, 0);
343                 if((vdpaddr & 1) == 0)
344                         *p = *p & 0xff00 | vdpdata;
345                 else
346                         *p = *p & 0xff | vdpdata << 8;
347                 break;
348         }
349         vdpaddr += reg[AUTOINC];
350         if(reg[DMACL]-- == 0)
351                 reg[DMACH]--;
352         if((reg[DMACL] | reg[DMACH]) == 0)
353                 dma = 0;
354 }
355
356 u8int
357 z80read(u16int a)
358 {
359         u16int v;
360
361         switch(a >> 13){
362         case 0:
363         case 1:
364                 return zram[a & 0x1fff];
365         case 2:
366                 return ymstat;
367         case 3:
368                 if(a >= 0x7f00){
369                         v = memread(0xc00000 | a & 0x7e);
370                         if((a & 1) == 0)
371                                 v >>= 8;
372                         return v;
373                 }
374                 sysfatal("z80 read from %#.4x (pc=%#.4x)", a, scurpc);
375         default:
376                 v = memread(z80bank << 15 | a & 0x7ffe);
377                 if((a & 1) == 0)
378                         v >>= 8;
379                 return v;
380         }
381 }
382
383 void
384 z80write(u16int a, u8int v)
385 {
386         switch(a >> 13){
387         case 0:
388         case 1:
389                 zram[a & 0x1fff] = v;
390                 return;
391         case 2:
392                 switch(a & 3){
393                 case 0: yma1 = v; return;
394                 case 1: ymwrite(yma1, v, 0); return;
395                 case 2: yma2 = v; return;
396                 case 3: ymwrite(yma2, v, 3); return;
397                 }
398         case 3:
399                 if(a < 0x6100){
400                         z80bank = z80bank >> 1 | v << 8 & 0x100;
401                         return;
402                 }
403                 if(a >= 0x7f00){
404                         memwrite(0xc00000 | a & 0x7e, v | v << 8, (a & 1) != 0 ? 0xff : 0xff00);
405                         return;
406                 }
407                 sysfatal("z80 write to %#.4x (pc=%#.4x)", a, scurpc);
408         default:
409                 memwrite(z80bank << 15 | a & 0x7ffe, v << 8 | v, (a & 1) != 0 ? 0xff : 0xff00);
410         }
411 }
412
413 u8int
414 z80in(u8int)
415 {
416         return 0xff;
417 }
418
419 void
420 z80out(u8int, u8int)
421 {
422 }
423
424 u32int irql[8] = {[6] INTVBL, [4] INTHOR};
425
426 int
427 intack(int l)
428 {
429         switch(l){
430         case 4:
431                 irq &= ~INTHOR;
432                 break;
433         case 6:
434                 irq &= ~INTVBL;
435                 break;
436         }
437         return 24 + l;
438 }