compat hacks for this old version of fceu
[fceu.git] / boards / bandai.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 2007 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
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * Bandai mappers\r
21  *\r
22  */\r
23 \r
24 #include "mapinc.h"\r
25 \r
26 static uint8 reg[16], is153;\r
27 static uint8 IRQa;\r
28 static int16 IRQCount, IRQLatch;\r
29 \r
30 static uint8 *WRAM=NULL;\r
31 static uint32 WRAMSIZE;\r
32 \r
33 static 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
42 static void FP_FASTAPASS(1) BandaiIRQHook(int a)\r
43 {\r
44   if(IRQa)\r
45   {\r
46     IRQCount-=a;\r
47     if(IRQCount<0)\r
48     {\r
49       X6502_IRQBegin(FCEU_IQEXT);\r
50       IRQa=0;\r
51       IRQCount=0xFFFF;\r
52     }\r
53   }\r
54 }\r
55 \r
56 static void BandaiSync(void)\r
57 {\r
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
65   if(is153)\r
66   {\r
67     int base=(reg[0]&1)<<4;\r
68     setprg16(0x8000,(reg[8]&0x0F)|base);\r
69     setprg16(0xC000,0x0F|base);\r
70   }\r
71   else\r
72   {\r
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
85 static 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
97       case 0x0B: IRQLatch&=0xFF00; IRQLatch|=V; break;\r
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
103 static void BandaiPower(void)\r
104 {\r
105   BandaiSync();\r
106   SetReadHandler(0x8000,0xFFFF,CartBR);\r
107   SetWriteHandler(0x6000,0xFFFF,BandaiWrite);\r
108 }\r
109 \r
110 static void StateRestore(int version)\r
111 {\r
112   BandaiSync();\r
113 }\r
114 \r
115 void 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
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
131 static void M153Power(void)\r
132 {\r
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
139 }\r
140 \r
141 \r
142 static void M153Close(void)\r
143 {\r
144   if(WRAM)\r
145     FCEU_gfree(WRAM);\r
146   WRAM=NULL;\r
147 }\r
148 \r
149 void 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
170 \r
171 // Datach Barcode Battler\r
172 \r
173 static uint8 BarcodeData[256];\r
174 static int BarcodeReadPos;\r
175 static int BarcodeCycleCount;\r
176 static uint32 BarcodeOut;\r
177 \r
178 int 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
306 static 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
327 static DECLFR(BarcodeRead)\r
328 {\r
329   return BarcodeOut;\r
330 }\r
331 \r
332 static 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
346 void Mapper157_Init(CartInfo *info)\r
347 {\r
348   is153=0;\r
349   info->Power=M157Power;\r
350   MapIRQHook=BarcodeIRQHook;\r
351 \r
352   GameInfo->cspecial = SIS_DATACH;\r
353 \r
354   GameStateRestore=StateRestore;\r
355   AddExState(&StateRegs, ~0, 0, 0);\r
356 }\r