merge mappers from FCEU-mm
[fceu.git] / boards / datalatch.c
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