updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
[fceu.git] / mbshare / mmc3.c
CommitLineData
c62d2810 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
36static void (*pwrap)(uint32 A, uint8 V);
37static void (*cwrap)(uint32 A, uint8 V);
38static void (*mwrap)(uint8 V);
39
40static int mmc3opts=0;
41
42static INLINE void FixMMC3PRG(int V);
43static INLINE void FixMMC3CHR(int V);
44
45static int latched;
46
47static 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;
c0bf6f9f 68 if(latched)
c62d2810 69 IRQCount=IRQLatch;
70 break;
71 }
72}
73
74static 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);
c0bf6f9f 88 X6502_Rebase();
c62d2810 89}
90
91static 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
105static 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
122static 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);
c0bf6f9f 152 X6502_Rebase();
c62d2810 153 break;
154 case 7: pwrap(0xA000,V);
c0bf6f9f 155 X6502_Rebase();
c62d2810 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
170static 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}
184static int isines;
185
186static 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
198static void GENCWRAP(uint32 A, uint8 V)
199{
200 setchr1(A,V);
201}
202
203static void GENPWRAP(uint32 A, uint8 V)
204{
205 setprg8(A,V&0x3F);
206}
207
208static void GENMWRAP(uint8 V)
209{
210 A000B=V;
211 setmirror(V^1);
212}
213
214static void GENNOMWRAP(uint8 V)
215{
216 A000B=V;
217}
218
c0bf6f9f 219static void genmmc3ii(void (*PW)(uint32 A, uint8 V),
220 void (*CW)(uint32 A, uint8 V),
c62d2810 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
244void Mapper4_init(void)
245{
246 genmmc3ii(0,0,0);
247}
248
249static void M47PW(uint32 A, uint8 V)
250{
251 V&=0xF;
252 V|=PIRREGS[0]<<4;
253 setprg8(A,V);
254}
255
256static 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
264static DECLFW(M47Write)
265{
266 PIRREGS[0]=V&1;
267 FixMMC3PRG(MMC3_cmd);
c0bf6f9f 268 FixMMC3CHR(MMC3_cmd);
c62d2810 269}
270
271void Mapper47_init(void)
272{
273 genmmc3ii(M47PW,M47CW,0);
274 SetWriteHandler(0x6000,0x7FFF,M47Write);
275 SetReadHandler(0x6000,0x7FFF,0);
276}
277
278static 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}
286static 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
294static 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
306void Mapper44_init(void)
307{
308 genmmc3ii(M44PW,M44CW,0);
309 SetWriteHandler(0xA000,0xBFFF,Mapper44_write);
310}
311
312static 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
320static 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
328static DECLFW(Mapper52_write)
329{
c0bf6f9f 330 if(PIRREGS[1])
c62d2810 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
341static void M52Reset(void)
342{
343 PIRREGS[0]=PIRREGS[1]=0;
c0bf6f9f 344 MMC3RegReset();
c62d2810 345}
346
347void Mapper52_init(void)
348{
349 genmmc3ii(M52PW,M52CW,0);
350 SetWriteHandler(0x6000,0x7FFF,Mapper52_write);
351 MapperReset=M52Reset;
352}
353
354static 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
365static void M45PW(uint32 A, uint8 V)
366{
367 V&=(PIRREGS[3]&0x3F)^0x3F;
368 V|=PIRREGS[1];
369 setprg8(A,V);
370}
371
372static 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
381static void M45Reset(void)
382{
383 FCEU_dwmemset(PIRREGS,0,5);
384 MMC3RegReset();
385}
386
387void Mapper45_init(void)
388{
389 genmmc3ii(M45PW,M45CW,0);
390 SetWriteHandler(0x6000,0x7FFF,Mapper45_write);
391 SetReadHandler(0x6000,0x7FFF,0);
392 MapperReset=M45Reset;
393}
394static 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
c0bf6f9f 403 {
c62d2810 404 setprg32(0x8000,(PIRREGS[0]>>4)&3);
c0bf6f9f 405 X6502_Rebase();
406 }
c62d2810 407}
408
409static 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
417static 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
428static void M49Reset(void)
429{
430 PIRREGS[0]=0;
431 MMC3RegReset();
432}
433
434void Mapper49_init(void)
435{
436 genmmc3ii(M49PW,M49CW,0);
437 SetWriteHandler(0x6000,0x7FFF,M49Write);
438 SetReadHandler(0x6000,0x7FFF,0);
439 MapperReset=M49Reset;
440}
441
442static DECLFW(Mapper250_write)
443{
444 Mapper4_write((A&0xE000)|((A&0x400)>>10),A&0xFF);
445}
446
447static DECLFW(M250_IRQWrite)
448{
449 MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
450}
451
452void Mapper250_init(void)
453{
454 genmmc3ii(0,0,0);
455 SetWriteHandler(0x8000,0xBFFF,Mapper250_write);
456 SetWriteHandler(0xC000,0xFFFF,M250_IRQWrite);
457}
458
459static 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;}
c0bf6f9f 468 // setmirror(MI_1);
c62d2810 469 //printf("$%04x\n",A);
470
471 A>>=10;
472 PPUCHRBus=A;
473 setmirror(MI_0+TKSMIR[A]);
474}
475
476static 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
484void Mapper118_init(void)
485{
486 genmmc3ii(0,TKSWRAP,GENNOMWRAP);
487 PPU_hook=TKSPPU;
488}
489
490static void TQWRAP(uint32 A, uint8 V)
491{
492 setchr1r((V&0x40)>>2,A,V&0x3F);
493}
494
495void Mapper119_init(void)
496{
497 genmmc3ii(0,TQWRAP,0);
498 SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
499}
500
501static int wrams;
502
503static void GenMMC3Close(void)
504{
505 UNIFOpenWRAM(UOW_WR,0,1);
506 UNIFWriteWRAM(WRAM,wrams);
507 UNIFCloseWRAM();
508}
509
510static DECLFW(MBWRAM)
511{
512 (WRAM-0x6000)[A]=V;
513}
514
515static DECLFR(MAWRAM)
516{
517 return((WRAM-0x6000)[A]);
518}
519
520static DECLFW(MBWRAMMMC6)
521{
522 WRAM[A&0x3ff]=V;
523}
524
525static DECLFR(MAWRAMMMC6)
526{
527 return(WRAM[A&0x3ff]);
528}
529
530static 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
556void 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
606void TFROM_Init(void)
607{
608 GenMMC3_Init(512, 64, 0, 0);
609}
610
611void TGROM_Init(void)
612{
613 GenMMC3_Init(512, 0, 0, 0);
614}
615
616void TKROM_Init(void)
617{
618 GenMMC3_Init(512, 256, 8, 1);
619}
620
621void TLROM_Init(void)
622{
623 GenMMC3_Init(512, 256, 0, 0);
624}
625
626void TSROM_Init(void)
627{
628 GenMMC3_Init(512, 256, 8, 0);
629}
630
631void TLSROM_Init(void)
632{
633 GenMMC3_Init(512, 256, 8, 0);
634 cwrap=TKSWRAP;
635 mwrap=GENNOMWRAP;
636}
637
638void TKSROM_Init(void)
639{
640 GenMMC3_Init(512, 256, 8, 1);
641 cwrap=TKSWRAP;
642 mwrap=GENNOMWRAP;
643}
644
645void TQROM_Init(void)
646{
647 GenMMC3_Init(512, 64, 0, 0);
648 cwrap=TQWRAP;
649}
650
651/* MMC6 board */
652void HKROM_Init(void)
653{
654 GenMMC3_Init(512, 512, 1, 1);
655}