merge mapper code from FCEUX
[fceu.git] / boards / datalatch.c
CommitLineData
d97315ac 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Xodnizel
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
386f5371 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
d97315ac 19 */
20
21#include "mapinc.h"
386f5371 22#include "../ines.h"
d97315ac 23
386f5371 24static uint8 latche, latcheinit, bus_conflict;
e2d0dd92 25static uint16 addrreg0, addrreg1;
386f5371 26static uint8 *WRAM=NULL;
27static uint32 WRAMSIZE;
e2d0dd92 28static void(*WSync)(void);
d97315ac 29
e2d0dd92 30static DECLFW(LatchWrite)
d97315ac 31{
386f5371 32// FCEU_printf("bs %04x %02x\n",A,V);
33 if(bus_conflict)
34 latche=V&CartBR(A);
35 else
e2d0dd92 36 latche=V;
37 WSync();
d97315ac 38}
39
e2d0dd92 40static void LatchPower(void)
d97315ac 41{
e2d0dd92 42 latche=latcheinit;
43 WSync();
386f5371 44 if(WRAM)
45 {
46 SetReadHandler(0x6000,0xFFFF,CartBR);
47 SetWriteHandler(0x6000,0x7FFF,CartBW);
48 }
49 else
50 {
51 SetReadHandler(0x8000,0xFFFF,CartBR);
52 }
e2d0dd92 53 SetWriteHandler(addrreg0,addrreg1,LatchWrite);
d97315ac 54}
55
386f5371 56static void LatchClose(void)
57{
58 if(WRAM)
59 FCEU_gfree(WRAM);
60 WRAM=NULL;
61}
62
e2d0dd92 63static void StateRestore(int version)
d97315ac 64{
e2d0dd92 65 WSync();
d97315ac 66}
67
386f5371 68static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1, uint8 wram, uint8 busc)
d97315ac 69{
386f5371 70 bus_conflict = busc;
e2d0dd92 71 latcheinit=init;
72 addrreg0=adr0;
73 addrreg1=adr1;
74 WSync=proc;
75 info->Power=LatchPower;
386f5371 76 info->Close=LatchClose;
e2d0dd92 77 GameStateRestore=StateRestore;
386f5371 78 if(wram)
79 {
80 WRAMSIZE=8192;
81 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
82 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
83 if(info->battery)
84 {
85 info->SaveGame[0]=WRAM;
86 info->SaveGameLen[0]=WRAMSIZE;
87 }
88 AddExState(WRAM, WRAMSIZE, 0, "WRAM");
89 }
d97315ac 90 AddExState(&latche, 1, 0, "LATC");
91}
92
e2d0dd92 93//------------------ CPROM ---------------------------
d97315ac 94
e2d0dd92 95static void CPROMSync(void)
d97315ac 96{
e2d0dd92 97 setchr4(0x0000,0);
98 setchr4(0x1000,latche&3);
99 setprg16(0x8000,0);
100 setprg16(0xC000,1);
d97315ac 101}
102
e2d0dd92 103void CPROM_Init(CartInfo *info)
d97315ac 104{
386f5371 105 Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 106}
107
386f5371 108//------------------ Map 184 ---------------------------
e2d0dd92 109
386f5371 110static void M184Sync(void)
d97315ac 111{
386f5371 112 setchr4(0x0000,latche);
113 setchr4(0x1000,latche>>4);
e2d0dd92 114 setprg16(0x8000,0);
115 setprg16(0xC000,1);
d97315ac 116}
117
386f5371 118void Mapper184_Init(CartInfo *info)
119{
120 Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF, 0, 0);
121}
122
123//------------------ CNROM ---------------------------
124
125static void CNROMSync(void)
126{
127 //mbg 8/10/08 - fixed this so that large homebrew roms would work.
128 //setchr8(latche&3);
129 setchr8(latche);
130 setprg16(0x8000,0);
131 setprg16(0xC000,1);
132 setprg8r(0x10,0x6000,0); // Hayauchy IGO uses 2Kb or RAM
133}
134
d97315ac 135void CNROM_Init(CartInfo *info)
136{
386f5371 137 bool busc = MasterRomInfoParams.ContainsKey("busc");
138 Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, busc?1:0);
d97315ac 139}
140
e2d0dd92 141//------------------ ANROM ---------------------------
d97315ac 142
e2d0dd92 143static void ANROMSync()
d97315ac 144{
e2d0dd92 145 setprg32(0x8000,latche&0xf);
146 setmirror(MI_0+((latche>>4)&1));
d97315ac 147 setchr8(0);
d97315ac 148}
149
e2d0dd92 150void ANROM_Init(CartInfo *info)
d97315ac 151{
386f5371 152 Latch_Init(info, ANROMSync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 153}
154
e2d0dd92 155//------------------ Map 70 ---------------------------
d97315ac 156
e2d0dd92 157static void M70Sync()
d97315ac 158{
e2d0dd92 159 setprg16(0x8000,latche>>4);
160 setprg16(0xc000,~0);
161 setchr8(latche&0xf);
d97315ac 162}
163
e2d0dd92 164void Mapper70_Init(CartInfo *info)
d97315ac 165{
386f5371 166 Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 167}
168
e2d0dd92 169//------------------ Map 152 ---------------------------
d97315ac 170
e2d0dd92 171static void M152Sync()
d97315ac 172{
e2d0dd92 173 setprg16(0x8000,(latche>>4)&7);
174 setprg16(0xc000,~0);
175 setchr8(latche&0xf);
176 setmirror(MI_0+((latche>>7)&1)); /* Saint Seiya...hmm. */
d97315ac 177}
178
e2d0dd92 179void Mapper152_Init(CartInfo *info)
d97315ac 180{
386f5371 181 Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 182}
183
e2d0dd92 184//------------------ Map 78 ---------------------------
185/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */
186static void M78Sync()
d97315ac 187{
e2d0dd92 188 setprg16(0x8000,(latche&7));
189 setprg16(0xc000,~0);
190 setchr8(latche>>4);
191 setmirror(MI_0+((latche>>3)&1));
192}
193
194void Mapper78_Init(CartInfo *info)
195{
386f5371 196 Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF, 0, 0);
e2d0dd92 197}
198
199//------------------ MHROM ---------------------------
200
201static void MHROMSync(void)
202{
203 setprg32(0x8000,latche>>4);
204 setchr8(latche&0xf);
d97315ac 205}
206
207void MHROM_Init(CartInfo *info)
386f5371 208{
209 Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF, 0, 0);
e2d0dd92 210}
211
212void Mapper140_Init(CartInfo *info)
386f5371 213{
214 Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF, 0, 0);
215}
216
217void Mapper240_Init(CartInfo *info)
218{
219 Latch_Init(info, MHROMSync, 0, 0x4020, 0x5FFF, 0, 0);
220 // need SRAM.
e2d0dd92 221}
222
223//------------------ Map 87 ---------------------------
224
225static void M87Sync(void)
226{
227 setprg16(0x8000,0);
228 setprg16(0xC000,1);
386f5371 229 setchr8(((latche>>1)&1)|((latche<<1)&2));
230// setchr8(latche);
e2d0dd92 231}
232
233void Mapper87_Init(CartInfo *info)
386f5371 234{
235 Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF, 0, 0);
236}
237
238//------------------ Map 101 ---------------------------
239
240static void M101Sync(void)
241{
242 setprg16(0x8000,0);
243 setprg16(0xC000,1);
244 setchr8(latche);
245}
246
247void Mapper101_Init(CartInfo *info)
248{
249 Latch_Init(info, M101Sync, ~0, 0x6000, 0x7FFF, 0, 0);
e2d0dd92 250}
251
252//------------------ Map 11 ---------------------------
253
254static void M11Sync(void)
255{
256 setprg32(0x8000,latche&0xf);
257 setchr8(latche>>4);
258}
259
260void Mapper11_Init(CartInfo *info)
386f5371 261{
262 Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF, 0, 0);
e2d0dd92 263}
264
265void Mapper144_Init(CartInfo *info)
386f5371 266{
267 Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF, 0, 0);
d97315ac 268}
269
386f5371 270//------------------ Map 38 ---------------------------
271
272static void M38Sync(void)
273{
274 setprg32(0x8000,latche&3);
275 setchr8(latche>>2);
276}
277
278void Mapper38_Init(CartInfo *info)
279{
280 Latch_Init(info, M38Sync, 0, 0x7000, 0x7FFF, 0, 0);
281}
282
283//------------------ Map 36 ---------------------------
284
285static void M36Sync(void)
286{
287 setprg32(0x8000,latche>>4);
288 setchr8((latche)&0xF);
289}
290
291void Mapper36_Init(CartInfo *info)
292{
293 Latch_Init(info, M36Sync, 0, 0x8400, 0xfffe, 0, 0);
294}
d97315ac 295//------------------ UNROM ---------------------------
296
e2d0dd92 297static void UNROMSync(void)
d97315ac 298{
299 setprg16(0x8000,latche);
e2d0dd92 300 setprg16(0xc000,~0);
301 setchr8(0);
d97315ac 302}
303
e2d0dd92 304void UNROM_Init(CartInfo *info)
d97315ac 305{
386f5371 306 Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF, 0, 1);
d97315ac 307}
308
e2d0dd92 309//------------------ Map 93 ---------------------------
310
311static void SSUNROMSync(void)
d97315ac 312{
e2d0dd92 313 setprg16(0x8000,latche>>4);
d97315ac 314 setprg16(0xc000,~0);
315 setchr8(0);
d97315ac 316}
317
e2d0dd92 318void SUNSOFT_UNROM_Init(CartInfo *info)
d97315ac 319{
386f5371 320 Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 321}
322
e2d0dd92 323//------------------ Map 94 ---------------------------
d97315ac 324
e2d0dd92 325static void M94Sync(void)
d97315ac 326{
e2d0dd92 327 setprg16(0x8000,latche>>2);
328 setprg16(0xc000,~0);
329 setchr8(0);
d97315ac 330}
331
e2d0dd92 332void Mapper94_Init(CartInfo *info)
d97315ac 333{
386f5371 334 Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF, 0, 0);
335}
336
337//------------------ Map 180 ---------------------------
338
339static void M180Sync(void)
340{
341 setprg16(0x8000,0);
342 setprg16(0xc000,latche);
343 setchr8(0);
344}
345
346void Mapper180_Init(CartInfo *info)
347{
348 Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF, 0, 0);
d97315ac 349}
350
e2d0dd92 351//------------------ Map 107 ---------------------------
352
353static void M107Sync(void)
d97315ac 354{
e2d0dd92 355 setprg32(0x8000,(latche>>1)&3);
356 setchr8(latche&7);
d97315ac 357}
358
e2d0dd92 359void Mapper107_Init(CartInfo *info)
d97315ac 360{
386f5371 361 Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF, 0, 0);
362}
363
364//------------------ Map 113 ---------------------------
365
366static void M113Sync(void)
367{
368 setprg32(0x8000,(latche>>3)&7);
369 setchr8(((latche>>3)&8)|(latche&7));
370// setmirror(latche>>7); // only for HES 6in1
371}
372
373void Mapper113_Init(CartInfo *info)
374{
375 Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF, 0, 0);
376}
377
378//------------------ A65AS ---------------------------
379
380// actually, there is two cart in one... First have extra mirroring
381// mode (one screen) and 32K bankswitching, second one have only
382// 16 bankswitching mode and normal mirroring... But there is no any
383// correlations between modes and they can be used in one mapper code.
384
385static void BMCA65ASSync(void)
386{
387 if(latche&0x40)
388 setprg32(0x8000,(latche>>1)&0x0F);
389 else
390 {
391 setprg16(0x8000,((latche&0x30)>>1)|(latche&7));
392 setprg16(0xC000,((latche&0x30)>>1)|7);
393 }
394 setchr8(0);
395 if(latche&0x80)
396 setmirror(MI_0+(((latche>>5)&1)));
397 else
398 setmirror(((latche>>3)&1)^1);
399}
400
401void BMCA65AS_Init(CartInfo *info)
402{
403 Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0);
e2d0dd92 404}
405
406//------------------ NROM ---------------------------
407
408#ifdef DEBUG_MAPPER
409static DECLFW(WriteHandler)
410{
386f5371 411 FCEU_printf("bs %04x %02x\n",A,V);
412 CartBW(A,V);
e2d0dd92 413}
414#endif
415
416static void NROMPower(void)
417{
386f5371 418 setprg8r(0x10,0x6000,0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB
e2d0dd92 419 setprg16(0x8000,0);
420 setprg16(0xC000,~0);
421 setchr8(0);
386f5371 422
423 SetReadHandler(0x6000,0x7FFF,CartBR);
424 SetWriteHandler(0x6000,0x7FFF,CartBW);
d97315ac 425 SetReadHandler(0x8000,0xFFFF,CartBR);
386f5371 426
e2d0dd92 427 #ifdef DEBUG_MAPPER
428 SetWriteHandler(0x4020,0xFFFF,WriteHandler);
429 #endif
d97315ac 430}
431
e2d0dd92 432void NROM_Init(CartInfo *info)
d97315ac 433{
e2d0dd92 434 info->Power=NROMPower;
386f5371 435 info->Close=LatchClose;
436
437 WRAMSIZE=8192;
438 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
439 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
440 if(info->battery)
441 {
442 info->SaveGame[0]=WRAM;
443 info->SaveGameLen[0]=WRAMSIZE;
444 }
445 AddExState(WRAM, WRAMSIZE, 0, "WRAM");
d97315ac 446}