c62d2810 |
1 | /* FCE Ultra - NES/Famicom Emulator |
2 | * |
3 | * Copyright notice for this file: |
d97315ac |
4 | * Copyright (C) 2002 Xodnizel |
c62d2810 |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software |
43725da7 |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
c62d2810 |
19 | */ |
20 | |
21 | #include "mapinc.h" |
22 | |
386f5371 |
23 | static uint8 cmd, dip; |
c62d2810 |
24 | static uint8 latch[8]; |
d97315ac |
25 | |
e2d0dd92 |
26 | static void S74LS374MSync(uint8 mirr) |
d97315ac |
27 | { |
28 | switch(mirr&3) |
29 | { |
30 | case 0:setmirror(MI_V);break; |
31 | case 1:setmirror(MI_H);break; |
32 | case 2:setmirrorw(0,1,1,1);break; |
33 | case 3:setmirror(MI_0);break; |
34 | } |
35 | } |
c62d2810 |
36 | |
37 | static void S74LS374NSynco(void) |
38 | { |
d97315ac |
39 | setprg32(0x8000,latch[0]); |
40 | setchr8(latch[1]|latch[3]|latch[4]); |
e2d0dd92 |
41 | S74LS374MSync(latch[2]); |
c62d2810 |
42 | } |
43 | |
44 | static DECLFW(S74LS374NWrite) |
45 | { |
d97315ac |
46 | A&=0x4101; |
47 | if(A==0x4100) |
48 | cmd=V&7; |
49 | else |
c62d2810 |
50 | { |
d97315ac |
51 | switch(cmd) |
52 | { |
e2d0dd92 |
53 | case 2:latch[0]=V&1; latch[3]=(V&1)<<3;break; |
d97315ac |
54 | case 4:latch[4]=(V&1)<<2;break; |
e2d0dd92 |
55 | case 5:latch[0]=V&7;break; |
d97315ac |
56 | case 6:latch[1]=V&3;break; |
57 | case 7:latch[2]=V>>1;break; |
58 | } |
59 | S74LS374NSynco(); |
c62d2810 |
60 | } |
c62d2810 |
61 | } |
62 | |
e2d0dd92 |
63 | static DECLFR(S74LS374NRead) |
64 | { |
65 | uint8 ret; |
66 | if((A&0x4100)==0x4100) |
386f5371 |
67 | // ret=(X.DB&0xC0)|((~cmd)&0x3F); |
68 | ret=((~cmd)&0x3F)^dip; |
e2d0dd92 |
69 | else |
70 | ret=X.DB; |
71 | return ret; |
72 | } |
73 | |
d97315ac |
74 | static void S74LS374NPower(void) |
c62d2810 |
75 | { |
386f5371 |
76 | dip=0; |
d97315ac |
77 | latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0; |
78 | S74LS374NSynco(); |
79 | SetReadHandler(0x8000,0xFFFF,CartBR); |
80 | SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite); |
e2d0dd92 |
81 | SetReadHandler(0x4100,0x5fff,S74LS374NRead); |
c62d2810 |
82 | } |
83 | |
386f5371 |
84 | static void S74LS374NReset(void) |
85 | { |
86 | dip^=1; |
87 | latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0; |
88 | S74LS374NSynco(); |
89 | } |
90 | |
c62d2810 |
91 | static void S74LS374NRestore(int version) |
92 | { |
d97315ac |
93 | S74LS374NSynco(); |
c62d2810 |
94 | } |
95 | |
d97315ac |
96 | void S74LS374N_Init(CartInfo *info) |
c62d2810 |
97 | { |
d97315ac |
98 | info->Power=S74LS374NPower; |
386f5371 |
99 | info->Reset=S74LS374NReset; |
d97315ac |
100 | GameStateRestore=S74LS374NRestore; |
101 | AddExState(latch, 5, 0, "LATC"); |
102 | AddExState(&cmd, 1, 0, "CMD"); |
386f5371 |
103 | AddExState(&dip, 1, 0, "DIP"); |
c62d2810 |
104 | } |
105 | |
d97315ac |
106 | static void S74LS374NASynco(void) |
c62d2810 |
107 | { |
d97315ac |
108 | setprg32(0x8000,latch[0]); |
109 | setchr8(latch[1]); |
e2d0dd92 |
110 | S74LS374MSync(latch[2]); |
d97315ac |
111 | } |
c62d2810 |
112 | |
d97315ac |
113 | static DECLFW(S74LS374NAWrite) |
114 | { |
115 | A&=0x4101; |
116 | if(A==0x4100) |
117 | cmd=V&7; |
118 | else |
c62d2810 |
119 | { |
d97315ac |
120 | switch(cmd) |
121 | { |
122 | case 0:latch[0]=0;latch[1]=3;break; |
123 | case 2:latch[3]=(V&1)<<3;break; |
124 | case 4:latch[1]=(latch[1]&6)|(V&3);break; |
125 | case 5:latch[0]=V&1;break; |
126 | case 6:latch[1]=(latch[1]&1)|latch[3]|((V&3)<<1);break; |
127 | case 7:latch[2]=V&1;break; |
128 | } |
e2d0dd92 |
129 | S74LS374NASynco(); |
c62d2810 |
130 | } |
d97315ac |
131 | } |
132 | |
133 | static void S74LS374NAPower(void) |
134 | { |
135 | latch[0]=latch[2]=latch[3]=latch[4]=0; |
136 | latch[1]=3; |
137 | S74LS374NASynco(); |
138 | SetReadHandler(0x8000,0xFFFF,CartBR); |
139 | SetWriteHandler(0x4100,0x7FFF,S74LS374NAWrite); |
140 | } |
141 | |
142 | void S74LS374NA_Init(CartInfo *info) |
143 | { |
144 | info->Power=S74LS374NAPower; |
145 | GameStateRestore=S74LS374NRestore; |
146 | AddExState(latch, 5, 0, "LATC"); |
147 | AddExState(&cmd, 1, 0, "CMD"); |
148 | } |
149 | |
150 | static int type; |
d97315ac |
151 | static void S8259Synco(void) |
152 | { |
153 | int x; |
154 | setprg32(0x8000,latch[5]&7); |
155 | |
156 | if(!UNIFchrrama) // No CHR RAM? Then BS'ing is ok. |
c62d2810 |
157 | { |
d97315ac |
158 | for(x=0;x<4;x++) |
159 | { |
160 | int bank; |
161 | if(latch[7]&1) |
162 | bank=(latch[0]&0x7)|((latch[4]&7)<<3); |
163 | else |
164 | bank=(latch[x]&0x7)|((latch[4]&7)<<3); |
165 | switch (type) |
166 | { |
167 | case 00: bank=(bank<<1)|(x&1); setchr2(0x800*x,bank); break; |
168 | case 01: setchr2(0x800*x,bank); break; |
169 | case 02: bank=(bank<<2)|(x&3); setchr2(0x800*x,bank); break; |
170 | case 03: bank=latch[x]&7; |
171 | switch (x&3) |
172 | { |
173 | case 01: bank|=(latch[4]&1)<<4;break; |
174 | case 02: bank|=(latch[4]&2)<<3;break; |
175 | case 03: bank|=((latch[4]&4)<<2)|((latch[6]&1)<<3);break; |
176 | } |
177 | setchr1(0x400*x,bank); |
178 | setchr4(0x1000,~0); |
179 | break; |
180 | } |
181 | } |
c62d2810 |
182 | } |
e2d0dd92 |
183 | if(!(latch[7]&1)) |
184 | S74LS374MSync(latch[7]>>1); |
185 | else |
186 | setmirror(MI_V); |
c62d2810 |
187 | } |
188 | |
189 | static DECLFW(S8259Write) |
190 | { |
d97315ac |
191 | A&=0x4101; |
192 | if(A==0x4100) |
193 | cmd=V; |
194 | else |
195 | { |
196 | latch[cmd&7]=V; |
197 | S8259Synco(); |
198 | } |
c62d2810 |
199 | } |
200 | |
201 | static void S8259Reset(void) |
202 | { |
d97315ac |
203 | int x; |
204 | cmd=0; |
c62d2810 |
205 | |
d97315ac |
206 | for(x=0;x<8;x++) latch[x]=0; |
207 | setchr8(0); |
c62d2810 |
208 | |
d97315ac |
209 | S8259Synco(); |
210 | SetReadHandler(0x8000,0xFFFF,CartBR); |
211 | SetWriteHandler(0x4100,0x7FFF,S8259Write); |
c62d2810 |
212 | } |
213 | |
214 | static void S8259Restore(int version) |
215 | { |
d97315ac |
216 | S8259Synco(); |
217 | } |
218 | |
219 | void S8259A_Init(CartInfo *info) // Kevin's Horton 141 mapper |
220 | { |
221 | info->Power=S8259Reset; |
222 | GameStateRestore=S8259Restore; |
223 | AddExState(latch, 8, 0, "LATC"); |
224 | AddExState(&cmd, 1, 0, "CMD"); |
225 | type=0; |
c62d2810 |
226 | } |
227 | |
d97315ac |
228 | void S8259B_Init(CartInfo *info) // Kevin's Horton 138 mapper |
c62d2810 |
229 | { |
d97315ac |
230 | info->Power=S8259Reset; |
231 | GameStateRestore=S8259Restore; |
232 | AddExState(latch, 8, 0, "LATC"); |
233 | AddExState(&cmd, 1, 0, "CMD"); |
234 | type=1; |
235 | } |
c62d2810 |
236 | |
d97315ac |
237 | void S8259C_Init(CartInfo *info) // Kevin's Horton 139 mapper |
238 | { |
239 | info->Power=S8259Reset; |
240 | GameStateRestore=S8259Restore; |
241 | AddExState(latch, 8, 0, "LATC"); |
242 | AddExState(&cmd, 1, 0, "CMD"); |
243 | type=2; |
c62d2810 |
244 | } |
245 | |
d97315ac |
246 | void S8259D_Init(CartInfo *info) // Kevin's Horton 137 mapper |
c62d2810 |
247 | { |
d97315ac |
248 | info->Power=S8259Reset; |
249 | GameStateRestore=S8259Restore; |
250 | AddExState(latch, 8, 0, "LATC"); |
251 | AddExState(&cmd, 1, 0, "CMD"); |
252 | type=3; |
c62d2810 |
253 | } |
254 | |
255 | static void(*WSync)(void); |
256 | |
c62d2810 |
257 | static DECLFW(SAWrite) |
258 | { |
d97315ac |
259 | if(A&0x100) |
260 | { |
261 | latch[0]=V; |
262 | WSync(); |
263 | } |
c62d2810 |
264 | } |
265 | |
e2d0dd92 |
266 | static void SAPower(void) |
c62d2810 |
267 | { |
d97315ac |
268 | latch[0]=0; |
269 | WSync(); |
270 | SetReadHandler(0x8000,0xFFFF,CartBR); |
271 | SetWriteHandler(0x4100,0x5FFF,SAWrite); |
c62d2810 |
272 | } |
273 | |
e2d0dd92 |
274 | static void SARestore(int version) |
c62d2810 |
275 | { |
e2d0dd92 |
276 | WSync(); |
d97315ac |
277 | } |
278 | |
e2d0dd92 |
279 | static DECLFW(SADWrite) |
d97315ac |
280 | { |
e2d0dd92 |
281 | latch[0]=V; |
282 | WSync(); |
c62d2810 |
283 | } |
284 | |
e2d0dd92 |
285 | static void SADPower(void) |
c62d2810 |
286 | { |
e2d0dd92 |
287 | latch[0]=0; |
288 | WSync(); |
289 | SetReadHandler(0x8000,0xFFFF,CartBR); |
290 | SetWriteHandler(0x8000,0xFFFF,SADWrite); |
d97315ac |
291 | } |
292 | |
e2d0dd92 |
293 | static void SA0161MSynco() |
d97315ac |
294 | { |
e2d0dd92 |
295 | setprg32(0x8000,(latch[0]>>3)&1); |
296 | setchr8(latch[0]&7); |
c62d2810 |
297 | } |
298 | |
e2d0dd92 |
299 | static void SA72007Synco() |
c62d2810 |
300 | { |
e2d0dd92 |
301 | setprg32(0x8000,0); |
302 | setchr8(latch[0]>>7); |
c62d2810 |
303 | } |
304 | |
386f5371 |
305 | static void SA009Synco() |
306 | { |
307 | setprg32(0x8000,0); |
308 | setchr8(latch[0]&1); |
309 | } |
310 | |
c62d2810 |
311 | static void SA72008Synco() |
312 | { |
d97315ac |
313 | setprg32(0x8000,(latch[0]>>2)&1); |
314 | setchr8(latch[0]&3); |
c62d2810 |
315 | } |
316 | |
e2d0dd92 |
317 | void SA0161M_Init(CartInfo *info) |
d97315ac |
318 | { |
e2d0dd92 |
319 | WSync=SA0161MSynco; |
320 | GameStateRestore=SARestore; |
321 | info->Power=SAPower; |
d97315ac |
322 | AddExState(&latch[0], 1, 0, "LATC"); |
c62d2810 |
323 | } |
324 | |
e2d0dd92 |
325 | void SA72007_Init(CartInfo *info) |
c62d2810 |
326 | { |
e2d0dd92 |
327 | WSync=SA72007Synco; |
328 | GameStateRestore=SARestore; |
329 | info->Power=SAPower; |
330 | AddExState(&latch[0], 1, 0, "LATC"); |
c62d2810 |
331 | } |
332 | |
e2d0dd92 |
333 | void SA72008_Init(CartInfo *info) |
c62d2810 |
334 | { |
e2d0dd92 |
335 | WSync=SA72008Synco; |
336 | GameStateRestore=SARestore; |
337 | info->Power=SAPower; |
338 | AddExState(&latch[0], 1, 0, "LATC"); |
c62d2810 |
339 | } |
340 | |
386f5371 |
341 | void SA009_Init(CartInfo *info) |
342 | { |
343 | WSync=SA009Synco; |
344 | GameStateRestore=SARestore; |
345 | info->Power=SAPower; |
346 | AddExState(&latch[0], 1, 0, "LATC"); |
347 | } |
348 | |
d97315ac |
349 | void SA0036_Init(CartInfo *info) |
c62d2810 |
350 | { |
d97315ac |
351 | WSync=SA72007Synco; |
e2d0dd92 |
352 | GameStateRestore=SARestore; |
353 | info->Power=SADPower; |
d97315ac |
354 | AddExState(&latch[0], 1, 0, "LATC"); |
c62d2810 |
355 | } |
356 | |
d97315ac |
357 | void SA0037_Init(CartInfo *info) |
c62d2810 |
358 | { |
e2d0dd92 |
359 | WSync=SA0161MSynco; |
360 | GameStateRestore=SARestore; |
361 | info->Power=SADPower; |
d97315ac |
362 | AddExState(&latch[0], 1, 0, "LATC"); |
c62d2810 |
363 | } |
364 | |
386f5371 |
365 | // ----------------------------------------------- |
366 | |
c62d2810 |
367 | static void TCU01Synco() |
368 | { |
386f5371 |
369 | setprg32(0x8000,((latch[0]&0x80)>>6)|((latch[0]>>2)&1)); |
d97315ac |
370 | setchr8((latch[0]>>3)&0xF); |
c62d2810 |
371 | } |
372 | |
386f5371 |
373 | static DECLFW(TCU01Write) |
c62d2810 |
374 | { |
d97315ac |
375 | if((A&0x103)==0x102) |
e2d0dd92 |
376 | { |
d97315ac |
377 | latch[0]=V; |
e2d0dd92 |
378 | TCU01Synco(); |
379 | } |
c62d2810 |
380 | } |
381 | |
386f5371 |
382 | static void TCU01Power(void) |
c62d2810 |
383 | { |
d97315ac |
384 | latch[0]=0; |
385 | SetReadHandler(0x8000,0xFFFF,CartBR); |
386f5371 |
386 | SetWriteHandler(0x4100,0xFFFF,TCU01Write); |
d97315ac |
387 | TCU01Synco(); |
c62d2810 |
388 | } |
389 | |
d97315ac |
390 | static void TCU01Restore(int version) |
c62d2810 |
391 | { |
d97315ac |
392 | TCU01Synco(); |
c62d2810 |
393 | } |
394 | |
d97315ac |
395 | void TCU01_Init(CartInfo *info) |
396 | { |
397 | GameStateRestore=TCU01Restore; |
386f5371 |
398 | info->Power=TCU01Power; |
d97315ac |
399 | AddExState(&latch[0], 1, 0, "LATC"); |
400 | } |
401 | |
386f5371 |
402 | //----------------------------------------------- |
403 | |
404 | static void TCU02Synco() |
405 | { |
406 | setprg32(0x8000,0); |
407 | setchr8(latch[0]&3); |
408 | } |
409 | |
410 | static DECLFW(TCU02Write) |
411 | { |
412 | if((A&0x103)==0x102) |
413 | { |
414 | latch[0]=V+3; |
415 | TCU02Synco(); |
416 | } |
417 | } |
418 | |
419 | static DECLFR(TCU02Read) |
420 | { |
421 | return (latch[0]&0x3F)|(X.DB&0xC0); |
422 | } |
423 | |
424 | static void TCU02Power(void) |
425 | { |
426 | latch[0]=0; |
427 | SetReadHandler(0x8000,0xFFFF,CartBR); |
428 | SetReadHandler(0x4100,0x4100,TCU02Read); |
429 | SetWriteHandler(0x4100,0xFFFF,TCU02Write); |
430 | TCU02Synco(); |
431 | } |
432 | |
433 | static void TCU02Restore(int version) |
434 | { |
435 | TCU02Synco(); |
436 | } |
437 | |
438 | void TCU02_Init(CartInfo *info) |
439 | { |
440 | GameStateRestore=TCU02Restore; |
441 | info->Power=TCU02Power; |
442 | AddExState(&latch[0], 1, 0, "LATC"); |
443 | } |
444 | |
445 | // --------------------------------------------- |
446 | |
d97315ac |
447 | static DECLFR(TCA01Read) |
448 | { |
449 | uint8 ret; |
450 | if((A&0x4100)==0x4100) |
451 | ret=(X.DB&0xC0)|((~A)&0x3F); |
452 | else |
453 | ret=X.DB; |
454 | return ret; |
455 | } |
456 | |
386f5371 |
457 | static void TCA01Power(void) |
d97315ac |
458 | { |
459 | setprg16(0x8000,0); |
460 | setprg16(0xC000,1); |
461 | setchr8(0); |
462 | SetReadHandler(0x8000,0xFFFF,CartBR); |
463 | SetReadHandler(0x4100,0x5FFF,TCA01Read); |
464 | } |
465 | |
466 | void TCA01_Init(CartInfo *info) |
467 | { |
386f5371 |
468 | info->Power=TCA01Power; |
d97315ac |
469 | } |
e2d0dd92 |
470 | |