9 u8int *romb, *vramb, *wramb, *eramb;
10 u8int wram[32768], vram[16384], oam[256], reg[256];
14 int nrom, nback, nbackbank;
17 MBC3Timer timer, timerl;
22 Var memvars[] = {ARR(wram), ARR(vram), ARR(oam), ARR(reg), ARR(palm), VAR(clock), VAR(divclock), VAR(mode), VAR(dma), {nil, 0, 0}};
32 if((reg[a] & 0x10) == 0)
34 if((reg[a] & 0x20) == 0)
35 v &= 0xf0 | ~(keys >> 4);
38 return reg[DIV] + (clock - divclock >> 7 - ((mode & TURBO) != 0));
42 return reg[a] & 0xf8 | (reg[LYC] == ppuy) << 2 | ppustate;
46 return palm[reg[BCPS] & 0x3f];
48 return palm[0x40 | reg[OCPS] & 0x3f];
49 case NR13: case NR23: case NR31: case NR33: case NR41:
51 case NR14: case NR24: case NR34: case NR44:
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);
66 colcol(int i, u16int v)
68 union { u8int c[4]; u32int l; } c;
70 c.c[0] = v >> 7 & 0xf8;
71 c.c[1] = v >> 2 & 0xf8;
78 regwrite(u8int a, u8int v)
80 extern Event evhblank;
85 case JOYP: v |= 0xcf; break;
86 case SC: v |= 0x7c; break;
101 if((v & IRQLYC) != 0 && ppuy == reg[LYC])
105 if((reg[STAT] & IRQLYC) != 0 && ppuy == v)
110 if((~v & reg[a] & LCDEN) != 0){
115 if((v & ~reg[a] & LCDEN) != 0)
116 addevent(&evhblank, 456*2);
118 case SCY: case SCX: case WY: case WX:
122 if((mode & COL) == 0)
124 vramb = vram + ((v & 1) << 13);
128 if((mode & COL) == 0)
131 wramb = wram + (v + (v - 1 >> 3 & 1) << 12);
137 if((mode & COL) != 0)
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];
147 for(i = 0; i < 160; i++)
148 oam[i] = memread(v << 8 | i);
150 case BCPS: v |= 0x40; break;
151 case OCPS: v |= 0x40; break;
153 if((mode & COL) == 0)
156 u = reg[BCPS] & 0x3f;
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);
163 if((mode & COL) == 0)
166 u = 0x40 | reg[OCPS] & 0x3f;
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);
172 case IF: v |= 0xe0; break;
173 case IE: v &= 0x1f; break;
174 case KEY1: v |= 0x7e; break;
176 if((mode & COL) == 0)
178 dma = (v & 0x80) != 0 ? -1 : 1;
180 case NR10: v |= 0x80; goto snd;
181 case NR14: case NR24: v |= 0x38; goto snd;
182 case NR30: v |= 0x7f; goto snd;
183 case NR32: v |= 0x9f; goto snd;
184 case NR41: v |= 0xc0; goto snd;
185 case NR44: v |= 0x3f; goto snd;
186 case NR52: v |= 0x70; goto snd;
187 case NR11: case NR12: case NR13:
188 case NR21: case NR22: case NR23:
189 case NR31: case NR33: case NR34:
190 case NR42: case NR43:
191 case NR50: case NR51:
198 case HDMASL: case HDMASH: case HDMADL: case HDMADH: case RP:
199 if((mode & COL) == 0)
202 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
203 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
204 wavewrite(a & 0xf, v);
218 print("unimplemented mapper function %d (mapper %d)\n", p, mbc);
244 static u8int ramen, b0, b1, romram;
245 static Var mbc1vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(romram), {nil, 0, 0}};
264 case 0: ramen = (v & 0xf) == 0xa; break;
265 case 1: v &= 0x1f; b0 = v != 0 ? v : 1; break;
266 case 2: b1 = v & 3; b1 %= nbackbank; break;
267 case 3: romram = v & 1; break;
273 romb = rom + (b << 14);
276 eramb = back + (b1 << 13);
288 static Var mbc2vars[] = {VAR(ramen), VAR(b), {nil, 0, 0}};
299 romb = rom + (b << 14);
303 return back[a & 0x1ff];
308 if((a & 0xc100) == 0)
309 ramen = (v & 0x0f) == 0x0a;
310 else if((a & 0xc100) == 0x100){
315 romb = rom + (b << 14);
316 }else if((a >> 12) == 0xa && ramen)
317 back[a & 0x1ff] = v | 0xf0;
322 timerforward(MBC3Timer *t)
331 if((t->dh & 0x40) != 0){
335 t->ns = n - nd % BILLION;
336 x = t->sec + t->min * 60 + t->hr * 3600 + t->dl * 86400 + t->dh * (256 * 86400);
346 t->dh = t->dh & 0xfe | x & 1;
347 if(x >= 2) t->dh |= 0x80;
353 static u8int ramen, b0, b1, latch;
354 static Var mbc3vars[] = {VAR(ramen), VAR(b0), VAR(b1), VAR(latch),
355 VAR(timer.ns), VAR(timer.sec), VAR(timer.min), VAR(timer.hr), VAR(timer.dl), VAR(timer.dh),
356 VAR(timerl.sec), VAR(timerl.min), VAR(timerl.hr), VAR(timerl.dl), VAR(timerl.dh), {nil, 0, 0}};
367 romb = rom + (b0 << 14);
373 case 8: return timerl.sec;
374 case 9: return timerl.min;
375 case 10: return timerl.hr;
376 case 11: return timerl.dl;
377 case 12: return timerl.dh;
384 case 0: ramen = (v & 0xf) == 0xa; break;
389 romb = rom + (b0 << 14);
391 case 2: b1 = v & 15; break;
393 if(latch == 0 && v == 1){
395 timerforward(&timerl);
403 case 8: timerforward(&timer); timer.sec = v; break;
404 case 9: timerforward(&timer); timer.min = v; break;
405 case 10: timerforward(&timer); timer.hr = v; break;
406 case 11: timerforward(&timer); timer.dl = v; break;
407 case 12: timerforward(&timer); timer.dh = v; break;
411 eramb = ramen && b1 < nbackbank ? back + (b1 << 13) : nil;
418 static u8int ramen, b1;
420 static Var mbc5vars[] = {VAR(ramen), VAR(b0), VAR(b1), {nil, 0, 0}};
438 case 0: case 1: ramen = (v & 0xf) == 0xa; break;
439 case 2: b0 = b0 & 0x100 | v; break;
440 case 3: b0 = b0 & 0xff | v << 8 & 0x100; break;
441 case 4: b1 = v & 0xff; b1 %= nbackbank; break;
444 romb = rom + (b0 << 14);
445 eramb = ramen ? back + (b1 << 13) : nil;
450 int (*mappers[7])(int, int) = {mbc0, mbc1, mbc2, mbc3, mbc0, mbc5, mbc0};
451 int (*mapper)(int, int);
457 case 0: case 1: case 2: case 3:
459 case 4: case 5: case 6: case 7:
460 return romb[a - 0x4000];
462 return vramb[a - 0x8000];
465 return eramb[a - 0xa000];
466 return mapper(READ, a);
468 return wram[a & 0xfff];
473 return oam[a - 0xfe00];
475 return wramb[a & 0xfff];
481 memwrite(u16int a, u8int v)
484 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
488 vramb[a - 0x8000] = v;
492 eramb[a - 0xa000] = v;
504 }else if(a >= 0xfe00){
509 wramb[a & 0xfff] = v;
516 union { u8int c[4]; u32int l; } c;
518 c.c[0] = c.c[1] = c.c[2] = 0;
520 for(; c.l != 1; prish++)
523 c.c[0] = c.c[1] = c.c[2] = 0xff;
528 wramb = wram + 0x1000;
530 mapper = mappers[mbc];
545 if((mode & COL) != 0){
546 for(i = 0; i < 64; i++)
547 colcol(i, palm[2*i] | palm[2*i+1] << 8);
548 vramb = vram + ((reg[VBK] & 1) << 13);
549 wramb = wram + (reg[SVBK] + (reg[SVBK] - 1 >> 3 & 1) << 12);
552 pal[0] = moncols[~v & 3];
553 pal[1] = moncols[~v >> 2 & 3];
554 pal[2] = moncols[~v >> 4 & 3];
555 pal[3] = moncols[~v >> 6 & 3];
557 pal[4] = moncols[~v & 3];
558 pal[5] = moncols[~v >> 2 & 3];
559 pal[6] = moncols[~v >> 4 & 3];
560 pal[7] = moncols[~v >> 6 & 3];
562 pal[8] = moncols[~v & 3];
563 pal[9] = moncols[~v >> 2 & 3];
564 pal[10] = moncols[~v >> 4 & 3];
565 pal[11] = moncols[~v >> 6 & 3];
576 sa = (reg[HDMASL] | reg[HDMASH] << 8) & 0xfff0;
577 da = (reg[HDMADL] | reg[HDMADH] << 8) & 0x1ff0 | 0x8000;
578 for(i = 0; i < 16; i++)
579 memwrite(da++, memread(sa++));
581 if((reg[HDMASL] & 0xf0) == 0)
584 if((reg[HDMADL] & 0xf0) == 0)
586 if((reg[HDMAC] & 0x7f) == 0)
590 if((reg[HDMAC] & 0x80) != 0)