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 |
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; |
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). |
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 | { |
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 | } |
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 | } |
d97315ac |
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 FP_FASTAPASS(1) 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 | FCEUGameInfo.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 | } |