mapper fixes for ncpu, debug is broken atm
[fceu.git] / mbshare / mmc3.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 1998 BERO
5  *  Copyright (C) 2002 Ben Parnell
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /*  Code for emulating iNES mappers 4, 118,119 */
23
24 #include "mapinc.h"
25
26 #define resetmode mapbyte1[0]
27 #define MMC3_cmd mapbyte1[1]
28 #define A000B mapbyte1[2]
29 #define A001B mapbyte1[3]
30 #define DRegBuf mapbyte4
31
32 #define PPUCHRBus mapbyte2[0]
33 #define TKSMIR mapbyte3
34 #define PIRREGS mapbyte2
35
36 static void (*pwrap)(uint32 A, uint8 V);
37 static void (*cwrap)(uint32 A, uint8 V);
38 static void (*mwrap)(uint8 V);
39
40 static int mmc3opts=0;
41
42 static INLINE void FixMMC3PRG(int V);
43 static INLINE void FixMMC3CHR(int V);
44
45 static int latched;
46
47 static DECLFW(MMC3_IRQWrite)
48 {
49         //printf("$%04x:$%02x, %d\n",A,V,scanline);
50         switch(A&0xE001)
51         {
52          case 0xc000:IRQLatch=V;
53                      latched=1;
54                      if(resetmode)
55                      {
56                       IRQCount=V;
57                       latched=0;
58                       //resetmode=0;
59                      }
60                      break;
61          case 0xc001:IRQCount=IRQLatch;
62                      break;
63          case 0xE000:IRQa=0;
64                      X6502_IRQEnd(FCEU_IQEXT);
65                      resetmode=1;
66                      break;
67          case 0xE001:IRQa=1;
68                      if(latched)
69                       IRQCount=IRQLatch;
70                      break;
71         }
72 }
73
74 static INLINE void FixMMC3PRG(int V)
75 {
76           if(V&0x40)
77           {
78            pwrap(0xC000,DRegBuf[6]);
79            pwrap(0x8000,~1);
80           }
81           else
82           {
83            pwrap(0x8000,DRegBuf[6]);
84            pwrap(0xC000,~1);
85           }
86           pwrap(0xA000,DRegBuf[7]);
87           pwrap(0xE000,~0);
88           X6502_Rebase();
89 }
90
91 static INLINE void FixMMC3CHR(int V)
92 {
93            int cbase=(V&0x80)<<5;
94            cwrap((cbase^0x000),DRegBuf[0]&(~1));
95            cwrap((cbase^0x400),DRegBuf[0]|1);
96            cwrap((cbase^0x800),DRegBuf[1]&(~1));
97            cwrap((cbase^0xC00),DRegBuf[1]|1);
98
99            cwrap(cbase^0x1000,DRegBuf[2]);
100            cwrap(cbase^0x1400,DRegBuf[3]);
101            cwrap(cbase^0x1800,DRegBuf[4]);
102            cwrap(cbase^0x1c00,DRegBuf[5]);
103 }
104
105 static void MMC3RegReset(void)
106 {
107  IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
108
109  DRegBuf[0]=0;
110  DRegBuf[1]=2;
111  DRegBuf[2]=4;
112  DRegBuf[3]=5;
113  DRegBuf[4]=6;
114  DRegBuf[5]=7;
115  DRegBuf[6]=0;
116  DRegBuf[7]=1;
117
118  FixMMC3PRG(0);
119  FixMMC3CHR(0);
120 }
121
122 static DECLFW(Mapper4_write)
123 {
124         switch(A&0xE001)
125         {
126          case 0x8000:
127           if((V&0x40) != (MMC3_cmd&0x40))
128            FixMMC3PRG(V);
129           if((V&0x80) != (MMC3_cmd&0x80))
130            FixMMC3CHR(V);
131           MMC3_cmd = V;
132           break;
133
134         case 0x8001:
135                 {
136                  int cbase=(MMC3_cmd&0x80)<<5;
137                  DRegBuf[MMC3_cmd&0x7]=V;
138                  switch(MMC3_cmd&0x07)
139                  {
140                   case 0: cwrap((cbase^0x000),V&(~1));
141                           cwrap((cbase^0x400),V|1);
142                           break;
143                   case 1: cwrap((cbase^0x800),V&(~1));
144                           cwrap((cbase^0xC00),V|1);
145                           break;
146                   case 2: cwrap(cbase^0x1000,V); break;
147                   case 3: cwrap(cbase^0x1400,V); break;
148                   case 4: cwrap(cbase^0x1800,V); break;
149                   case 5: cwrap(cbase^0x1C00,V); break;
150                   case 6: if (MMC3_cmd&0x40) pwrap(0xC000,V);
151                           else pwrap(0x8000,V);
152                           X6502_Rebase();
153                           break;
154                   case 7: pwrap(0xA000,V);
155                           X6502_Rebase();
156                           break;
157                  }
158                 }
159                 break;
160
161         case 0xA000:
162                 if(mwrap) mwrap(V&1);
163                 break;
164         case 0xA001:
165                 A001B=V;
166                 break;
167  }
168 }
169
170 static void MMC3_hb(void)
171 {
172       resetmode=0;
173       if(IRQCount>=0)
174       {
175         IRQCount--;
176         if(IRQCount<0)
177         {
178          //printf("IRQ: %d\n",scanline);
179          if(IRQa)
180           X6502_IRQBegin(FCEU_IQEXT);
181         }
182       }
183 }
184 static int isines;
185
186 static void genmmc3restore(int version)
187 {
188  if(version>=56)
189  {
190   mwrap(A000B&1);
191   FixMMC3PRG(MMC3_cmd);
192   FixMMC3CHR(MMC3_cmd);
193  }
194  else if(isines)
195   iNESStateRestore(version);
196 }
197
198 static void GENCWRAP(uint32 A, uint8 V)
199 {
200  setchr1(A,V);
201 }
202
203 static void GENPWRAP(uint32 A, uint8 V)
204 {
205  setprg8(A,V&0x3F);
206 }
207
208 static void GENMWRAP(uint8 V)
209 {
210  A000B=V;
211  setmirror(V^1);
212 }
213
214 static void GENNOMWRAP(uint8 V)
215 {
216  A000B=V;
217 }
218
219 static void genmmc3ii(void (*PW)(uint32 A, uint8 V),
220                       void (*CW)(uint32 A, uint8 V),
221                       void (*MW)(uint8 V))
222 {
223  pwrap=GENPWRAP;
224  cwrap=GENCWRAP;
225  mwrap=GENMWRAP;
226  if(PW) pwrap=PW;
227  if(CW) cwrap=CW;
228  if(MW) mwrap=MW;
229  A000B=(Mirroring&1)^1; // For hard-wired mirroring on some MMC3 games.
230                         // iNES format needs to die or be extended...
231  mmc3opts=0;
232  SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
233  SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
234
235  GameHBIRQHook=MMC3_hb;
236  GameStateRestore=genmmc3restore;
237  if(!VROM_size)
238   SetupCartCHRMapping(0, CHRRAM, 8192, 1);
239  isines=1;
240  MMC3RegReset();
241  MapperReset=MMC3RegReset;
242 }
243
244 void Mapper4_init(void)
245 {
246  genmmc3ii(0,0,0);
247 }
248
249 static void M47PW(uint32 A, uint8 V)
250 {
251  V&=0xF;
252  V|=PIRREGS[0]<<4;
253  setprg8(A,V);
254 }
255
256 static void M47CW(uint32 A, uint8 V)
257 {
258  uint32 NV=V;
259  NV&=0x7F;
260  NV|=PIRREGS[0]<<7;
261  setchr1(A,NV);
262 }
263
264 static DECLFW(M47Write)
265 {
266  PIRREGS[0]=V&1;
267  FixMMC3PRG(MMC3_cmd);
268  FixMMC3CHR(MMC3_cmd);
269 }
270
271 void Mapper47_init(void)
272 {
273  genmmc3ii(M47PW,M47CW,0);
274  SetWriteHandler(0x6000,0x7FFF,M47Write);
275  SetReadHandler(0x6000,0x7FFF,0);
276 }
277
278 static void M44PW(uint32 A, uint8 V)
279 {
280  uint32 NV=V;
281  if(PIRREGS[0]>=6) NV&=0x1F;
282  else NV&=0x0F;
283  NV|=PIRREGS[0]<<4;
284  setprg8(A,NV);
285 }
286 static void M44CW(uint32 A, uint8 V)
287 {
288  uint32 NV=V;
289  if(PIRREGS[0]<6) NV&=0x7F;
290  NV|=PIRREGS[0]<<7;
291  setchr1(A,NV);
292 }
293
294 static DECLFW(Mapper44_write)
295 {
296  if(A&1)
297  {
298   PIRREGS[0]=V&7;
299   FixMMC3PRG(MMC3_cmd);
300   FixMMC3CHR(MMC3_cmd);
301  }
302  else
303   Mapper4_write(A,V);
304 }
305
306 void Mapper44_init(void)
307 {
308  genmmc3ii(M44PW,M44CW,0);
309  SetWriteHandler(0xA000,0xBFFF,Mapper44_write);
310 }
311
312 static void M52PW(uint32 A, uint8 V)
313 {
314  uint32 NV=V;
315  NV&=0x1F^((PIRREGS[0]&8)<<1);
316  NV|=((PIRREGS[0]&6)|((PIRREGS[0]>>3)&PIRREGS[0]&1))<<4;
317  setprg8(A,NV);
318 }
319
320 static void M52CW(uint32 A, uint8 V)
321 {
322  uint32 NV=V;
323  NV&=0xFF^((PIRREGS[0]&0x40)<<1);
324  NV|=(((PIRREGS[0]>>3)&4)|((PIRREGS[0]>>1)&2)|((PIRREGS[0]>>6)&(PIRREGS[0]>>4)&1))<<7;
325  setchr1(A,NV);
326 }
327
328 static DECLFW(Mapper52_write)
329 {
330  if(PIRREGS[1])
331  {
332   (WRAM-0x6000)[A]=V;
333   return;
334  }
335  PIRREGS[1]=1;
336  PIRREGS[0]=V;
337  FixMMC3PRG(MMC3_cmd);
338  FixMMC3CHR(MMC3_cmd);
339 }
340
341 static void M52Reset(void)
342 {
343  PIRREGS[0]=PIRREGS[1]=0;
344  MMC3RegReset();
345 }
346
347 void Mapper52_init(void)
348 {
349  genmmc3ii(M52PW,M52CW,0);
350  SetWriteHandler(0x6000,0x7FFF,Mapper52_write);
351  MapperReset=M52Reset;
352 }
353
354 static void M45CW(uint32 A, uint8 V)
355 {
356  uint32 NV=V;
357  if(PIRREGS[2]&8)
358   NV&=(1<<( (PIRREGS[2]&7)+1 ))-1;
359  else
360   NV&=0;
361  NV|=PIRREGS[0]|((PIRREGS[2]&0x10)<<4);
362  setchr1(A,NV);
363 }
364
365 static void M45PW(uint32 A, uint8 V)
366 {
367  V&=(PIRREGS[3]&0x3F)^0x3F;
368  V|=PIRREGS[1];
369  setprg8(A,V);
370 }
371
372 static DECLFW(Mapper45_write)
373 {
374  if(PIRREGS[3]&0x40) return;
375  PIRREGS[PIRREGS[4]]=V;
376  PIRREGS[4]=(PIRREGS[4]+1)&3;
377  FixMMC3PRG(MMC3_cmd);
378  FixMMC3CHR(MMC3_cmd);
379 }
380
381 static void M45Reset(void)
382 {
383  FCEU_dwmemset(PIRREGS,0,5);
384  MMC3RegReset();
385 }
386
387 void Mapper45_init(void)
388 {
389  genmmc3ii(M45PW,M45CW,0);
390  SetWriteHandler(0x6000,0x7FFF,Mapper45_write);
391  SetReadHandler(0x6000,0x7FFF,0);
392  MapperReset=M45Reset;
393 }
394 static void M49PW(uint32 A, uint8 V)
395 {
396  if(PIRREGS[0]&1)
397  {
398   V&=0xF;
399   V|=(PIRREGS[0]&0xC0)>>2;
400   setprg8(A,V);
401  }
402  else
403  {
404   setprg32(0x8000,(PIRREGS[0]>>4)&3);
405   X6502_Rebase();
406  }
407 }
408
409 static void M49CW(uint32 A, uint8 V)
410 {
411  uint32 NV=V;
412  NV&=0x7F;
413  NV|=(PIRREGS[0]&0xC0)<<1;
414  setchr1(A,NV);
415 }
416
417 static DECLFW(M49Write)
418 {
419  //printf("$%04x:$%02x\n",A,V);
420  if(A001B&0x80)
421  {
422   PIRREGS[0]=V;
423   FixMMC3PRG(MMC3_cmd);
424   FixMMC3CHR(MMC3_cmd);
425  }
426 }
427
428 static void M49Reset(void)
429 {
430  PIRREGS[0]=0;
431  MMC3RegReset();
432 }
433
434 void Mapper49_init(void)
435 {
436  genmmc3ii(M49PW,M49CW,0);
437  SetWriteHandler(0x6000,0x7FFF,M49Write);
438  SetReadHandler(0x6000,0x7FFF,0);
439  MapperReset=M49Reset;
440 }
441
442 static DECLFW(Mapper250_write)
443 {
444         Mapper4_write((A&0xE000)|((A&0x400)>>10),A&0xFF);
445 }
446
447 static DECLFW(M250_IRQWrite)
448 {
449         MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
450 }
451
452 void Mapper250_init(void)
453 {
454  genmmc3ii(0,0,0);
455  SetWriteHandler(0x8000,0xBFFF,Mapper250_write);
456  SetWriteHandler(0xC000,0xFFFF,M250_IRQWrite);
457 }
458
459 static void FP_FASTAPASS(1) TKSPPU(uint32 A)
460 {
461  //static uint8 z;
462  //if(A>=0x2000 || type<0) return;
463  //if(type<0) return;
464  A&=0x1FFF;
465  //if(scanline>=140 && scanline<=200) {setmirror(MI_1);return;}
466  //if(scanline>=140 && scanline<=200)
467  // if(scanline>=190 && scanline<=200) {setmirror(MI_1);return;}
468  // setmirror(MI_1);
469  //printf("$%04x\n",A);
470
471  A>>=10;
472  PPUCHRBus=A;
473  setmirror(MI_0+TKSMIR[A]);
474 }
475
476 static void TKSWRAP(uint32 A, uint8 V)
477 {
478  TKSMIR[A>>10]=V>>7;
479  setchr1(A,V&0x7F);
480  if(PPUCHRBus==(A>>10))
481   setmirror(MI_0+(V>>7));
482 }
483
484 void Mapper118_init(void)
485 {
486   genmmc3ii(0,TKSWRAP,GENNOMWRAP);
487   PPU_hook=TKSPPU;
488 }
489
490 static void TQWRAP(uint32 A, uint8 V)
491 {
492  setchr1r((V&0x40)>>2,A,V&0x3F);
493 }
494
495 void Mapper119_init(void)
496 {
497   genmmc3ii(0,TQWRAP,0);
498   SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
499 }
500
501 static int wrams;
502
503 static void GenMMC3Close(void)
504 {
505  UNIFOpenWRAM(UOW_WR,0,1);
506  UNIFWriteWRAM(WRAM,wrams);
507  UNIFCloseWRAM();
508 }
509
510 static DECLFW(MBWRAM)
511 {
512   (WRAM-0x6000)[A]=V;
513 }
514
515 static DECLFR(MAWRAM)
516 {
517  return((WRAM-0x6000)[A]);
518 }
519
520 static DECLFW(MBWRAMMMC6)
521 {
522  WRAM[A&0x3ff]=V;
523 }
524
525 static DECLFR(MAWRAMMMC6)
526 {
527  return(WRAM[A&0x3ff]);
528 }
529
530 static void GenMMC3Power(void)
531 {
532  SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
533  SetReadHandler(0x8000,0xFFFF,CartBR);
534  SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
535
536  if(mmc3opts&1)
537  {
538   if(wrams==1024)
539   {
540    FCEU_CheatAddRAM(1,0x7000,WRAM);
541    SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
542    SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
543   }
544   else
545   {
546    FCEU_CheatAddRAM(wrams/1024,0x6000,WRAM);
547    SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
548    SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
549   }
550   if(!(mmc3opts&2))
551    FCEU_dwmemset(WRAM,0,wrams);
552  }
553  MMC3RegReset();
554 }
555
556 void GenMMC3_Init(int prg, int chr, int wram, int battery)
557 {
558  pwrap=GENPWRAP;
559  cwrap=GENCWRAP;
560  mwrap=GENMWRAP;
561
562  wrams=wram*1024;
563
564  PRGmask8[0]&=(prg>>13)-1;
565  CHRmask1[0]&=(chr>>10)-1;
566  CHRmask2[0]&=(chr>>11)-1;
567
568  if(wram)
569  {
570   mmc3opts|=1;
571   AddExState(WRAM, wram*1024, 0, "WRAM");
572  }
573
574  if(battery)
575  {
576   mmc3opts|=2;
577   BoardClose=GenMMC3Close;
578
579   UNIFOpenWRAM(UOW_RD,0,1);
580   UNIFReadWRAM(WRAM,wram*1024);
581   UNIFCloseWRAM();
582  }
583
584  if(!chr)
585  {
586   CHRmask1[0]=7;
587   CHRmask2[0]=3;
588   SetupCartCHRMapping(0, CHRRAM, 8192, 1);
589   AddExState(CHRRAM, 8192, 0, "CHRR");
590  }
591  AddExState(mapbyte1, 32, 0, "MPBY");
592  AddExState(&IRQa, 1, 0, "IRQA");
593  AddExState(&IRQCount, 4, 1, "IRQC");
594  AddExState(&IRQLatch, 4, 1, "IQL1");
595
596  BoardPower=GenMMC3Power;
597  BoardReset=MMC3RegReset;
598
599  GameHBIRQHook=MMC3_hb;
600  GameStateRestore=genmmc3restore;
601  isines=0;
602 }
603
604 // void GenMMC3_Init(int prg, int chr, int wram, int battery)
605
606 void TFROM_Init(void)
607 {
608  GenMMC3_Init(512, 64, 0, 0);
609 }
610
611 void TGROM_Init(void)
612 {
613  GenMMC3_Init(512, 0, 0, 0);
614 }
615
616 void TKROM_Init(void)
617 {
618  GenMMC3_Init(512, 256, 8, 1);
619 }
620
621 void TLROM_Init(void)
622 {
623  GenMMC3_Init(512, 256, 0, 0);
624 }
625
626 void TSROM_Init(void)
627 {
628  GenMMC3_Init(512, 256, 8, 0);
629 }
630
631 void TLSROM_Init(void)
632 {
633  GenMMC3_Init(512, 256, 8, 0);
634  cwrap=TKSWRAP;
635  mwrap=GENNOMWRAP;
636 }
637
638 void TKSROM_Init(void)
639 {
640  GenMMC3_Init(512, 256, 8, 1);
641  cwrap=TKSWRAP;
642  mwrap=GENNOMWRAP;
643 }
644
645 void TQROM_Init(void)
646 {
647  GenMMC3_Init(512, 64, 0, 0);
648  cwrap=TQWRAP;
649 }
650
651 /* MMC6 board */
652 void HKROM_Init(void)
653 {
654  GenMMC3_Init(512, 512, 1, 1);
655 }