merge mapper code from FCEUX
[fceu.git] / mappers / 16.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
d97315ac 5 * Copyright (C) 2002 Xodnizel
c62d2810 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
386f5371 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
c62d2810 20 */
21
22#include "mapinc.h"
23
386f5371 24static void BandaiIRQHook(int a)
c62d2810 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
39static 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;
e2d0dd92 59 case 0xB:IRQLatch&=0xFF00; IRQLatch|=V;
c62d2810 60 break;
e2d0dd92 61 case 0xC:IRQLatch&=0xFF; IRQLatch|=V<<8;
c62d2810 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).
386f5371 73/*
c62d2810 74static 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
81static DECLFW(Mapper153_write)
82{
d97315ac 83 A&=0xF;
c0bf6f9f 84 if(A<=0x7)
d97315ac 85 {
86 mapbyte1[A&7]=V;
87 PRGO();
88 }
c0bf6f9f 89 else if(A==0x8)
d97315ac 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;
c62d2810 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);
d97315ac 103 IRQa=V&1;
104 IRQCount=IRQLatch;
105 break;
c62d2810 106 case 0xB:IRQLatch&=0xFF00;
d97315ac 107 IRQLatch|=V;
108 break;
c62d2810 109 case 0xC:IRQLatch&=0xFF;
d97315ac 110 IRQLatch|=V<<8;
111 break;
c62d2810 112 }
386f5371 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);
c62d2810 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. */
386f5371 127//}
d97315ac 128
129
130static uint8 BarcodeData[256];
131static int BarcodeReadPos;
132static int BarcodeCycleCount;
133static uint32 BarcodeOut;
134
135int 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
386f5371 263static void BarcodeIRQHook(int a)
d97315ac 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
284static DECLFR(Mapper157_read)
285{
286 uint8 ret;
287
288 ret=BarcodeOut;
289 return(ret);
290}
291
292void Mapper157_init(void)
293{
386f5371 294 GameInfo->cspecial = SIS_DATACH;
d97315ac 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}