43725da7 |
1 | /* FCE Ultra - NES/Famicom Emulator\r |
2 | *\r |
3 | * Copyright notice for this file:\r |
4 | * Copyright (C) 2002 Xodnizel\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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r |
19 | */\r |
20 | \r |
21 | #include "mapinc.h"\r |
22 | \r |
23 | static uint8 latche, latcheinit, bus_conflict;\r |
24 | static uint16 addrreg0, addrreg1;\r |
25 | static uint8 *WRAM=NULL;\r |
26 | static uint32 WRAMSIZE;\r |
27 | static void(*WSync)(void);\r |
28 | \r |
29 | static DECLFW(LatchWrite)\r |
30 | {\r |
31 | // FCEU_printf("bs %04x %02x\n",A,V);\r |
32 | if(bus_conflict)\r |
33 | latche=V&CartBR(A);\r |
34 | else\r |
35 | latche=V;\r |
36 | WSync();\r |
37 | }\r |
38 | \r |
39 | static void LatchPower(void)\r |
40 | {\r |
41 | latche=latcheinit;\r |
42 | WSync();\r |
43 | SetReadHandler(0x6000,0xFFFF,CartBR);\r |
44 | SetWriteHandler(0x6000,0x7FFF,CartBW);\r |
45 | SetWriteHandler(addrreg0,addrreg1,LatchWrite);\r |
46 | }\r |
47 | \r |
48 | static void LatchClose(void)\r |
49 | {\r |
50 | if(WRAM)\r |
51 | FCEU_gfree(WRAM);\r |
52 | WRAM=NULL;\r |
53 | }\r |
54 | \r |
55 | static void StateRestore(int version)\r |
56 | {\r |
57 | WSync();\r |
58 | }\r |
59 | \r |
60 | static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1, uint8 wram, uint8 busc)\r |
61 | {\r |
62 | bus_conflict = busc;\r |
63 | latcheinit=init;\r |
64 | addrreg0=adr0;\r |
65 | addrreg1=adr1;\r |
66 | WSync=proc;\r |
67 | info->Power=LatchPower;\r |
68 | info->Close=LatchClose;\r |
69 | GameStateRestore=StateRestore;\r |
70 | if(wram)\r |
71 | {\r |
72 | WRAMSIZE=8192;\r |
73 | WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r |
74 | SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r |
75 | if(info->battery)\r |
76 | {\r |
77 | info->SaveGame[0]=WRAM;\r |
78 | info->SaveGameLen[0]=WRAMSIZE;\r |
79 | }\r |
80 | AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r |
81 | }\r |
82 | AddExState(&latche, 1, 0, "LATC");\r |
83 | }\r |
84 | \r |
85 | //------------------ Map 0 ---------------------------\r |
86 | \r |
87 | #ifdef DEBUG_MAPPER\r |
88 | static DECLFW(NROMWrite)\r |
89 | {\r |
90 | FCEU_printf("bs %04x %02x\n",A,V);\r |
91 | CartBW(A,V);\r |
92 | }\r |
93 | #endif\r |
94 | \r |
95 | static void NROMPower(void)\r |
96 | {\r |
97 | setprg8r(0x10,0x6000,0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB\r |
98 | setprg16(0x8000,0);\r |
99 | setprg16(0xC000,~0);\r |
100 | setchr8(0);\r |
101 | \r |
102 | SetReadHandler(0x6000,0x7FFF,CartBR);\r |
103 | SetWriteHandler(0x6000,0x7FFF,CartBW);\r |
104 | SetReadHandler(0x8000,0xFFFF,CartBR);\r |
105 | \r |
106 | #ifdef DEBUG_MAPPER\r |
107 | SetWriteHandler(0x4020,0xFFFF,NROMWrite);\r |
108 | #endif\r |
109 | }\r |
110 | \r |
111 | void NROM_Init(CartInfo *info)\r |
112 | {\r |
113 | info->Power=NROMPower;\r |
114 | info->Close=LatchClose;\r |
115 | \r |
116 | WRAMSIZE=8192;\r |
117 | WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r |
118 | SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r |
119 | if(info->battery)\r |
120 | {\r |
121 | info->SaveGame[0]=WRAM;\r |
122 | info->SaveGameLen[0]=WRAMSIZE;\r |
123 | }\r |
124 | AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r |
125 | }\r |
126 | \r |
127 | //------------------ Map 2 ---------------------------\r |
128 | \r |
129 | static void UNROMSync(void)\r |
130 | {\r |
131 | static uint32 mirror_in_use = 0;\r |
132 | setprg16(0x8000,latche&7);\r |
133 | if(latche&8) mirror_in_use = 1;\r |
134 | if(mirror_in_use)\r |
135 | setmirror(((latche >> 3)&1)^1); // Higway Star Hacked mapper\r |
136 | setprg16(0xc000,~0);\r |
137 | setchr8(0);\r |
138 | }\r |
139 | \r |
140 | void UNROM_Init(CartInfo *info)\r |
141 | {\r |
142 | Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF, 0, 1);\r |
143 | }\r |
144 | \r |
145 | //------------------ Map 3 ---------------------------\r |
146 | \r |
147 | static void CNROMSync(void)\r |
148 | {\r |
149 | setchr8(latche);\r |
150 | setprg32(0x8000,0);\r |
151 | setprg8r(0x10,0x6000,0); // Hayauchy IGO uses 2Kb or RAM\r |
152 | }\r |
153 | \r |
154 | void CNROM_Init(CartInfo *info)\r |
155 | {\r |
156 | Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, 0);\r |
157 | }\r |
158 | \r |
159 | //------------------ Map 7 ---------------------------\r |
160 | \r |
161 | static void ANROMSync()\r |
162 | {\r |
163 | setprg32(0x8000,latche&0xf);\r |
164 | setmirror(MI_0+((latche>>4)&1));\r |
165 | setchr8(0);\r |
166 | }\r |
167 | \r |
168 | void ANROM_Init(CartInfo *info)\r |
169 | {\r |
170 | Latch_Init(info, ANROMSync, 0, 0x8000, 0xFFFF, 0, 0);\r |
171 | }\r |
172 | \r |
173 | //------------------ Map 8 ---------------------------\r |
174 | \r |
175 | static void M8Sync()\r |
176 | {\r |
177 | setprg16(0x8000,latche>>3);\r |
178 | setprg16(0xc000,1);\r |
179 | setchr8(latche&3);\r |
180 | }\r |
181 | \r |
182 | void Mapper8_Init(CartInfo *info)\r |
183 | {\r |
184 | Latch_Init(info, M8Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
185 | }\r |
186 | \r |
187 | //------------------ Map 11 ---------------------------\r |
188 | \r |
189 | static void M11Sync(void)\r |
190 | {\r |
191 | setprg32(0x8000,latche&0xf);\r |
192 | setchr8(latche>>4);\r |
193 | }\r |
194 | \r |
195 | void Mapper11_Init(CartInfo *info)\r |
196 | {\r |
197 | Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
198 | }\r |
199 | \r |
200 | void Mapper144_Init(CartInfo *info)\r |
201 | {\r |
202 | Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF, 0, 0);\r |
203 | }\r |
204 | \r |
205 | //------------------ Map 13 ---------------------------\r |
206 | \r |
207 | static void CPROMSync(void)\r |
208 | {\r |
209 | setchr4(0x0000,0);\r |
210 | setchr4(0x1000,latche&3);\r |
211 | setprg32(0x8000,0);\r |
212 | }\r |
213 | \r |
214 | void CPROM_Init(CartInfo *info)\r |
215 | {\r |
216 | Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0);\r |
217 | }\r |
218 | \r |
219 | //------------------ Map 36 ---------------------------\r |
220 | \r |
221 | static void M36Sync(void)\r |
222 | {\r |
223 | setprg32(0x8000,latche>>4);\r |
224 | setchr8((latche)&0xF);\r |
225 | }\r |
226 | \r |
227 | void Mapper36_Init(CartInfo *info)\r |
228 | {\r |
229 | Latch_Init(info, M36Sync, 0, 0x8400, 0xfffe, 0, 0);\r |
230 | }\r |
231 | \r |
232 | //------------------ Map 38 ---------------------------\r |
233 | \r |
234 | static void M38Sync(void)\r |
235 | {\r |
236 | setprg32(0x8000,latche&3);\r |
237 | setchr8(latche>>2);\r |
238 | }\r |
239 | \r |
240 | void Mapper38_Init(CartInfo *info)\r |
241 | {\r |
242 | Latch_Init(info, M38Sync, 0, 0x7000, 0x7FFF, 0, 0);\r |
243 | }\r |
244 | \r |
245 | //------------------ Map 66 ---------------------------\r |
246 | \r |
247 | static void MHROMSync(void)\r |
248 | {\r |
249 | setprg32(0x8000,latche>>4);\r |
250 | setchr8(latche&0xf);\r |
251 | }\r |
252 | \r |
253 | void MHROM_Init(CartInfo *info)\r |
254 | {\r |
255 | Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF, 0, 0);\r |
256 | }\r |
257 | \r |
258 | //------------------ Map 70 ---------------------------\r |
259 | \r |
260 | static void M70Sync()\r |
261 | {\r |
262 | setprg16(0x8000,latche>>4);\r |
263 | setprg16(0xc000,~0);\r |
264 | setchr8(latche&0xf);\r |
265 | }\r |
266 | \r |
267 | void Mapper70_Init(CartInfo *info)\r |
268 | {\r |
269 | Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
270 | }\r |
271 | \r |
272 | //------------------ Map 78 ---------------------------\r |
273 | /* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */\r |
274 | static void M78Sync()\r |
275 | {\r |
276 | setprg16(0x8000,(latche&7));\r |
277 | setprg16(0xc000,~0);\r |
278 | setchr8(latche>>4);\r |
279 | setmirror(MI_0+((latche>>3)&1));\r |
280 | }\r |
281 | \r |
282 | void Mapper78_Init(CartInfo *info)\r |
283 | {\r |
284 | Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
285 | }\r |
286 | \r |
287 | //------------------ Map 86 ---------------------------\r |
288 | \r |
289 | static void M86Sync(void)\r |
290 | {\r |
291 | setprg32(0x8000,(latche >> 4) & 3);\r |
292 | setchr8((latche & 3) | ((latche >> 4) & 4));\r |
293 | }\r |
294 | \r |
295 | void Mapper86_Init(CartInfo *info)\r |
296 | {\r |
297 | Latch_Init(info, M86Sync, ~0, 0x6000, 0x6FFF, 0, 0);\r |
298 | }\r |
299 | \r |
300 | //------------------ Map 87 ---------------------------\r |
301 | \r |
302 | static void M87Sync(void)\r |
303 | {\r |
304 | setprg32(0x8000,0);\r |
305 | setchr8(((latche>>1)&1)|((latche<<1)&2));\r |
306 | }\r |
307 | \r |
308 | void Mapper87_Init(CartInfo *info)\r |
309 | {\r |
310 | Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF, 0, 0);\r |
311 | }\r |
312 | \r |
313 | //------------------ Map 89 ---------------------------\r |
314 | \r |
315 | static void M89Sync(void)\r |
316 | {\r |
317 | setprg16(0x8000,(latche >> 4) & 7);\r |
318 | setprg16(0xc000, ~0);\r |
319 | setchr8((latche & 7) | ((latche >> 4) & 8));\r |
320 | setmirror(MI_0 + ((latche >> 3) & 1));\r |
321 | }\r |
322 | \r |
323 | void Mapper89_Init(CartInfo *info)\r |
324 | {\r |
325 | Latch_Init(info, M89Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
326 | }\r |
327 | \r |
328 | //------------------ Map 93 ---------------------------\r |
329 | \r |
330 | static void SSUNROMSync(void)\r |
331 | {\r |
332 | setprg16(0x8000,latche>>4);\r |
333 | setprg16(0xc000,~0);\r |
334 | setchr8(0);\r |
335 | }\r |
336 | \r |
337 | void SUNSOFT_UNROM_Init(CartInfo *info)\r |
338 | {\r |
339 | Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF, 0, 0);\r |
340 | }\r |
341 | \r |
342 | //------------------ Map 94 ---------------------------\r |
343 | \r |
344 | static void M94Sync(void)\r |
345 | {\r |
346 | setprg16(0x8000,latche>>2);\r |
347 | setprg16(0xc000,~0);\r |
348 | setchr8(0);\r |
349 | }\r |
350 | \r |
351 | void Mapper94_Init(CartInfo *info)\r |
352 | {\r |
353 | Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
354 | }\r |
355 | \r |
356 | //------------------ Map 97 ---------------------------\r |
357 | \r |
358 | static void M97Sync(void)\r |
359 | {\r |
360 | setchr8(0);\r |
361 | setprg16(0x8000,~0);\r |
362 | setprg16(0xc000,latche & 15);\r |
363 | switch(latche >> 6)\r |
364 | {\r |
365 | case 0: break;\r |
366 | case 1: setmirror(MI_H); break;\r |
367 | case 2: setmirror(MI_V); break;\r |
368 | case 3: break;\r |
369 | }\r |
370 | setchr8(((latche>>1)&1)|((latche<<1)&2));\r |
371 | }\r |
372 | \r |
373 | void Mapper97_Init(CartInfo *info)\r |
374 | {\r |
375 | Latch_Init(info, M97Sync, ~0, 0x8000, 0xFFFF, 0, 0);\r |
376 | }\r |
377 | \r |
378 | //------------------ Map 101 ---------------------------\r |
379 | \r |
380 | static void M101Sync(void)\r |
381 | {\r |
382 | setprg32(0x8000,0);\r |
383 | setchr8(latche);\r |
384 | }\r |
385 | \r |
386 | void Mapper101_Init(CartInfo *info)\r |
387 | {\r |
388 | Latch_Init(info, M101Sync, ~0, 0x6000, 0x7FFF, 0, 0);\r |
389 | }\r |
390 | \r |
391 | //------------------ Map 107 ---------------------------\r |
392 | \r |
393 | static void M107Sync(void)\r |
394 | {\r |
395 | setprg32(0x8000,(latche>>1)&3);\r |
396 | setchr8(latche&7);\r |
397 | }\r |
398 | \r |
399 | void Mapper107_Init(CartInfo *info)\r |
400 | {\r |
401 | Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF, 0, 0);\r |
402 | }\r |
403 | \r |
404 | //------------------ Map 113 ---------------------------\r |
405 | \r |
406 | static void M113Sync(void)\r |
407 | {\r |
408 | setprg32(0x8000,(latche>>3)&7);\r |
409 | setchr8(((latche>>3)&8)|(latche&7));\r |
410 | // setmirror(latche>>7); // only for HES 6in1\r |
411 | }\r |
412 | \r |
413 | void Mapper113_Init(CartInfo *info)\r |
414 | {\r |
415 | Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF, 0, 0);\r |
416 | }\r |
417 | \r |
418 | //------------------ Map 140 ---------------------------\r |
419 | \r |
420 | void Mapper140_Init(CartInfo *info)\r |
421 | {\r |
422 | Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF, 0, 0);\r |
423 | }\r |
424 | \r |
425 | //------------------ Map 152 ---------------------------\r |
426 | \r |
427 | static void M152Sync()\r |
428 | {\r |
429 | setprg16(0x8000,(latche>>4)&7);\r |
430 | setprg16(0xc000,~0);\r |
431 | setchr8(latche&0xf);\r |
432 | setmirror(MI_0+((latche>>7)&1)); /* Saint Seiya...hmm. */\r |
433 | }\r |
434 | \r |
435 | void Mapper152_Init(CartInfo *info)\r |
436 | {\r |
437 | Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
438 | }\r |
439 | \r |
440 | //------------------ Map 180 ---------------------------\r |
441 | \r |
442 | static void M180Sync(void)\r |
443 | {\r |
444 | setprg16(0x8000,0);\r |
445 | setprg16(0xc000,latche);\r |
446 | setchr8(0);\r |
447 | }\r |
448 | \r |
449 | void Mapper180_Init(CartInfo *info)\r |
450 | {\r |
451 | Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF, 0, 0);\r |
452 | }\r |
453 | \r |
454 | //------------------ Map 184 ---------------------------\r |
455 | \r |
456 | static void M184Sync(void)\r |
457 | {\r |
458 | setchr4(0x0000,latche);\r |
459 | setchr4(0x1000,latche>>4);\r |
460 | setprg32(0x8000,0);\r |
461 | }\r |
462 | \r |
463 | void Mapper184_Init(CartInfo *info)\r |
464 | {\r |
465 | Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF, 0, 0);\r |
466 | }\r |
467 | \r |
468 | //------------------ Map 240 ---------------------------\r |
469 | \r |
470 | void Mapper240_Init(CartInfo *info)\r |
471 | {\r |
472 | Latch_Init(info, MHROMSync, 0, 0x4020, 0x5FFF, 0, 0);\r |
473 | // need SRAM.\r |
474 | }\r |
475 | \r |
476 | //------------------ A65AS ---------------------------\r |
477 | \r |
478 | // actually, there is two cart in one... First have extra mirroring\r |
479 | // mode (one screen) and 32K bankswitching, second one have only\r |
480 | // 16 bankswitching mode and normal mirroring... But there is no any\r |
481 | // correlations between modes and they can be used in one mapper code.\r |
482 | \r |
483 | static void BMCA65ASSync(void)\r |
484 | {\r |
485 | if(latche&0x40)\r |
486 | setprg32(0x8000,(latche>>1)&0x0F);\r |
487 | else\r |
488 | {\r |
489 | setprg16(0x8000,((latche&0x30)>>1)|(latche&7));\r |
490 | setprg16(0xC000,((latche&0x30)>>1)|7);\r |
491 | }\r |
492 | setchr8(0);\r |
493 | if(latche&0x80)\r |
494 | setmirror(MI_0+(((latche>>5)&1)));\r |
495 | else\r |
496 | setmirror(((latche>>3)&1)^1);\r |
497 | }\r |
498 | \r |
499 | void BMCA65AS_Init(CartInfo *info)\r |
500 | {\r |
501 | Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0);\r |
502 | }\r |
503 | \r |