fd922fbdd993c7c37209fbea5bf7fe814119f6e4
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "mapinc.h"
23
24 static void FP_FASTAPASS(1) 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;
60                   IRQLatch|=V;
61                   break;
62          case 0xC:IRQLatch&=0xFF;
63                   IRQLatch|=V<<8;
64                   break;
65          case 0xD: break;/* Serial EEPROM control port */
66  }
67 }
68
69 // Famicom jump 2:
70 // 0-7: Lower bit of data selects which 256KB PRG block is in use.
71 // This seems to be a hack on the developers' part, so I'll make emulation
72 // of it a hack(I think the current PRG block would depend on whatever the
73 // lowest bit of the CHR bank switching register that corresponds to the
74 // last CHR address read).
75
76 static void PRGO(void)
77 {
78  uint32 base=(mapbyte1[0]&1)<<4;
79  ROM_BANK16(0x8000,(mapbyte2[0]&0xF)|base);
80  ROM_BANK16(0xC000,base|0xF);
81 }
82
83 static DECLFW(Mapper153_write)
84 {
85         A&=0xF;
86         if(A<=0x7)
87         {
88          mapbyte1[A&7]=V;
89          PRGO();
90         }
91         else if(A==0x8)
92         {
93          mapbyte2[0]=V;
94          PRGO();
95         }
96         else switch(A) {
97          case 0x9: switch(V&3) {
98                            case 0x00:MIRROR_SET2(1);break;
99                     case 0x01:MIRROR_SET2(0);break;
100                     case 0x02:onemir(0);break;
101                     case 0x03:onemir(1);break;
102                    }
103                    break;
104          case 0xA:X6502_IRQEnd(FCEU_IQEXT);
105                     IRQa=V&1;
106                   IRQCount=IRQLatch;
107                   break;
108          case 0xB:IRQLatch&=0xFF00;
109                   IRQLatch|=V;
110                    break;
111          case 0xC:IRQLatch&=0xFF;
112                    IRQLatch|=V<<8;
113                   break;
114         }
115 }
116
117 void Mapper16_init(void)
118 {
119  MapIRQHook=BandaiIRQHook;
120  SetWriteHandler(0x6000,0xFFFF,Mapper16_write);
121 }
122
123 void Mapper153_init(void)
124 {
125  MapIRQHook=BandaiIRQHook;
126  SetWriteHandler(0x8000,0xFFFF,Mapper153_write);
127  /* This mapper/board seems to have WRAM at $6000-$7FFF, so I'll let the
128     main ines code take care of that memory region. */
129 }
130
131
132 static uint8 BarcodeData[256];
133 static int BarcodeReadPos;
134 static int BarcodeCycleCount;
135 static uint32 BarcodeOut;
136
137 int FCEUI_DatachSet(const uint8 *rcode)
138 {
139         int    prefix_parity_type[10][6] = {
140                 {0,0,0,0,0,0}, {0,0,1,0,1,1}, {0,0,1,1,0,1}, {0,0,1,1,1,0},
141                 {0,1,0,0,1,1}, {0,1,1,0,0,1}, {0,1,1,1,0,0}, {0,1,0,1,0,1},
142                 {0,1,0,1,1,0}, {0,1,1,0,1,0}
143         };
144         int    data_left_odd[10][7] = {
145                 {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},
146                 {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},
147                 {0,1,1,0,1,1,1}, {0,0,0,1,0,1,1}
148         };
149         int    data_left_even[10][7] = {
150                 {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},
151                 {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},
152                 {0,0,0,1,0,0,1}, {0,0,1,0,1,1,1}
153         };
154         int    data_right[10][7] = {
155                 {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},
156                 {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},
157                 {1,0,0,1,0,0,0}, {1,1,1,0,1,0,0}
158         };
159         uint8 code[13+1];
160         uint32 tmp_p=0;
161         int i, j;
162         int len;
163
164         for(i=len=0;i<13;i++)
165         {
166          if(!rcode[i]) break;
167
168          if((code[i]=rcode[i]-'0') > 9)
169           return(0);
170          len++;
171         }
172         if(len!=13 && len!=12 && len!=8 && len!=7) return(0);
173
174         #define BS(x) BarcodeData[tmp_p]=x;tmp_p++
175
176         for(j=0;j<32;j++)
177         {
178          BS(0x00);
179         }
180
181         /* Left guard bars */
182         BS(1);        BS(0); BS(1);
183
184         if(len==13 || len==12)
185         {
186          uint32 csum;
187
188           for(i=0;i<6;i++)
189           if(prefix_parity_type[code[0]][i])
190           {
191            for(j=0;j<7;j++)
192            {
193             BS(data_left_even[code[i+1]][j]);
194            }
195           }
196           else
197            for(j=0;j<7;j++)
198            {
199             BS(data_left_odd[code[i+1]][j]);
200            }
201
202          /* Center guard bars */
203          BS(0); BS(1); BS(0); BS(1); BS(0);
204
205          for(i=7;i<12;i++)
206           for(j=0;j<7;j++)
207           {
208            BS(data_right[code[i]][j]);
209           }
210          csum=0;
211          for(i=0;i<12;i++) csum+=code[i]*((i&1)?3:1);
212          csum=(10-(csum%10))%10;
213          //printf("%d\n",csum);
214          for(j=0;j<7;j++)
215          {
216           BS(data_right[csum][j]);
217          }
218
219         }
220         else if(len==8 || len==7)
221         {
222          uint32 csum=0;
223
224          for(i=0;i<7;i++) csum+=(i&1)?code[i]:(code[i]*3);
225
226          csum=(10-(csum%10))%10;
227
228          for(i=0;i<4;i++)
229           for(j=0;j<7;j++)
230           {
231            BS(data_left_odd[code[i]][j]);
232           }
233
234
235          /* Center guard bars */
236          BS(0); BS(1); BS(0); BS(1); BS(0);
237
238          for(i=4;i<7;i++)
239           for(j=0;j<7;j++)
240           {
241            BS(data_right[code[i]][j]);
242           }
243
244          for(j=0;j<7;j++)
245           { BS(data_right[csum][j]);}
246
247         }
248
249         /* Right guard bars */
250         BS(1); BS(0); BS(1);
251
252         for(j=0;j<32;j++)
253         {
254          BS(0x00);
255         }
256
257         BS(0xFF);
258         #undef BS
259         BarcodeReadPos=0;
260         BarcodeOut=0x8;
261         BarcodeCycleCount=0;
262         return(1);
263 }
264
265 static void FP_FASTAPASS(1) BarcodeIRQHook(int a)
266 {
267  BandaiIRQHook(a);
268
269  BarcodeCycleCount+=a;
270
271  if(BarcodeCycleCount >= 1000)
272  {
273   BarcodeCycleCount -= 1000;
274   if(BarcodeData[BarcodeReadPos]==0xFF)
275   {
276    BarcodeOut=0;
277   }
278   else
279   {
280    BarcodeOut=(BarcodeData[BarcodeReadPos]^1)<<3;
281    BarcodeReadPos++;
282   }
283  }
284 }
285
286 static DECLFR(Mapper157_read)
287 {
288  uint8 ret;
289
290  ret=BarcodeOut;
291  return(ret);
292 }
293
294 void Mapper157_init(void)
295 {
296  FCEUGameInfo.cspecial = SIS_DATACH;
297  MapIRQHook=BarcodeIRQHook;
298  SetWriteHandler(0x6000,0xFFFF,Mapper16_write);
299  SetReadHandler(0x6000,0x7FFF,Mapper157_read);
300
301  BarcodeData[0]=0xFF;
302  BarcodeReadPos=0;
303  BarcodeOut=0;
304  BarcodeCycleCount=0;
305 }