random warning fixes
[fceu.git] / boards / onebus.c
CommitLineData
386f5371 1/* FCE Ultra - NES/Famicom Emulator\r
2 *\r
3 * Copyright notice for this file:\r
4 * Copyright (C) 2007-2010 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
43725da7 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
19 *\r
20 * VR02/VT03 Console and OneBus System\r
386f5371 21 *\r
386f5371 22 * Street Dance (Dance pad) (Unl)\r
23 * 101-in-1 Arcade Action II\r
43725da7 24 * DreamGEAR 75-in-1, etc.\r
25 *\r
386f5371 26 */\r
27\r
28#include "mapinc.h"\r
29\r
43725da7 30// General Purpose Registers\r
31static uint8 cpu410x[16], ppu201x[16], apu40xx[64];\r
32\r
33// IRQ Registers\r
34static uint8 IRQCount, IRQa, IRQReload;\r
35#define IRQLatch cpu410x[0x1]\r
36\r
37// MMC3 Registers\r
38static uint8 inv_hack = 0; // some OneBus Systems have swapped PRG reg commans in MMC3 inplementation,\r
39 // trying to autodetect unusual behavior, due not to add a new mapper.\r
40#define mmc3cmd cpu410x[0x5]\r
41#define mirror cpu410x[0x6]\r
42\r
43// APU Registers\r
44static uint8 pcm_enable = 0, pcm_irq = 0;\r
386f5371 45static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xF6;\r
43725da7 46\r
47static writefunc defapuwrite[64];\r
48static readfunc defapuread[64];\r
386f5371 49\r
50static SFORMAT StateRegs[]=\r
51{\r
43725da7 52 {cpu410x, 16, "REGC"},\r
53 {ppu201x, 16, "REGS"},\r
54 {apu40xx, 64, "REGA"},\r
386f5371 55 {&IRQReload, 1, "IRQR"},\r
56 {&IRQCount, 1, "IRQC"},\r
386f5371 57 {&IRQa, 1, "IRQA"},\r
58 {&pcm_enable, 1, "PCME"},\r
43725da7 59 {&pcm_irq, 1, "PCMI"},\r
60 {&pcm_addr, 2, "PCMA"},\r
61 {&pcm_size, 2, "PCMS"},\r
62 {&pcm_latch, 2, "PCML"},\r
63 {&pcm_clock, 2, "PCMC"},\r
386f5371 64 {0}\r
65};\r
66\r
43725da7 67static void PSync(void)\r
386f5371 68{\r
43725da7 69 uint8 bankmode = cpu410x[0xb] & 7;\r
70 uint8 mask = (bankmode == 0x7)?(0xff):(0x3f >> bankmode);\r
71 uint32 block = ((cpu410x[0x0] & 0xf0) << 4) + (cpu410x[0xa] & (~mask));\r
72 uint32 pswap = (mmc3cmd & 0x40) << 8;\r
73\r
74// uint8 bank0 = (cpu410x[0xb] & 0x40)?(~1):(cpu410x[0x7]);\r
75// uint8 bank1 = cpu410x[0x8];\r
76// uint8 bank2 = (cpu410x[0xb] & 0x40)?(cpu410x[0x9]):(~1);\r
77// uint8 bank3 = ~0;\r
78 uint8 bank0 = cpu410x[0x7^inv_hack];\r
79 uint8 bank1 = cpu410x[0x8^inv_hack];\r
80 uint8 bank2 = (cpu410x[0xb] & 0x40)?(cpu410x[0x9]):(~1);\r
81 uint8 bank3 = ~0;\r
386f5371 82\r
43725da7 83// FCEU_printf(" PRG: %04x [%02x]",0x8000^pswap,block | (bank0 & mask));\r
84 setprg8(0x8000^pswap, block | (bank0 & mask));\r
85// FCEU_printf(" %04x [%02x]",0xa000^pswap,block | (bank1 & mask));\r
86 setprg8(0xa000, block | (bank1 & mask));\r
87// FCEU_printf(" %04x [%02x]",0xc000^pswap,block | (bank2 & mask));\r
88 setprg8(0xc000^pswap, block | (bank2 & mask));\r
89// FCEU_printf(" %04x [%02x]\n",0xe000^pswap,block | (bank3 & mask));\r
90 setprg8(0xe000, block | (bank3 & mask));\r
386f5371 91}\r
92\r
43725da7 93static void CSync(void)\r
386f5371 94{\r
43725da7 95 static const uint8 midx[8] = {0, 1, 2, 0, 3, 4, 5, 0 };\r
96 uint8 mask = 0xff >> midx[ppu201x[0xa] & 7];\r
97 uint32 block = ((cpu410x[0x0] & 0x0f) << 11) + ((ppu201x[0x8] & 0x70) << 4) + (ppu201x[0xa] & (~mask));\r
98 uint32 cswap = (mmc3cmd & 0x80) << 5;\r
99\r
100 uint8 bank0 = ppu201x[0x6]&(~1);\r
101 uint8 bank1 = ppu201x[0x6]|1;\r
102 uint8 bank2 = ppu201x[0x7]&(~1);\r
103 uint8 bank3 = ppu201x[0x7]|1;\r
104 uint8 bank4 = ppu201x[0x2];\r
105 uint8 bank5 = ppu201x[0x3];\r
106 uint8 bank6 = ppu201x[0x4];\r
107 uint8 bank7 = ppu201x[0x5];\r
108\r
109 setchr1(0x0000^cswap, block | (bank0 & mask));\r
110 setchr1(0x0400^cswap, block | (bank1 & mask));\r
111 setchr1(0x0800^cswap, block | (bank2 & mask));\r
112 setchr1(0x0c00^cswap, block | (bank3 & mask));\r
113 setchr1(0x1000^cswap, block | (bank4 & mask));\r
114 setchr1(0x1400^cswap, block | (bank5 & mask));\r
115 setchr1(0x1800^cswap, block | (bank6 & mask));\r
116 setchr1(0x1c00^cswap, block | (bank7 & mask));\r
117\r
118 setmirror((mirror & 1) ^ 1);\r
386f5371 119}\r
120\r
43725da7 121static void Sync(void)\r
386f5371 122{\r
43725da7 123 PSync();\r
124 CSync();\r
386f5371 125}\r
126\r
43725da7 127static DECLFW(UNLOneBusWriteCPU410X)\r
386f5371 128{\r
43725da7 129// FCEU_printf("CPU %04x:%04x\n",A,V);\r
130 switch(A & 0xf)\r
131 {\r
132 case 0x1: IRQLatch = V & 0xfe; break;\r
133 case 0x2: IRQReload = 1; break;\r
134 case 0x3: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;\r
135 case 0x4: IRQa = 1; break;\r
136 default:\r
137 cpu410x[A & 0xf] = V;\r
138 Sync();\r
139 }\r
386f5371 140}\r
141\r
43725da7 142static DECLFW(UNLOneBusWritePPU201X)\r
143{\r
144// FCEU_printf("PPU %04x:%04x\n",A,V);\r
145 ppu201x[A & 0x0f] = V;\r
146 Sync();\r
147}\r
148\r
149static DECLFW(UNLOneBusWriteMMC3)\r
386f5371 150{\r
151// FCEU_printf("MMC %04x:%04x\n",A,V);\r
43725da7 152 switch(A&0xe001)\r
386f5371 153 {\r
43725da7 154 case 0x8000: mmc3cmd = (mmc3cmd & 0x38) | (V & 0xc7); Sync(); break;\r
386f5371 155 case 0x8001:\r
156 {\r
43725da7 157 switch(mmc3cmd & 7)\r
386f5371 158 {\r
43725da7 159 case 0: ppu201x[0x6] = V; CSync(); break;\r
160 case 1: ppu201x[0x7] = V; CSync(); break;\r
161 case 2: ppu201x[0x2] = V; CSync(); break;\r
162 case 3: ppu201x[0x3] = V; CSync(); break;\r
163 case 4: ppu201x[0x4] = V; CSync(); break;\r
164 case 5: ppu201x[0x5] = V; CSync(); break;\r
165 case 6: cpu410x[0x7] = V; PSync(); break;\r
166 case 7: cpu410x[0x8] = V; PSync(); break;\r
386f5371 167 }\r
386f5371 168 break;\r
169 }\r
43725da7 170 case 0xa000: mirror = V; CSync(); break;\r
171 case 0xc000: IRQLatch = V & 0xfe; break;\r
172 case 0xc001: IRQReload = 1; break;\r
173 case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break;\r
174 case 0xe001: IRQa = 1; break;\r
386f5371 175 }\r
176}\r
177\r
178static void UNLOneBusIRQHook(void)\r
179{\r
180 int count = IRQCount;\r
181 if(!count || IRQReload)\r
182 {\r
183 IRQCount = IRQLatch;\r
184 IRQReload = 0;\r
185 }\r
186 else\r
187 IRQCount--;\r
188 if(count && !IRQCount)\r
189 {\r
190 if(IRQa)\r
191 X6502_IRQBegin(FCEU_IQEXT);\r
192 }\r
193}\r
194\r
43725da7 195static DECLFW(UNLOneBusWriteAPU40XX)\r
386f5371 196{\r
43725da7 197// FCEU_printf("APU %04x:%04x\n",A,V);\r
198 apu40xx[A & 0x3f] = V;\r
199 switch(A & 0x3f)\r
386f5371 200 {\r
43725da7 201 case 0x12:\r
202 if(apu40xx[0x30] & 0x10)\r
203 {\r
204 pcm_addr = V << 6;\r
205 }\r
206 case 0x13:\r
207 if(apu40xx[0x30] & 0x10)\r
208 {\r
209 pcm_size = (V << 4) + 1;\r
210 }\r
211 case 0x15:\r
212 if(apu40xx[0x30] & 0x10)\r
213 {\r
214 pcm_enable = V&0x10;\r
215 if(pcm_irq)\r
216 {\r
217 X6502_IRQEnd(FCEU_IQEXT);\r
218 pcm_irq = 0;\r
219 }\r
220 if(pcm_enable)\r
221 pcm_latch = pcm_clock;\r
222 V &= 0xef;\r
223 }\r
386f5371 224 }\r
43725da7 225 defapuwrite[A & 0x3f](A, V);\r
386f5371 226}\r
227\r
43725da7 228static DECLFR(UNLOneBusReadAPU40XX)\r
386f5371 229{\r
43725da7 230 uint8 result = defapuread[A & 0x3f](A);\r
386f5371 231// FCEU_printf("read %04x, %02x\n",A,result);\r
43725da7 232 switch(A & 0x3f)\r
233 {\r
234 case 0x15:\r
235 if(apu40xx[0x30] & 0x10)\r
236 {\r
237 result = (result & 0x7f) | pcm_irq;\r
238 }\r
239 }\r
386f5371 240 return result;\r
241}\r
242\r
243static void UNLOneBusCpuHook(int a)\r
244{\r
245 if(pcm_enable)\r
246 {\r
247 pcm_latch-=a;\r
248 if(pcm_latch<=0)\r
249 {\r
250 pcm_latch+=pcm_clock;\r
251 pcm_size--;\r
252 if(pcm_size<0)\r
253 {\r
254 pcm_irq = 0x80;\r
255 pcm_enable = 0;\r
256 X6502_IRQBegin(FCEU_IQEXT);\r
257 }\r
258 else\r
259 {\r
260 uint8 raw_pcm = ARead[pcm_addr](pcm_addr) >> 1;\r
43725da7 261 defapuwrite[0x11](0x4011,raw_pcm);\r
386f5371 262 pcm_addr++;\r
263 pcm_addr&=0x7FFF;\r
264 }\r
265 }\r
266 }\r
267}\r
268\r
269static void UNLOneBusPower(void)\r
270{\r
43725da7 271 uint32 i;\r
272 IRQReload = IRQCount = IRQa = 0;\r
273\r
274 memset(cpu410x, 0x00, sizeof(cpu410x));\r
275 memset(ppu201x, 0x00, sizeof(ppu201x));\r
276 memset(apu40xx, 0x00, sizeof(apu40xx));\r
386f5371 277\r
43725da7 278 SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0);\r
386f5371 279\r
43725da7 280 for(i=0; i<64; i++)\r
386f5371 281 {\r
43725da7 282 defapuread[i] = GetReadHandler(0x4000|i);\r
283 defapuwrite[i] = GetWriteHandler(0x4000|i);\r
386f5371 284 }\r
43725da7 285 SetReadHandler(0x4000,0x403f,UNLOneBusReadAPU40XX);\r
286 SetWriteHandler(0x4000,0x403f,UNLOneBusWriteAPU40XX);\r
386f5371 287\r
288 SetReadHandler(0x8000,0xFFFF,CartBR);\r
43725da7 289 SetWriteHandler(0x2010,0x201f,UNLOneBusWritePPU201X);\r
290 SetWriteHandler(0x4100,0x410f,UNLOneBusWriteCPU410X);\r
291 SetWriteHandler(0x8000,0xffff,UNLOneBusWriteMMC3);\r
292\r
386f5371 293 Sync();\r
294}\r
295\r
296static void UNLOneBusReset(void)\r
297{\r
43725da7 298 IRQReload = IRQCount = IRQa = 0;\r
299\r
300 memset(cpu410x, 0x00, sizeof(cpu410x));\r
301 memset(ppu201x, 0x00, sizeof(ppu201x));\r
302 memset(apu40xx, 0x00, sizeof(apu40xx));\r
303\r
386f5371 304 Sync();\r
305}\r
306\r
307static void StateRestore(int version)\r
308{\r
309 Sync();\r
310}\r
311\r
312void UNLOneBus_Init(CartInfo *info)\r
313{\r
386f5371 314 info->Power=UNLOneBusPower;\r
315 info->Reset=UNLOneBusReset;\r
386f5371 316\r
43725da7 317 if(((*(uint32*)&(info->MD5)) == 0x305fcdc3) || // PowerJoy Supermax Carts\r
318 ((*(uint32*)&(info->MD5)) == 0x6abfce8e) )\r
319 inv_hack = 0xf;\r
320\r
386f5371 321 GameHBIRQHook=UNLOneBusIRQHook;\r
322 MapIRQHook=UNLOneBusCpuHook;\r
323 GameStateRestore=StateRestore;\r
324 AddExState(&StateRegs, ~0, 0, 0);\r
325}\r