merge mapper code from FCEUX
[fceu.git] / mappers / 16.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 1998 BERO
5  *  Copyright (C) 2002 Xodnizel
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "mapinc.h"
23
24 static void BandaiIRQHook(int a)
25 {
26   if(IRQa)
27   {
28    IRQCount-=a;
29    if(IRQCount<0)
30    {
31     X6502_IRQBegin(FCEU_IQEXT);
32     //printf("IRQ: %d, %d\n",scanline,timestamp);
33     IRQa=0;
34     IRQCount=0xFFFF;
35    }
36   }
37 }
38
39 static DECLFW(Mapper16_write)
40 {
41         A&=0xF;
42
43         if(A<=0x7)
44          VROM_BANK1(A<<10,V);
45         else if(A==0x8)
46          ROM_BANK16(0x8000,V);
47         else switch(A) {
48          case 0x9: switch(V&3) {
49                     case 0x00:MIRROR_SET2(1);break;
50                     case 0x01:MIRROR_SET2(0);break;
51                     case 0x02:onemir(0);break;
52                     case 0x03:onemir(1);break;
53                    }
54                    break;
55          case 0xA:X6502_IRQEnd(FCEU_IQEXT);
56                   IRQa=V&1;
57                   IRQCount=IRQLatch;
58                   break;
59          case 0xB:IRQLatch&=0xFF00; IRQLatch|=V;
60                   break;
61          case 0xC:IRQLatch&=0xFF; IRQLatch|=V<<8;
62                   break;
63          case 0xD: break;/* Serial EEPROM control port */
64  }
65 }
66
67 // Famicom jump 2:
68 // 0-7: Lower bit of data selects which 256KB PRG block is in use.
69 // This seems to be a hack on the developers' part, so I'll make emulation
70 // of it a hack(I think the current PRG block would depend on whatever the
71 // lowest bit of the CHR bank switching register that corresponds to the
72 // last CHR address read).
73 /*
74 static void PRGO(void)
75 {
76  uint32 base=(mapbyte1[0]&1)<<4;
77  ROM_BANK16(0x8000,(mapbyte2[0]&0xF)|base);
78  ROM_BANK16(0xC000,base|0xF);
79 }
80
81 static DECLFW(Mapper153_write)
82 {
83         A&=0xF;
84         if(A<=0x7)
85         {
86          mapbyte1[A&7]=V;
87          PRGO();
88         }
89         else if(A==0x8)
90         {
91          mapbyte2[0]=V;
92          PRGO();
93         }
94         else switch(A) {
95          case 0x9: switch(V&3) {
96                            case 0x00:MIRROR_SET2(1);break;
97                     case 0x01:MIRROR_SET2(0);break;
98                     case 0x02:onemir(0);break;
99                     case 0x03:onemir(1);break;
100                    }
101                    break;
102          case 0xA:X6502_IRQEnd(FCEU_IQEXT);
103                     IRQa=V&1;
104                   IRQCount=IRQLatch;
105                   break;
106          case 0xB:IRQLatch&=0xFF00;
107                   IRQLatch|=V;
108                    break;
109          case 0xC:IRQLatch&=0xFF;
110                    IRQLatch|=V<<8;
111                   break;
112         }
113 }*/
114
115 //void Mapper16_init(void)
116 //{
117 // MapIRQHook=BandaiIRQHook;
118 //SetWriteHandler(0x6000,0xFFFF,Mapper16_write);
119 //}
120
121 //void Mapper153_init(void)
122 //{
123 // MapIRQHook=BandaiIRQHook;
124 // SetWriteHandler(0x8000,0xFFFF,Mapper153_write);
125  /* This mapper/board seems to have WRAM at $6000-$7FFF, so I'll let the
126     main ines code take care of that memory region. */
127 //}
128
129
130 static uint8 BarcodeData[256];
131 static int BarcodeReadPos;
132 static int BarcodeCycleCount;
133 static uint32 BarcodeOut;
134
135 int FCEUI_DatachSet(const uint8 *rcode)
136 {
137         int    prefix_parity_type[10][6] = {
138                 {0,0,0,0,0,0}, {0,0,1,0,1,1}, {0,0,1,1,0,1}, {0,0,1,1,1,0},
139                 {0,1,0,0,1,1}, {0,1,1,0,0,1}, {0,1,1,1,0,0}, {0,1,0,1,0,1},
140                 {0,1,0,1,1,0}, {0,1,1,0,1,0}
141         };
142         int    data_left_odd[10][7] = {
143                 {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},
144                 {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},
145                 {0,1,1,0,1,1,1}, {0,0,0,1,0,1,1}
146         };
147         int    data_left_even[10][7] = {
148                 {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},
149                 {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},
150                 {0,0,0,1,0,0,1}, {0,0,1,0,1,1,1}
151         };
152         int    data_right[10][7] = {
153                 {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},
154                 {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},
155                 {1,0,0,1,0,0,0}, {1,1,1,0,1,0,0}
156         };
157         uint8 code[13+1];
158         uint32 tmp_p=0;
159         int i, j;
160         int len;
161
162         for(i=len=0;i<13;i++)
163         {
164          if(!rcode[i]) break;
165
166          if((code[i]=rcode[i]-'0') > 9)
167           return(0);
168          len++;
169         }
170         if(len!=13 && len!=12 && len!=8 && len!=7) return(0);
171
172         #define BS(x) BarcodeData[tmp_p]=x;tmp_p++
173
174         for(j=0;j<32;j++)
175         {
176          BS(0x00);
177         }
178
179         /* Left guard bars */
180         BS(1);        BS(0); BS(1);
181
182         if(len==13 || len==12)
183         {
184          uint32 csum;
185
186           for(i=0;i<6;i++)
187           if(prefix_parity_type[code[0]][i])
188           {
189            for(j=0;j<7;j++)
190            {
191             BS(data_left_even[code[i+1]][j]);
192            }
193           }
194           else
195            for(j=0;j<7;j++)
196            {
197             BS(data_left_odd[code[i+1]][j]);
198            }
199
200          /* Center guard bars */
201          BS(0); BS(1); BS(0); BS(1); BS(0);
202
203          for(i=7;i<12;i++)
204           for(j=0;j<7;j++)
205           {
206            BS(data_right[code[i]][j]);
207           }
208          csum=0;
209          for(i=0;i<12;i++) csum+=code[i]*((i&1)?3:1);
210          csum=(10-(csum%10))%10;
211          //printf("%d\n",csum);
212          for(j=0;j<7;j++)
213          {
214           BS(data_right[csum][j]);
215          }
216
217         }
218         else if(len==8 || len==7)
219         {
220          uint32 csum=0;
221
222          for(i=0;i<7;i++) csum+=(i&1)?code[i]:(code[i]*3);
223
224          csum=(10-(csum%10))%10;
225
226          for(i=0;i<4;i++)
227           for(j=0;j<7;j++)
228           {
229            BS(data_left_odd[code[i]][j]);
230           }
231
232
233          /* Center guard bars */
234          BS(0); BS(1); BS(0); BS(1); BS(0);
235
236          for(i=4;i<7;i++)
237           for(j=0;j<7;j++)
238           {
239            BS(data_right[code[i]][j]);
240           }
241
242          for(j=0;j<7;j++)
243           { BS(data_right[csum][j]);}
244
245         }
246
247         /* Right guard bars */
248         BS(1); BS(0); BS(1);
249
250         for(j=0;j<32;j++)
251         {
252          BS(0x00);
253         }
254
255         BS(0xFF);
256         #undef BS
257         BarcodeReadPos=0;
258         BarcodeOut=0x8;
259         BarcodeCycleCount=0;
260         return(1);
261 }
262
263 static void BarcodeIRQHook(int a)
264 {
265  BandaiIRQHook(a);
266
267  BarcodeCycleCount+=a;
268
269  if(BarcodeCycleCount >= 1000)
270  {
271   BarcodeCycleCount -= 1000;
272   if(BarcodeData[BarcodeReadPos]==0xFF)
273   {
274    BarcodeOut=0;
275   }
276   else
277   {
278    BarcodeOut=(BarcodeData[BarcodeReadPos]^1)<<3;
279    BarcodeReadPos++;
280   }
281  }
282 }
283
284 static DECLFR(Mapper157_read)
285 {
286  uint8 ret;
287
288  ret=BarcodeOut;
289  return(ret);
290 }
291
292 void Mapper157_init(void)
293 {
294  GameInfo->cspecial = SIS_DATACH;
295  MapIRQHook=BarcodeIRQHook;
296  SetWriteHandler(0x6000,0xFFFF,Mapper16_write);
297  SetReadHandler(0x6000,0x7FFF,Mapper157_read);
298
299  BarcodeData[0]=0xFF;
300  BarcodeReadPos=0;
301  BarcodeOut=0;
302  BarcodeCycleCount=0;
303 }