]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/gb/mem.c
audiohda: fix syntax error
[plan9front.git] / sys / src / games / gb / 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 u8int *rom;
9 u8int *romb, *vramb, *wramb, *eramb;
10 u8int wram[32768], vram[16384], oam[256], reg[256];
11 u8int *back;
12 u8int palm[128];
13 u32int pal[64];
14 int nrom, nback, nbackbank;
15 u32int divclock;
16 int prish;
17 MBC3Timer timer, timerl;
18 u8int dma;
19 u32int white;
20 u32int moncols[4];
21
22 Var memvars[] = {ARR(wram), ARR(vram), ARR(oam), ARR(reg), ARR(palm), VAR(clock), VAR(divclock), VAR(mode), VAR(dma), {nil, 0, 0}};
23
24 u8int
25 regread(u8int a)
26 {
27         u8int v;
28
29         switch(a){
30         case JOYP:
31                 v = reg[a] & 0xff;
32                 if((reg[a] & 0x10) == 0)
33                         v &= 0xf0 | ~keys;
34                 if((reg[a] & 0x20) == 0)
35                         v &= 0xf0 | ~(keys >> 4);
36                 return v;
37         case DIV:
38                 return reg[DIV] + (clock - divclock >> 7 - ((mode & TURBO) != 0));
39         case TIMA:
40                 return timread();
41         case STAT:
42                 return reg[a] & 0xf8 | (reg[LYC] == ppuy) << 2 | ppustate;
43         case LY:
44                 return ppuy;
45         case BCPD:
46                 return palm[reg[BCPS] & 0x3f];
47         case OCPD:
48                 return palm[0x40 | reg[OCPS] & 0x3f];
49         case NR13: case NR23: case NR31: case NR33: case NR41:
50                 return 0xff;
51         case NR14: case NR24: case NR34: case NR44:
52                 return reg[a] | 0xbf;
53         case NR52:
54                 return apustatus;
55         case NR11: case NR21:
56                 return reg[a] | 0x3f;
57         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
58         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
59                 return waveread(a & 0xf);
60         default:
61                 return reg[a];
62         }
63 }
64
65 void
66 colcol(int i, u16int v)
67 {
68         union { u8int c[4]; u32int l; } c;
69
70         c.c[0] = v >> 7 & 0xf8;
71         c.c[1] = v >> 2 & 0xf8;
72         c.c[2] = v << 3;
73         c.c[3] = 0;
74         pal[i] = c.l;   
75 }
76
77 void
78 regwrite(u8int a, u8int v)
79 {
80         extern Event evhblank;
81         int i;
82         u8int u;
83
84         switch(a){
85         case JOYP: v |= 0xcf; break;
86         case SC: v |= 0x7c; break;
87         case DIV:
88                 divclock = clock;
89                 v = 0;
90                 break;
91         case TIMA:
92                 reg[a] = v;
93                 timerset();
94                 return;
95         case TAC:
96                 v |= 0xf8;
97                 timertac(v, 0);
98                 break;
99         case STAT:
100                 v |= 0x80;
101                 if((v & IRQLYC) != 0 && ppuy == reg[LYC])
102                         reg[IF] |= IRQLCDS;
103                 break;
104         case LYC:
105                 if((reg[STAT] & IRQLYC) != 0 && ppuy == v)
106                         reg[IF] |= IRQLCDS;
107                 break;
108         case LCDC:
109                 ppusync();
110                 if((~v & reg[a] & LCDEN) != 0){
111                         ppuy = 0;
112                         ppustate = 0;
113                         delevent(&evhblank);
114                 }
115                 if((v & ~reg[a] & LCDEN) != 0)
116                         addevent(&evhblank, 456*2);
117                 break;
118         case SCY: case SCX: case WY: case WX:
119                 ppusync();
120                 break;
121         case VBK:
122                 if((mode & COL) == 0)
123                         goto ff;
124                 vramb = vram + ((v & 1) << 13);
125                 v |= 0xfe;
126                 break;
127         case SVBK:
128                 if((mode & COL) == 0)
129                         goto ff;
130                 v &= 7;
131                 wramb = wram + (v + (v - 1 >> 3 & 1) << 12);
132                 v |= 0xf8;
133                 break;
134         case BGP:
135         case OBP0:
136         case OBP1:
137                 if((mode & COL) != 0)
138                         break;
139                 ppusync();
140                 i = a - BGP << 2;
141                 pal[i] = moncols[~v & 3];
142                 pal[i+1] = moncols[~v >> 2 & 3];
143                 pal[i+2] = moncols[~v >> 4 & 3];
144                 pal[i+3] = moncols[~v >> 6 & 3];
145                 break;
146         case DMA:
147                 for(i = 0; i < 160; i++)
148                         oam[i] = memread(v << 8 | i);
149                 break;
150         case BCPS: v |= 0x40; break;
151         case OCPS: v |= 0x40; break;
152         case BCPD:
153                 if((mode & COL) == 0)
154                         break;
155                 ppusync();
156                 u = reg[BCPS] & 0x3f;
157                 palm[u] = v;
158                 colcol(u / 2, palm[u & 0xfe] | palm[u | 1] << 8);
159                 if((reg[BCPS] & 0x80) != 0)
160                         reg[BCPS] = reg[BCPS] + 1 - (u + 1 & 0x40);
161                 break;
162         case OCPD:
163                 if((mode & COL) == 0)
164                         break;
165                 ppusync();
166                 u = 0x40 | reg[OCPS] & 0x3f;
167                 palm[u] = v;
168                 colcol(u / 2, palm[u & 0xfe] | palm[u | 1] << 8);
169                 if((reg[OCPS] & 0x80) != 0)
170                         reg[OCPS] = reg[OCPS] + 1 - ((reg[OCPS] & 0x3f) + 1 & 0x40);
171                 break;
172         case IF: v |= 0xe0; break;
173         case IE: v &= 0x1f; break;
174         case KEY1: v |= 0x7e; break;
175         case HDMAC:
176                 if((mode & COL) == 0)
177                         goto ff;
178                 if(v & 0x80){
179                         v &= 0x7f;
180                         dma = DMAHBLANK;
181                 }else if(dma){
182                         v |= 0x80;
183                         dma = 0;
184                 }else
185                         dma = DMAREADY;
186                 break;
187         case NR10: v |= 0x80; goto snd;
188         case NR14: case NR24: v |= 0x38; goto snd;
189         case NR30: v |= 0x7f; goto snd;
190         case NR32: v |= 0x9f; goto snd;
191         case NR41: v |= 0xc0; goto snd;
192         case NR44: v |= 0x3f; goto snd;
193         case NR52: v |= 0x70; goto snd;
194         case NR11: case NR12: case NR13:
195         case NR21: case NR22: case NR23:
196         case NR31: case NR33: case NR34:
197         case NR42: case NR43:
198         case NR50: case NR51:
199         snd:
200                 sndwrite(a, v);
201                 return;
202         case SB:
203         case TMA:
204                 break;
205         case HDMASL: case HDMASH: case HDMADL: case HDMADH: case RP:
206                 if((mode & COL) == 0)
207                         goto ff;
208                 break;
209         case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
210         case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
211                 wavewrite(a & 0xf, v);
212                 return;
213         default:
214                 if(a >= 0x80)
215                         break;
216         ff:
217                 v = 0xff;
218         }
219         reg[a] = v;
220 }
221
222 static void
223 nope(int p)
224 {
225         print("unimplemented mapper function %d (mapper %d)\n", p, mbc);
226 }
227
228 static int
229 mbc0(int a, int)
230 {
231         if(a < 0)
232                 switch(a){
233                 case INIT:
234                         if(nback != 0)
235                                 eramb = back;
236                         return 0;
237                 case SAVE:
238                 case RSTR:
239                         return 0;
240                 case READ:
241                         return -1;
242                 default:
243                         nope(a);
244                 }
245         return 0;
246 }
247
248 static int
249 mbc1(int a, int v)
250 {
251         static u8int ramen, b0, b1, romram;
252         static Var mbc1vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(romram), {nil, 0, 0}};
253         u16int b;
254
255         if(a < 0)
256                 switch(a){
257                 case INIT:
258                         return 0;
259                 case SAVE:
260                         putvars(mbc1vars);
261                         break;
262                 case RSTR:
263                         getvars(mbc1vars);
264                         break;
265                 case READ:
266                         return -1;
267                 default:
268                         nope(a);
269                 }
270         switch(a >> 13){
271         case 0: ramen = (v & 0xf) == 0xa; break;
272         case 1: v &= 0x1f; b0 = v != 0 ? v : 1; break;
273         case 2: b1 = v & 3; b1 %= nbackbank; break;
274         case 3: romram = v & 1; break;
275         }
276         b = b0;
277         if(!romram)
278                 b |= b1 << 5;
279         b %= nrom >> 14;
280         romb = rom + (b << 14);
281         if(ramen)
282                 if(romram)
283                         eramb = back + (b1 << 13);
284                 else
285                         eramb = back;
286         else
287                 eramb = nil;
288         return 0;
289 }
290
291 static int
292 mbc2(int a, int v)
293 {
294         static int ramen, b;
295         static Var mbc2vars[] = {VAR(ramen), VAR(b), {nil, 0, 0}};
296
297         if(a < 0)
298                 switch(a){
299                 case INIT:
300                         return 0;
301                 case SAVE:
302                         putvars(mbc2vars);
303                         return 0;
304                 case RSTR:
305                         getvars(mbc2vars);
306                         romb = rom + (b << 14);
307                         return 0;
308                 case READ:
309                         if(ramen)
310                                 return back[a & 0x1ff];
311                         return 0xff;
312                 default:
313                         nope(a);
314                 }
315         if((a & 0xc100) == 0)
316                 ramen = (v & 0x0f) == 0x0a;
317         else if((a & 0xc100) == 0x100){
318                 b = v & 0x0f;
319                 if(b == 0)
320                         b++;
321                 b %= nrom >> 14;
322                 romb = rom + (b << 14);
323         }else if((a >> 12) == 0xa && ramen)
324                 back[a & 0x1ff] = v | 0xf0;
325         return 0;
326 }
327
328 void
329 timerforward(MBC3Timer *t)
330 {
331         vlong n, nd;
332         int x;
333         
334         n = nsec();
335         nd = n - t->ns;
336         if(nd < 0)
337                 return;
338         if((t->dh & 0x40) != 0){
339                 t->ns = n;
340                 return;
341         }
342         t->ns = n - nd % BILLION;
343         x = t->sec + t->min * 60 + t->hr * 3600 + t->dl * 86400 + t->dh * (256 * 86400);
344         x += nd / BILLION;
345         t->sec = x % 60;
346         x /= 60;
347         t->min = x % 60;
348         x /= 60;
349         t->hr = x % 24;
350         x /= 24;
351         t->dl = x & 0xff;
352         x >>= 8;
353         t->dh = t->dh & 0xfe | x & 1;
354         if(x >= 2) t->dh |= 0x80;
355 }
356
357 static int
358 mbc3(int a, int v)
359 {
360         static u8int ramen, b0, b1, latch;
361         static Var mbc3vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(latch),
362                 VAR(timer.ns), VAR(timer.sec), VAR(timer.min), VAR(timer.hr), VAR(timer.dl), VAR(timer.dh),
363                 VAR(timerl.sec), VAR(timerl.min), VAR(timerl.hr), VAR(timerl.dl), VAR(timerl.dh), {nil, 0, 0}};
364
365         if(a < 0)
366                 switch(a){
367                 case INIT:
368                         return 0;
369                 case SAVE:
370                         putvars(mbc3vars);
371                         return 0;
372                 case RSTR:
373                         getvars(mbc3vars);
374                         romb = rom + (b0 << 14);
375                         break;
376                 case READ:
377                         if(!ramen)
378                                 return -1;
379                         switch(b1){
380                         case 8: return timerl.sec;
381                         case 9: return timerl.min;
382                         case 10: return timerl.hr;
383                         case 11: return timerl.dl;
384                         case 12: return timerl.dh;
385                         }
386                         return -1;
387                 default:
388                         nope(a);
389                 }
390         switch(a >> 13){
391         case 0: ramen = (v & 0xf) == 0xa; break;
392         case 1:
393                 v &= 0x7f;
394                 b0 = v != 0 ? v : 1;
395                 b0 %= nrom >> 14;
396                 romb = rom + (b0 << 14);
397                 return 0;
398         case 2: b1 = v & 15; break;
399         case 3:
400                 if(latch == 0 && v == 1){
401                         timerl = timer;
402                         timerforward(&timerl);
403                 }
404                 latch = v;
405                 break;
406         case 0xa:
407                 if(!ramen)
408                         return 0;
409                 switch(b1){
410                 case 8: timerforward(&timer); timer.sec = v; break;
411                 case 9: timerforward(&timer); timer.min = v; break;
412                 case 10: timerforward(&timer); timer.hr = v; break;
413                 case 11: timerforward(&timer); timer.dl = v; break;
414                 case 12: timerforward(&timer); timer.dh = v; break;
415                 }
416                 return 0;
417         }
418         eramb = ramen && b1 < nbackbank ? back + (b1 << 13) : nil;
419         return 0;
420 }
421
422 static int
423 mbc5(int a, int v)
424 {
425         static u8int ramen, b1;
426         static u16int b0;
427         static Var mbc5vars[] = {VAR(ramen), VAR(b0), VAR(b1), {nil, 0, 0}};
428
429         if(a < 0)
430                 switch(a){
431                 case INIT:
432                         return 0;
433                 case SAVE:
434                         putvars(mbc5vars);
435                         return 0;
436                 case RSTR:
437                         getvars(mbc5vars);
438                         break;
439                 case READ:
440                         return -1;
441                 default:
442                         nope(a);
443                 }
444         switch(a >> 12){
445         case 0: case 1: ramen = (v & 0xf) == 0xa; break;
446         case 2: b0 = b0 & 0x100 | v; break;
447         case 3: b0 = b0 & 0xff | v << 8 & 0x100; break;
448         case 4: b1 = v & 0xff; b1 %= nbackbank; break;
449         }
450         b0 %= nrom >> 14;
451         romb = rom + (b0 << 14); 
452         eramb = ramen ? back + (b1 << 13) : nil;
453         return 0;
454         
455 }
456
457 int (*mappers[7])(int, int) = {mbc0, mbc1, mbc2, mbc3, mbc0, mbc5, mbc0};
458 int (*mapper)(int, int);
459
460 u8int
461 memread(u16int a)
462 {
463         switch(a >> 12){
464         case 0: case 1: case 2: case 3:
465                 return rom[a];
466         case 4: case 5: case 6: case 7:
467                 return romb[a - 0x4000];
468         case 8: case 9:
469                 return vramb[a - 0x8000];
470         case 10: case 11:
471                 if(eramb != nil)
472                         return eramb[a - 0xa000];
473                 return mapper(READ, a);
474         case 12: case 14:
475                 return wram[a & 0xfff];
476         case 15:
477                 if(a >= 0xff00)
478                         return regread(a);
479                 else if(a >= 0xfe00)
480                         return oam[a - 0xfe00];
481         case 13:
482                 return wramb[a & 0xfff];
483         }
484         return 0xff;
485 }
486
487 void
488 memwrite(u16int a, u8int v)
489 {
490         switch(a >> 12){
491         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
492                 mapper(a, v);
493                 return;
494         case 8: case 9:
495                 vramb[a - 0x8000] = v;
496                 return;
497         case 10: case 11:
498                 if(eramb != nil)
499                         eramb[a - 0xa000] = v;
500                 else
501                         mapper(a, v);
502                 writeback();
503                 return;
504         case 12: case 14:
505                 wram[a & 0xfff] = v;
506                 return;
507         case 15:
508                 if(a >= 0xff00){
509                         regwrite(a, v);
510                         return;
511                 }else if(a >= 0xfe00){
512                         oam[a - 0xfe00] = v;
513                         return;
514                 }
515         case 13:
516                 wramb[a & 0xfff] = v;
517         }
518 }
519
520 void
521 meminit(void)
522 {
523         union { u8int c[4]; u32int l; } c;
524
525         c.c[0] = c.c[1] = c.c[2] = 0;
526         c.c[3] = 1;
527         for(; c.l != 1; prish++)
528                 c.l >>= 1;
529         
530         c.c[0] = c.c[1] = c.c[2] = 0xff;
531         c.c[3] = 0;
532         white = c.l;
533
534         romb = rom + 0x4000;
535         wramb = wram + 0x1000;
536         vramb = vram;
537         mapper = mappers[mbc];
538         mapper(INIT, 0);
539         
540         reg[LCDC] = 0x91;
541         reg[VBK] = 0xfe;
542         reg[SVBK] = 0xf8;
543         reg[IF] = 0xe0;
544         reg[HDMAC] = 0xff;
545 }
546
547 void
548 memload(void)
549 {
550         int i;
551         u8int v;
552
553         if((mode & COL) != 0){
554                 for(i = 0; i < 64; i++)
555                         colcol(i, palm[2*i] | palm[2*i+1] << 8);
556                 vramb = vram + ((reg[VBK] & 1) << 13);
557                 wramb = wram + (reg[SVBK] + (reg[SVBK] - 1 >> 3 & 1) << 12);
558         }else{
559                 v = reg[BGP];
560                 pal[0] = moncols[~v & 3];
561                 pal[1] = moncols[~v >> 2 & 3];
562                 pal[2] = moncols[~v >> 4 & 3];
563                 pal[3] = moncols[~v >> 6 & 3];
564                 v = reg[OBP0];
565                 pal[4] = moncols[~v & 3];
566                 pal[5] = moncols[~v >> 2 & 3];
567                 pal[6] = moncols[~v >> 4 & 3];
568                 pal[7] = moncols[~v >> 6 & 3];
569                 v = reg[OBP1];
570                 pal[8] = moncols[~v & 3];
571                 pal[9] = moncols[~v >> 2 & 3];
572                 pal[10] = moncols[~v >> 4 & 3];
573                 pal[11] = moncols[~v >> 6 & 3];
574         }
575
576 }
577
578 int
579 dmastep(void)
580 {
581         int i;
582         u16int sa, da;
583
584         sa = (reg[HDMASL] | reg[HDMASH] << 8) & 0xfff0;
585         da = (reg[HDMADL] | reg[HDMADH] << 8) & 0x1ff0 | 0x8000;
586         for(i = 0; i < 16; i++)
587                 memwrite(da++, memread(sa++));
588         reg[HDMASL] += 16;
589         if((reg[HDMASL] & 0xf0) == 0)
590                 reg[HDMASH]++;
591         reg[HDMADL] += 16;
592         if((reg[HDMADL] & 0xf0) == 0)
593                 reg[HDMADH]++;
594         if(--reg[HDMAC] == 0xff)
595                 dma = 0;
596         else if(dma & DMAHBLANK)
597                 dma &= ~DMAREADY;
598         return 64;
599 }