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