updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
[fceu.git] / mbshare / mmc5.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /* None of this code should use any of the iNES bank switching wrappers. */
22
23 #include "mapinc.h"
24
25 void MMC5Sound(int Count);
26 void Do5SQ(int P);
27
28 static INLINE void MMC5SPRVROM_BANK1(uint32 A,uint32 V)
29 {
30  if(CHRptr[0])
31  {
32   V&=CHRmask1[0];
33   MMC5SPRVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);
34  }
35 }
36
37 static INLINE void MMC5BGVROM_BANK1(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask1[0];MMC5BGVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);}}
38
39 static INLINE void MMC5SPRVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
40 static INLINE void MMC5BGVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
41
42 static INLINE void MMC5SPRVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]= MMC5SPRVPage[((A)>>10)+2]=MMC5SPRVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
43 static INLINE void MMC5BGVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=MMC5BGVPage[((A)>>10)+2]=MMC5BGVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
44
45 static INLINE void MMC5SPRVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5SPRVPage[0]=MMC5SPRVPage[1]=MMC5SPRVPage[2]=MMC5SPRVPage[3]=MMC5SPRVPage[4]=MMC5SPRVPage[5]=MMC5SPRVPage[6]=MMC5SPRVPage[7]=&CHRptr[0][(V)<<13];}}
46 static INLINE void MMC5BGVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5BGVPage[0]=MMC5BGVPage[1]=MMC5BGVPage[2]=MMC5BGVPage[3]=MMC5BGVPage[4]=MMC5BGVPage[5]=MMC5BGVPage[6]=MMC5BGVPage[7]=&CHRptr[0][(V)<<13];}}
47
48 static int32 inc;
49 uint8 MMC5fill[0x400] __attribute__ ((aligned (4)));
50
51 #define MMC5IRQR        mapbyte3[4]
52 #define MMC5LineCounter mapbyte3[5]
53 #define mmc5psize mapbyte1[0]
54 #define mmc5vsize mapbyte1[1]
55
56 uint8 MMC5WRAMsize;
57 uint8 MMC5WRAMIndex[8];
58
59 uint8 MMC5ROMWrProtect[4];
60 uint8 MMC5MemIn[5];
61
62 static void MMC5CHRA(void);
63 static void MMC5CHRB(void);
64
65 typedef struct __cartdata {
66         unsigned long crc32;
67         unsigned char size;
68 } cartdata;
69
70
71 // ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
72 // EWROM seems to have 32KB of WRAM
73
74 #define MMC5_NOCARTS 14
75 cartdata MMC5CartList[MMC5_NOCARTS]=
76 {
77  {0x9c18762b,2},         /* L'Empereur */
78  {0x26533405,2},
79  {0x6396b988,2},
80
81  {0xaca15643,2},        /* Uncharted Waters */
82  {0xfe3488d1,2},        /* Dai Koukai Jidai */
83
84  {0x15fe6d0f,2},        /* BKAC             */
85  {0x39f2ce4b,2},        /* Suikoden              */
86
87  {0x8ce478db,2},        /* Nobunaga's Ambition 2 */
88  {0xeee9a682,2},
89
90  {0x1ced086f,2},        /* Ishin no Arashi */
91
92  {0xf540677b,4},        /* Nobunaga...Bushou Fuuun Roku */
93
94  {0x6f4e4312,4},        /* Aoki Ookami..Genchou */
95
96  {0xf011e490,4},        /* Romance of the 3 Kingdoms 2 */
97  {0x184c2124,4},        /* Sangokushi 2 */
98 };
99
100
101 // Called by iNESLoad()
102 void DetectMMC5WRAMSize(void)
103 {
104  int x;
105
106  MMC5WRAMsize=1;
107
108  for(x=0;x<MMC5_NOCARTS;x++)
109   if(iNESGameCRC32==MMC5CartList[x].crc32)
110    {
111    MMC5WRAMsize=MMC5CartList[x].size;
112    break;
113    }
114 }
115
116 static void BuildWRAMSizeTable(void)
117 {
118  int x;
119
120  for(x=0;x<8;x++)
121  {
122   switch(MMC5WRAMsize)
123   {
124     default:
125     case 1:MMC5WRAMIndex[x]=(x>3)?255:0;break;
126     case 2:MMC5WRAMIndex[x]=(x&4)>>2;break;
127     case 4:MMC5WRAMIndex[x]=(x>3)?255:(x&3);break;
128   }
129  }
130 }
131
132 static void MMC5CHRA(void)
133 {
134         int x;
135         switch(mapbyte1[1]&3)
136         {
137          case 0:MMC5SPRVROM_BANK8(mapbyte2[7]);
138                 setchr8(mapbyte2[7]);
139                 break;
140          case 1:MMC5SPRVROM_BANK4(0x0000,mapbyte2[3]);
141                 MMC5SPRVROM_BANK4(0x1000,mapbyte2[7]);
142                 setchr4(0x0000,mapbyte2[3]);
143                 setchr4(0x1000,mapbyte2[7]);
144                 break;
145          case 2:MMC5SPRVROM_BANK2(0x0000,mapbyte2[1]);
146                 MMC5SPRVROM_BANK2(0x0800,mapbyte2[3]);
147                 MMC5SPRVROM_BANK2(0x1000,mapbyte2[5]);
148                 MMC5SPRVROM_BANK2(0x1800,mapbyte2[7]);
149                 setchr2(0x0000,mapbyte2[1]);
150                 setchr2(0x0800,mapbyte2[3]);
151                 setchr2(0x1000,mapbyte2[5]);
152                 setchr2(0x1800,mapbyte2[7]);
153                 break;
154          case 3:
155                 for(x=0;x<8;x++)
156                 {
157                  setchr1(x<<10,mapbyte2[x]);
158                  MMC5SPRVROM_BANK1(x<<10,mapbyte2[x]);
159                 }
160                 break;
161  }
162 }
163
164 static void MMC5CHRB(void)
165 {
166 int x;
167 switch(mapbyte1[1]&3)
168  {
169  case 0:MMC5BGVROM_BANK8(mapbyte3[3]);
170         setchr8(mapbyte3[3]);
171         break;
172  case 1:
173         MMC5BGVROM_BANK4(0x0000,mapbyte3[3]);
174         MMC5BGVROM_BANK4(0x1000,mapbyte3[3]);
175         setchr4(0x0000,mapbyte3[3]);
176         setchr4(0x1000,mapbyte3[3]);
177         break;
178  case 2:MMC5BGVROM_BANK2(0x0000,mapbyte3[1]);
179         MMC5BGVROM_BANK2(0x0800,mapbyte3[3]);
180         MMC5BGVROM_BANK2(0x1000,mapbyte3[1]);
181         MMC5BGVROM_BANK2(0x1800,mapbyte3[3]);
182         setchr2(0x0000,mapbyte3[1]);
183         setchr2(0x0800,mapbyte3[3]);
184         setchr2(0x1000,mapbyte3[1]);
185         setchr2(0x1800,mapbyte3[3]);
186         break;
187  case 3:
188         for(x=0;x<8;x++)
189         {
190          setchr1(x<<10,mapbyte3[x&3]);
191          MMC5BGVROM_BANK1(x<<10,mapbyte3[x&3]);
192         }
193         break;
194  }
195 }
196
197 static void FASTAPASS(2) MMC5WRAM(uint32 A, uint32 V)
198 {
199    V=MMC5WRAMIndex[V&7];
200    if(V!=255)
201    {
202     setprg8r(0x10,A,V);
203     MMC5MemIn[(A-0x6000)>>13]=1;
204    }
205    else
206     MMC5MemIn[(A-0x6000)>>13]=0;
207 }
208
209 static void MMC5PRG(void)
210 {
211  int x;
212
213  switch(mapbyte1[0]&3)
214   {
215   case 0:
216            MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=
217            MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
218            setprg32(0x8000,((mapbyte1[5]&0x7F)>>2));
219            X6502_Rebase();
220            for(x=0;x<4;x++)
221             MMC5MemIn[1+x]=1;
222            break;
223   case 1:
224          if(mapbyte1[5]&0x80)
225           {
226            MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
227            setprg16(0x8000,(mapbyte1[5]>>1));
228            MMC5MemIn[1]=MMC5MemIn[2]=1;
229           }
230          else
231           {
232            MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
233            MMC5WRAM(0x8000,mapbyte1[5]&7&0xFE);
234            MMC5WRAM(0xA000,(mapbyte1[5]&7&0xFE)+1);
235           }
236           MMC5MemIn[3]=MMC5MemIn[4]=1;
237           MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
238           setprg16(0xC000,(mapbyte1[7]&0x7F)>>1);
239          break;
240   case 2:
241          if(mapbyte1[5]&0x80)
242           {
243            MMC5MemIn[1]=MMC5MemIn[2]=1;
244            MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
245            setprg16(0x8000,(mapbyte1[5]&0x7F)>>1);
246           }
247          else
248           {
249            MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
250            MMC5WRAM(0x8000,mapbyte1[5]&7&0xFE);
251            MMC5WRAM(0xA000,(mapbyte1[5]&7&0xFE)+1);
252           }
253          if(mapbyte1[6]&0x80)
254           {MMC5ROMWrProtect[2]=1;MMC5MemIn[3]=1;setprg8(0xC000,mapbyte1[6]&0x7F);}
255          else
256           {MMC5ROMWrProtect[2]=0;MMC5WRAM(0xC000,mapbyte1[6]&7);}
257          MMC5MemIn[4]=1;
258          MMC5ROMWrProtect[3]=1;
259          setprg8(0xE000,mapbyte1[7]&0x7F);
260          break;
261   case 3:
262          for(x=0;x<3;x++)
263           if(mapbyte1[4+x]&0x80)
264           {
265            MMC5ROMWrProtect[0]=1;
266            setprg8(0x8000+(x<<13),mapbyte1[4+x]&0x7F);
267            MMC5MemIn[1+x]=1;
268           }
269           else
270           {
271            MMC5ROMWrProtect[0]=0;
272            MMC5WRAM(0x8000+(x<<13),mapbyte1[4+x]&7);
273           }
274          MMC5MemIn[4]=1;
275          MMC5ROMWrProtect[3]=1;
276          setprg8(0xE000,mapbyte1[7]&0x7F);
277          break;
278   }
279 }
280
281 #define mul1 mapbyte3[6]
282 #define mul2 mapbyte3[7]
283
284 static DECLFW(Mapper5_write)
285 {
286  switch(A)
287   {
288    default:break;
289    case 0x5105:
290                 {
291                 int x;
292                 for(x=0;x<4;x++)
293                 {
294                  switch((V>>(x<<1))&3)
295                  {
296                   case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
297                   case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
298                   case 2:PPUNTARAM|=1<<x;vnapage[x]=MapperExRAM+0x6000;break;
299                   case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
300                  }
301                 }
302                }
303                mapbyte4[3]=V;
304                break;
305
306    case 0x5113:mapbyte4[6]=V;MMC5WRAM(0x6000,V&7);
307                X6502_Rebase();break;
308    case 0x5100:mapbyte1[0]=V;MMC5PRG();
309                X6502_Rebase();break;
310    case 0x5101:mapbyte1[1]=V;
311                if(!mapbyte4[7])
312                 {MMC5CHRB();MMC5CHRA();}
313                else
314                 {MMC5CHRA();MMC5CHRB();}
315                break;
316
317    case 0x5114:
318    case 0x5115:
319    case 0x5116:
320    case 0x5117:
321                mapbyte1[A&7]=V;MMC5PRG();
322                X6502_Rebase();break;
323
324    case 0x5120:
325    case 0x5121:
326    case 0x5122:
327    case 0x5123:
328    case 0x5124:
329    case 0x5125:
330    case 0x5126:
331    case 0x5127:mapbyte4[7]=0;
332                mapbyte2[A&7]=V;MMC5CHRA();break;
333    case 0x5128:
334    case 0x5129:
335    case 0x512a:
336    case 0x512b:mapbyte4[7]=1;
337                mapbyte3[A&3]=V;MMC5CHRB();break;
338    case 0x5102:mapbyte4[0]=V;break;
339    case 0x5103:mapbyte4[1]=V;break;
340    case 0x5104:mapbyte4[2]=V;MMC5HackCHRMode=V&3;break;
341    case 0x5106:if(V!=mapbyte4[4])
342                {
343                 uint32 t;
344                 t=V|(V<<8)|(V<<16)|(V<<24);
345                 FCEU_dwmemset(MMC5fill,t,0x3c0);
346                }
347                mapbyte4[4]=V;
348                break;
349    case 0x5107:if(V!=mapbyte4[5])
350                {
351                 unsigned char moop;
352                 uint32 t;
353                 moop=V|(V<<2)|(V<<4)|(V<<6);
354                 t=moop|(moop<<8)|(moop<<16)|(moop<<24);
355                 FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
356                }
357                mapbyte4[5]=V;
358                break;
359    case 0x5200:MMC5HackSPMode=V;break;
360    case 0x5201:MMC5HackSPScroll=(V>>3)&0x1F;break;
361    case 0x5202:MMC5HackSPPage=V&0x3F;break;
362    case 0x5203:X6502_IRQEnd(FCEU_IQEXT);IRQCount=V;break;
363    case 0x5204:X6502_IRQEnd(FCEU_IQEXT);IRQa=V&0x80;break;
364    case 0x5205:mul1=V;break;
365    case 0x5206:mul2=V;break;
366   }
367 }
368
369 DECLFR(MMC5_ReadROMRAM)
370 {
371         if(MMC5MemIn[(A-0x6000)>>13])
372          return Page[A>>11][A];
373         else
374          return X.DB;
375 }
376
377 DECLFW(MMC5_WriteROMRAM)
378 {
379        if(A>=0x8000)
380         if(MMC5ROMWrProtect[(A-0x8000)>>13])
381          return;
382        if(MMC5MemIn[(A-0x6000)>>13])
383         if(((mapbyte4[0]&3)|((mapbyte4[1]&3)<<2)) == 6)
384          Page[A>>11][A]=V;
385 }
386
387 static DECLFW(MMC5_ExRAMWr)
388 {
389  if(MMC5HackCHRMode!=3)
390   (MapperExRAM+0x6000)[A&0x3ff]=V;
391 }
392
393 static DECLFR(MMC5_ExRAMRd)
394 {
395  /* Not sure if this is correct, so I'll comment it out for now. */
396  //if(MMC5HackCHRMode>=2)
397   return (MapperExRAM+0x6000)[A&0x3ff];
398  //else
399  // return(X.DB);
400 }
401
402 static DECLFR(MMC5_read)
403 {
404  switch(A)
405  {
406   //default:printf("$%04x\n",A);break;
407   case 0x5204:X6502_IRQEnd(FCEU_IQEXT);
408               {
409                 uint8 x;
410                 x=MMC5IRQR;
411                 MMC5IRQR&=0x40;
412                 return x;
413               }
414   case 0x5205:return (mul1*mul2);
415   case 0x5206:return ((mul1*mul2)>>8);
416  }
417  return(X.DB);
418 }
419
420 uint8 dorko[0x400];
421
422 void MMC5Synco(void)
423 {
424  int x;
425
426  MMC5PRG();
427  for(x=0;x<4;x++)
428  {
429   switch((mapbyte4[3]>>(x<<1))&3)
430    {
431     case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
432     case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
433     case 2:PPUNTARAM|=1<<x;vnapage[x]=MapperExRAM+0x6000;break;
434     case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
435    }
436  }
437  MMC5WRAM(0x6000,mapbyte4[6]&7);
438  if(!mapbyte4[7])
439  {
440   MMC5CHRB();
441   MMC5CHRA();
442  }
443  else
444  {
445    MMC5CHRA();
446    MMC5CHRB();
447  }
448   {
449     uint32 t;
450     t=mapbyte4[4]|(mapbyte4[4]<<8)|(mapbyte4[4]<<16)|(mapbyte4[4]<<24);
451     FCEU_dwmemset(MMC5fill,t,0x3c0);
452   }
453   {
454    unsigned char moop;
455    uint32 t;
456    moop=mapbyte4[5]|(mapbyte4[5]<<2)|(mapbyte4[5]<<4)|(mapbyte4[5]<<6);
457    t=moop|(moop<<8)|(moop<<16)|(moop<<24);
458    FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
459   }
460   X6502_IRQEnd(FCEU_IQEXT);
461   MMC5HackCHRMode=mapbyte4[2]&3;
462   X6502_Rebase();
463 }
464
465 void MMC5_hbo(void)
466 {
467   if(scanline==0)
468    MMC5LineCounter=0;
469
470   if(MMC5LineCounter<245)
471   {
472    MMC5LineCounter++;
473    if(MMC5LineCounter==IRQCount) MMC5IRQR|=0x80;
474    if((MMC5LineCounter==IRQCount && IRQa&0x80))
475     X6502_IRQBegin(FCEU_IQEXT);
476   }
477   if(MMC5LineCounter>=239)
478     MMC5IRQR|=0x40;
479 }
480
481 void MMC5_hb(void)
482 {
483   if(scanline==240)
484   {
485    MMC5LineCounter=0;
486    MMC5IRQR=0x40;
487    return;
488   }
489
490   if(MMC5LineCounter<240)
491   {
492    MMC5LineCounter++;
493    if(MMC5LineCounter==IRQCount)
494    {
495     MMC5IRQR|=0x80;
496     if(IRQa&0x80)
497      X6502_IRQBegin(FCEU_IQEXT);
498    }
499   }
500 //  printf("%d:%d\n",MMC5LineCounter,scanline);
501  if(MMC5LineCounter==240)
502    MMC5IRQR=0;
503 }
504
505 void Mapper5_StateRestore(int version)
506 {
507  if(version<=70)
508  {
509   uint8 tmp[8192];
510
511   FCEU_memmove(tmp,MapperExRAM,8192);
512   FCEU_memmove(MapperExRAM,MapperExRAM+8192,16384+8192);
513   FCEU_memmove(MapperExRAM+16384+8192,tmp,8192);
514  }
515  MMC5Synco();
516 }
517
518 #define MMC5PSG         (MapperExRAM+0x640B+8)
519
520 static int C5BC[3]={0,0,0};
521
522 static void Do5PCM(void)
523 {
524    int32 V;
525    int32 start,end;
526
527    start=C5BC[2];
528    end=(SOUNDTS<<16)/soundtsinc;
529    if(end<=start) return;
530    C5BC[2]=end;
531
532    if(!(MMC5PSG[0x10]&0x40) && MMC5PSG[0x11])
533     for(V=start;V<end;V++)
534      Wave[V>>4]+=MMC5PSG[0x11]<<2;
535 }
536
537 DECLFW(Mapper5_SW)
538 {
539  GameExpSound.Fill=MMC5Sound;
540  A&=0x1F;
541
542  switch(A)
543  {
544   case 0x10:
545   case 0x11:Do5PCM();break;
546
547   case 0x0:Do5SQ(0);break;
548   case 0x2:Do5SQ(0);break;
549   case 0x3:Do5SQ(0);break;
550   case 0x4:Do5SQ(1);break;
551   case 0x6:Do5SQ(1);break;
552   case 0x7:Do5SQ(1);break;
553   case 0x15:
554           {
555            int t=V^MMC5PSG[0x15];
556            if(t&1)
557             Do5SQ(0);
558            if(t&2)
559             Do5SQ(1);
560           }
561           break;
562  }
563  MMC5PSG[A]=V;
564 }
565
566 static int32 vcount[2];
567 void Do5SQ(int P)
568 {
569     int32 start,end;
570     int V;
571     int32 freq;
572
573     start=C5BC[P];
574     end=(SOUNDTS<<16)/soundtsinc;
575     if(end<=start) return;
576     C5BC[P]=end;
577
578
579
580     if(MMC5PSG[0x15]&(P+1))
581     {
582      unsigned long dcycs;
583      unsigned char amplitude;
584      long vcoo;
585
586      freq=(((MMC5PSG[(P<<2)+0x2]|((MMC5PSG[(P<<2)+0x3]&7)<<8))));
587
588      if(freq<8) goto mmc5enda;
589      freq+=1;
590      inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
591
592      switch(MMC5PSG[P<<2]&0xC0)
593      {
594      default:
595      case 0x00:dcycs=inc>>3;break;
596      case 0x40:dcycs=inc>>2;break;
597      case 0x80:dcycs=inc>>1;break;
598      case 0xC0:dcycs=(inc+inc+inc)>>2;break;
599      }
600
601       amplitude=(MMC5PSG[P<<2]&15)<<4;
602
603       vcoo=vcount[P];
604              for(V=start;V<end;V++)
605               {
606                if(vcoo<dcycs)
607                 Wave[V>>4]+=amplitude;
608                vcoo+=0x1000;
609                if(vcoo>=inc) vcoo-=inc;
610                }
611       vcount[P]=vcoo;
612     }
613   mmc5enda:; // semi-colon must be here for MSVC
614 }
615
616 void MMC5Sound(int Count)
617 {
618   int x;
619   Do5SQ(0);
620   Do5SQ(1);
621   Do5PCM();
622   for(x=0;x<3;x++)
623    C5BC[x]=Count;
624 }
625
626 static void MMC5SoundC(void)
627 {
628  if(FSettings.SndRate)
629   Mapper5_ESI();
630  else
631   SetWriteHandler(0x5000,0x5015,0);
632 }
633
634 void Mapper5_ESI(void)
635 {
636  GameExpSound.RChange=MMC5SoundC;
637
638  if(FSettings.SndRate)
639  {
640   SetWriteHandler(0x5000,0x5015,Mapper5_SW);
641   SetWriteHandler(0x5205,0x5206,Mapper5_write);
642   SetReadHandler(0x5205,0x5206,MMC5_read);
643  }
644  if(FCEUGameInfo.type==GIT_NSF)
645  {
646   SetWriteHandler(0x5c00,0x5fef,MMC5_ExRAMWr);
647   SetReadHandler(0x5c00,0x5fef,MMC5_ExRAMRd);
648   MMC5HackCHRMode=2;
649  }
650  else
651   GameHBIRQHook=MMC5_hb;
652 }
653
654 static void GenMMC5Reset(void)
655 {
656  mapbyte1[4]=mapbyte1[5]=mapbyte1[6]=mapbyte1[7]=~0;
657  mapbyte1[0]=mapbyte1[1]=3;
658  mapbyte4[2]=0;
659
660  mapbyte4[3]=mapbyte4[4]=mapbyte4[5]=0xFF;
661
662  MMC5Synco();
663
664  SetWriteHandler(0x4020,0x5bff,Mapper5_write);
665  SetReadHandler(0x4020,0x5bff,MMC5_read);
666
667  SetWriteHandler(0x5c00,0x5fff,MMC5_ExRAMWr);
668  SetReadHandler(0x5c00,0x5fff,MMC5_ExRAMRd);
669
670  SetWriteHandler(0x6000,0xFFFF,MMC5_WriteROMRAM);
671  SetReadHandler(0x6000,0xFFFF,MMC5_ReadROMRAM);
672
673  Mapper5_ESI();
674
675  GameHBIRQHook=MMC5_hb;
676  FCEU_CheatAddRAM(8,0x6000,WRAM);
677  FCEU_CheatAddRAM(1,0x5c00,MapperExRAM+0x6000);
678 }
679
680 void Mapper5_init(void)
681 {
682  AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
683  AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
684  AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
685  SetupCartPRGMapping(0x10,WRAM,32768,1);
686  GenMMC5Reset();
687  BuildWRAMSizeTable();
688  GameStateRestore=Mapper5_StateRestore;
689 }
690
691 static int m5boo;
692 static void GenMMC5_Close(void)
693 {
694  UNIFOpenWRAM(UOW_WR,0,1);
695  if(m5boo<=16)
696   UNIFWriteWRAM(WRAM,8192);
697  else
698   UNIFWriteWRAM(WRAM,32768);
699  UNIFCloseWRAM();
700 }
701
702 static void GenMMC5_Init(int wsize, int battery)
703 {
704  SetupCartPRGMapping(0x10,WRAM,32768,1);
705  AddExState(WRAM, 8192, 0, "WRAM");
706  AddExState(MapperExRAM, 32768, 0, "MEXR");
707  AddExState(&IRQCount, 4, 1, "IRQC");
708  AddExState(&IRQa, 1, 0, "IRQA");
709  AddExState(mapbyte1, 32, 0, "MPBY");
710  AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
711  AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
712  AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
713
714  MMC5WRAMsize=wsize/8;
715  BuildWRAMSizeTable();
716  GameStateRestore=Mapper5_StateRestore;
717  BoardPower=GenMMC5Reset;
718
719  if(battery)
720  {
721   UNIFOpenWRAM(UOW_RD,0,1);
722   if(wsize<=16)
723    UNIFReadWRAM(WRAM,8192);
724   else
725    UNIFReadWRAM(WRAM,32768);
726   UNIFCloseWRAM();
727   BoardClose=GenMMC5_Close;
728   m5boo=wsize;
729  }
730
731  MMC5HackVROMMask=CHRmask4[0];
732  MMC5HackExNTARAMPtr=MapperExRAM+0x6000;
733  MMC5Hack=1;
734  MMC5HackVROMPTR=CHRptr[0];
735  MMC5HackCHRMode=0;
736  MMC5HackSPMode=MMC5HackSPScroll=MMC5HackSPPage=0;
737
738 }
739
740 // ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
741 // EWROM seems to have 32KB of WRAM
742
743 // ETROM and EWROM are battery-backed, ELROM isn't.
744
745 void ETROM_Init(void)
746 {
747  GenMMC5_Init(16,1);
748 }
749
750 void ELROM_Init(void)
751 {
752  GenMMC5_Init(8,0);
753 }
754
755 void EWROM_Init(void)
756 {
757  GenMMC5_Init(32,1);
758 }
759
760 void EKROM_Init(void)
761 {
762  GenMMC5_Init(8,1);
763 }