1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2006 CaH4e3
\r
6 * This program is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * This program is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program; if not, write to the Free Software
\r
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\r
23 #include "../ines.h"
\r
25 static bool is_BMCFK23CA;
\r
26 static uint8 unromchr;
\r
27 static uint32 dipswitch;
\r
28 static uint8 *CHRRAM=NULL;
\r
29 static uint32 CHRRAMSize;
\r
31 static void BMCFK23CCW(uint32 A, uint8 V)
\r
34 setchr8(EXPREGS[2]|unromchr);
\r
35 else if(EXPREGS[0]&0x20) {
\r
36 setchr1r(0x10, A, V);
\r
40 uint16 base=(EXPREGS[2]&0x7F)<<3;
\r
43 int cbase=(MMC3_cmd&0x80)<<5;
\r
45 setchr1(0x0000^cbase,DRegBuf[0]|base);
\r
46 setchr1(0x0400^cbase,EXPREGS[6]|base);
\r
47 setchr1(0x0800^cbase,DRegBuf[1]|base);
\r
48 setchr1(0x0c00^cbase,EXPREGS[7]|base);
\r
55 //some games are wired differently, and this will need to be changed.
\r
56 //all the WXN games require prg_bonus = 1, and cah4e3's multicarts require prg_bonus = 0
\r
57 //we'll populate this from a game database
\r
58 static int prg_bonus;
\r
59 static int prg_mask;
\r
62 //4-in-1 (FK23C8021)[p1][!].nes
\r
63 //4-in-1 (FK23C8033)[p1][!].nes
\r
64 //4-in-1 (FK23C8043)[p1][!].nes
\r
65 //4-in-1 (FK23Cxxxx, S-0210A PCB)[p1][!].nes
\r
68 //[m176]大富翁2-上海大亨.wxn.nes
\r
69 //[m176]宠物翡翠.fix.nes
\r
70 //[m176]格兰帝亚.wxn.nes
\r
71 //[m176]梦幻之星.wxn.nes
\r
72 //[m176]水浒神兽.fix.nes
\r
73 //[m176]西楚霸王.fix.nes
\r
74 //[m176]超级大富翁.wxn.nes
\r
75 //[m176]雄霸天下.wxn.nes
\r
77 //works as-is under virtuanes m176
\r
78 //[m176]三侠五义.wxn.nes
\r
80 //[m176]爆笑三国.fix.nes
\r
82 //needs other tweaks
\r
83 //[m176]三国忠烈传.wxn.nes
\r
84 //[m176]破釜沉舟.fix.nes
\r
87 static void BMCFK23CPW(uint32 A, uint8 V)
\r
89 uint32 bank = (EXPREGS[1] & 0x1F);
\r
90 uint32 hiblock = ((EXPREGS[0] & 8) << 4)|((EXPREGS[0] & 0x80) << 1)|(UNIFchrrama?((EXPREGS[2] & 0x40)<<3):0);
\r
91 uint32 block = (EXPREGS[1] & 0x60) | hiblock;
\r
92 uint32 extra = (EXPREGS[3] & 2);
\r
94 if((EXPREGS[0]&7)==4)
\r
95 setprg32(0x8000,EXPREGS[1]>>1);
\r
96 else if ((EXPREGS[0]&7)==3)
\r
98 setprg16(0x8000,EXPREGS[1]);
\r
99 setprg16(0xC000,EXPREGS[1]);
\r
105 uint32 blocksize = (6)-(EXPREGS[0]&3);
\r
106 uint32 mask = (1<<blocksize)-1;
\r
108 //V &= 63; //? is this a good idea?
\r
109 V |= (EXPREGS[1]<<1);
\r
113 setprg8(A,V & prg_mask);
\r
117 setprg8(0xC000,EXPREGS[4]);
\r
118 setprg8(0xE000,EXPREGS[5]);
\r
121 setprg8r(0x10,0x6000,A001B&3);
\r
124 //PRG handler ($8000-$FFFF)
\r
125 static DECLFW(BMCFK23CHiWrite)
\r
127 if(EXPREGS[0]&0x40)
\r
129 if(EXPREGS[0]&0x30)
\r
134 FixMMC3CHR(MMC3_cmd);
\r
139 if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
\r
141 EXPREGS[4|(MMC3_cmd&3)]=V;
\r
142 FixMMC3PRG(MMC3_cmd);
\r
143 FixMMC3CHR(MMC3_cmd);
\r
147 if(UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions
\r
148 // check if it not interfer with other dumps
\r
149 if((A==0x8000)&&(V==0x46))
\r
151 else if((A==0x8000)&&(V==0x47))
\r
154 MMC3_CMDWrite(A,V);
\r
155 FixMMC3PRG(MMC3_cmd);
\r
158 MMC3_IRQWrite(A,V);
\r
162 //EXP handler ($5000-$5FFF)
\r
163 static DECLFW(BMCFK23CWrite)
\r
165 if(A&(1<<(dipswitch+4)))
\r
170 bool remap = false;
\r
172 //sometimes writing to reg0 causes remappings to occur. we think the 2 signifies this.
\r
173 //if not, 0x24 is a value that is known to work
\r
174 //however, the low 4 bits are known to control the mapping mode, so 0x20 is more likely to be the immediate remap flag
\r
175 remap |= ((EXPREGS[0]&0xF0)==0x20);
\r
177 //this is an actual mapping reg. i think reg0 controls what happens when reg1 is written. anyway, we have to immediately remap these
\r
178 remap |= (A&3)==1;
\r
180 remap |= (A&3)==2;
\r
184 FixMMC3PRG(MMC3_cmd);
\r
185 FixMMC3CHR(MMC3_cmd);
\r
192 EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper)
\r
195 //printf("%04X = $%02X\n",A,V);
\r
196 //printf("%02X %02X %02X %02X\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);
\r
199 static void BMCFK23CReset(void)
\r
201 //NOT NECESSARY ANYMORE
\r
202 //this little hack makes sure that we try all the dip switch settings eventually, if we reset enough
\r
205 //printf("BMCFK23C dipswitch set to %d\n",dipswitch);
\r
207 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
\r
208 EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
\r
210 FixMMC3PRG(MMC3_cmd);
\r
211 FixMMC3CHR(MMC3_cmd);
\r
214 static void BMCFK23CPower(void)
\r
218 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
\r
219 EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
\r
221 SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
\r
222 SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
\r
223 FixMMC3PRG(MMC3_cmd);
\r
224 FixMMC3CHR(MMC3_cmd);
\r
227 static void BMCFK23CAPower(void)
\r
231 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
\r
232 EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
\r
233 SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);
\r
234 SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);
\r
235 FixMMC3PRG(MMC3_cmd);
\r
236 FixMMC3CHR(MMC3_cmd);
\r
239 static void BMCFK23CAClose(void)
\r
242 FCEU_gfree(CHRRAM);
\r
246 void BMCFK23C_Init(CartInfo *info)
\r
248 is_BMCFK23CA = false;
\r
250 GenMMC3_Init(info, 512, 256, 8, 0);
\r
253 info->Power=BMCFK23CPower;
\r
254 info->Reset=BMCFK23CReset;
\r
255 AddExState(EXPREGS, 8, 0, "EXPR");
\r
256 AddExState(&unromchr, 1, 0, "UNCHR");
\r
257 AddExState(&dipswitch, 1, 0, "DIPSW");
\r
260 if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
\r
261 prg_bonus = atoi(MasterRomInfoParams["bonus"].c_str());
\r
263 prg_mask = 0x7F>>(prg_bonus);
\r
266 void BMCFK23CA_Init(CartInfo *info)
\r
268 is_BMCFK23CA = true;
\r
270 GenMMC3_Init(info, 512, 256, 8, 0);
\r
273 info->Power=BMCFK23CAPower;
\r
274 info->Reset=BMCFK23CReset;
\r
275 info->Close=BMCFK23CAClose;
\r
278 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
\r
279 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
\r
280 AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");
\r
282 AddExState(EXPREGS, 8, 0, "EXPR");
\r
283 AddExState(&unromchr, 1, 0, "UNCHR");
\r
284 AddExState(&dipswitch, 1, 0, "DIPSW");
\r
287 if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())
\r
288 prg_bonus = atoi(MasterRomInfoParams["bonus"].c_str());
\r
289 prg_mask = 0x7F>>(prg_bonus);
\r