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