1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2007-2010 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
21 * Street Dance (Dance pad) (Unl)
\r
22 * 101-in-1 Arcade Action II
\r
28 static uint8 isDance;
\r
29 static uint8 regs[16],regc[6];
\r
30 static uint8 IRQCount,IRQLatch,IRQa, IRQReload, pcm_enable = 0, pcm_irq = 0;
\r
31 static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xF6;
\r
32 static writefunc old4011write, old4012write, old4013write, old4015write;
\r
33 static readfunc old4015read;
\r
35 static SFORMAT StateRegs[]=
\r
39 {&IRQReload, 1, "IRQR"},
\r
40 {&IRQCount, 1, "IRQC"},
\r
41 {&IRQLatch, 1, "IRQL"},
\r
43 {&pcm_enable, 1, "PCME"},
\r
44 {&pcm_irq, 1, "PCMIRQ"},
\r
45 {&pcm_addr, 2, "PCMADDR"},
\r
46 {&pcm_size, 2, "PCMSIZE"},
\r
47 {&pcm_latch, 2, "PCMLATCH"},
\r
48 {&pcm_clock, 2, "PCMCLOCK"},
\r
52 static void Sync(void)
\r
54 uint16 cswap = (regs[0xf] & 0x80) << 5;
\r
55 uint16 pswap = (regs[0xd]&1)?((regs[0xf] & 0x40) << 8):0;
\r
56 uint16 pbase = (regs[0]&0xf0)<<4;
\r
57 uint16 cbase = (((regs[0]&0x0f)<<8)|(regs[0xc]<<1)|((regs[0xd]&0xf8)>>3))<<3;
\r
58 uint16 pmask = 0x3f>>(regs[0xb]&0xf);
\r
60 setchr1(cswap^0x0000,cbase|(regc[0]&(~1)));
\r
61 setchr1(cswap^0x0400,cbase|(regc[0]|1));
\r
62 setchr1(cswap^0x0800,cbase|(regc[1]&(-1)));
\r
63 setchr1(cswap^0x0c00,cbase|(regc[1]|1));
\r
64 setchr1(cswap^0x1000,cbase|(regc[2]));
\r
65 setchr1(cswap^0x1400,cbase|(regc[3]));
\r
66 setchr1(cswap^0x1800,cbase|(regc[4]));
\r
67 setchr1(cswap^0x1c00,cbase|(regc[5]));
\r
71 setprg8(pswap^0x8000, pbase|(regs[0x7]&pmask)|(regs[0xa]&(~pmask)));
\r
72 setprg8( 0xA000, pbase|(regs[0x8]&pmask)|(regs[0xa]&(~pmask)));
\r
73 setprg8(pswap^0xC000, pbase|(regs[0x9]&pmask)|(regs[0xa]&(~pmask)));
\r
74 setprg8( 0xE000, pbase|regs[0xa]);
\r
78 setprg8(pswap^0x8000, pbase|(regs[0x7]&pmask)|(regs[0xa]&(~pmask)));
\r
79 setprg8( 0xA000, pbase|(regs[0x8]&pmask)|(regs[0xa]&(~pmask)));
\r
80 setprg8(pswap^0xC000, pbase|((~1)&pmask)|(regs[0xa]&(~pmask)));
\r
81 setprg8( 0xE000, pbase|((~0)&pmask)|(regs[0xa]&(~pmask)));
\r
84 setmirror(regs[0xe]);
\r
87 static DECLFW(UNLOneBusWrite20XX)
\r
89 // FCEU_printf("PPU %04x:%04x\n",A,V);
\r
92 else if(A == 0x2018)
\r
97 static DECLFW(UNLOneBusWriteExp)
\r
99 // FCEU_printf("EXP %04x:%04x\n",A,V);
\r
100 // switch(A & 0x0F)
\r
102 // case 2: pcm_latch = pcm_clock; FCEU_printf("write %04x:%04x\n",A,V); break;
\r
103 // case 3: pcm_irqa = 0; X6502_IRQEnd(FCEU_IQEXT); pcm_irq = 0; FCEU_printf("write %04x:%04x\n",A,V); break;
\r
104 // case 4: pcm_irqa = 1; FCEU_printf("write %04x:%04x\n",A,V); break;
\r
106 regs[A & 0x0F] = V;
\r
111 static DECLFW(UNLOneBusWriteDebug)
\r
113 // FCEU_printf("write %04x:%04x\n",A,V);
\r
116 static DECLFW(UNLOneBusWriteMMC)
\r
118 // FCEU_printf("MMC %04x:%04x\n",A,V);
\r
121 case 0x8000: regs[0xf] = V; Sync(); break;
\r
124 uint8 mask = 0xff, mmc3cmd = regs[0xf]&7;
\r
136 mask >>= ((regs[0xb]&0xf0)>>4);
\r
137 regc[mmc3cmd] = V&mask;
\r
141 mask = (mask&0x3f)>>(regs[0xb]&0xf);
\r
142 regs[mmc3cmd+1] = (regs[mmc3cmd+1]&(~mask))|(V&mask);
\r
149 case 0xA000: regs[0xe] = (V & 1)^1; Sync(); break;
\r
150 case 0xC000: IRQLatch = V&0xfe; break;
\r
151 case 0xC001: IRQReload = 1; break;
\r
152 case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;
\r
153 case 0xE001: IRQa = 1; break;
\r
157 static void UNLOneBusIRQHook(void)
\r
159 int count = IRQCount;
\r
160 if(!count || IRQReload)
\r
162 IRQCount = IRQLatch;
\r
167 if(count && !IRQCount)
\r
170 X6502_IRQBegin(FCEU_IQEXT);
\r
174 static DECLFW(UNLOneBusWriteAPU2)
\r
176 // FCEU_printf("APU2 %04x:%04x\n",A,V);
\r
177 CartBW(A&0xffdf,V);
\r
180 static DECLFW(UNLOneBusWrite4012)
\r
182 // FCEU_printf("write %04x:%04x\n",A,V);
\r
187 static DECLFW(UNLOneBusWrite4013)
\r
189 // FCEU_printf("write %04x:%04x\n",A,V);
\r
190 pcm_size = (V << 4) + 1;
\r
194 static DECLFW(UNLOneBusWrite4015)
\r
196 // FCEU_printf("write %04x:%04x\n",A,V);
\r
197 pcm_enable = V&0x10;
\r
200 X6502_IRQEnd(FCEU_IQEXT);
\r
204 pcm_latch = pcm_clock;
\r
205 old4015write(A,V&0xEF);
\r
208 static DECLFR(UNLOneBusRead4015)
\r
210 uint8 result = (old4015read(A) & 0x7F)|pcm_irq;
\r
211 // FCEU_printf("read %04x, %02x\n",A,result);
\r
215 static void UNLOneBusCpuHook(int a)
\r
222 pcm_latch+=pcm_clock;
\r
228 X6502_IRQBegin(FCEU_IQEXT);
\r
232 uint8 raw_pcm = ARead[pcm_addr](pcm_addr) >> 1;
\r
233 old4011write(0x4011,raw_pcm);
\r
241 static void UNLOneBusPower(void)
\r
243 IRQCount=IRQLatch=IRQa==0;
\r
244 regs[0]=regs[1]=regs[1]=regs[2]=regs[3]=regs[4]=regs[5]=regs[6]=0;
\r
245 regs[7]=regs[8]=regs[11]=regs[12]=regs[13]=regs[14]=regs[15]=0;
\r
249 SetupCartCHRMapping(0,PRGptr[0],4096 * 1024,0);
\r
251 if(isDance) // quick workaround, TODO: figure out how it works together
\r
253 old4015read=GetReadHandler(0x4015);
\r
254 SetReadHandler(0x4015,0x4015,UNLOneBusRead4015);
\r
255 old4011write=GetWriteHandler(0x4011);
\r
256 old4012write=GetWriteHandler(0x4012);
\r
257 SetWriteHandler(0x4012,0x4012,UNLOneBusWrite4012);
\r
258 old4013write=GetWriteHandler(0x4013);
\r
259 SetWriteHandler(0x4013,0x4013,UNLOneBusWrite4013);
\r
260 old4015write=GetWriteHandler(0x4015);
\r
261 SetWriteHandler(0x4015,0x4015,UNLOneBusWrite4015);
\r
264 SetReadHandler(0x8000,0xFFFF,CartBR);
\r
265 SetWriteHandler(0x2009,0x2fff,UNLOneBusWrite20XX);
\r
266 // SetWriteHandler(0x4020,0xffff,UNLOneBusWriteDebug);
\r
267 // SetWriteHandler(0x4020,0x4040,UNLOneBusWriteAPU2);
\r
268 SetWriteHandler(0x4100,0x410f,UNLOneBusWriteExp);
\r
269 SetWriteHandler(0x8000,0xefff,UNLOneBusWriteMMC);
\r
273 static void UNLOneBusReset(void)
\r
275 IRQCount=IRQLatch=IRQa=0;
\r
276 regs[0]=regs[1]=regs[1]=regs[2]=regs[3]=regs[4]=regs[5]=regs[6]=0;
\r
277 regs[7]=regs[8]=regs[11]=regs[12]=regs[13]=regs[14]=regs[15]=0;
\r
283 static void StateRestore(int version)
\r
288 void UNLOneBus_Init(CartInfo *info)
\r
291 info->Power=UNLOneBusPower;
\r
292 info->Reset=UNLOneBusReset;
\r
293 GameHBIRQHook=UNLOneBusIRQHook;
\r
294 // MapIRQHook=UNLOneBusCpuHook;
\r
295 GameStateRestore=StateRestore;
\r
296 AddExState(&StateRegs, ~0, 0, 0);
\r
299 void UNLDANCE_Init(CartInfo *info)
\r
302 info->Power=UNLOneBusPower;
\r
303 info->Reset=UNLOneBusReset;
\r
304 GameHBIRQHook=UNLOneBusIRQHook;
\r
305 MapIRQHook=UNLOneBusCpuHook;
\r
306 GameStateRestore=StateRestore;
\r
307 AddExState(&StateRegs, ~0, 0, 0);
\r