mapper fixes for ncpu, debug is broken atm
[fceu.git] / mbshare / mmc5.c
... / ...
CommitLineData
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] __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
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 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
284static 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
369DECLFR(MMC5_ReadROMRAM)
370{
371 if(MMC5MemIn[(A-0x6000)>>13])
372 return Page[A>>11][A];
373 else
374 return X.DB;
375}
376
377DECLFW(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
387static DECLFW(MMC5_ExRAMWr)
388{
389 if(MMC5HackCHRMode!=3)
390 (MapperExRAM+0x6000)[A&0x3ff]=V;
391}
392
393static 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
402static 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
420uint8 dorko[0x400];
421
422void 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
465void 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
481void 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
505void 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
520static int C5BC[3]={0,0,0};
521
522static void Do5PCM(void)
523{
524 int32 V;
525 int32 start,end;
526
527 start=C5BC[2];
528 end=(timestamp<<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
537DECLFW(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
566static int32 vcount[2];
567void Do5SQ(int P)
568{
569 int32 start,end;
570 int V;
571 int32 freq;
572
573 start=C5BC[P];
574 end=(timestamp<<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
616void 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
626static void MMC5SoundC(void)
627{
628 if(FSettings.SndRate)
629 Mapper5_ESI();
630 else
631 SetWriteHandler(0x5000,0x5015,0);
632}
633
634void 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
654static 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
680void 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
691static int m5boo;
692static 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
702static 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
745void ETROM_Init(void)
746{
747 GenMMC5_Init(16,1);
748}
749
750void ELROM_Init(void)
751{
752 GenMMC5_Init(8,0);
753}
754
755void EWROM_Init(void)
756{
757 GenMMC5_Init(32,1);
758}
759
760void EKROM_Init(void)
761{
762 GenMMC5_Init(8,1);
763}