386f5371 |
1 | /* FCE Ultra - NES/Famicom Emulator\r |
2 | *\r |
3 | * Copyright notice for this file:\r |
4 | * Copyright (C) 2006 CaH4e3\r |
5 | *\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 |
10 | *\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 |
15 | *\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 |
19 | */\r |
20 | \r |
21 | #include "mapinc.h"\r |
22 | #include "mmc3.h"\r |
23 | #include "../ines.h"\r |
24 | \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 |
30 | \r |
31 | static void BMCFK23CCW(uint32 A, uint8 V)\r |
32 | {\r |
33 | if(EXPREGS[0]&0x40)\r |
34 | setchr8(EXPREGS[2]|unromchr);\r |
35 | else if(EXPREGS[0]&0x20) {\r |
36 | setchr1r(0x10, A, V);\r |
37 | }\r |
38 | else\r |
39 | {\r |
40 | uint16 base=(EXPREGS[2]&0x7F)<<3;\r |
41 | if(EXPREGS[3]&2)\r |
42 | {\r |
43 | int cbase=(MMC3_cmd&0x80)<<5;\r |
44 | setchr1(A,V|base);\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 |
49 | }\r |
50 | else\r |
51 | setchr1(A,V|base);\r |
52 | }\r |
53 | }\r |
54 | \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 |
60 | \r |
61 | //prg_bonus = 0\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 |
66 | \r |
67 | //prg_bonus = 1\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 |
76 | \r |
77 | //works as-is under virtuanes m176\r |
78 | //[m176]三侠五义.wxn.nes\r |
79 | //[m176]口袋金.fix.nes\r |
80 | //[m176]爆笑三国.fix.nes\r |
81 | \r |
82 | //needs other tweaks\r |
83 | //[m176]三国忠烈传.wxn.nes\r |
84 | //[m176]破釜沉舟.fix.nes\r |
85 | \r |
86 | //PRG wrapper\r |
87 | static void BMCFK23CPW(uint32 A, uint8 V)\r |
88 | {\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 |
93 | \r |
94 | if((EXPREGS[0]&7)==4)\r |
95 | setprg32(0x8000,EXPREGS[1]>>1);\r |
96 | else if ((EXPREGS[0]&7)==3)\r |
97 | {\r |
98 | setprg16(0x8000,EXPREGS[1]);\r |
99 | setprg16(0xC000,EXPREGS[1]);\r |
100 | } \r |
101 | else\r |
102 | { \r |
103 | if(EXPREGS[0]&3)\r |
104 | {\r |
105 | uint32 blocksize = (6)-(EXPREGS[0]&3);\r |
106 | uint32 mask = (1<<blocksize)-1;\r |
107 | V &= mask;\r |
108 | //V &= 63; //? is this a good idea?\r |
109 | V |= (EXPREGS[1]<<1);\r |
110 | setprg8(A,V);\r |
111 | }\r |
112 | else\r |
113 | setprg8(A,V & prg_mask);\r |
114 | \r |
115 | if(EXPREGS[3]&2)\r |
116 | {\r |
117 | setprg8(0xC000,EXPREGS[4]);\r |
118 | setprg8(0xE000,EXPREGS[5]);\r |
119 | }\r |
120 | }\r |
121 | setprg8r(0x10,0x6000,A001B&3);\r |
122 | }\r |
123 | \r |
124 | //PRG handler ($8000-$FFFF)\r |
125 | static DECLFW(BMCFK23CHiWrite)\r |
126 | {\r |
127 | if(EXPREGS[0]&0x40)\r |
128 | {\r |
129 | if(EXPREGS[0]&0x30)\r |
130 | unromchr=0;\r |
131 | else\r |
132 | {\r |
133 | unromchr=V&3;\r |
134 | FixMMC3CHR(MMC3_cmd);\r |
135 | }\r |
136 | }\r |
137 | else\r |
138 | {\r |
139 | if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))\r |
140 | {\r |
141 | EXPREGS[4|(MMC3_cmd&3)]=V;\r |
142 | FixMMC3PRG(MMC3_cmd);\r |
143 | FixMMC3CHR(MMC3_cmd);\r |
144 | }\r |
145 | else\r |
146 | if(A<0xC000) {\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 |
150 | V=0x47;\r |
151 | else if((A==0x8000)&&(V==0x47))\r |
152 | V=0x46;\r |
153 | }\r |
154 | MMC3_CMDWrite(A,V);\r |
155 | FixMMC3PRG(MMC3_cmd);\r |
156 | }\r |
157 | else\r |
158 | MMC3_IRQWrite(A,V);\r |
159 | }\r |
160 | }\r |
161 | \r |
162 | //EXP handler ($5000-$5FFF)\r |
163 | static DECLFW(BMCFK23CWrite)\r |
164 | {\r |
165 | if(A&(1<<(dipswitch+4)))\r |
166 | {\r |
167 | //printf("+ ");\r |
168 | EXPREGS[A&3]=V;\r |
169 | \r |
170 | bool remap = false;\r |
171 | \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 |
176 | \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 |
179 | //this too.\r |
180 | remap |= (A&3)==2; \r |
181 | \r |
182 | if(remap)\r |
183 | {\r |
184 | FixMMC3PRG(MMC3_cmd);\r |
185 | FixMMC3CHR(MMC3_cmd);\r |
186 | }\r |
187 | }\r |
188 | \r |
189 | if(is_BMCFK23CA)\r |
190 | {\r |
191 | if(EXPREGS[3]&2)\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 |
193 | }\r |
194 | \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 |
197 | }\r |
198 | \r |
199 | static void BMCFK23CReset(void)\r |
200 | {\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 |
203 | // dipswitch++;\r |
204 | // dipswitch&=7;\r |
205 | //printf("BMCFK23C dipswitch set to %d\n",dipswitch);\r |
206 | \r |
207 | EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;\r |
208 | EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;\r |
209 | MMC3RegReset();\r |
210 | FixMMC3PRG(MMC3_cmd);\r |
211 | FixMMC3CHR(MMC3_cmd);\r |
212 | }\r |
213 | \r |
214 | static void BMCFK23CPower(void)\r |
215 | {\r |
216 | dipswitch = 0;\r |
217 | GenMMC3Power();\r |
218 | EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;\r |
219 | EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;\r |
220 | GenMMC3Power();\r |
221 | SetWriteHandler(0x5000,0x5fff,BMCFK23CWrite);\r |
222 | SetWriteHandler(0x8000,0xFFFF,BMCFK23CHiWrite);\r |
223 | FixMMC3PRG(MMC3_cmd);\r |
224 | FixMMC3CHR(MMC3_cmd);\r |
225 | }\r |
226 | \r |
227 | static void BMCFK23CAPower(void)\r |
228 | {\r |
229 | GenMMC3Power();\r |
230 | dipswitch = 0;\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 |
237 | }\r |
238 | \r |
239 | static void BMCFK23CAClose(void)\r |
240 | {\r |
241 | if(CHRRAM)\r |
242 | FCEU_gfree(CHRRAM);\r |
243 | CHRRAM=NULL;\r |
244 | }\r |
245 | \r |
246 | void BMCFK23C_Init(CartInfo *info)\r |
247 | {\r |
248 | is_BMCFK23CA = false;\r |
249 | \r |
250 | GenMMC3_Init(info, 512, 256, 8, 0);\r |
251 | cwrap=BMCFK23CCW;\r |
252 | pwrap=BMCFK23CPW;\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 |
258 | \r |
259 | prg_bonus = 1;\r |
260 | if(MasterRomInfoParams.find("bonus") != MasterRomInfoParams.end())\r |
261 | prg_bonus = atoi(MasterRomInfoParams["bonus"].c_str());\r |
262 | \r |
263 | prg_mask = 0x7F>>(prg_bonus);\r |
264 | }\r |
265 | \r |
266 | void BMCFK23CA_Init(CartInfo *info)\r |
267 | {\r |
268 | is_BMCFK23CA = true;\r |
269 | \r |
270 | GenMMC3_Init(info, 512, 256, 8, 0);\r |
271 | cwrap=BMCFK23CCW;\r |
272 | pwrap=BMCFK23CPW;\r |
273 | info->Power=BMCFK23CAPower;\r |
274 | info->Reset=BMCFK23CReset;\r |
275 | info->Close=BMCFK23CAClose;\r |
276 | \r |
277 | CHRRAMSize=8192;\r |
278 | CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r |
279 | SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r |
280 | AddExState(CHRRAM, CHRRAMSize, 0, "CRAM");\r |
281 | \r |
282 | AddExState(EXPREGS, 8, 0, "EXPR");\r |
283 | AddExState(&unromchr, 1, 0, "UNCHR");\r |
284 | AddExState(&dipswitch, 1, 0, "DIPSW");\r |
285 | \r |
286 | prg_bonus = 1;\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 |
290 | }\r |