compat hacks for this old version of fceu
[fceu.git] / boards / bandai.c
CommitLineData
386f5371 1/* FCE Ultra - NES/Famicom Emulator\r
2 *\r
3 * Copyright notice for this file:\r
4 * Copyright (C) 2007 CaH4e3\r
386f5371 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
386f5371 19 *\r
20 * Bandai mappers\r
21 *\r
22 */\r
23\r
386f5371 24#include "mapinc.h"\r
25\r
26static uint8 reg[16], is153;\r
27static uint8 IRQa;\r
28static int16 IRQCount, IRQLatch;\r
29\r
30static uint8 *WRAM=NULL;\r
31static uint32 WRAMSIZE;\r
32\r
33static SFORMAT StateRegs[]=\r
34{\r
35 {reg, 16, "REGS"},\r
36 {&IRQa, 1, "IRQA"},\r
37 {&IRQCount, 2, "IRQC"},\r
38 {&IRQLatch, 2, "IRQL"}, // need for Famicom Jump II - Saikyou no 7 Nin (J) [!]\r
39 {0}\r
40};\r
41\r
43725da7 42static void FP_FASTAPASS(1) BandaiIRQHook(int a)\r
386f5371 43{\r
44 if(IRQa)\r
45 {\r
43725da7 46 IRQCount-=a;\r
386f5371 47 if(IRQCount<0)\r
48 {\r
49 X6502_IRQBegin(FCEU_IQEXT);\r
43725da7 50 IRQa=0;\r
51 IRQCount=0xFFFF;\r
386f5371 52 }\r
53 }\r
54}\r
55\r
56static void BandaiSync(void)\r
57{\r
43725da7 58 if(!UNIFchrrama)\r
59 {\r
60 int i;\r
61 for(i=0; i<8; i++) setchr1(i<<10,reg[i]);\r
62 }\r
63 else\r
64 setchr8(0);\r
386f5371 65 if(is153)\r
66 {\r
67 int base=(reg[0]&1)<<4;\r
386f5371 68 setprg16(0x8000,(reg[8]&0x0F)|base);\r
69 setprg16(0xC000,0x0F|base);\r
70 }\r
71 else\r
72 {\r
386f5371 73 setprg16(0x8000,reg[8]);\r
74 setprg16(0xC000,~0);\r
75 }\r
76 switch(reg[9]&3)\r
77 {\r
78 case 0: setmirror(MI_V); break;\r
79 case 1: setmirror(MI_H); break;\r
80 case 2: setmirror(MI_0); break;\r
81 case 3: setmirror(MI_1); break;\r
82 }\r
83}\r
84\r
85static DECLFW(BandaiWrite)\r
86{\r
87 A&=0x0F;\r
88 if(A<0x0A)\r
89 {\r
90 reg[A&0x0F]=V;\r
91 BandaiSync();\r
92 }\r
93 else\r
94 switch(A)\r
95 {\r
96 case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa=V&1; IRQCount=IRQLatch; break;\r
43725da7 97 case 0x0B: IRQLatch&=0xFF00; IRQLatch|=V; break;\r
386f5371 98 case 0x0C: IRQLatch&=0xFF; IRQLatch|=V<<8; break;\r
99 case 0x0D: break;// Serial EEPROM control port\r
100 }\r
101}\r
102\r
386f5371 103static void BandaiPower(void)\r
104{\r
105 BandaiSync();\r
106 SetReadHandler(0x8000,0xFFFF,CartBR);\r
107 SetWriteHandler(0x6000,0xFFFF,BandaiWrite);\r
386f5371 108}\r
109\r
110static void StateRestore(int version)\r
111{\r
112 BandaiSync();\r
113}\r
114\r
115void Mapper16_Init(CartInfo *info)\r
116{\r
117 is153=0;\r
118 info->Power=BandaiPower;\r
119 MapIRQHook=BandaiIRQHook;\r
120 GameStateRestore=StateRestore;\r
121 AddExState(&StateRegs, ~0, 0, 0);\r
122}\r
123\r
43725da7 124// Famicom jump 2:\r
125// 0-7: Lower bit of data selects which 256KB PRG block is in use.\r
126// This seems to be a hack on the developers' part, so I'll make emulation\r
127// of it a hack(I think the current PRG block would depend on whatever the\r
128// lowest bit of the CHR bank switching register that corresponds to the\r
129// last CHR address read).\r
130\r
131static void M153Power(void)\r
386f5371 132{\r
43725da7 133 BandaiSync();\r
134 setprg8r(0x10,0x6000,0);\r
135 SetReadHandler(0x6000,0x7FFF,CartBR);\r
136 SetWriteHandler(0x6000,0x7FFF,CartBW);\r
137 SetReadHandler(0x8000,0xFFFF,CartBR);\r
138 SetWriteHandler(0x8000,0xFFFF,BandaiWrite);\r
386f5371 139}\r
140\r
141\r
43725da7 142static void M153Close(void)\r
143{\r
144 if(WRAM)\r
145 FCEU_gfree(WRAM);\r
146 WRAM=NULL;\r
147}\r
148\r
386f5371 149void Mapper153_Init(CartInfo *info)\r
150{\r
151 is153=1;\r
152 info->Power=M153Power;\r
153 info->Close=M153Close;\r
154 MapIRQHook=BandaiIRQHook;\r
155\r
156 WRAMSIZE=8192;\r
157 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
158 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
159 AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
160\r
161 if(info->battery)\r
162 {\r
163 info->SaveGame[0]=WRAM;\r
164 info->SaveGameLen[0]=WRAMSIZE;\r
165 }\r
166\r
167 GameStateRestore=StateRestore;\r
168 AddExState(&StateRegs, ~0, 0, 0);\r
169}\r
43725da7 170\r
171// Datach Barcode Battler\r
172\r
173static uint8 BarcodeData[256];\r
174static int BarcodeReadPos;\r
175static int BarcodeCycleCount;\r
176static uint32 BarcodeOut;\r
177\r
178int FCEUI_DatachSet(const uint8 *rcode)\r
179{\r
180 int prefix_parity_type[10][6] = {\r
181 {0,0,0,0,0,0}, {0,0,1,0,1,1}, {0,0,1,1,0,1}, {0,0,1,1,1,0},\r
182 {0,1,0,0,1,1}, {0,1,1,0,0,1}, {0,1,1,1,0,0}, {0,1,0,1,0,1},\r
183 {0,1,0,1,1,0}, {0,1,1,0,1,0}\r
184 };\r
185 int data_left_odd[10][7] = {\r
186 {0,0,0,1,1,0,1}, {0,0,1,1,0,0,1}, {0,0,1,0,0,1,1}, {0,1,1,1,1,0,1},\r
187 {0,1,0,0,0,1,1}, {0,1,1,0,0,0,1}, {0,1,0,1,1,1,1}, {0,1,1,1,0,1,1},\r
188 {0,1,1,0,1,1,1}, {0,0,0,1,0,1,1}\r
189 };\r
190 int data_left_even[10][7] = {\r
191 {0,1,0,0,1,1,1}, {0,1,1,0,0,1,1}, {0,0,1,1,0,1,1}, {0,1,0,0,0,0,1},\r
192 {0,0,1,1,1,0,1}, {0,1,1,1,0,0,1}, {0,0,0,0,1,0,1}, {0,0,1,0,0,0,1},\r
193 {0,0,0,1,0,0,1}, {0,0,1,0,1,1,1}\r
194 };\r
195 int data_right[10][7] = {\r
196 {1,1,1,0,0,1,0}, {1,1,0,0,1,1,0}, {1,1,0,1,1,0,0}, {1,0,0,0,0,1,0},\r
197 {1,0,1,1,1,0,0}, {1,0,0,1,1,1,0}, {1,0,1,0,0,0,0}, {1,0,0,0,1,0,0},\r
198 {1,0,0,1,0,0,0}, {1,1,1,0,1,0,0}\r
199 };\r
200 uint8 code[13+1];\r
201 uint32 tmp_p=0;\r
202 int i, j;\r
203 int len;\r
204\r
205 for(i=len=0;i<13;i++)\r
206 {\r
207 if(!rcode[i]) break;\r
208 if((code[i]=rcode[i]-'0') > 9)\r
209 return(0);\r
210 len++;\r
211 }\r
212 if(len!=13 && len!=12 && len!=8 && len!=7) return(0);\r
213\r
214 #define BS(x) BarcodeData[tmp_p]=x;tmp_p++\r
215\r
216 for(j=0;j<32;j++)\r
217 {\r
218 BS(0x00);\r
219 }\r
220\r
221 /* Left guard bars */\r
222 BS(1); BS(0); BS(1);\r
223\r
224 if(len==13 || len==12)\r
225 {\r
226 uint32 csum;\r
227\r
228 for(i=0;i<6;i++)\r
229 if(prefix_parity_type[code[0]][i])\r
230 {\r
231 for(j=0;j<7;j++)\r
232 {\r
233 BS(data_left_even[code[i+1]][j]);\r
234 }\r
235 }\r
236 else\r
237 for(j=0;j<7;j++)\r
238 {\r
239 BS(data_left_odd[code[i+1]][j]);\r
240 }\r
241\r
242 /* Center guard bars */\r
243 BS(0); BS(1); BS(0); BS(1); BS(0);\r
244\r
245 for(i=7;i<12;i++)\r
246 for(j=0;j<7;j++)\r
247 {\r
248 BS(data_right[code[i]][j]);\r
249 }\r
250 csum=0;\r
251 for(i=0;i<12;i++) csum+=code[i]*((i&1)?3:1);\r
252 csum=(10-(csum%10))%10;\r
253 for(j=0;j<7;j++)\r
254 {\r
255 BS(data_right[csum][j]);\r
256 }\r
257\r
258 }\r
259 else if(len==8 || len==7)\r
260 {\r
261 uint32 csum=0;\r
262\r
263 for(i=0;i<7;i++) csum+=(i&1)?code[i]:(code[i]*3);\r
264\r
265 csum=(10-(csum%10))%10;\r
266\r
267 for(i=0;i<4;i++)\r
268 for(j=0;j<7;j++)\r
269 {\r
270 BS(data_left_odd[code[i]][j]);\r
271 }\r
272\r
273\r
274 /* Center guard bars */\r
275 BS(0); BS(1); BS(0); BS(1); BS(0);\r
276\r
277 for(i=4;i<7;i++)\r
278 for(j=0;j<7;j++)\r
279 {\r
280 BS(data_right[code[i]][j]);\r
281 }\r
282\r
283 for(j=0;j<7;j++)\r
284 { BS(data_right[csum][j]);}\r
285\r
286 }\r
287\r
288 /* Right guard bars */\r
289 BS(1); BS(0); BS(1);\r
290\r
291 for(j=0;j<32;j++)\r
292 {\r
293 BS(0x00);\r
294 }\r
295\r
296 BS(0xFF);\r
297\r
298 #undef BS\r
299\r
300 BarcodeReadPos=0;\r
301 BarcodeOut=0x8;\r
302 BarcodeCycleCount=0;\r
303 return(1);\r
304}\r
305\r
306static void FP_FASTAPASS(1) BarcodeIRQHook(int a)\r
307{\r
308 BandaiIRQHook(a);\r
309\r
310 BarcodeCycleCount+=a;\r
311\r
312 if(BarcodeCycleCount >= 1000)\r
313 {\r
314 BarcodeCycleCount -= 1000;\r
315 if(BarcodeData[BarcodeReadPos]==0xFF)\r
316 {\r
317 BarcodeOut=0;\r
318 }\r
319 else\r
320 {\r
321 BarcodeOut=(BarcodeData[BarcodeReadPos]^1)<<3;\r
322 BarcodeReadPos++;\r
323 }\r
324 }\r
325}\r
326\r
327static DECLFR(BarcodeRead)\r
328{\r
329 return BarcodeOut;\r
330}\r
331\r
332static void M157Power(void)\r
333{\r
334 BarcodeData[0]=0xFF;\r
335 BarcodeReadPos=0;\r
336 BarcodeOut=0;\r
337 BarcodeCycleCount=0;\r
338\r
339 BandaiSync();\r
340\r
341 SetWriteHandler(0x6000,0xFFFF,BandaiWrite);\r
342 SetReadHandler(0x6000,0x7FFF,BarcodeRead);\r
343 SetReadHandler(0x8000,0xFFFF,CartBR);\r
344}\r
345\r
346void Mapper157_Init(CartInfo *info)\r
347{\r
348 is153=0;\r
349 info->Power=M157Power;\r
350 MapIRQHook=BarcodeIRQHook;\r
351\r
ebde7d27 352 GameInfo->cspecial = SIS_DATACH;\r
43725da7 353\r
354 GameStateRestore=StateRestore;\r
355 AddExState(&StateRegs, ~0, 0, 0);\r
356}\r