initial fce ultra 0.81 import
[fceu.git] / mbshare / mmc5.c
CommitLineData
c62d2810 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
25void MMC5Sound(int Count);
26void Do5SQ(int P);
27
28static 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
37static INLINE void MMC5BGVROM_BANK1(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask1[0];MMC5BGVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);}}
38
39static 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);}}
40static 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
42static 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);}}
43static 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
45static 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];}}
46static 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
48static int32 inc;
49uint8 MMC5fill[0x400];
50
51#define MMC5IRQR mapbyte3[4]
52#define MMC5LineCounter mapbyte3[5]
53#define mmc5psize mapbyte1[0]
54#define mmc5vsize mapbyte1[1]
55
56uint8 MMC5WRAMsize;
57uint8 MMC5WRAMIndex[8];
58
59uint8 MMC5ROMWrProtect[4];
60uint8 MMC5MemIn[5];
61
62static void MMC5CHRA(void);
63static void MMC5CHRB(void);
64
65typedef 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
75cartdata 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()
102void 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
116static 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
132static 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
164static void MMC5CHRB(void)
165{
166int x;
167switch(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
197static 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
209static 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 for(x=0;x<4;x++)
220 MMC5MemIn[1+x]=1;
221 break;
222 case 1:
223 if(mapbyte1[5]&0x80)
224 {
225 MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
226 setprg16(0x8000,(mapbyte1[5]>>1));
227 MMC5MemIn[1]=MMC5MemIn[2]=1;
228 }
229 else
230 {
231 MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
232 MMC5WRAM(0x8000,mapbyte1[5]&7&0xFE);
233 MMC5WRAM(0xA000,(mapbyte1[5]&7&0xFE)+1);
234 }
235 MMC5MemIn[3]=MMC5MemIn[4]=1;
236 MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
237 setprg16(0xC000,(mapbyte1[7]&0x7F)>>1);
238 break;
239 case 2:
240 if(mapbyte1[5]&0x80)
241 {
242 MMC5MemIn[1]=MMC5MemIn[2]=1;
243 MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
244 setprg16(0x8000,(mapbyte1[5]&0x7F)>>1);
245 }
246 else
247 {
248 MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
249 MMC5WRAM(0x8000,mapbyte1[5]&7&0xFE);
250 MMC5WRAM(0xA000,(mapbyte1[5]&7&0xFE)+1);
251 }
252 if(mapbyte1[6]&0x80)
253 {MMC5ROMWrProtect[2]=1;MMC5MemIn[3]=1;setprg8(0xC000,mapbyte1[6]&0x7F);}
254 else
255 {MMC5ROMWrProtect[2]=0;MMC5WRAM(0xC000,mapbyte1[6]&7);}
256 MMC5MemIn[4]=1;
257 MMC5ROMWrProtect[3]=1;
258 setprg8(0xE000,mapbyte1[7]&0x7F);
259 break;
260 case 3:
261 for(x=0;x<3;x++)
262 if(mapbyte1[4+x]&0x80)
263 {
264 MMC5ROMWrProtect[0]=1;
265 setprg8(0x8000+(x<<13),mapbyte1[4+x]&0x7F);
266 MMC5MemIn[1+x]=1;
267 }
268 else
269 {
270 MMC5ROMWrProtect[0]=0;
271 MMC5WRAM(0x8000+(x<<13),mapbyte1[4+x]&7);
272 }
273 MMC5MemIn[4]=1;
274 MMC5ROMWrProtect[3]=1;
275 setprg8(0xE000,mapbyte1[7]&0x7F);
276 break;
277 }
278}
279
280#define mul1 mapbyte3[6]
281#define mul2 mapbyte3[7]
282
283static DECLFW(Mapper5_write)
284{
285 switch(A)
286 {
287 default:break;
288 case 0x5105:
289 {
290 int x;
291 for(x=0;x<4;x++)
292 {
293 switch((V>>(x<<1))&3)
294 {
295 case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
296 case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
297 case 2:PPUNTARAM|=1<<x;vnapage[x]=MapperExRAM+0x6000;break;
298 case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
299 }
300 }
301 }
302 mapbyte4[3]=V;
303 break;
304
305 case 0x5113:mapbyte4[6]=V;MMC5WRAM(0x6000,V&7);break;
306 case 0x5100:mapbyte1[0]=V;MMC5PRG();break;
307 case 0x5101:mapbyte1[1]=V;
308 if(!mapbyte4[7])
309 {MMC5CHRB();MMC5CHRA();}
310 else
311 {MMC5CHRA();MMC5CHRB();}
312 break;
313
314 case 0x5114:
315 case 0x5115:
316 case 0x5116:
317 case 0x5117:
318 mapbyte1[A&7]=V;MMC5PRG();break;
319
320 case 0x5120:
321 case 0x5121:
322 case 0x5122:
323 case 0x5123:
324 case 0x5124:
325 case 0x5125:
326 case 0x5126:
327 case 0x5127:mapbyte4[7]=0;
328 mapbyte2[A&7]=V;MMC5CHRA();break;
329 case 0x5128:
330 case 0x5129:
331 case 0x512a:
332 case 0x512b:mapbyte4[7]=1;
333 mapbyte3[A&3]=V;MMC5CHRB();break;
334 case 0x5102:mapbyte4[0]=V;break;
335 case 0x5103:mapbyte4[1]=V;break;
336 case 0x5104:mapbyte4[2]=V;MMC5HackCHRMode=V&3;break;
337 case 0x5106:if(V!=mapbyte4[4])
338 {
339 uint32 t;
340 t=V|(V<<8)|(V<<16)|(V<<24);
341 FCEU_dwmemset(MMC5fill,t,0x3c0);
342 }
343 mapbyte4[4]=V;
344 break;
345 case 0x5107:if(V!=mapbyte4[5])
346 {
347 unsigned char moop;
348 uint32 t;
349 moop=V|(V<<2)|(V<<4)|(V<<6);
350 t=moop|(moop<<8)|(moop<<16)|(moop<<24);
351 FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
352 }
353 mapbyte4[5]=V;
354 break;
355 case 0x5200:MMC5HackSPMode=V;break;
356 case 0x5201:MMC5HackSPScroll=(V>>3)&0x1F;break;
357 case 0x5202:MMC5HackSPPage=V&0x3F;break;
358 case 0x5203:X6502_IRQEnd(FCEU_IQEXT);IRQCount=V;break;
359 case 0x5204:X6502_IRQEnd(FCEU_IQEXT);IRQa=V&0x80;break;
360 case 0x5205:mul1=V;break;
361 case 0x5206:mul2=V;break;
362 }
363}
364
365DECLFR(MMC5_ReadROMRAM)
366{
367 if(MMC5MemIn[(A-0x6000)>>13])
368 return Page[A>>11][A];
369 else
370 return X.DB;
371}
372
373DECLFW(MMC5_WriteROMRAM)
374{
375 if(A>=0x8000)
376 if(MMC5ROMWrProtect[(A-0x8000)>>13])
377 return;
378 if(MMC5MemIn[(A-0x6000)>>13])
379 if(((mapbyte4[0]&3)|((mapbyte4[1]&3)<<2)) == 6)
380 Page[A>>11][A]=V;
381}
382
383static DECLFW(MMC5_ExRAMWr)
384{
385 if(MMC5HackCHRMode!=3)
386 (MapperExRAM+0x6000)[A&0x3ff]=V;
387}
388
389static DECLFR(MMC5_ExRAMRd)
390{
391 /* Not sure if this is correct, so I'll comment it out for now. */
392 //if(MMC5HackCHRMode>=2)
393 return (MapperExRAM+0x6000)[A&0x3ff];
394 //else
395 // return(X.DB);
396}
397
398static DECLFR(MMC5_read)
399{
400 switch(A)
401 {
402 //default:printf("$%04x\n",A);break;
403 case 0x5204:X6502_IRQEnd(FCEU_IQEXT);
404 {
405 uint8 x;
406 x=MMC5IRQR;
407 MMC5IRQR&=0x40;
408 return x;
409 }
410 case 0x5205:return (mul1*mul2);
411 case 0x5206:return ((mul1*mul2)>>8);
412 }
413 return(X.DB);
414}
415
416uint8 dorko[0x400];
417
418void MMC5Synco(void)
419{
420 int x;
421
422 MMC5PRG();
423 for(x=0;x<4;x++)
424 {
425 switch((mapbyte4[3]>>(x<<1))&3)
426 {
427 case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
428 case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
429 case 2:PPUNTARAM|=1<<x;vnapage[x]=MapperExRAM+0x6000;break;
430 case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
431 }
432 }
433 MMC5WRAM(0x6000,mapbyte4[6]&7);
434 if(!mapbyte4[7])
435 {
436 MMC5CHRB();
437 MMC5CHRA();
438 }
439 else
440 {
441 MMC5CHRA();
442 MMC5CHRB();
443 }
444 {
445 uint32 t;
446 t=mapbyte4[4]|(mapbyte4[4]<<8)|(mapbyte4[4]<<16)|(mapbyte4[4]<<24);
447 FCEU_dwmemset(MMC5fill,t,0x3c0);
448 }
449 {
450 unsigned char moop;
451 uint32 t;
452 moop=mapbyte4[5]|(mapbyte4[5]<<2)|(mapbyte4[5]<<4)|(mapbyte4[5]<<6);
453 t=moop|(moop<<8)|(moop<<16)|(moop<<24);
454 FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
455 }
456 X6502_IRQEnd(FCEU_IQEXT);
457 MMC5HackCHRMode=mapbyte4[2]&3;
458}
459
460void MMC5_hbo(void)
461{
462 if(scanline==0)
463 MMC5LineCounter=0;
464
465 if(MMC5LineCounter<245)
466 {
467 MMC5LineCounter++;
468 if(MMC5LineCounter==IRQCount) MMC5IRQR|=0x80;
469 if((MMC5LineCounter==IRQCount && IRQa&0x80))
470 X6502_IRQBegin(FCEU_IQEXT);
471 }
472 if(MMC5LineCounter>=239)
473 MMC5IRQR|=0x40;
474}
475
476void MMC5_hb(void)
477{
478 if(scanline==240)
479 {
480 MMC5LineCounter=0;
481 MMC5IRQR=0x40;
482 return;
483 }
484
485 if(MMC5LineCounter<240)
486 {
487 MMC5LineCounter++;
488 if(MMC5LineCounter==IRQCount)
489 {
490 MMC5IRQR|=0x80;
491 if(IRQa&0x80)
492 X6502_IRQBegin(FCEU_IQEXT);
493 }
494 }
495// printf("%d:%d\n",MMC5LineCounter,scanline);
496 if(MMC5LineCounter==240)
497 MMC5IRQR=0;
498}
499
500void Mapper5_StateRestore(int version)
501{
502 if(version<=70)
503 {
504 uint8 tmp[8192];
505
506 FCEU_memmove(tmp,MapperExRAM,8192);
507 FCEU_memmove(MapperExRAM,MapperExRAM+8192,16384+8192);
508 FCEU_memmove(MapperExRAM+16384+8192,tmp,8192);
509 }
510 MMC5Synco();
511}
512
513#define MMC5PSG (MapperExRAM+0x640B+8)
514
515static int C5BC[3]={0,0,0};
516
517static void Do5PCM(void)
518{
519 int32 V;
520 int32 start,end;
521
522 start=C5BC[2];
523 end=(timestamp<<16)/soundtsinc;
524 if(end<=start) return;
525 C5BC[2]=end;
526
527 if(!(MMC5PSG[0x10]&0x40) && MMC5PSG[0x11])
528 for(V=start;V<end;V++)
529 Wave[V>>4]+=MMC5PSG[0x11]<<2;
530}
531
532DECLFW(Mapper5_SW)
533{
534 GameExpSound.Fill=MMC5Sound;
535 A&=0x1F;
536
537 switch(A)
538 {
539 case 0x10:
540 case 0x11:Do5PCM();break;
541
542 case 0x0:Do5SQ(0);break;
543 case 0x2:Do5SQ(0);break;
544 case 0x3:Do5SQ(0);break;
545 case 0x4:Do5SQ(1);break;
546 case 0x6:Do5SQ(1);break;
547 case 0x7:Do5SQ(1);break;
548 case 0x15:
549 {
550 int t=V^MMC5PSG[0x15];
551 if(t&1)
552 Do5SQ(0);
553 if(t&2)
554 Do5SQ(1);
555 }
556 break;
557 }
558 MMC5PSG[A]=V;
559}
560
561static int32 vcount[2];
562void Do5SQ(int P)
563{
564 int32 start,end;
565 int V;
566 int32 freq;
567
568 start=C5BC[P];
569 end=(timestamp<<16)/soundtsinc;
570 if(end<=start) return;
571 C5BC[P]=end;
572
573
574
575 if(MMC5PSG[0x15]&(P+1))
576 {
577 unsigned long dcycs;
578 unsigned char amplitude;
579 long vcoo;
580
581 freq=(((MMC5PSG[(P<<2)+0x2]|((MMC5PSG[(P<<2)+0x3]&7)<<8))));
582
583 if(freq<8) goto mmc5enda;
584 freq+=1;
585 inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
586
587 switch(MMC5PSG[P<<2]&0xC0)
588 {
589 default:
590 case 0x00:dcycs=inc>>3;break;
591 case 0x40:dcycs=inc>>2;break;
592 case 0x80:dcycs=inc>>1;break;
593 case 0xC0:dcycs=(inc+inc+inc)>>2;break;
594 }
595
596 amplitude=(MMC5PSG[P<<2]&15)<<4;
597
598 vcoo=vcount[P];
599 for(V=start;V<end;V++)
600 {
601 if(vcoo<dcycs)
602 Wave[V>>4]+=amplitude;
603 vcoo+=0x1000;
604 if(vcoo>=inc) vcoo-=inc;
605 }
606 vcount[P]=vcoo;
607 }
608 mmc5enda:; // semi-colon must be here for MSVC
609}
610
611void MMC5Sound(int Count)
612{
613 int x;
614 Do5SQ(0);
615 Do5SQ(1);
616 Do5PCM();
617 for(x=0;x<3;x++)
618 C5BC[x]=Count;
619}
620
621static void MMC5SoundC(void)
622{
623 if(FSettings.SndRate)
624 Mapper5_ESI();
625 else
626 SetWriteHandler(0x5000,0x5015,0);
627}
628
629void Mapper5_ESI(void)
630{
631 GameExpSound.RChange=MMC5SoundC;
632
633 if(FSettings.SndRate)
634 {
635 SetWriteHandler(0x5000,0x5015,Mapper5_SW);
636 SetWriteHandler(0x5205,0x5206,Mapper5_write);
637 SetReadHandler(0x5205,0x5206,MMC5_read);
638 }
639 if(FCEUGameInfo.type==GIT_NSF)
640 {
641 SetWriteHandler(0x5c00,0x5fef,MMC5_ExRAMWr);
642 SetReadHandler(0x5c00,0x5fef,MMC5_ExRAMRd);
643 MMC5HackCHRMode=2;
644 }
645 else
646 GameHBIRQHook=MMC5_hb;
647}
648
649static void GenMMC5Reset(void)
650{
651 mapbyte1[4]=mapbyte1[5]=mapbyte1[6]=mapbyte1[7]=~0;
652 mapbyte1[0]=mapbyte1[1]=3;
653 mapbyte4[2]=0;
654
655 mapbyte4[3]=mapbyte4[4]=mapbyte4[5]=0xFF;
656
657 MMC5Synco();
658
659 SetWriteHandler(0x4020,0x5bff,Mapper5_write);
660 SetReadHandler(0x4020,0x5bff,MMC5_read);
661
662 SetWriteHandler(0x5c00,0x5fff,MMC5_ExRAMWr);
663 SetReadHandler(0x5c00,0x5fff,MMC5_ExRAMRd);
664
665 SetWriteHandler(0x6000,0xFFFF,MMC5_WriteROMRAM);
666 SetReadHandler(0x6000,0xFFFF,MMC5_ReadROMRAM);
667
668 Mapper5_ESI();
669
670 GameHBIRQHook=MMC5_hb;
671 FCEU_CheatAddRAM(8,0x6000,WRAM);
672 FCEU_CheatAddRAM(1,0x5c00,MapperExRAM+0x6000);
673}
674
675void Mapper5_init(void)
676{
677 AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
678 AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
679 AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
680 SetupCartPRGMapping(0x10,WRAM,32768,1);
681 GenMMC5Reset();
682 BuildWRAMSizeTable();
683 GameStateRestore=Mapper5_StateRestore;
684}
685
686static int m5boo;
687static void GenMMC5_Close(void)
688{
689 UNIFOpenWRAM(UOW_WR,0,1);
690 if(m5boo<=16)
691 UNIFWriteWRAM(WRAM,8192);
692 else
693 UNIFWriteWRAM(WRAM,32768);
694 UNIFCloseWRAM();
695}
696
697static void GenMMC5_Init(int wsize, int battery)
698{
699 SetupCartPRGMapping(0x10,WRAM,32768,1);
700 AddExState(WRAM, 8192, 0, "WRAM");
701 AddExState(MapperExRAM, 32768, 0, "MEXR");
702 AddExState(&IRQCount, 4, 1, "IRQC");
703 AddExState(&IRQa, 1, 0, "IRQA");
704 AddExState(mapbyte1, 32, 0, "MPBY");
705 AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
706 AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
707 AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
708
709 MMC5WRAMsize=wsize/8;
710 BuildWRAMSizeTable();
711 GameStateRestore=Mapper5_StateRestore;
712 BoardPower=GenMMC5Reset;
713
714 if(battery)
715 {
716 UNIFOpenWRAM(UOW_RD,0,1);
717 if(wsize<=16)
718 UNIFReadWRAM(WRAM,8192);
719 else
720 UNIFReadWRAM(WRAM,32768);
721 UNIFCloseWRAM();
722 BoardClose=GenMMC5_Close;
723 m5boo=wsize;
724 }
725
726 MMC5HackVROMMask=CHRmask4[0];
727 MMC5HackExNTARAMPtr=MapperExRAM+0x6000;
728 MMC5Hack=1;
729 MMC5HackVROMPTR=CHRptr[0];
730 MMC5HackCHRMode=0;
731 MMC5HackSPMode=MMC5HackSPScroll=MMC5HackSPPage=0;
732
733}
734
735// ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
736// EWROM seems to have 32KB of WRAM
737
738// ETROM and EWROM are battery-backed, ELROM isn't.
739
740void ETROM_Init(void)
741{
742 GenMMC5_Init(16,1);
743}
744
745void ELROM_Init(void)
746{
747 GenMMC5_Init(8,0);
748}
749
750void EWROM_Init(void)
751{
752 GenMMC5_Init(32,1);
753}
754
755void EKROM_Init(void)
756{
757 GenMMC5_Init(8,1);
758}