c62d2810 |
1 | /* FCE Ultra - NES/Famicom Emulator |
2 | * |
3 | * Copyright notice for this file: |
4 | * Copyright (C) 2002 Ben Parnell |
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 |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ |
20 | |
21 | #include "mapinc.h" |
22 | //undef printf |
23 | |
24 | static int32 IRQCount,IRQLatch; |
25 | static uint8 IRQa,resetmode,mbia; |
26 | static uint8 sizer,bigbank,bigbank2; |
27 | |
28 | static uint8 DRegBuf[8],MMC3_cmd; |
29 | |
30 | static int masko8[8]={63,31,15,1,3,0,0,0}; |
31 | //static int masko1[8]={511,255,127,7,7,0,0,0}; |
32 | |
33 | static void swsetprg8(uint32 A, uint32 V) |
34 | { |
35 | V&=masko8[sizer&7]; |
36 | V|=(bigbank*2); |
37 | setprg8r((V/64)&15,A,V); |
38 | } |
39 | |
40 | static void swsetchr1(uint32 A, uint32 V) |
41 | { |
42 | if(sizer&0x20) |
43 | setchr1r(0x10,A,V); |
44 | else |
45 | { |
46 | // V&=masko1[sizer&7]; |
47 | V|=bigbank2*8; |
48 | setchr1r((V/512)&15,A,V); |
49 | } |
50 | } |
51 | |
52 | static void swsetchr2(uint32 A, uint32 V) |
53 | { |
54 | if(sizer&0x20) |
55 | setchr2r(0x10,A,V); |
56 | else |
57 | { |
58 | //V&=masko1[sizer&7]>>1; |
59 | V|=bigbank2*4; |
60 | setchr2r((V/256)&15,A,V); |
61 | } |
62 | } |
63 | |
64 | static void Sup24_hb(void) |
65 | { |
66 | if(ScreenON || SpriteON) |
67 | { |
68 | resetmode=0; |
69 | if(IRQCount>=0) |
70 | { |
71 | IRQCount--; |
72 | if(IRQCount<0) |
73 | { |
74 | if(IRQa) |
75 | { |
76 | resetmode = 1; |
77 | X6502_IRQBegin(FCEU_IQEXT); |
78 | } |
79 | } |
80 | } |
81 | } |
82 | } |
83 | |
84 | static DECLFW(Sup24IRQWrite) |
85 | { |
86 | switch(A&0xE001) |
87 | { |
88 | case 0xc000:IRQLatch=V; |
89 | if(resetmode==1) |
90 | IRQCount=IRQLatch; |
91 | break; |
92 | case 0xc001:resetmode=1; |
93 | IRQCount=IRQLatch; |
94 | break; |
95 | case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT); |
96 | if(resetmode==1) |
97 | {IRQCount=IRQLatch;} |
98 | break; |
99 | case 0xE001:IRQa=1; |
100 | if(resetmode==1) |
101 | {IRQCount=IRQLatch;} |
102 | break; |
103 | } |
104 | } |
105 | |
106 | static INLINE void FixMMC3PRG(int V) |
107 | { |
108 | swsetprg8(0xA000,DRegBuf[7]); |
109 | swsetprg8(0xE000,~0); |
110 | if(V&0x40) |
111 | { |
112 | swsetprg8(0xC000,DRegBuf[6]); |
113 | swsetprg8(0x8000,~1); |
114 | } |
115 | else |
116 | { |
117 | swsetprg8(0x8000,DRegBuf[6]); |
118 | swsetprg8(0xC000,~1); |
119 | } |
120 | } |
121 | |
122 | static INLINE void FixMMC3CHR(int V) |
123 | { |
124 | int cbase=(V&0x80)<<5; |
125 | swsetchr2((cbase^0x000),DRegBuf[0]>>1); |
126 | swsetchr2((cbase^0x800),DRegBuf[1]>>1); |
127 | swsetchr1(cbase^0x1000,DRegBuf[2]); |
128 | swsetchr1(cbase^0x1400,DRegBuf[3]); |
129 | swsetchr1(cbase^0x1800,DRegBuf[4]); |
130 | swsetchr1(cbase^0x1c00,DRegBuf[5]); |
131 | } |
132 | |
133 | static DECLFW(Super24hiwrite) |
134 | { |
135 | //printf("$%04x:$%02x, %d\n",A,V,scanline); |
136 | switch(A&0xE001) |
137 | { |
138 | case 0x8000: |
139 | if((V&0x40) != (MMC3_cmd&0x40)) |
140 | FixMMC3PRG(V); |
141 | if((V&0x80) != (MMC3_cmd&0x80)) |
142 | FixMMC3CHR(V); |
143 | MMC3_cmd = V; |
144 | break; |
145 | |
146 | case 0x8001: |
147 | { |
148 | int cbase=(MMC3_cmd&0x80)<<5; |
149 | DRegBuf[MMC3_cmd&0x7]=V; |
150 | switch(MMC3_cmd&0x07) |
151 | { |
152 | case 0: V>>=1;swsetchr2((cbase^0x000),V);break; |
153 | case 1: V>>=1;swsetchr2((cbase^0x800),V);break; |
154 | case 2: swsetchr1(cbase^0x1000,V); break; |
155 | case 3: swsetchr1(cbase^0x1400,V); break; |
156 | case 4: swsetchr1(cbase^0x1800,V); break; |
157 | case 5: swsetchr1(cbase^0x1C00,V); break; |
158 | case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V); |
159 | else swsetprg8(0x8000,V); |
160 | break; |
161 | case 7: swsetprg8(0xA000,V); |
162 | break; |
163 | } |
164 | } |
165 | break; |
166 | |
167 | case 0xA000: |
168 | mbia=V; |
169 | setmirror((V&1)^1); |
170 | break; |
171 | } |
172 | } |
173 | |
174 | |
175 | DECLFW(Super24Write) |
176 | { |
177 | //printf("$%04x:$%02x\n",A,V); |
178 | switch(A) |
179 | { |
180 | case 0x5ff0:sizer=V; |
181 | FixMMC3PRG(MMC3_cmd); |
182 | FixMMC3CHR(MMC3_cmd); |
183 | break; |
184 | case 0x5FF1: |
185 | bigbank=V; |
186 | FixMMC3PRG(MMC3_cmd); |
187 | break; |
188 | case 0x5FF2: |
189 | bigbank2=V; |
190 | FixMMC3CHR(MMC3_cmd); |
191 | break; |
192 | } |
193 | } |
194 | |
195 | static void Super24Reset(void) |
196 | { |
197 | SetWriteHandler(0x8000,0xBFFF,Super24hiwrite); |
198 | SetWriteHandler(0x5000,0x7FFF,Super24Write); |
199 | SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite); |
200 | SetReadHandler(0x8000,0xFFFF,CartBR); |
201 | GameHBIRQHook=Sup24_hb; |
202 | IRQCount=IRQLatch=IRQa=resetmode=0; |
203 | sizer=0x24; |
204 | bigbank=159; |
205 | bigbank2=0; |
206 | |
207 | MMC3_cmd=0; |
208 | DRegBuf[6]=0; |
209 | DRegBuf[7]=1; |
210 | |
211 | FixMMC3PRG(0); |
212 | FixMMC3CHR(0); |
213 | } |
214 | |
215 | static void MrRestore(int version) |
216 | { |
217 | FixMMC3PRG(MMC3_cmd); |
218 | FixMMC3CHR(MMC3_cmd); |
219 | setmirror((mbia&1)^1); |
220 | } |
221 | |
222 | void Super24_Init(void) |
223 | { |
224 | BoardPower=Super24Reset; |
225 | SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1); |
226 | GameStateRestore=MrRestore; |
227 | |
228 | AddExState(GameMemBlock, 8192, 0, "CHRR"); |
229 | AddExState(DRegBuf, 8, 0, "DREG"); |
230 | AddExState(&IRQCount, 4, 1, "IRQC"); |
231 | AddExState(&IRQLatch, 4, 1, "IQL1"); |
232 | AddExState(&IRQa, 1, 0, "IRQA"); |
233 | AddExState(&sizer, 1, 0, "SIZA"); |
234 | AddExState(&bigbank, 1, 0, "BIG1"); |
235 | AddExState(&bigbank2, 1, 0, "BIG2"); |
236 | } |