Mercurial > vba-linux
comparison src/gb/GB.cpp @ 33:44974c3e093b
found source of problem for video recording
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 05 Mar 2012 01:25:11 -0600 |
parents | f9f4f1b99eed |
children | 3e36553d0cbf |
comparison
equal
deleted
inserted
replaced
32:0dc331ec7f27 | 33:44974c3e093b |
---|---|
161 | 161 |
162 static bool newFrame = true; | 162 static bool newFrame = true; |
163 static bool pauseAfterFrameAdvance = false; | 163 static bool pauseAfterFrameAdvance = false; |
164 | 164 |
165 int32 gbRomSizes[] = { 0x00008000, // 32K | 165 int32 gbRomSizes[] = { 0x00008000, // 32K |
166 0x00010000, // 64K | 166 0x00010000, // 64K |
167 0x00020000, // 128K | 167 0x00020000, // 128K |
168 0x00040000, // 256K | 168 0x00040000, // 256K |
169 0x00080000, // 512K | 169 0x00080000, // 512K |
170 0x00100000, // 1024K | 170 0x00100000, // 1024K |
171 0x00200000, // 2048K | 171 0x00200000, // 2048K |
172 0x00400000, // 4096K | 172 0x00400000, // 4096K |
173 0x00800000 // 8192K | 173 0x00800000 // 8192K |
174 }; | 174 }; |
175 int32 gbRomSizesMasks[] = { 0x00007fff, | 175 int32 gbRomSizesMasks[] = { 0x00007fff, |
176 0x0000ffff, | 176 0x0000ffff, |
177 0x0001ffff, | 177 0x0001ffff, |
178 0x0003ffff, | 178 0x0003ffff, |
179 0x0007ffff, | 179 0x0007ffff, |
180 0x000fffff, | 180 0x000fffff, |
181 0x001fffff, | 181 0x001fffff, |
182 0x003fffff, | 182 0x003fffff, |
183 0x007fffff }; | 183 0x007fffff }; |
184 | 184 |
185 int32 gbRamSizes[6] = { 0x00000000, // 0K | 185 int32 gbRamSizes[6] = { 0x00000000, // 0K |
186 0x00000800, // 2K | 186 0x00000800, // 2K |
187 0x00002000, // 8K | 187 0x00002000, // 8K |
188 0x00008000, // 32K | 188 0x00008000, // 32K |
189 0x00020000, // 128K | 189 0x00020000, // 128K |
190 0x00010000 // 64K | 190 0x00010000 // 64K |
191 }; | 191 }; |
192 | 192 |
193 int32 gbRamSizesMasks[6] = { 0x00000000, | 193 int32 gbRamSizesMasks[6] = { 0x00000000, |
194 0x000007ff, | 194 0x000007ff, |
195 0x00001fff, | 195 0x00001fff, |
196 0x00007fff, | 196 0x00007fff, |
197 0x0001ffff, | 197 0x0001ffff, |
198 0x0000ffff }; | 198 0x0000ffff }; |
199 | 199 |
200 int32 gbCycles[] = | 200 int32 gbCycles[] = |
201 { | 201 { |
202 // 0 1 2 3 4 5 6 7 8 9 a b c d e f | 202 // 0 1 2 3 4 5 6 7 8 9 a b c d e f |
203 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0 | 203 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0 |
204 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1 | 204 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1 |
205 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2 | 205 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2 |
206 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3 | 206 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3 |
207 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4 | 207 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4 |
208 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5 | 208 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5 |
209 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6 | 209 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6 |
210 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7 | 210 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7 |
211 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8 | 211 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8 |
212 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9 | 212 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9 |
213 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a | 213 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a |
214 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b | 214 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b |
215 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c | 215 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c |
216 2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4, // d | 216 2, 3, 3, 0, 3, 4, 2, 4, 2, 4, 3, 0, 3, 0, 2, 4, // d |
217 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, // e | 217 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4, // e |
218 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f | 218 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f |
219 }; | 219 }; |
220 | 220 |
221 int32 gbCyclesCB[] = | 221 int32 gbCyclesCB[] = |
222 { | 222 { |
223 // 0 1 2 3 4 5 6 7 8 9 a b c d e f | 223 // 0 1 2 3 4 5 6 7 8 9 a b c d e f |
224 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0 | 224 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0 |
225 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1 | 225 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1 |
226 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2 | 226 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2 |
227 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3 | 227 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3 |
228 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4 | 228 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4 |
229 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5 | 229 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5 |
230 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6 | 230 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6 |
231 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7 | 231 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7 |
232 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 8 | 232 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 8 |
233 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 9 | 233 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 9 |
234 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // a | 234 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // a |
235 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // b | 235 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // b |
236 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // c | 236 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // c |
237 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // d | 237 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // d |
238 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // e | 238 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // e |
239 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f | 239 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f |
240 }; | 240 }; |
241 | 241 |
242 u16 DAATable[] = | 242 u16 DAATable[] = |
243 { | 243 { |
244 0x0080, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, | 244 0x0080, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, |
245 0x0800, 0x0900, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, | 245 0x0800, 0x0900, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, |
246 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, | 246 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, |
247 0x1800, 0x1900, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, | 247 0x1800, 0x1900, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, |
248 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, | 248 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, |
249 0x2800, 0x2900, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, | 249 0x2800, 0x2900, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, |
250 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, | 250 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, |
251 0x3800, 0x3900, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, | 251 0x3800, 0x3900, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, |
252 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, | 252 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, |
253 0x4800, 0x4900, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, | 253 0x4800, 0x4900, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, |
254 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, | 254 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, |
255 0x5800, 0x5900, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, | 255 0x5800, 0x5900, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, |
256 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, | 256 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, |
257 0x6800, 0x6900, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, | 257 0x6800, 0x6900, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, |
258 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, | 258 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, |
259 0x7800, 0x7900, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, | 259 0x7800, 0x7900, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, |
260 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, | 260 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, |
261 0x8800, 0x8900, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, | 261 0x8800, 0x8900, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, |
262 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, | 262 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, |
263 0x9800, 0x9900, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | 263 0x9800, 0x9900, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, |
264 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, | 264 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, |
265 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | 265 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, |
266 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, | 266 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, |
267 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | 267 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, |
268 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, | 268 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, |
269 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | 269 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, |
270 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, | 270 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, |
271 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | 271 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, |
272 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, | 272 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, |
273 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | 273 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, |
274 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, | 274 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, |
275 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | 275 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, |
276 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510, 0x6610, 0x6710, | 276 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510, 0x6610, 0x6710, |
277 0x6810, 0x6910, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, | 277 0x6810, 0x6910, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, |
278 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510, 0x7610, 0x7710, | 278 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510, 0x7610, 0x7710, |
279 0x7810, 0x7910, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, | 279 0x7810, 0x7910, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, |
280 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510, 0x8610, 0x8710, | 280 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510, 0x8610, 0x8710, |
281 0x8810, 0x8910, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, | 281 0x8810, 0x8910, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, |
282 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510, 0x9610, 0x9710, | 282 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510, 0x9610, 0x9710, |
283 0x9810, 0x9910, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, | 283 0x9810, 0x9910, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, |
284 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510, 0xA610, 0xA710, | 284 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510, 0xA610, 0xA710, |
285 0xA810, 0xA910, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, | 285 0xA810, 0xA910, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, |
286 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510, 0xB610, 0xB710, | 286 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510, 0xB610, 0xB710, |
287 0xB810, 0xB910, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, | 287 0xB810, 0xB910, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, |
288 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510, 0xC610, 0xC710, | 288 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510, 0xC610, 0xC710, |
289 0xC810, 0xC910, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, | 289 0xC810, 0xC910, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, |
290 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510, 0xD610, 0xD710, | 290 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510, 0xD610, 0xD710, |
291 0xD810, 0xD910, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, | 291 0xD810, 0xD910, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, |
292 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510, 0xE610, 0xE710, | 292 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510, 0xE610, 0xE710, |
293 0xE810, 0xE910, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, | 293 0xE810, 0xE910, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, |
294 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510, 0xF610, 0xF710, | 294 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510, 0xF610, 0xF710, |
295 0xF810, 0xF910, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | 295 0xF810, 0xF910, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, |
296 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, | 296 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, |
297 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | 297 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, |
298 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, | 298 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, |
299 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | 299 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, |
300 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, | 300 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, |
301 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | 301 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, |
302 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, | 302 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, |
303 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | 303 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, |
304 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, | 304 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, |
305 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | 305 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, |
306 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, | 306 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, |
307 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | 307 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, |
308 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, | 308 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, |
309 0x0E00, 0x0F00, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, | 309 0x0E00, 0x0F00, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, |
310 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, | 310 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, |
311 0x1E00, 0x1F00, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, | 311 0x1E00, 0x1F00, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, |
312 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, | 312 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, |
313 0x2E00, 0x2F00, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, | 313 0x2E00, 0x2F00, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, |
314 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, | 314 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, |
315 0x3E00, 0x3F00, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, | 315 0x3E00, 0x3F00, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, |
316 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, | 316 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, |
317 0x4E00, 0x4F00, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, | 317 0x4E00, 0x4F00, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, |
318 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, | 318 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, |
319 0x5E00, 0x5F00, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, | 319 0x5E00, 0x5F00, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, |
320 0x6600, 0x6700, 0x6800, 0x6900, 0x6A00, 0x6B00, 0x6C00, 0x6D00, | 320 0x6600, 0x6700, 0x6800, 0x6900, 0x6A00, 0x6B00, 0x6C00, 0x6D00, |
321 0x6E00, 0x6F00, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, | 321 0x6E00, 0x6F00, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, |
322 0x7600, 0x7700, 0x7800, 0x7900, 0x7A00, 0x7B00, 0x7C00, 0x7D00, | 322 0x7600, 0x7700, 0x7800, 0x7900, 0x7A00, 0x7B00, 0x7C00, 0x7D00, |
323 0x7E00, 0x7F00, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, | 323 0x7E00, 0x7F00, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, |
324 0x8600, 0x8700, 0x8800, 0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, | 324 0x8600, 0x8700, 0x8800, 0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, |
325 0x8E00, 0x8F00, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, | 325 0x8E00, 0x8F00, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, |
326 0x9600, 0x9700, 0x9800, 0x9900, 0x9A00, 0x9B00, 0x9C00, 0x9D00, | 326 0x9600, 0x9700, 0x9800, 0x9900, 0x9A00, 0x9B00, 0x9C00, 0x9D00, |
327 0x9E00, 0x9F00, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | 327 0x9E00, 0x9F00, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, |
328 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, | 328 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, |
329 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | 329 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, |
330 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, | 330 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, |
331 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | 331 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, |
332 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, | 332 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, |
333 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | 333 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, |
334 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, | 334 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, |
335 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | 335 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, |
336 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, | 336 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, |
337 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | 337 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, |
338 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, | 338 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, |
339 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | 339 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, |
340 0x6610, 0x6710, 0x6810, 0x6910, 0x6A10, 0x6B10, 0x6C10, 0x6D10, | 340 0x6610, 0x6710, 0x6810, 0x6910, 0x6A10, 0x6B10, 0x6C10, 0x6D10, |
341 0x6E10, 0x6F10, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, | 341 0x6E10, 0x6F10, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, |
342 0x7610, 0x7710, 0x7810, 0x7910, 0x7A10, 0x7B10, 0x7C10, 0x7D10, | 342 0x7610, 0x7710, 0x7810, 0x7910, 0x7A10, 0x7B10, 0x7C10, 0x7D10, |
343 0x7E10, 0x7F10, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, | 343 0x7E10, 0x7F10, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, |
344 0x8610, 0x8710, 0x8810, 0x8910, 0x8A10, 0x8B10, 0x8C10, 0x8D10, | 344 0x8610, 0x8710, 0x8810, 0x8910, 0x8A10, 0x8B10, 0x8C10, 0x8D10, |
345 0x8E10, 0x8F10, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, | 345 0x8E10, 0x8F10, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, |
346 0x9610, 0x9710, 0x9810, 0x9910, 0x9A10, 0x9B10, 0x9C10, 0x9D10, | 346 0x9610, 0x9710, 0x9810, 0x9910, 0x9A10, 0x9B10, 0x9C10, 0x9D10, |
347 0x9E10, 0x9F10, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, | 347 0x9E10, 0x9F10, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, |
348 0xA610, 0xA710, 0xA810, 0xA910, 0xAA10, 0xAB10, 0xAC10, 0xAD10, | 348 0xA610, 0xA710, 0xA810, 0xA910, 0xAA10, 0xAB10, 0xAC10, 0xAD10, |
349 0xAE10, 0xAF10, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, | 349 0xAE10, 0xAF10, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, |
350 0xB610, 0xB710, 0xB810, 0xB910, 0xBA10, 0xBB10, 0xBC10, 0xBD10, | 350 0xB610, 0xB710, 0xB810, 0xB910, 0xBA10, 0xBB10, 0xBC10, 0xBD10, |
351 0xBE10, 0xBF10, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, | 351 0xBE10, 0xBF10, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, |
352 0xC610, 0xC710, 0xC810, 0xC910, 0xCA10, 0xCB10, 0xCC10, 0xCD10, | 352 0xC610, 0xC710, 0xC810, 0xC910, 0xCA10, 0xCB10, 0xCC10, 0xCD10, |
353 0xCE10, 0xCF10, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, | 353 0xCE10, 0xCF10, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, |
354 0xD610, 0xD710, 0xD810, 0xD910, 0xDA10, 0xDB10, 0xDC10, 0xDD10, | 354 0xD610, 0xD710, 0xD810, 0xD910, 0xDA10, 0xDB10, 0xDC10, 0xDD10, |
355 0xDE10, 0xDF10, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, | 355 0xDE10, 0xDF10, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, |
356 0xE610, 0xE710, 0xE810, 0xE910, 0xEA10, 0xEB10, 0xEC10, 0xED10, | 356 0xE610, 0xE710, 0xE810, 0xE910, 0xEA10, 0xEB10, 0xEC10, 0xED10, |
357 0xEE10, 0xEF10, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, | 357 0xEE10, 0xEF10, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, |
358 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, 0xFC10, 0xFD10, | 358 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, 0xFC10, 0xFD10, |
359 0xFE10, 0xFF10, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | 359 0xFE10, 0xFF10, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, |
360 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, | 360 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, |
361 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | 361 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, |
362 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, | 362 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, |
363 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | 363 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, |
364 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, | 364 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, |
365 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | 365 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, |
366 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, | 366 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, |
367 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | 367 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, |
368 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, | 368 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, |
369 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | 369 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, |
370 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, | 370 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, |
371 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | 371 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, |
372 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, | 372 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, |
373 0x0840, 0x0940, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, | 373 0x0840, 0x0940, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, |
374 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, | 374 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, |
375 0x1840, 0x1940, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, | 375 0x1840, 0x1940, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, |
376 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, | 376 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, |
377 0x2840, 0x2940, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, | 377 0x2840, 0x2940, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, |
378 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, | 378 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, |
379 0x3840, 0x3940, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, | 379 0x3840, 0x3940, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, |
380 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, | 380 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, |
381 0x4840, 0x4940, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, | 381 0x4840, 0x4940, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, |
382 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, | 382 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, |
383 0x5840, 0x5940, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, | 383 0x5840, 0x5940, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, |
384 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, | 384 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, |
385 0x6840, 0x6940, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, | 385 0x6840, 0x6940, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, |
386 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, | 386 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, |
387 0x7840, 0x7940, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, | 387 0x7840, 0x7940, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, |
388 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, | 388 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, |
389 0x8840, 0x8940, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, | 389 0x8840, 0x8940, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, |
390 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, | 390 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, |
391 0x9840, 0x9940, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | 391 0x9840, 0x9940, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, |
392 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, | 392 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, |
393 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | 393 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, |
394 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, | 394 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, |
395 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | 395 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, |
396 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, | 396 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, |
397 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | 397 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, |
398 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, | 398 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, |
399 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | 399 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, |
400 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, | 400 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, |
401 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | 401 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, |
402 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, | 402 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, |
403 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | 403 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, |
404 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, | 404 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, |
405 0xA850, 0xA950, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, | 405 0xA850, 0xA950, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, |
406 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, | 406 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, |
407 0xB850, 0xB950, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, | 407 0xB850, 0xB950, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, |
408 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, | 408 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, |
409 0xC850, 0xC950, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, | 409 0xC850, 0xC950, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, |
410 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, | 410 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, |
411 0xD850, 0xD950, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, | 411 0xD850, 0xD950, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, |
412 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, | 412 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, |
413 0xE850, 0xE950, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, | 413 0xE850, 0xE950, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, |
414 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, | 414 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, |
415 0xF850, 0xF950, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, | 415 0xF850, 0xF950, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, |
416 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, | 416 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, |
417 0x0850, 0x0950, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, | 417 0x0850, 0x0950, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, |
418 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, | 418 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, |
419 0x1850, 0x1950, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, | 419 0x1850, 0x1950, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, |
420 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, | 420 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, |
421 0x2850, 0x2950, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, | 421 0x2850, 0x2950, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, |
422 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, | 422 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, |
423 0x3850, 0x3950, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | 423 0x3850, 0x3950, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, |
424 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, | 424 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, |
425 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | 425 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, |
426 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, | 426 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, |
427 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | 427 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, |
428 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, | 428 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, |
429 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | 429 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, |
430 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, | 430 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, |
431 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | 431 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, |
432 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, | 432 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, |
433 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | 433 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, |
434 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, | 434 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, |
435 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | 435 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, |
436 0xFA60, 0xFB60, 0xFC60, 0xFD60, 0xFE60, 0xFF60, 0x00C0, 0x0140, | 436 0xFA60, 0xFB60, 0xFC60, 0xFD60, 0xFE60, 0xFF60, 0x00C0, 0x0140, |
437 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, | 437 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, |
438 0x0A60, 0x0B60, 0x0C60, 0x0D60, 0x0E60, 0x0F60, 0x1040, 0x1140, | 438 0x0A60, 0x0B60, 0x0C60, 0x0D60, 0x0E60, 0x0F60, 0x1040, 0x1140, |
439 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, | 439 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, |
440 0x1A60, 0x1B60, 0x1C60, 0x1D60, 0x1E60, 0x1F60, 0x2040, 0x2140, | 440 0x1A60, 0x1B60, 0x1C60, 0x1D60, 0x1E60, 0x1F60, 0x2040, 0x2140, |
441 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, | 441 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, |
442 0x2A60, 0x2B60, 0x2C60, 0x2D60, 0x2E60, 0x2F60, 0x3040, 0x3140, | 442 0x2A60, 0x2B60, 0x2C60, 0x2D60, 0x2E60, 0x2F60, 0x3040, 0x3140, |
443 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, | 443 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, |
444 0x3A60, 0x3B60, 0x3C60, 0x3D60, 0x3E60, 0x3F60, 0x4040, 0x4140, | 444 0x3A60, 0x3B60, 0x3C60, 0x3D60, 0x3E60, 0x3F60, 0x4040, 0x4140, |
445 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, | 445 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, |
446 0x4A60, 0x4B60, 0x4C60, 0x4D60, 0x4E60, 0x4F60, 0x5040, 0x5140, | 446 0x4A60, 0x4B60, 0x4C60, 0x4D60, 0x4E60, 0x4F60, 0x5040, 0x5140, |
447 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, | 447 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, |
448 0x5A60, 0x5B60, 0x5C60, 0x5D60, 0x5E60, 0x5F60, 0x6040, 0x6140, | 448 0x5A60, 0x5B60, 0x5C60, 0x5D60, 0x5E60, 0x5F60, 0x6040, 0x6140, |
449 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, | 449 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, |
450 0x6A60, 0x6B60, 0x6C60, 0x6D60, 0x6E60, 0x6F60, 0x7040, 0x7140, | 450 0x6A60, 0x6B60, 0x6C60, 0x6D60, 0x6E60, 0x6F60, 0x7040, 0x7140, |
451 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, | 451 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, |
452 0x7A60, 0x7B60, 0x7C60, 0x7D60, 0x7E60, 0x7F60, 0x8040, 0x8140, | 452 0x7A60, 0x7B60, 0x7C60, 0x7D60, 0x7E60, 0x7F60, 0x8040, 0x8140, |
453 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, | 453 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, |
454 0x8A60, 0x8B60, 0x8C60, 0x8D60, 0x8E60, 0x8F60, 0x9040, 0x9140, | 454 0x8A60, 0x8B60, 0x8C60, 0x8D60, 0x8E60, 0x8F60, 0x9040, 0x9140, |
455 0x9240, 0x9340, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | 455 0x9240, 0x9340, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, |
456 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, | 456 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, |
457 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | 457 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, |
458 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, | 458 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, |
459 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | 459 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, |
460 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, | 460 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, |
461 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | 461 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, |
462 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, | 462 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, |
463 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | 463 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, |
464 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, | 464 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, |
465 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | 465 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, |
466 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, | 466 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, |
467 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | 467 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, |
468 0x9A70, 0x9B70, 0x9C70, 0x9D70, 0x9E70, 0x9F70, 0xA050, 0xA150, | 468 0x9A70, 0x9B70, 0x9C70, 0x9D70, 0x9E70, 0x9F70, 0xA050, 0xA150, |
469 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, | 469 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, |
470 0xAA70, 0xAB70, 0xAC70, 0xAD70, 0xAE70, 0xAF70, 0xB050, 0xB150, | 470 0xAA70, 0xAB70, 0xAC70, 0xAD70, 0xAE70, 0xAF70, 0xB050, 0xB150, |
471 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, | 471 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, |
472 0xBA70, 0xBB70, 0xBC70, 0xBD70, 0xBE70, 0xBF70, 0xC050, 0xC150, | 472 0xBA70, 0xBB70, 0xBC70, 0xBD70, 0xBE70, 0xBF70, 0xC050, 0xC150, |
473 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, | 473 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, |
474 0xCA70, 0xCB70, 0xCC70, 0xCD70, 0xCE70, 0xCF70, 0xD050, 0xD150, | 474 0xCA70, 0xCB70, 0xCC70, 0xCD70, 0xCE70, 0xCF70, 0xD050, 0xD150, |
475 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, | 475 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, |
476 0xDA70, 0xDB70, 0xDC70, 0xDD70, 0xDE70, 0xDF70, 0xE050, 0xE150, | 476 0xDA70, 0xDB70, 0xDC70, 0xDD70, 0xDE70, 0xDF70, 0xE050, 0xE150, |
477 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, | 477 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, |
478 0xEA70, 0xEB70, 0xEC70, 0xED70, 0xEE70, 0xEF70, 0xF050, 0xF150, | 478 0xEA70, 0xEB70, 0xEC70, 0xED70, 0xEE70, 0xEF70, 0xF050, 0xF150, |
479 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, | 479 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, |
480 0xFA70, 0xFB70, 0xFC70, 0xFD70, 0xFE70, 0xFF70, 0x00D0, 0x0150, | 480 0xFA70, 0xFB70, 0xFC70, 0xFD70, 0xFE70, 0xFF70, 0x00D0, 0x0150, |
481 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, | 481 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, |
482 0x0A70, 0x0B70, 0x0C70, 0x0D70, 0x0E70, 0x0F70, 0x1050, 0x1150, | 482 0x0A70, 0x0B70, 0x0C70, 0x0D70, 0x0E70, 0x0F70, 0x1050, 0x1150, |
483 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, | 483 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, |
484 0x1A70, 0x1B70, 0x1C70, 0x1D70, 0x1E70, 0x1F70, 0x2050, 0x2150, | 484 0x1A70, 0x1B70, 0x1C70, 0x1D70, 0x1E70, 0x1F70, 0x2050, 0x2150, |
485 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, | 485 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, |
486 0x2A70, 0x2B70, 0x2C70, 0x2D70, 0x2E70, 0x2F70, 0x3050, 0x3150, | 486 0x2A70, 0x2B70, 0x2C70, 0x2D70, 0x2E70, 0x2F70, 0x3050, 0x3150, |
487 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | 487 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, |
488 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, | 488 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, |
489 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | 489 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, |
490 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, | 490 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, |
491 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | 491 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, |
492 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, | 492 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, |
493 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | 493 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, |
494 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, | 494 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, |
495 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | 495 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, |
496 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, | 496 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, |
497 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | 497 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, |
498 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, | 498 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, |
499 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | 499 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, |
500 }; | 500 }; |
501 | 501 |
502 u8 ZeroTable[] = | 502 u8 ZeroTable[] = |
503 { | 503 { |
504 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 504 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
508 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 508 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
509 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 509 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
510 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 510 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
511 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 511 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
512 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 512 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
515 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 515 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
516 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 516 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
517 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 517 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
518 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 518 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
519 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 519 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
520 }; | 520 }; |
521 | 521 |
522 #define GBSAVE_GAME_VERSION_1 1 | 522 #define GBSAVE_GAME_VERSION_1 1 |
523 #define GBSAVE_GAME_VERSION_2 2 | 523 #define GBSAVE_GAME_VERSION_2 2 |
524 #define GBSAVE_GAME_VERSION_3 3 | 524 #define GBSAVE_GAME_VERSION_3 3 |
525 #define GBSAVE_GAME_VERSION_4 4 | 525 #define GBSAVE_GAME_VERSION_4 4 |
534 #define GBSAVE_GAME_VERSION_13 13 | 534 #define GBSAVE_GAME_VERSION_13 13 |
535 #define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_13 | 535 #define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_13 |
536 | 536 |
537 int inline gbGetValue(int min, int max, int v) | 537 int inline gbGetValue(int min, int max, int v) |
538 { | 538 { |
539 return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0))); | 539 return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0))); |
540 } | 540 } |
541 | 541 |
542 void gbGenFilter() | 542 void gbGenFilter() |
543 { | 543 { |
544 for (int r = 0; r < 32; r++) | 544 for (int r = 0; r < 32; r++) |
545 { | 545 { |
546 for (int g = 0; g < 32; g++) | 546 for (int g = 0; g < 32; g++) |
547 { | 547 { |
548 for (int b = 0; b < 32; b++) | 548 for (int b = 0; b < 32; b++) |
549 { | 549 { |
550 int nr = gbGetValue(gbGetValue(4, 14, g), | 550 int nr = gbGetValue(gbGetValue(4, 14, g), |
551 gbGetValue(24, 29, g), r) - 4; | 551 gbGetValue(24, 29, g), r) - 4; |
552 int ng = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), | 552 int ng = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), |
553 14 + gbGetValue(0, 3, r), b), | 553 14 + gbGetValue(0, 3, r), b), |
554 gbGetValue(24 + gbGetValue(0, 3, r), | 554 gbGetValue(24 + gbGetValue(0, 3, r), |
555 29 + gbGetValue(0, 1, r), b), g) - 4; | 555 29 + gbGetValue(0, 1, r), b), g) - 4; |
556 int nb = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), | 556 int nb = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), |
557 14 + gbGetValue(0, 3, r), g), | 557 14 + gbGetValue(0, 3, r), g), |
558 gbGetValue(24 + gbGetValue(0, 3, r), | 558 gbGetValue(24 + gbGetValue(0, 3, r), |
559 29 + gbGetValue(0, 1, r), g), b) - 4; | 559 29 + gbGetValue(0, 1, r), g), b) - 4; |
560 gbColorFilter[(b << 10) | (g << 5) | r] = (nb << 10) | (ng << 5) | nr; | 560 gbColorFilter[(b << 10) | (g << 5) | r] = (nb << 10) | (ng << 5) | nr; |
561 } | 561 } |
562 } | 562 } |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 void gbCopyMemory(u16 d, u16 s, int count) | 566 void gbCopyMemory(u16 d, u16 s, int count) |
567 { | 567 { |
568 while (count) | 568 while (count) |
569 { | 569 { |
570 gbWriteMemoryQuick(d, gbReadMemoryQuick(s)); | 570 gbWriteMemoryQuick(d, gbReadMemoryQuick(s)); |
571 s++; | 571 s++; |
572 d++; | 572 d++; |
573 count--; | 573 count--; |
574 } | 574 } |
575 } | 575 } |
576 | 576 |
577 void gbDoHdma() | 577 void gbDoHdma() |
578 { | 578 { |
579 gbCopyMemory(gbHdmaDestination, gbHdmaSource, 0x10); | 579 gbCopyMemory(gbHdmaDestination, gbHdmaSource, 0x10); |
580 | 580 |
581 gbHdmaDestination += 0x10; | 581 gbHdmaDestination += 0x10; |
582 gbHdmaSource += 0x10; | 582 gbHdmaSource += 0x10; |
583 | 583 |
584 register_HDMA2 = (register_HDMA2 + 0x10) & 0xFF; | 584 register_HDMA2 = (register_HDMA2 + 0x10) & 0xFF; |
585 if (register_HDMA2 == 0x00) | 585 if (register_HDMA2 == 0x00) |
586 register_HDMA1++; | 586 register_HDMA1++; |
587 | 587 |
588 register_HDMA4 = (register_HDMA4 + 0x10) & 0xFF; | 588 register_HDMA4 = (register_HDMA4 + 0x10) & 0xFF; |
589 if (register_HDMA4 == 0x00) | 589 if (register_HDMA4 == 0x00) |
590 register_HDMA3++; | 590 register_HDMA3++; |
591 | 591 |
592 if (gbHdmaDestination == 0x96b0) | 592 if (gbHdmaDestination == 0x96b0) |
593 gbHdmaBytes = gbHdmaBytes; | 593 gbHdmaBytes = gbHdmaBytes; |
594 gbHdmaBytes -= 0x10; | 594 gbHdmaBytes -= 0x10; |
595 register_HDMA5--; | 595 register_HDMA5--; |
596 if (register_HDMA5 == 0xff) | 596 if (register_HDMA5 == 0xff) |
597 gbHdmaOn = 0; | 597 gbHdmaOn = 0; |
598 } | 598 } |
599 | 599 |
600 // fix for Harley and Lego Racers | 600 // fix for Harley and Lego Racers |
601 void gbCompareLYToLYC() | 601 void gbCompareLYToLYC() |
602 { | 602 { |
603 if (register_LY == register_LYC) | 603 if (register_LY == register_LYC) |
604 { | 604 { |
605 // mark that we have a match | 605 // mark that we have a match |
606 register_STAT |= 4; | 606 register_STAT |= 4; |
607 | 607 |
608 // check if we need an interrupt | 608 // check if we need an interrupt |
609 if ((register_STAT & 0x40) && (register_IE & 2)) | 609 if ((register_STAT & 0x40) && (register_IE & 2)) |
610 gbInterrupt |= 2; | 610 gbInterrupt |= 2; |
611 } | 611 } |
612 else // no match | 612 else // no match |
613 register_STAT &= 0xfb; | 613 register_STAT &= 0xfb; |
614 } | 614 } |
615 | 615 |
616 // FIXME: horrible kludge to workaround the frame timing bug | 616 // FIXME: horrible kludge to workaround the frame timing bug |
617 static int32 s_gbJoymask[4] = { 0, 0, 0, 0 }; | 617 static int32 s_gbJoymask[4] = { 0, 0, 0, 0 }; |
618 | 618 |
619 void gbWriteMemoryWrapped(register u16 address, register u8 value) | 619 void gbWriteMemoryWrapped(register u16 address, register u8 value) |
620 { | 620 { |
621 if (address < 0x8000) | 621 if (address < 0x8000) |
622 { | 622 { |
623 #ifndef FINAL_VERSION | 623 #ifndef FINAL_VERSION |
624 if (memorydebug && (address > 0x3fff || address < 0x2000)) | 624 if (memorydebug && (address > 0x3fff || address < 0x2000)) |
625 { | 625 { |
626 log("Memory register write %04x=%02x PC=%04x\n", | 626 log("Memory register write %04x=%02x PC=%04x\n", |
627 address, | 627 address, |
628 value, | 628 value, |
629 PC.W); | 629 PC.W); |
630 } | 630 } |
631 #endif | 631 #endif |
632 if (mapper) | 632 if (mapper) |
633 (*mapper)(address, value); | 633 (*mapper)(address, value); |
634 return; | 634 return; |
635 } | 635 } |
636 | 636 |
637 if (address < 0xa000) | 637 if (address < 0xa000) |
638 { | 638 { |
639 gbWriteMemoryQuick(address, value); | 639 gbWriteMemoryQuick(address, value); |
640 return; | 640 return; |
641 } | 641 } |
642 | 642 |
643 if (address < 0xc000) | 643 if (address < 0xc000) |
644 { | 644 { |
645 #ifndef FINAL_VERSION | 645 #ifndef FINAL_VERSION |
646 if (memorydebug) | 646 if (memorydebug) |
647 { | 647 { |
648 log("Memory register write %04x=%02x PC=%04x\n", | 648 log("Memory register write %04x=%02x PC=%04x\n", |
649 address, | 649 address, |
650 value, | 650 value, |
651 PC.W); | 651 PC.W); |
652 } | 652 } |
653 #endif | 653 #endif |
654 | 654 |
655 if (mapper) | 655 if (mapper) |
656 (*mapperRAM)(address, value); | 656 (*mapperRAM)(address, value); |
657 return; | 657 return; |
658 } | 658 } |
659 | 659 |
660 if (address < 0xfe00) | 660 if (address < 0xfe00) |
661 { | 661 { |
662 gbWriteMemoryQuick(address, value); | 662 gbWriteMemoryQuick(address, value); |
663 return; | 663 return; |
664 } | 664 } |
665 | 665 |
666 if (address < 0xff00) | 666 if (address < 0xff00) |
667 { | 667 { |
668 gbMemory[address] = value; | 668 gbMemory[address] = value; |
669 return; | 669 return; |
670 } | 670 } |
671 | 671 |
672 switch (address & 0x00ff) | 672 switch (address & 0x00ff) |
673 { | |
674 case 0x00: | |
675 { | |
676 gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | | |
677 (value & 0x30)); | |
678 if (gbSgbMode) | |
679 { | |
680 gbSgbDoBitTransfer(value); | |
681 } | |
682 | |
683 return; | |
684 } | |
685 | |
686 case 0x01: | |
687 { | |
688 gbMemory[0xff01] = value; | |
689 return; | |
690 } | |
691 | |
692 // serial control | |
693 case 0x02: | |
694 { | |
695 gbSerialOn = (value & 0x80); | |
696 gbMemory[0xff02] = value; | |
697 if (gbSerialOn) | |
698 { | |
699 gbSerialTicks = GBSERIAL_CLOCK_TICKS; | |
700 #ifdef LINK_EMULATION | |
701 if (linkConnected) | |
702 { | |
703 if (value & 1) | |
704 { | |
705 linkSendByte(0x100 | gbMemory[0xFF01]); | |
706 Sleep(5); | |
707 } | |
708 } | |
709 #endif | |
710 } | |
711 | |
712 gbSerialBits = 0; | |
713 return; | |
714 } | |
715 | |
716 // DIV register resets on any write | |
717 case 0x04: | |
718 { | |
719 register_DIV = 0; | |
720 return; | |
721 } | |
722 case 0x05: | |
723 register_TIMA = value; | |
724 return; | |
725 | |
726 case 0x06: | |
727 register_TMA = value; | |
728 return; | |
729 | |
730 // TIMER control | |
731 case 0x07: | |
732 { | |
733 register_TAC = value; | |
734 | |
735 gbTimerOn = (value & 4); | |
736 gbTimerMode = value & 3; | |
737 // register_TIMA = register_TMA; | |
738 switch (gbTimerMode) | |
739 { | |
740 case 0: | |
741 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; | |
742 break; | |
743 case 1: | |
744 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS; | |
745 break; | |
746 case 2: | |
747 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS; | |
748 break; | |
749 case 3: | |
750 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS; | |
751 break; | |
752 } | |
753 return; | |
754 } | |
755 | |
756 case 0x0f: | |
757 { | |
758 register_IF = value; | |
759 gbInterrupt = value; | |
760 return; | |
761 } | |
762 | |
763 case 0x10: | |
764 case 0x11: | |
765 case 0x12: | |
766 case 0x13: | |
767 case 0x14: | |
768 case 0x15: | |
769 case 0x16: | |
770 case 0x17: | |
771 case 0x18: | |
772 case 0x19: | |
773 case 0x1a: | |
774 case 0x1b: | |
775 case 0x1c: | |
776 case 0x1d: | |
777 case 0x1e: | |
778 case 0x1f: | |
779 case 0x20: | |
780 case 0x21: | |
781 case 0x22: | |
782 case 0x23: | |
783 case 0x24: | |
784 case 0x25: | |
785 case 0x26: | |
786 { | |
787 SOUND_EVENT(address, value); | |
788 return; | |
789 } | |
790 case 0x40: | |
791 { | |
792 int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); | |
793 | |
794 if (lcdChange) | |
795 { | |
796 if (value & 0x80) | |
797 { | |
798 gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS; | |
799 gbLcdMode = 0; | |
800 register_STAT &= 0xfc; | |
801 register_LY = 0x00; | |
802 // FIXME: horrible workaround | |
803 if (gbNullInputHackTempEnabled && !useOldFrameTiming) | |
804 memcpy(gbJoymask, s_gbJoymask, sizeof(gbJoymask)); | |
805 } | |
806 else | |
807 { | |
808 gbLcdTicks = 0; | |
809 gbLcdMode = 0; | |
810 register_STAT &= 0xfc; | |
811 register_LY = 0x00; | |
812 // FIXME: horrible workaround | |
813 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | |
814 if (gbNullInputHackTempEnabled && !useOldFrameTiming) | |
815 memset(gbJoymask, 0, sizeof(gbJoymask)); | |
816 } | |
817 // compareLYToLYC(); | |
818 } | |
819 // don't draw the window if it was not enabled and not being drawn before | |
820 if (!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && | |
821 register_LY > register_WY) | |
822 gbWindowLine = 144; | |
823 | |
824 register_LCDC = value; | |
825 | |
826 return; | |
827 } | |
828 | |
829 // STAT | |
830 case 0x41: | |
831 { | |
832 //register_STAT = (register_STAT & 0x87) | | |
833 // (value & 0x7c); | |
834 register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? | |
835 // GB bug from Devrs FAQ | |
836 if (!gbCgbMode && (register_LCDC & 0x80) && gbLcdMode < 2) | |
837 gbInterrupt |= 2; | |
838 return; | |
839 } | |
840 | |
841 // SCY | |
842 case 0x42: | |
843 { | |
844 register_SCY = value; | |
845 return; | |
846 } | |
847 | |
848 // SCX | |
849 case 0x43: | |
850 { | |
851 register_SCX = value; | |
852 return; | |
853 } | |
854 | |
855 // LY | |
856 case 0x44: | |
857 { | |
858 // read only | |
859 return; | |
860 } | |
861 | |
862 // LYC | |
863 case 0x45: | |
864 { | |
865 register_LYC = value; | |
866 if ((register_LCDC & 0x80)) | |
867 { | |
868 gbCompareLYToLYC(); | |
869 } | |
870 return; | |
871 } | |
872 | |
873 // DMA! | |
874 case 0x46: | |
875 { | |
876 int source = value * 0x0100; | |
877 | |
878 gbCopyMemory(0xfe00, | |
879 source, | |
880 0xa0); | |
881 register_DMA = value; | |
882 return; | |
883 } | |
884 | |
885 // BGP | |
886 case 0x47: | |
887 { | |
888 gbBgp[0] = value & 0x03; | |
889 gbBgp[1] = (value & 0x0c) >> 2; | |
890 gbBgp[2] = (value & 0x30) >> 4; | |
891 gbBgp[3] = (value & 0xc0) >> 6; | |
892 break; | |
893 } | |
894 | |
895 // OBP0 | |
896 case 0x48: | |
897 { | |
898 gbObp0[0] = value & 0x03; | |
899 gbObp0[1] = (value & 0x0c) >> 2; | |
900 gbObp0[2] = (value & 0x30) >> 4; | |
901 gbObp0[3] = (value & 0xc0) >> 6; | |
902 break; | |
903 } | |
904 | |
905 // OBP1 | |
906 case 0x49: | |
907 { | |
908 gbObp1[0] = value & 0x03; | |
909 gbObp1[1] = (value & 0x0c) >> 2; | |
910 gbObp1[2] = (value & 0x30) >> 4; | |
911 gbObp1[3] = (value & 0xc0) >> 6; | |
912 break; | |
913 } | |
914 | |
915 case 0x4a: | |
916 register_WY = value; | |
917 return; | |
918 | |
919 case 0x4b: | |
920 register_WX = value; | |
921 return; | |
922 | |
923 // KEY1 | |
924 case 0x4d: | |
925 { | |
926 if (gbCgbMode) | |
927 { | |
928 gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1); | |
929 return; | |
930 } | |
931 break; | |
932 } | |
933 | |
934 // VBK | |
935 case 0x4f: | |
936 { | |
937 if (gbCgbMode) | |
938 { | |
939 value = value & 1; | |
940 if (value == gbVramBank) | |
941 return; | |
942 | |
943 int vramAddress = value * 0x2000; | |
944 gbMemoryMap[0x08] = &gbVram[vramAddress]; | |
945 gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; | |
946 | |
947 gbVramBank = value; | |
948 register_VBK = value; | |
949 } | |
950 return; | |
951 break; | |
952 } | |
953 | |
954 // HDMA1 | |
955 case 0x51: | |
956 { | |
957 if (gbCgbMode) | |
958 { | |
959 if (value > 0x7f && value < 0xa0) | |
960 value = 0; | |
961 | |
962 gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0); | |
963 | |
964 register_HDMA1 = value; | |
965 return; | |
966 } | |
967 break; | |
968 } | |
969 | |
970 // HDMA2 | |
971 case 0x52: | |
972 { | |
973 if (gbCgbMode) | |
974 { | |
975 value = value & 0xf0; | |
976 | |
977 gbHdmaSource = (register_HDMA1 << 8) | (value); | |
978 | |
979 register_HDMA2 = value; | |
980 return; | |
981 } | |
982 break; | |
983 } | |
984 | |
985 // HDMA3 | |
986 case 0x53: | |
987 { | |
988 if (gbCgbMode) | |
989 { | |
990 value = value & 0x1f; | |
991 gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0); | |
992 gbHdmaDestination += 0x8000; | |
993 register_HDMA3 = value; | |
994 return; | |
995 } | |
996 break; | |
997 } | |
998 | |
999 // HDMA4 | |
1000 case 0x54: | |
1001 { | |
1002 if (gbCgbMode) | |
1003 { | |
1004 value = value & 0xf0; | |
1005 gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value; | |
1006 gbHdmaDestination += 0x8000; | |
1007 register_HDMA4 = value; | |
1008 return; | |
1009 } | |
1010 break; | |
1011 } | |
1012 | |
1013 // HDMA5 | |
1014 case 0x55: | |
1015 { | |
1016 if (gbCgbMode) | |
1017 { | |
1018 gbHdmaBytes = 16 + (value & 0x7f) * 16; | |
1019 if (gbHdmaOn) | |
1020 { | |
1021 if (value & 0x80) | |
1022 { | |
1023 register_HDMA5 = (value & 0x7f); | |
1024 } | |
1025 else | |
1026 { | |
1027 register_HDMA5 = 0xff; | |
1028 gbHdmaOn = 0; | |
1029 } | |
1030 } | |
1031 else | |
1032 { | |
1033 if (value & 0x80) | |
1034 { | |
1035 gbHdmaOn = 1; | |
1036 register_HDMA5 = value & 0x7f; | |
1037 if (gbLcdMode == 0) | |
1038 gbDoHdma(); | |
1039 } | |
1040 else | |
1041 { | |
1042 // we need to take the time it takes to complete the transfer into | |
1043 // account... according to GB DEV FAQs, the setup time is the same | |
1044 // for single and double speed, but the actual transfer takes the | |
1045 // same time // (is that a typo?) | |
1046 switch (gbDMASpeedVersion) | |
1047 { | |
1048 case 1: // I believe this is more correct | |
1049 // the lower 7 bits of FF55 specify the Transfer Length (divided by 16, minus 1) | |
1050 // and we make gbDmaTicks twice as many cycles at double speed to make the transfer take the same time | |
1051 if (gbSpeed) | |
1052 gbDmaTicks = 16 * ((value & 0x7f) + 1); | |
1053 else | |
1054 gbDmaTicks = 8 * ((value & 0x7f) + 1); | |
1055 break; | |
1056 case 0: // here for backward compatibility | |
1057 // I think this was a guess that approximates the above in most but not all games | |
1058 if (gbSpeed) | |
1059 gbDmaTicks = 231 + 16 * (value & 0x7f); | |
1060 else | |
1061 gbDmaTicks = 231 + 8 * (value & 0x7f); | |
1062 break; | |
1063 default: // shouldn't happen | |
1064 //assert(0); | |
1065 break; | |
1066 } | |
1067 gbCopyMemory(gbHdmaDestination, gbHdmaSource, gbHdmaBytes); | |
1068 gbHdmaDestination += gbHdmaBytes; | |
1069 gbHdmaSource += gbHdmaBytes; | |
1070 | |
1071 register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; | |
1072 register_HDMA4 = gbHdmaDestination & 0xf0; | |
1073 register_HDMA1 = (gbHdmaSource >> 8) & 0xff; | |
1074 register_HDMA2 = gbHdmaSource & 0xf0; | |
1075 } | |
1076 } | |
1077 return; | |
1078 } | |
1079 break; | |
1080 } | |
1081 | |
1082 // BCPS | |
1083 case 0x68: | |
1084 { | |
1085 if (gbCgbMode) | |
1086 { | |
1087 int paletteIndex = (value & 0x3f) >> 1; | |
1088 int paletteHiLo = (value & 0x01); | |
1089 | |
1090 gbMemory[0xff68] = value; | |
1091 gbMemory[0xff69] = (paletteHiLo ? | |
1092 (gbPalette[paletteIndex] >> 8) : | |
1093 (gbPalette[paletteIndex] & 0x00ff)); | |
1094 return; | |
1095 } | |
1096 break; | |
1097 } | |
1098 | |
1099 // BCPD | |
1100 case 0x69: | |
1101 { | |
1102 if (gbCgbMode) | |
1103 { | |
1104 int v = gbMemory[0xff68]; | |
1105 int paletteIndex = (v & 0x3f) >> 1; | |
1106 int paletteHiLo = (v & 0x01); | |
1107 gbMemory[0xff69] = value; | |
1108 gbPalette[paletteIndex] = (paletteHiLo ? | |
1109 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : | |
1110 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; | |
1111 | |
1112 if (gbMemory[0xff68] & 0x80) | |
1113 { | |
1114 int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; | |
1115 | |
1116 gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; | |
1117 | |
1118 gbMemory[0xff69] = (index & 1 ? | |
1119 (gbPalette[index >> 1] >> 8) : | |
1120 (gbPalette[index >> 1] & 0x00ff)); | |
1121 } | |
1122 return; | |
1123 } | |
1124 break; | |
1125 } | |
1126 | |
1127 // OCPS | |
1128 case 0x6a: | |
1129 { | |
1130 if (gbCgbMode) | |
1131 { | |
1132 int paletteIndex = (value & 0x3f) >> 1; | |
1133 int paletteHiLo = (value & 0x01); | |
1134 | |
1135 paletteIndex += 32; | |
1136 | |
1137 gbMemory[0xff6a] = value; | |
1138 gbMemory[0xff6b] = (paletteHiLo ? | |
1139 (gbPalette[paletteIndex] >> 8) : | |
1140 (gbPalette[paletteIndex] & 0x00ff)); | |
1141 return; | |
1142 } | |
1143 break; | |
1144 } | |
1145 | |
1146 // OCPD | |
1147 case 0x6b: | |
1148 { | |
1149 if (gbCgbMode) | |
1150 { | |
1151 int v = gbMemory[0xff6a]; | |
1152 int paletteIndex = (v & 0x3f) >> 1; | |
1153 int paletteHiLo = (v & 0x01); | |
1154 | |
1155 paletteIndex += 32; | |
1156 | |
1157 gbMemory[0xff6b] = value; | |
1158 gbPalette[paletteIndex] = (paletteHiLo ? | |
1159 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : | |
1160 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; | |
1161 if (gbMemory[0xff6a] & 0x80) | |
1162 { | |
1163 int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; | |
1164 | |
1165 gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; | |
1166 | |
1167 gbMemory[0xff6b] = (index & 1 ? | |
1168 (gbPalette[(index >> 1) + 32] >> 8) : | |
1169 (gbPalette[(index >> 1) + 32] & 0x00ff)); | |
1170 } | |
1171 return; | |
1172 } | |
1173 break; | |
1174 } | |
1175 | |
1176 // SVBK | |
1177 case 0x70: | |
1178 { | |
1179 if (gbCgbMode) | |
1180 { | |
1181 value = value & 7; | |
1182 | |
1183 int bank = value; | |
1184 if (value == 0) | |
1185 bank = 1; | |
1186 | |
1187 if (bank == gbWramBank) | |
1188 return; | |
1189 | |
1190 int wramAddress = bank * 0x1000; | |
1191 gbMemoryMap[0x0d] = &gbWram[wramAddress]; | |
1192 | |
1193 gbWramBank = bank; | |
1194 register_SVBK = value; | |
1195 return; | |
1196 } | |
1197 break; | |
1198 } | |
1199 | |
1200 case 0xff: | |
1201 { | |
1202 register_IE = value; | |
1203 register_IF &= value; | |
1204 return; | |
1205 } | |
1206 } | |
1207 | |
1208 gbWriteMemoryQuick(address, value); | |
1209 } | |
1210 | |
1211 u8 gbReadOpcode(register u16 address) | |
1212 { | |
1213 if (gbCheatMap[address]) | |
1214 return gbCheatRead(address); | |
1215 | |
1216 // the following fix does more than Echo RAM fix, anyway... | |
1217 switch (gbEchoRAMFixOn ? (address >> 12) & 0x000f : address & 0xf000) | |
1218 { | |
1219 case 0x0a: | |
1220 case 0x0b: | |
1221 if (mapperReadRAM) | |
1222 return mapperReadRAM(address); | |
1223 break; | |
1224 case 0x0f: | |
1225 if (address > 0xff00) | |
1226 { | |
1227 switch (address & 0x00ff) | |
1228 { | |
1229 case 0x04: | |
1230 return register_DIV; | |
1231 case 0x05: | |
1232 return register_TIMA; | |
1233 case 0x06: | |
1234 return register_TMA; | |
1235 case 0x07: | |
1236 return (0xf8 | register_TAC); | |
1237 case 0x0f: | |
1238 return (0xe0 | register_IF); | |
1239 case 0x40: | |
1240 return register_LCDC; | |
1241 case 0x41: | |
1242 return (0x80 | register_STAT); | |
1243 case 0x42: | |
1244 return register_SCY; | |
1245 case 0x43: | |
1246 return register_SCX; | |
1247 case 0x44: | |
1248 return register_LY; | |
1249 case 0x45: | |
1250 return register_LYC; | |
1251 case 0x46: | |
1252 return register_DMA; | |
1253 case 0x4a: | |
1254 return register_WY; | |
1255 case 0x4b: | |
1256 return register_WX; | |
1257 case 0x4f: | |
1258 return (0xfe | register_VBK); | |
1259 case 0x51: | |
1260 return register_HDMA1; | |
1261 case 0x52: | |
1262 return register_HDMA2; | |
1263 case 0x53: | |
1264 return register_HDMA3; | |
1265 case 0x54: | |
1266 return register_HDMA4; | |
1267 case 0x55: | |
1268 return register_HDMA5; | |
1269 case 0x70: | |
1270 return (0xf8 | register_SVBK); | |
1271 case 0xff: | |
1272 return register_IE; | |
1273 } | |
1274 } | |
1275 break; | |
1276 } | |
1277 return gbReadMemoryQuick(address); | |
1278 } | |
1279 | |
1280 void gbWriteMemory(register u16 address, register u8 value) | |
1281 { | |
1282 gbWriteMemoryWrapped(address, value); | |
1283 CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_WRITE); | |
1284 } | |
1285 | |
1286 u8 gbReadMemory(register u16 address) | |
1287 { | |
1288 if (gbCheatMap[address]) | |
1289 return gbCheatRead(address); | |
1290 | |
1291 if (address < 0xa000) | |
1292 return gbReadMemoryQuick(address); | |
1293 | |
1294 if (address < 0xc000) | |
1295 { | |
1296 #ifndef FINAL_VERSION | |
1297 if (memorydebug) | |
1298 { | |
1299 log("Memory register read %04x PC=%04x\n", | |
1300 address, | |
1301 PC.W); | |
1302 } | |
1303 #endif | |
1304 | |
1305 if (mapperReadRAM) | |
1306 return mapperReadRAM(address); | |
1307 return gbReadMemoryQuick(address); | |
1308 } | |
1309 | |
1310 if (address >= 0xff00) | |
1311 { | |
1312 switch (address & 0x00ff) | |
673 { | 1313 { |
674 case 0x00: | 1314 case 0x00: |
675 { | 1315 { |
676 gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) | | 1316 if (gbSgbMode) |
677 (value & 0x30)); | 1317 { |
678 if (gbSgbMode) | 1318 gbSgbReadingController |= 4; |
679 { | 1319 gbSgbResetPacketState(); |
680 gbSgbDoBitTransfer(value); | 1320 } |
681 } | 1321 |
682 | 1322 int b = gbMemory[0xff00]; |
683 return; | 1323 |
684 } | 1324 if ((b & 0x30) == 0x20) |
685 | 1325 { |
1326 b &= 0xf0; | |
1327 | |
1328 int joy = 0; | |
1329 if (gbSgbMode && gbSgbMultiplayer) | |
1330 { | |
1331 switch (gbSgbNextController) | |
1332 { | |
1333 case 0x0f: | |
1334 joy = 0; | |
1335 break; | |
1336 case 0x0e: | |
1337 joy = 1; | |
1338 break; | |
1339 case 0x0d: | |
1340 joy = 2; | |
1341 break; | |
1342 case 0x0c: | |
1343 joy = 3; | |
1344 break; | |
1345 default: | |
1346 joy = 0; | |
1347 } | |
1348 } | |
1349 int joystate = gbJoymask[joy]; | |
1350 if (!(joystate & 128)) | |
1351 b |= 0x08; | |
1352 if (!(joystate & 64)) | |
1353 b |= 0x04; | |
1354 if (!(joystate & 32)) | |
1355 b |= 0x02; | |
1356 if (!(joystate & 16)) | |
1357 b |= 0x01; | |
1358 | |
1359 gbMemory[0xff00] = b; | |
1360 } | |
1361 else if ((b & 0x30) == 0x10) | |
1362 { | |
1363 b &= 0xf0; | |
1364 | |
1365 int joy = 0; | |
1366 if (gbSgbMode && gbSgbMultiplayer) | |
1367 { | |
1368 switch (gbSgbNextController) | |
1369 { | |
1370 case 0x0f: | |
1371 joy = 0; | |
1372 break; | |
1373 case 0x0e: | |
1374 joy = 1; | |
1375 break; | |
1376 case 0x0d: | |
1377 joy = 2; | |
1378 break; | |
1379 case 0x0c: | |
1380 joy = 3; | |
1381 break; | |
1382 default: | |
1383 joy = 0; | |
1384 } | |
1385 } | |
1386 int joystate = gbJoymask[joy]; | |
1387 if (!(joystate & 8)) | |
1388 b |= 0x08; | |
1389 if (!(joystate & 4)) | |
1390 b |= 0x04; | |
1391 if (!(joystate & 2)) | |
1392 b |= 0x02; | |
1393 if (!(joystate & 1)) | |
1394 b |= 0x01; | |
1395 | |
1396 gbMemory[0xff00] = b; | |
1397 } | |
1398 else | |
1399 { | |
1400 if (gbSgbMode && gbSgbMultiplayer) | |
1401 { | |
1402 gbMemory[0xff00] = 0xf0 | gbSgbNextController; | |
1403 } | |
1404 else | |
1405 { | |
1406 gbMemory[0xff00] = 0xff; | |
1407 } | |
1408 } | |
1409 } | |
1410 GBSystemCounters.lagged = false; | |
1411 return gbMemory[0xff00]; | |
1412 break; | |
686 case 0x01: | 1413 case 0x01: |
687 { | 1414 return gbMemory[0xff01]; |
688 gbMemory[0xff01] = value; | |
689 return; | |
690 } | |
691 | |
692 // serial control | |
693 case 0x02: | |
694 { | |
695 gbSerialOn = (value & 0x80); | |
696 gbMemory[0xff02] = value; | |
697 if (gbSerialOn) | |
698 { | |
699 gbSerialTicks = GBSERIAL_CLOCK_TICKS; | |
700 #ifdef LINK_EMULATION | |
701 if (linkConnected) | |
702 { | |
703 if (value & 1) | |
704 { | |
705 linkSendByte(0x100 | gbMemory[0xFF01]); | |
706 Sleep(5); | |
707 } | |
708 } | |
709 #endif | |
710 } | |
711 | |
712 gbSerialBits = 0; | |
713 return; | |
714 } | |
715 | |
716 // DIV register resets on any write | |
717 case 0x04: | 1415 case 0x04: |
718 { | 1416 return register_DIV; |
719 register_DIV = 0; | |
720 return; | |
721 } | |
722 case 0x05: | 1417 case 0x05: |
723 register_TIMA = value; | 1418 return register_TIMA; |
724 return; | |
725 | |
726 case 0x06: | 1419 case 0x06: |
727 register_TMA = value; | 1420 return register_TMA; |
728 return; | |
729 | |
730 // TIMER control | |
731 case 0x07: | 1421 case 0x07: |
732 { | 1422 return (0xf8 | register_TAC); |
733 register_TAC = value; | |
734 | |
735 gbTimerOn = (value & 4); | |
736 gbTimerMode = value & 3; | |
737 // register_TIMA = register_TMA; | |
738 switch (gbTimerMode) | |
739 { | |
740 case 0: | |
741 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS; | |
742 break; | |
743 case 1: | |
744 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_1_CLOCK_TICKS; | |
745 break; | |
746 case 2: | |
747 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_2_CLOCK_TICKS; | |
748 break; | |
749 case 3: | |
750 gbTimerClockTicks = gbTimerTicks = GBTIMER_MODE_3_CLOCK_TICKS; | |
751 break; | |
752 } | |
753 return; | |
754 } | |
755 | |
756 case 0x0f: | 1423 case 0x0f: |
757 { | 1424 return (0xe0 | register_IF); |
758 register_IF = value; | |
759 gbInterrupt = value; | |
760 return; | |
761 } | |
762 | |
763 case 0x10: | |
764 case 0x11: | |
765 case 0x12: | |
766 case 0x13: | |
767 case 0x14: | |
768 case 0x15: | |
769 case 0x16: | |
770 case 0x17: | |
771 case 0x18: | |
772 case 0x19: | |
773 case 0x1a: | |
774 case 0x1b: | |
775 case 0x1c: | |
776 case 0x1d: | |
777 case 0x1e: | |
778 case 0x1f: | |
779 case 0x20: | |
780 case 0x21: | |
781 case 0x22: | |
782 case 0x23: | |
783 case 0x24: | |
784 case 0x25: | |
785 case 0x26: | |
786 { | |
787 SOUND_EVENT(address, value); | |
788 return; | |
789 } | |
790 case 0x40: | 1425 case 0x40: |
791 { | 1426 return register_LCDC; |
792 int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80); | |
793 | |
794 if (lcdChange) | |
795 { | |
796 if (value & 0x80) | |
797 { | |
798 gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS; | |
799 gbLcdMode = 0; | |
800 register_STAT &= 0xfc; | |
801 register_LY = 0x00; | |
802 // FIXME: horrible workaround | |
803 if (gbNullInputHackTempEnabled && !useOldFrameTiming) | |
804 memcpy(gbJoymask, s_gbJoymask, sizeof(gbJoymask)); | |
805 } | |
806 else | |
807 { | |
808 gbLcdTicks = 0; | |
809 gbLcdMode = 0; | |
810 register_STAT &= 0xfc; | |
811 register_LY = 0x00; | |
812 // FIXME: horrible workaround | |
813 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | |
814 if (gbNullInputHackTempEnabled && !useOldFrameTiming) | |
815 memset(gbJoymask, 0, sizeof(gbJoymask)); | |
816 } | |
817 // compareLYToLYC(); | |
818 } | |
819 // don't draw the window if it was not enabled and not being drawn before | |
820 if (!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 && | |
821 register_LY > register_WY) | |
822 gbWindowLine = 144; | |
823 | |
824 register_LCDC = value; | |
825 | |
826 return; | |
827 } | |
828 | |
829 // STAT | |
830 case 0x41: | 1427 case 0x41: |
831 { | 1428 return (0x80 | register_STAT); |
832 //register_STAT = (register_STAT & 0x87) | | |
833 // (value & 0x7c); | |
834 register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ? | |
835 // GB bug from Devrs FAQ | |
836 if (!gbCgbMode && (register_LCDC & 0x80) && gbLcdMode < 2) | |
837 gbInterrupt |= 2; | |
838 return; | |
839 } | |
840 | |
841 // SCY | |
842 case 0x42: | 1429 case 0x42: |
843 { | 1430 return register_SCY; |
844 register_SCY = value; | |
845 return; | |
846 } | |
847 | |
848 // SCX | |
849 case 0x43: | 1431 case 0x43: |
850 { | 1432 return register_SCX; |
851 register_SCX = value; | |
852 return; | |
853 } | |
854 | |
855 // LY | |
856 case 0x44: | 1433 case 0x44: |
857 { | 1434 return register_LY; |
858 // read only | |
859 return; | |
860 } | |
861 | |
862 // LYC | |
863 case 0x45: | 1435 case 0x45: |
864 { | 1436 return register_LYC; |
865 register_LYC = value; | |
866 if ((register_LCDC & 0x80)) | |
867 { | |
868 gbCompareLYToLYC(); | |
869 } | |
870 return; | |
871 } | |
872 | |
873 // DMA! | |
874 case 0x46: | 1437 case 0x46: |
875 { | 1438 return register_DMA; |
876 int source = value * 0x0100; | |
877 | |
878 gbCopyMemory(0xfe00, | |
879 source, | |
880 0xa0); | |
881 register_DMA = value; | |
882 return; | |
883 } | |
884 | |
885 // BGP | |
886 case 0x47: | |
887 { | |
888 gbBgp[0] = value & 0x03; | |
889 gbBgp[1] = (value & 0x0c) >> 2; | |
890 gbBgp[2] = (value & 0x30) >> 4; | |
891 gbBgp[3] = (value & 0xc0) >> 6; | |
892 break; | |
893 } | |
894 | |
895 // OBP0 | |
896 case 0x48: | |
897 { | |
898 gbObp0[0] = value & 0x03; | |
899 gbObp0[1] = (value & 0x0c) >> 2; | |
900 gbObp0[2] = (value & 0x30) >> 4; | |
901 gbObp0[3] = (value & 0xc0) >> 6; | |
902 break; | |
903 } | |
904 | |
905 // OBP1 | |
906 case 0x49: | |
907 { | |
908 gbObp1[0] = value & 0x03; | |
909 gbObp1[1] = (value & 0x0c) >> 2; | |
910 gbObp1[2] = (value & 0x30) >> 4; | |
911 gbObp1[3] = (value & 0xc0) >> 6; | |
912 break; | |
913 } | |
914 | |
915 case 0x4a: | 1439 case 0x4a: |
916 register_WY = value; | 1440 return register_WY; |
917 return; | |
918 | |
919 case 0x4b: | 1441 case 0x4b: |
920 register_WX = value; | 1442 return register_WX; |
921 return; | |
922 | |
923 // KEY1 | |
924 case 0x4d: | |
925 { | |
926 if (gbCgbMode) | |
927 { | |
928 gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1); | |
929 return; | |
930 } | |
931 break; | |
932 } | |
933 | |
934 // VBK | |
935 case 0x4f: | 1443 case 0x4f: |
936 { | 1444 return (0xfe | register_VBK); |
937 if (gbCgbMode) | |
938 { | |
939 value = value & 1; | |
940 if (value == gbVramBank) | |
941 return; | |
942 | |
943 int vramAddress = value * 0x2000; | |
944 gbMemoryMap[0x08] = &gbVram[vramAddress]; | |
945 gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000]; | |
946 | |
947 gbVramBank = value; | |
948 register_VBK = value; | |
949 } | |
950 return; | |
951 break; | |
952 } | |
953 | |
954 // HDMA1 | |
955 case 0x51: | 1445 case 0x51: |
956 { | 1446 return register_HDMA1; |
957 if (gbCgbMode) | |
958 { | |
959 if (value > 0x7f && value < 0xa0) | |
960 value = 0; | |
961 | |
962 gbHdmaSource = (value << 8) | (register_HDMA2 & 0xf0); | |
963 | |
964 register_HDMA1 = value; | |
965 return; | |
966 } | |
967 break; | |
968 } | |
969 | |
970 // HDMA2 | |
971 case 0x52: | 1447 case 0x52: |
972 { | 1448 return register_HDMA2; |
973 if (gbCgbMode) | |
974 { | |
975 value = value & 0xf0; | |
976 | |
977 gbHdmaSource = (register_HDMA1 << 8) | (value); | |
978 | |
979 register_HDMA2 = value; | |
980 return; | |
981 } | |
982 break; | |
983 } | |
984 | |
985 // HDMA3 | |
986 case 0x53: | 1449 case 0x53: |
987 { | 1450 return register_HDMA3; |
988 if (gbCgbMode) | |
989 { | |
990 value = value & 0x1f; | |
991 gbHdmaDestination = (value << 8) | (register_HDMA4 & 0xf0); | |
992 gbHdmaDestination += 0x8000; | |
993 register_HDMA3 = value; | |
994 return; | |
995 } | |
996 break; | |
997 } | |
998 | |
999 // HDMA4 | |
1000 case 0x54: | 1451 case 0x54: |
1001 { | 1452 return register_HDMA4; |
1002 if (gbCgbMode) | |
1003 { | |
1004 value = value & 0xf0; | |
1005 gbHdmaDestination = ((register_HDMA3 & 0x1f) << 8) | value; | |
1006 gbHdmaDestination += 0x8000; | |
1007 register_HDMA4 = value; | |
1008 return; | |
1009 } | |
1010 break; | |
1011 } | |
1012 | |
1013 // HDMA5 | |
1014 case 0x55: | 1453 case 0x55: |
1015 { | 1454 return register_HDMA5; |
1016 if (gbCgbMode) | |
1017 { | |
1018 gbHdmaBytes = 16 + (value & 0x7f) * 16; | |
1019 if (gbHdmaOn) | |
1020 { | |
1021 if (value & 0x80) | |
1022 { | |
1023 register_HDMA5 = (value & 0x7f); | |
1024 } | |
1025 else | |
1026 { | |
1027 register_HDMA5 = 0xff; | |
1028 gbHdmaOn = 0; | |
1029 } | |
1030 } | |
1031 else | |
1032 { | |
1033 if (value & 0x80) | |
1034 { | |
1035 gbHdmaOn = 1; | |
1036 register_HDMA5 = value & 0x7f; | |
1037 if (gbLcdMode == 0) | |
1038 gbDoHdma(); | |
1039 } | |
1040 else | |
1041 { | |
1042 // we need to take the time it takes to complete the transfer into | |
1043 // account... according to GB DEV FAQs, the setup time is the same | |
1044 // for single and double speed, but the actual transfer takes the | |
1045 // same time // (is that a typo?) | |
1046 switch (gbDMASpeedVersion) | |
1047 { | |
1048 case 1: // I believe this is more correct | |
1049 // the lower 7 bits of FF55 specify the Transfer Length (divided by 16, minus 1) | |
1050 // and we make gbDmaTicks twice as many cycles at double speed to make the transfer take the same time | |
1051 if (gbSpeed) | |
1052 gbDmaTicks = 16 * ((value & 0x7f) + 1); | |
1053 else | |
1054 gbDmaTicks = 8 * ((value & 0x7f) + 1); | |
1055 break; | |
1056 case 0: // here for backward compatibility | |
1057 // I think this was a guess that approximates the above in most but not all games | |
1058 if (gbSpeed) | |
1059 gbDmaTicks = 231 + 16 * (value & 0x7f); | |
1060 else | |
1061 gbDmaTicks = 231 + 8 * (value & 0x7f); | |
1062 break; | |
1063 default: // shouldn't happen | |
1064 //assert(0); | |
1065 break; | |
1066 } | |
1067 gbCopyMemory(gbHdmaDestination, gbHdmaSource, gbHdmaBytes); | |
1068 gbHdmaDestination += gbHdmaBytes; | |
1069 gbHdmaSource += gbHdmaBytes; | |
1070 | |
1071 register_HDMA3 = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f; | |
1072 register_HDMA4 = gbHdmaDestination & 0xf0; | |
1073 register_HDMA1 = (gbHdmaSource >> 8) & 0xff; | |
1074 register_HDMA2 = gbHdmaSource & 0xf0; | |
1075 } | |
1076 } | |
1077 return; | |
1078 } | |
1079 break; | |
1080 } | |
1081 | |
1082 // BCPS | |
1083 case 0x68: | |
1084 { | |
1085 if (gbCgbMode) | |
1086 { | |
1087 int paletteIndex = (value & 0x3f) >> 1; | |
1088 int paletteHiLo = (value & 0x01); | |
1089 | |
1090 gbMemory[0xff68] = value; | |
1091 gbMemory[0xff69] = (paletteHiLo ? | |
1092 (gbPalette[paletteIndex] >> 8) : | |
1093 (gbPalette[paletteIndex] & 0x00ff)); | |
1094 return; | |
1095 } | |
1096 break; | |
1097 } | |
1098 | |
1099 // BCPD | |
1100 case 0x69: | |
1101 { | |
1102 if (gbCgbMode) | |
1103 { | |
1104 int v = gbMemory[0xff68]; | |
1105 int paletteIndex = (v & 0x3f) >> 1; | |
1106 int paletteHiLo = (v & 0x01); | |
1107 gbMemory[0xff69] = value; | |
1108 gbPalette[paletteIndex] = (paletteHiLo ? | |
1109 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : | |
1110 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; | |
1111 | |
1112 if (gbMemory[0xff68] & 0x80) | |
1113 { | |
1114 int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f; | |
1115 | |
1116 gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index; | |
1117 | |
1118 gbMemory[0xff69] = (index & 1 ? | |
1119 (gbPalette[index >> 1] >> 8) : | |
1120 (gbPalette[index >> 1] & 0x00ff)); | |
1121 } | |
1122 return; | |
1123 } | |
1124 break; | |
1125 } | |
1126 | |
1127 // OCPS | |
1128 case 0x6a: | |
1129 { | |
1130 if (gbCgbMode) | |
1131 { | |
1132 int paletteIndex = (value & 0x3f) >> 1; | |
1133 int paletteHiLo = (value & 0x01); | |
1134 | |
1135 paletteIndex += 32; | |
1136 | |
1137 gbMemory[0xff6a] = value; | |
1138 gbMemory[0xff6b] = (paletteHiLo ? | |
1139 (gbPalette[paletteIndex] >> 8) : | |
1140 (gbPalette[paletteIndex] & 0x00ff)); | |
1141 return; | |
1142 } | |
1143 break; | |
1144 } | |
1145 | |
1146 // OCPD | |
1147 case 0x6b: | |
1148 { | |
1149 if (gbCgbMode) | |
1150 { | |
1151 int v = gbMemory[0xff6a]; | |
1152 int paletteIndex = (v & 0x3f) >> 1; | |
1153 int paletteHiLo = (v & 0x01); | |
1154 | |
1155 paletteIndex += 32; | |
1156 | |
1157 gbMemory[0xff6b] = value; | |
1158 gbPalette[paletteIndex] = (paletteHiLo ? | |
1159 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) : | |
1160 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff; | |
1161 if (gbMemory[0xff6a] & 0x80) | |
1162 { | |
1163 int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f; | |
1164 | |
1165 gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index; | |
1166 | |
1167 gbMemory[0xff6b] = (index & 1 ? | |
1168 (gbPalette[(index >> 1) + 32] >> 8) : | |
1169 (gbPalette[(index >> 1) + 32] & 0x00ff)); | |
1170 } | |
1171 return; | |
1172 } | |
1173 break; | |
1174 } | |
1175 | |
1176 // SVBK | |
1177 case 0x70: | 1455 case 0x70: |
1178 { | 1456 return (0xf8 | register_SVBK); |
1179 if (gbCgbMode) | |
1180 { | |
1181 value = value & 7; | |
1182 | |
1183 int bank = value; | |
1184 if (value == 0) | |
1185 bank = 1; | |
1186 | |
1187 if (bank == gbWramBank) | |
1188 return; | |
1189 | |
1190 int wramAddress = bank * 0x1000; | |
1191 gbMemoryMap[0x0d] = &gbWram[wramAddress]; | |
1192 | |
1193 gbWramBank = bank; | |
1194 register_SVBK = value; | |
1195 return; | |
1196 } | |
1197 break; | |
1198 } | |
1199 | |
1200 case 0xff: | 1457 case 0xff: |
1201 { | 1458 return register_IE; |
1202 register_IE = value; | 1459 } |
1203 register_IF &= value; | 1460 } |
1204 return; | 1461 |
1205 } | 1462 return gbReadMemoryQuick(address); |
1206 } | |
1207 | |
1208 gbWriteMemoryQuick(address, value); | |
1209 } | |
1210 | |
1211 u8 gbReadOpcode(register u16 address) | |
1212 { | |
1213 if (gbCheatMap[address]) | |
1214 return gbCheatRead(address); | |
1215 | |
1216 // the following fix does more than Echo RAM fix, anyway... | |
1217 switch (gbEchoRAMFixOn ? (address >> 12) & 0x000f : address & 0xf000) | |
1218 { | |
1219 case 0x0a: | |
1220 case 0x0b: | |
1221 if (mapperReadRAM) | |
1222 return mapperReadRAM(address); | |
1223 break; | |
1224 case 0x0f: | |
1225 if (address > 0xff00) | |
1226 { | |
1227 switch (address & 0x00ff) | |
1228 { | |
1229 case 0x04: | |
1230 return register_DIV; | |
1231 case 0x05: | |
1232 return register_TIMA; | |
1233 case 0x06: | |
1234 return register_TMA; | |
1235 case 0x07: | |
1236 return (0xf8 | register_TAC); | |
1237 case 0x0f: | |
1238 return (0xe0 | register_IF); | |
1239 case 0x40: | |
1240 return register_LCDC; | |
1241 case 0x41: | |
1242 return (0x80 | register_STAT); | |
1243 case 0x42: | |
1244 return register_SCY; | |
1245 case 0x43: | |
1246 return register_SCX; | |
1247 case 0x44: | |
1248 return register_LY; | |
1249 case 0x45: | |
1250 return register_LYC; | |
1251 case 0x46: | |
1252 return register_DMA; | |
1253 case 0x4a: | |
1254 return register_WY; | |
1255 case 0x4b: | |
1256 return register_WX; | |
1257 case 0x4f: | |
1258 return (0xfe | register_VBK); | |
1259 case 0x51: | |
1260 return register_HDMA1; | |
1261 case 0x52: | |
1262 return register_HDMA2; | |
1263 case 0x53: | |
1264 return register_HDMA3; | |
1265 case 0x54: | |
1266 return register_HDMA4; | |
1267 case 0x55: | |
1268 return register_HDMA5; | |
1269 case 0x70: | |
1270 return (0xf8 | register_SVBK); | |
1271 case 0xff: | |
1272 return register_IE; | |
1273 } | |
1274 } | |
1275 break; | |
1276 } | |
1277 return gbReadMemoryQuick(address); | |
1278 } | |
1279 | |
1280 void gbWriteMemory(register u16 address, register u8 value) | |
1281 { | |
1282 gbWriteMemoryWrapped(address, value); | |
1283 CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_WRITE); | |
1284 } | |
1285 | |
1286 u8 gbReadMemory(register u16 address) | |
1287 { | |
1288 if (gbCheatMap[address]) | |
1289 return gbCheatRead(address); | |
1290 | |
1291 if (address < 0xa000) | |
1292 return gbReadMemoryQuick(address); | |
1293 | |
1294 if (address < 0xc000) | |
1295 { | |
1296 #ifndef FINAL_VERSION | |
1297 if (memorydebug) | |
1298 { | |
1299 log("Memory register read %04x PC=%04x\n", | |
1300 address, | |
1301 PC.W); | |
1302 } | |
1303 #endif | |
1304 | |
1305 if (mapperReadRAM) | |
1306 return mapperReadRAM(address); | |
1307 return gbReadMemoryQuick(address); | |
1308 } | |
1309 | |
1310 if (address >= 0xff00) | |
1311 { | |
1312 switch (address & 0x00ff) | |
1313 { | |
1314 case 0x00: | |
1315 { | |
1316 if (gbSgbMode) | |
1317 { | |
1318 gbSgbReadingController |= 4; | |
1319 gbSgbResetPacketState(); | |
1320 } | |
1321 | |
1322 int b = gbMemory[0xff00]; | |
1323 | |
1324 if ((b & 0x30) == 0x20) | |
1325 { | |
1326 b &= 0xf0; | |
1327 | |
1328 int joy = 0; | |
1329 if (gbSgbMode && gbSgbMultiplayer) | |
1330 { | |
1331 switch (gbSgbNextController) | |
1332 { | |
1333 case 0x0f: | |
1334 joy = 0; | |
1335 break; | |
1336 case 0x0e: | |
1337 joy = 1; | |
1338 break; | |
1339 case 0x0d: | |
1340 joy = 2; | |
1341 break; | |
1342 case 0x0c: | |
1343 joy = 3; | |
1344 break; | |
1345 default: | |
1346 joy = 0; | |
1347 } | |
1348 } | |
1349 int joystate = gbJoymask[joy]; | |
1350 if (!(joystate & 128)) | |
1351 b |= 0x08; | |
1352 if (!(joystate & 64)) | |
1353 b |= 0x04; | |
1354 if (!(joystate & 32)) | |
1355 b |= 0x02; | |
1356 if (!(joystate & 16)) | |
1357 b |= 0x01; | |
1358 | |
1359 gbMemory[0xff00] = b; | |
1360 } | |
1361 else if ((b & 0x30) == 0x10) | |
1362 { | |
1363 b &= 0xf0; | |
1364 | |
1365 int joy = 0; | |
1366 if (gbSgbMode && gbSgbMultiplayer) | |
1367 { | |
1368 switch (gbSgbNextController) | |
1369 { | |
1370 case 0x0f: | |
1371 joy = 0; | |
1372 break; | |
1373 case 0x0e: | |
1374 joy = 1; | |
1375 break; | |
1376 case 0x0d: | |
1377 joy = 2; | |
1378 break; | |
1379 case 0x0c: | |
1380 joy = 3; | |
1381 break; | |
1382 default: | |
1383 joy = 0; | |
1384 } | |
1385 } | |
1386 int joystate = gbJoymask[joy]; | |
1387 if (!(joystate & 8)) | |
1388 b |= 0x08; | |
1389 if (!(joystate & 4)) | |
1390 b |= 0x04; | |
1391 if (!(joystate & 2)) | |
1392 b |= 0x02; | |
1393 if (!(joystate & 1)) | |
1394 b |= 0x01; | |
1395 | |
1396 gbMemory[0xff00] = b; | |
1397 } | |
1398 else | |
1399 { | |
1400 if (gbSgbMode && gbSgbMultiplayer) | |
1401 { | |
1402 gbMemory[0xff00] = 0xf0 | gbSgbNextController; | |
1403 } | |
1404 else | |
1405 { | |
1406 gbMemory[0xff00] = 0xff; | |
1407 } | |
1408 } | |
1409 } | |
1410 GBSystemCounters.lagged = false; | |
1411 return gbMemory[0xff00]; | |
1412 break; | |
1413 case 0x01: | |
1414 return gbMemory[0xff01]; | |
1415 case 0x04: | |
1416 return register_DIV; | |
1417 case 0x05: | |
1418 return register_TIMA; | |
1419 case 0x06: | |
1420 return register_TMA; | |
1421 case 0x07: | |
1422 return (0xf8 | register_TAC); | |
1423 case 0x0f: | |
1424 return (0xe0 | register_IF); | |
1425 case 0x40: | |
1426 return register_LCDC; | |
1427 case 0x41: | |
1428 return (0x80 | register_STAT); | |
1429 case 0x42: | |
1430 return register_SCY; | |
1431 case 0x43: | |
1432 return register_SCX; | |
1433 case 0x44: | |
1434 return register_LY; | |
1435 case 0x45: | |
1436 return register_LYC; | |
1437 case 0x46: | |
1438 return register_DMA; | |
1439 case 0x4a: | |
1440 return register_WY; | |
1441 case 0x4b: | |
1442 return register_WX; | |
1443 case 0x4f: | |
1444 return (0xfe | register_VBK); | |
1445 case 0x51: | |
1446 return register_HDMA1; | |
1447 case 0x52: | |
1448 return register_HDMA2; | |
1449 case 0x53: | |
1450 return register_HDMA3; | |
1451 case 0x54: | |
1452 return register_HDMA4; | |
1453 case 0x55: | |
1454 return register_HDMA5; | |
1455 case 0x70: | |
1456 return (0xf8 | register_SVBK); | |
1457 case 0xff: | |
1458 return register_IE; | |
1459 } | |
1460 } | |
1461 | |
1462 return gbReadMemoryQuick(address); | |
1463 } | 1463 } |
1464 | 1464 |
1465 void gbVblank_interrupt() | 1465 void gbVblank_interrupt() |
1466 { | 1466 { |
1467 if (IFF & 0x80) | 1467 if (IFF & 0x80) |
1468 { | 1468 { |
1469 PC.W++; | 1469 PC.W++; |
1470 IFF &= 0x7f; | 1470 IFF &= 0x7f; |
1471 } | 1471 } |
1472 gbInterrupt &= 0xfe; | 1472 gbInterrupt &= 0xfe; |
1473 | 1473 |
1474 IFF &= 0x7e; | 1474 IFF &= 0x7e; |
1475 register_IF &= 0xfe; | 1475 register_IF &= 0xfe; |
1476 | 1476 |
1477 gbWriteMemory(--SP.W, PC.B.B1); | 1477 gbWriteMemory(--SP.W, PC.B.B1); |
1478 gbWriteMemory(--SP.W, PC.B.B0); | 1478 gbWriteMemory(--SP.W, PC.B.B0); |
1479 PC.W = 0x40; | 1479 PC.W = 0x40; |
1480 } | 1480 } |
1481 | 1481 |
1482 void gbLcd_interrupt() | 1482 void gbLcd_interrupt() |
1483 { | 1483 { |
1484 if (IFF & 0x80) | 1484 if (IFF & 0x80) |
1485 { | 1485 { |
1486 PC.W++; | 1486 PC.W++; |
1487 IFF &= 0x7f; | 1487 IFF &= 0x7f; |
1488 } | 1488 } |
1489 gbInterrupt &= 0xfd; | 1489 gbInterrupt &= 0xfd; |
1490 IFF &= 0x7e; | 1490 IFF &= 0x7e; |
1491 register_IF &= 0xfd; | 1491 register_IF &= 0xfd; |
1492 | 1492 |
1493 gbWriteMemory(--SP.W, PC.B.B1); | 1493 gbWriteMemory(--SP.W, PC.B.B1); |
1494 gbWriteMemory(--SP.W, PC.B.B0); | 1494 gbWriteMemory(--SP.W, PC.B.B0); |
1495 | 1495 |
1496 PC.W = 0x48; | 1496 PC.W = 0x48; |
1497 } | 1497 } |
1498 | 1498 |
1499 void gbTimer_interrupt() | 1499 void gbTimer_interrupt() |
1500 { | 1500 { |
1501 if (IFF & 0x80) | 1501 if (IFF & 0x80) |
1502 { | 1502 { |
1503 PC.W++; | 1503 PC.W++; |
1504 IFF &= 0x7f; | 1504 IFF &= 0x7f; |
1505 } | 1505 } |
1506 IFF &= 0x7e; | 1506 IFF &= 0x7e; |
1507 gbInterrupt &= 0xfb; | 1507 gbInterrupt &= 0xfb; |
1508 register_IF &= 0xfb; | 1508 register_IF &= 0xfb; |
1509 | 1509 |
1510 gbWriteMemory(--SP.W, PC.B.B1); | 1510 gbWriteMemory(--SP.W, PC.B.B1); |
1511 gbWriteMemory(--SP.W, PC.B.B0); | 1511 gbWriteMemory(--SP.W, PC.B.B0); |
1512 | 1512 |
1513 PC.W = 0x50; | 1513 PC.W = 0x50; |
1514 } | 1514 } |
1515 | 1515 |
1516 void gbSerial_interrupt() | 1516 void gbSerial_interrupt() |
1517 { | 1517 { |
1518 if (IFF & 0x80) | 1518 if (IFF & 0x80) |
1519 { | 1519 { |
1520 PC.W++; | 1520 PC.W++; |
1521 IFF &= 0x7f; | 1521 IFF &= 0x7f; |
1522 } | 1522 } |
1523 IFF &= 0x7e; | 1523 IFF &= 0x7e; |
1524 gbInterrupt &= 0xf7; | 1524 gbInterrupt &= 0xf7; |
1525 register_IF &= 0xf7; | 1525 register_IF &= 0xf7; |
1526 | 1526 |
1527 gbWriteMemory(--SP.W, PC.B.B1); | 1527 gbWriteMemory(--SP.W, PC.B.B1); |
1528 gbWriteMemory(--SP.W, PC.B.B0); | 1528 gbWriteMemory(--SP.W, PC.B.B0); |
1529 | 1529 |
1530 PC.W = 0x58; | 1530 PC.W = 0x58; |
1531 } | 1531 } |
1532 | 1532 |
1533 void gbJoypad_interrupt() | 1533 void gbJoypad_interrupt() |
1534 { | 1534 { |
1535 if (IFF & 0x80) | 1535 if (IFF & 0x80) |
1536 { | 1536 { |
1537 PC.W++; | 1537 PC.W++; |
1538 IFF &= 0x7f; | 1538 IFF &= 0x7f; |
1539 } | 1539 } |
1540 IFF &= 0x7e; | 1540 IFF &= 0x7e; |
1541 gbInterrupt &= 0xef; | 1541 gbInterrupt &= 0xef; |
1542 register_IF &= 0xef; | 1542 register_IF &= 0xef; |
1543 | 1543 |
1544 gbWriteMemory(--SP.W, PC.B.B1); | 1544 gbWriteMemory(--SP.W, PC.B.B1); |
1545 gbWriteMemory(--SP.W, PC.B.B0); | 1545 gbWriteMemory(--SP.W, PC.B.B0); |
1546 | 1546 |
1547 PC.W = 0x60; | 1547 PC.W = 0x60; |
1548 } | 1548 } |
1549 | 1549 |
1550 void gbSpeedSwitch() | 1550 void gbSpeedSwitch() |
1551 { | 1551 { |
1552 if (gbSpeed == 0) | 1552 if (gbSpeed == 0) |
1553 { | 1553 { |
1554 gbSpeed = 1; | 1554 gbSpeed = 1; |
1555 GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2; | 1555 GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2; |
1556 GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; | 1556 GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; |
1557 GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2; | 1557 GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2; |
1558 GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2; | 1558 GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2; |
1559 GBDIV_CLOCK_TICKS = 64 * 2; | 1559 GBDIV_CLOCK_TICKS = 64 * 2; |
1560 GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; | 1560 GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; |
1561 GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2; | 1561 GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2; |
1562 GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2; | 1562 GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2; |
1563 GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2; | 1563 GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2; |
1564 GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2; | 1564 GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2; |
1565 GBSERIAL_CLOCK_TICKS = 128 * 2; | 1565 GBSERIAL_CLOCK_TICKS = 128 * 2; |
1566 gbDivTicks *= 2; | 1566 gbDivTicks *= 2; |
1567 gbLcdTicks *= 2; | 1567 gbLcdTicks *= 2; |
1568 gbLcdLYIncrementTicks *= 2; | 1568 gbLcdLYIncrementTicks *= 2; |
1569 // timerTicks *= 2; | 1569 // timerTicks *= 2; |
1570 // timerClockTicks *= 2; | 1570 // timerClockTicks *= 2; |
1571 gbSerialTicks *= 2; | 1571 gbSerialTicks *= 2; |
1572 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS * 2; | 1572 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS * 2; |
1573 soundTicks *= 2; | 1573 soundTicks *= 2; |
1574 // synchronizeTicks *= 2; | 1574 // synchronizeTicks *= 2; |
1575 // SYNCHRONIZE_CLOCK_TICKS *= 2; | 1575 // SYNCHRONIZE_CLOCK_TICKS *= 2; |
1576 } | 1576 } |
1577 else | 1577 else |
1578 { | 1578 { |
1579 gbSpeed = 0; | 1579 gbSpeed = 0; |
1580 GBLCD_MODE_0_CLOCK_TICKS = 51; | 1580 GBLCD_MODE_0_CLOCK_TICKS = 51; |
1581 GBLCD_MODE_1_CLOCK_TICKS = 1140; | 1581 GBLCD_MODE_1_CLOCK_TICKS = 1140; |
1582 GBLCD_MODE_2_CLOCK_TICKS = 20; | 1582 GBLCD_MODE_2_CLOCK_TICKS = 20; |
1583 GBLCD_MODE_3_CLOCK_TICKS = 43; | 1583 GBLCD_MODE_3_CLOCK_TICKS = 43; |
1584 GBDIV_CLOCK_TICKS = 64; | 1584 GBDIV_CLOCK_TICKS = 64; |
1585 GBLY_INCREMENT_CLOCK_TICKS = 114; | 1585 GBLY_INCREMENT_CLOCK_TICKS = 114; |
1586 GBTIMER_MODE_0_CLOCK_TICKS = 256; | 1586 GBTIMER_MODE_0_CLOCK_TICKS = 256; |
1587 GBTIMER_MODE_1_CLOCK_TICKS = 4; | 1587 GBTIMER_MODE_1_CLOCK_TICKS = 4; |
1588 GBTIMER_MODE_2_CLOCK_TICKS = 16; | 1588 GBTIMER_MODE_2_CLOCK_TICKS = 16; |
1589 GBTIMER_MODE_3_CLOCK_TICKS = 64; | 1589 GBTIMER_MODE_3_CLOCK_TICKS = 64; |
1590 GBSERIAL_CLOCK_TICKS = 128; | 1590 GBSERIAL_CLOCK_TICKS = 128; |
1591 gbDivTicks /= 2; | 1591 gbDivTicks /= 2; |
1592 gbLcdTicks /= 2; | 1592 gbLcdTicks /= 2; |
1593 gbLcdLYIncrementTicks /= 2; | 1593 gbLcdLYIncrementTicks /= 2; |
1594 // timerTicks /= 2; | 1594 // timerTicks /= 2; |
1595 // timerClockTicks /= 2; | 1595 // timerClockTicks /= 2; |
1596 gbSerialTicks /= 2; | 1596 gbSerialTicks /= 2; |
1597 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; | 1597 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; |
1598 soundTicks /= 2; | 1598 soundTicks /= 2; |
1599 // synchronizeTicks /= 2; | 1599 // synchronizeTicks /= 2; |
1600 // SYNCHRONIZE_CLOCK_TICKS /= 2; | 1600 // SYNCHRONIZE_CLOCK_TICKS /= 2; |
1601 } | 1601 } |
1602 } | 1602 } |
1603 | 1603 |
1604 void gbGetHardwareType() | 1604 void gbGetHardwareType() |
1605 { | 1605 { |
1606 gbCgbMode = 0; | 1606 gbCgbMode = 0; |
1607 if (gbRom[0x143] & 0x80) | 1607 if (gbRom[0x143] & 0x80) |
1608 { | 1608 { |
1609 if (gbEmulatorType == 0 || | 1609 if (gbEmulatorType == 0 || |
1610 gbEmulatorType == 1 || | 1610 gbEmulatorType == 1 || |
1611 gbEmulatorType == 4 || | 1611 gbEmulatorType == 4 || |
1612 gbEmulatorType == 5 || | 1612 gbEmulatorType == 5 || |
1613 (gbRom[0x146] != 0x03 && (gbEmulatorType == 2))) | 1613 (gbRom[0x146] != 0x03 && (gbEmulatorType == 2))) |
1614 { | 1614 { |
1615 gbCgbMode = 1; | 1615 gbCgbMode = 1; |
1616 } | 1616 } |
1617 } | 1617 } |
1618 | 1618 |
1619 if (gbSgbMode == 2) | 1619 if (gbSgbMode == 2) |
1620 { | 1620 { |
1621 gbSgbMode = 0; | 1621 gbSgbMode = 0; |
1622 return; | 1622 return; |
1623 } | 1623 } |
1624 | 1624 |
1625 gbSgbMode = 0; | 1625 gbSgbMode = 0; |
1626 if (gbRom[0x146] == 0x03) | 1626 if (gbRom[0x146] == 0x03) |
1627 { | 1627 { |
1628 if (gbEmulatorType == 0 || | 1628 if (gbEmulatorType == 0 || |
1629 gbEmulatorType == 2 || | 1629 gbEmulatorType == 2 || |
1630 gbEmulatorType == 5 || | 1630 gbEmulatorType == 5 || |
1631 (!(gbRom[0x143] & 0x80) && (gbEmulatorType == 1 || gbEmulatorType == 4))) | 1631 (!(gbRom[0x143] & 0x80) && (gbEmulatorType == 1 || gbEmulatorType == 4))) |
1632 gbSgbMode = 1; | 1632 gbSgbMode = 1; |
1633 } | 1633 } |
1634 } | 1634 } |
1635 | 1635 |
1636 void gbReset(bool userReset) | 1636 void gbReset(bool userReset) |
1637 { | 1637 { |
1638 // movie must be closed while opening/creating a movie | 1638 // movie must be closed while opening/creating a movie |
1639 if (userReset && VBAMovieRecording()) | 1639 if (userReset && VBAMovieRecording()) |
1640 { | 1640 { |
1641 VBAMovieSignalReset(); | 1641 VBAMovieSignalReset(); |
1642 return; | 1642 return; |
1643 } | 1643 } |
1644 | 1644 |
1645 if (!VBAMovieActive()) | 1645 if (!VBAMovieActive()) |
1646 { | 1646 { |
1647 GBSystemCounters.frameCount = 0; | 1647 GBSystemCounters.frameCount = 0; |
1648 GBSystemCounters.lagCount = 0; | 1648 GBSystemCounters.lagCount = 0; |
1649 GBSystemCounters.extraCount = 0; | 1649 GBSystemCounters.extraCount = 0; |
1650 GBSystemCounters.lagged = true; | 1650 GBSystemCounters.lagged = true; |
1651 GBSystemCounters.laggedLast = true; | 1651 GBSystemCounters.laggedLast = true; |
1652 } | 1652 } |
1653 | 1653 |
1654 SP.W = 0xfffe; | 1654 SP.W = 0xfffe; |
1655 AF.W = 0x01b0; | 1655 AF.W = 0x01b0; |
1656 BC.W = 0x0013; | 1656 BC.W = 0x0013; |
1657 DE.W = 0x00d8; | 1657 DE.W = 0x00d8; |
1658 HL.W = 0x014d; | 1658 HL.W = 0x014d; |
1659 PC.W = 0x0100; | 1659 PC.W = 0x0100; |
1660 IFF = 0; | 1660 IFF = 0; |
1661 gbInterrupt = 1; | 1661 gbInterrupt = 1; |
1662 gbInterruptWait = 0; | 1662 gbInterruptWait = 0; |
1663 | 1663 |
1664 register_DIV = 0; | 1664 register_DIV = 0; |
1665 register_TIMA = 0; | 1665 register_TIMA = 0; |
1666 register_TMA = 0; | 1666 register_TMA = 0; |
1667 register_TAC = 0; | 1667 register_TAC = 0; |
1668 register_IF = 1; | 1668 register_IF = 1; |
1669 register_LCDC = 0x91; | 1669 register_LCDC = 0x91; |
1670 register_STAT = 0; | 1670 register_STAT = 0; |
1671 register_SCY = 0; | 1671 register_SCY = 0; |
1672 register_SCX = 0; | 1672 register_SCX = 0; |
1673 register_LY = 0; | 1673 register_LY = 0; |
1674 register_LYC = 0; | 1674 register_LYC = 0; |
1675 register_DMA = 0; | 1675 register_DMA = 0; |
1676 register_WY = 0; | 1676 register_WY = 0; |
1677 register_WX = 0; | 1677 register_WX = 0; |
1678 register_VBK = 0; | 1678 register_VBK = 0; |
1679 register_HDMA1 = 0; | 1679 register_HDMA1 = 0; |
1680 register_HDMA2 = 0; | 1680 register_HDMA2 = 0; |
1681 register_HDMA3 = 0; | 1681 register_HDMA3 = 0; |
1682 register_HDMA4 = 0; | 1682 register_HDMA4 = 0; |
1683 register_HDMA5 = 0; | 1683 register_HDMA5 = 0; |
1684 register_SVBK = 0; | 1684 register_SVBK = 0; |
1685 register_IE = 0; | 1685 register_IE = 0; |
1686 | 1686 |
1687 gbGetHardwareType(); | 1687 gbGetHardwareType(); |
1688 if (gbCgbMode) | 1688 if (gbCgbMode) |
1689 { | 1689 { |
1690 if (!gbVram) | 1690 if (!gbVram) |
1691 gbVram = (u8 *)malloc(0x4000 + 4); | 1691 gbVram = (u8 *)malloc(0x4000 + 4); |
1692 if (!gbWram) | 1692 if (!gbWram) |
1693 gbWram = (u8 *)malloc(0x8000 + 4); | 1693 gbWram = (u8 *)malloc(0x8000 + 4); |
1694 memset(gbVram, 0, 0x4000 + 4); | 1694 memset(gbVram, 0, 0x4000 + 4); |
1695 memset(gbWram, 0, 0x8000 + 4); | 1695 memset(gbWram, 0, 0x8000 + 4); |
1696 } | 1696 } |
1697 else | 1697 else |
1698 { | 1698 { |
1699 if (gbVram) | 1699 if (gbVram) |
1700 { | 1700 { |
1701 free(gbVram); | 1701 free(gbVram); |
1702 gbVram = NULL; | 1702 gbVram = NULL; |
1703 } | 1703 } |
1704 if (gbWram) | 1704 if (gbWram) |
1705 { | 1705 { |
1706 free(gbWram); | 1706 free(gbWram); |
1707 gbWram = NULL; | 1707 gbWram = NULL; |
1708 } | 1708 } |
1709 } | 1709 } |
1710 | 1710 |
1711 // clean LineBuffer | 1711 // clean LineBuffer |
1712 if (gbLineBuffer) | 1712 if (gbLineBuffer) |
1713 memset(gbLineBuffer, 0, 160 * sizeof(u16)); | 1713 memset(gbLineBuffer, 0, 160 * sizeof(u16)); |
1714 // clean Pix | 1714 // clean Pix |
1715 if (pix) | 1715 if (pix) |
1716 memset(pix, 0, 4 * 257 * 226); | 1716 memset(pix, 0, 4 * 257 * 226); |
1717 | 1717 |
1718 if (gbCgbMode) | 1718 if (gbCgbMode) |
1719 { | 1719 { |
1720 if (gbSgbMode) | 1720 if (gbSgbMode) |
1721 { | 1721 { |
1722 if (gbEmulatorType == 5) | 1722 if (gbEmulatorType == 5) |
1723 AF.W = 0xffb0; | 1723 AF.W = 0xffb0; |
1724 else | 1724 else |
1725 AF.W = 0x01b0; | 1725 AF.W = 0x01b0; |
1726 BC.W = 0x0013; | 1726 BC.W = 0x0013; |
1727 DE.W = 0x00d8; | 1727 DE.W = 0x00d8; |
1728 HL.W = 0x014d; | 1728 HL.W = 0x014d; |
1729 } | 1729 } |
1730 else | 1730 else |
1731 { | 1731 { |
1732 AF.W = 0x11b0; | 1732 AF.W = 0x11b0; |
1733 BC.W = 0x0000; | 1733 BC.W = 0x0000; |
1734 DE.W = 0xff56; | 1734 DE.W = 0xff56; |
1735 HL.W = 0x000d; | 1735 HL.W = 0x000d; |
1736 } | 1736 } |
1737 if (gbEmulatorType == 4) | 1737 if (gbEmulatorType == 4) |
1738 BC.B.B1 |= 0x01; | 1738 BC.B.B1 |= 0x01; |
1739 | 1739 |
1740 register_HDMA5 = 0xff; | 1740 register_HDMA5 = 0xff; |
1741 gbMemory[0xff68] = 0xc0; | 1741 gbMemory[0xff68] = 0xc0; |
1742 gbMemory[0xff6a] = 0xc0; | 1742 gbMemory[0xff6a] = 0xc0; |
1743 | 1743 |
1744 for (int i = 0; i < 64; i++) | 1744 for (int i = 0; i < 64; i++) |
1745 gbPalette[i] = 0x7fff; | 1745 gbPalette[i] = 0x7fff; |
1746 } | 1746 } |
1747 else | 1747 else |
1748 { | 1748 { |
1749 for (int i = 0; i < 8; i++) | 1749 for (int i = 0; i < 8; i++) |
1750 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; | 1750 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; |
1751 } | 1751 } |
1752 | 1752 |
1753 if (gbSpeed) | 1753 if (gbSpeed) |
1754 { | 1754 { |
1755 gbSpeedSwitch(); | 1755 gbSpeedSwitch(); |
1756 gbMemory[0xff4d] = 0; | 1756 gbMemory[0xff4d] = 0; |
1757 } | 1757 } |
1758 | 1758 |
1759 gbDivTicks = GBDIV_CLOCK_TICKS; | 1759 gbDivTicks = GBDIV_CLOCK_TICKS; |
1760 gbLcdMode = 2; | 1760 gbLcdMode = 2; |
1761 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; | 1761 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; |
1762 gbLcdLYIncrementTicks = 0; | 1762 gbLcdLYIncrementTicks = 0; |
1763 gbTimerTicks = 0; | 1763 gbTimerTicks = 0; |
1764 gbTimerClockTicks = 0; | 1764 gbTimerClockTicks = 0; |
1765 gbSerialTicks = 0; | 1765 gbSerialTicks = 0; |
1766 gbSerialBits = 0; | 1766 gbSerialBits = 0; |
1767 gbSerialOn = 0; | 1767 gbSerialOn = 0; |
1768 gbWindowLine = -1; | 1768 gbWindowLine = -1; |
1769 gbTimerOn = 0; | 1769 gbTimerOn = 0; |
1770 gbTimerMode = 0; | 1770 gbTimerMode = 0; |
1771 // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; | 1771 // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; |
1772 gbSpeed = 0; | 1772 gbSpeed = 0; |
1773 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; | 1773 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; |
1774 | 1774 |
1775 // FIXME: horrible kludge | 1775 // FIXME: horrible kludge |
1776 memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); | 1776 memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); |
1777 | 1777 |
1778 if (gbCgbMode) | 1778 if (gbCgbMode) |
1779 { | 1779 { |
1780 gbSpeed = 0; | 1780 gbSpeed = 0; |
1781 gbHdmaOn = 0; | 1781 gbHdmaOn = 0; |
1782 gbHdmaSource = 0x0000; | 1782 gbHdmaSource = 0x0000; |
1783 gbHdmaDestination = 0x8000; | 1783 gbHdmaDestination = 0x8000; |
1784 gbVramBank = 0; | 1784 gbVramBank = 0; |
1785 gbWramBank = 1; | 1785 gbWramBank = 1; |
1786 register_LY = 0x90; | 1786 register_LY = 0x90; |
1787 gbLcdMode = 1; | 1787 gbLcdMode = 1; |
1788 } | 1788 } |
1789 | 1789 |
1790 if (gbSgbMode) | 1790 if (gbSgbMode) |
1791 { | 1791 { |
1792 gbSgbReset(); | 1792 gbSgbReset(); |
1793 } | 1793 } |
1794 | 1794 |
1795 for (int i = 0; i < 4; i++) | 1795 for (int i = 0; i < 4; i++) |
1796 gbBgp[i] = gbObp0[i] = gbObp1[i] = i; | 1796 gbBgp[i] = gbObp0[i] = gbObp1[i] = i; |
1797 | 1797 |
1798 memset(&gbDataMBC1, 0, sizeof(gbDataMBC1)); | 1798 memset(&gbDataMBC1, 0, sizeof(gbDataMBC1)); |
1799 gbDataMBC1.mapperROMBank = 1; | 1799 gbDataMBC1.mapperROMBank = 1; |
1800 | 1800 |
1801 gbDataMBC2.mapperRAMEnable = 0; | 1801 gbDataMBC2.mapperRAMEnable = 0; |
1802 gbDataMBC2.mapperROMBank = 1; | 1802 gbDataMBC2.mapperROMBank = 1; |
1803 | 1803 |
1804 memset(&gbDataMBC3, 0, 6 * sizeof(int32)); | 1804 memset(&gbDataMBC3, 0, 6 * sizeof(int32)); |
1805 gbDataMBC3.mapperROMBank = 1; | 1805 gbDataMBC3.mapperROMBank = 1; |
1806 | 1806 |
1807 memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); | 1807 memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); |
1808 gbDataMBC5.mapperROMBank = 1; | 1808 gbDataMBC5.mapperROMBank = 1; |
1809 switch (gbRom[0x147]) | 1809 switch (gbRom[0x147]) |
1810 { | 1810 { |
1811 case 0x1c: | 1811 case 0x1c: |
1812 case 0x1d: | 1812 case 0x1d: |
1813 case 0x1e: | 1813 case 0x1e: |
1814 gbDataMBC5.isRumbleCartridge = 1; | 1814 gbDataMBC5.isRumbleCartridge = 1; |
1815 } | 1815 } |
1816 | 1816 |
1817 memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); | 1817 memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); |
1818 gbDataHuC1.mapperROMBank = 1; | 1818 gbDataHuC1.mapperROMBank = 1; |
1819 | 1819 |
1820 memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); | 1820 memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); |
1821 gbDataHuC3.mapperROMBank = 1; | 1821 gbDataHuC3.mapperROMBank = 1; |
1822 | 1822 |
1823 gbMemoryMap[0x00] = &gbRom[0x0000]; | 1823 gbMemoryMap[0x00] = &gbRom[0x0000]; |
1824 gbMemoryMap[0x01] = &gbRom[0x1000]; | 1824 gbMemoryMap[0x01] = &gbRom[0x1000]; |
1825 gbMemoryMap[0x02] = &gbRom[0x2000]; | 1825 gbMemoryMap[0x02] = &gbRom[0x2000]; |
1826 gbMemoryMap[0x03] = &gbRom[0x3000]; | 1826 gbMemoryMap[0x03] = &gbRom[0x3000]; |
1827 gbMemoryMap[0x04] = &gbRom[0x4000]; | 1827 gbMemoryMap[0x04] = &gbRom[0x4000]; |
1828 gbMemoryMap[0x05] = &gbRom[0x5000]; | 1828 gbMemoryMap[0x05] = &gbRom[0x5000]; |
1829 gbMemoryMap[0x06] = &gbRom[0x6000]; | 1829 gbMemoryMap[0x06] = &gbRom[0x6000]; |
1830 gbMemoryMap[0x07] = &gbRom[0x7000]; | 1830 gbMemoryMap[0x07] = &gbRom[0x7000]; |
1831 if (gbCgbMode) | 1831 if (gbCgbMode) |
1832 { | 1832 { |
1833 gbMemoryMap[0x08] = &gbVram[0x0000]; | 1833 gbMemoryMap[0x08] = &gbVram[0x0000]; |
1834 gbMemoryMap[0x09] = &gbVram[0x1000]; | 1834 gbMemoryMap[0x09] = &gbVram[0x1000]; |
1835 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | 1835 gbMemoryMap[0x0a] = &gbMemory[0xa000]; |
1836 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | 1836 gbMemoryMap[0x0b] = &gbMemory[0xb000]; |
1837 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | 1837 gbMemoryMap[0x0c] = &gbMemory[0xc000]; |
1838 gbMemoryMap[0x0d] = &gbWram[0x1000]; | 1838 gbMemoryMap[0x0d] = &gbWram[0x1000]; |
1839 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | 1839 gbMemoryMap[0x0e] = &gbMemory[0xe000]; |
1840 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | 1840 gbMemoryMap[0x0f] = &gbMemory[0xf000]; |
1841 } | 1841 } |
1842 else | 1842 else |
1843 { | 1843 { |
1844 gbMemoryMap[0x08] = &gbMemory[0x8000]; | 1844 gbMemoryMap[0x08] = &gbMemory[0x8000]; |
1845 gbMemoryMap[0x09] = &gbMemory[0x9000]; | 1845 gbMemoryMap[0x09] = &gbMemory[0x9000]; |
1846 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | 1846 gbMemoryMap[0x0a] = &gbMemory[0xa000]; |
1847 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | 1847 gbMemoryMap[0x0b] = &gbMemory[0xb000]; |
1848 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | 1848 gbMemoryMap[0x0c] = &gbMemory[0xc000]; |
1849 gbMemoryMap[0x0d] = &gbMemory[0xd000]; | 1849 gbMemoryMap[0x0d] = &gbMemory[0xd000]; |
1850 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | 1850 gbMemoryMap[0x0e] = &gbMemory[0xe000]; |
1851 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | 1851 gbMemoryMap[0x0f] = &gbMemory[0xf000]; |
1852 } | 1852 } |
1853 | 1853 |
1854 if (gbRam) | 1854 if (gbRam) |
1855 { | 1855 { |
1856 gbMemoryMap[0x0a] = &gbRam[0x0000]; | 1856 gbMemoryMap[0x0a] = &gbRam[0x0000]; |
1857 gbMemoryMap[0x0b] = &gbRam[0x1000]; | 1857 gbMemoryMap[0x0b] = &gbRam[0x1000]; |
1858 } | 1858 } |
1859 | 1859 |
1860 gbSoundReset(); | 1860 gbSoundReset(); |
1861 | 1861 |
1862 systemResetSensor(); | 1862 systemResetSensor(); |
1863 | 1863 |
1864 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | 1864 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; |
1865 | 1865 |
1866 gbLastTime = systemGetClock(); | 1866 gbLastTime = systemGetClock(); |
1867 gbFrameCount = 0; | 1867 gbFrameCount = 0; |
1868 | 1868 |
1869 systemRefreshScreen(); | 1869 systemRefreshScreen(); |
1870 } | 1870 } |
1871 | 1871 |
1872 void gbWriteSaveMBC1(const char *name) | 1872 void gbWriteSaveMBC1(const char *name) |
1873 { | 1873 { |
1874 FILE *gzFile = fopen(name, "wb"); | 1874 FILE *gzFile = fopen(name, "wb"); |
1875 | 1875 |
1876 if (gzFile == NULL) | 1876 if (gzFile == NULL) |
1877 { | 1877 { |
1878 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | 1878 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); |
1879 return; | 1879 return; |
1880 } | 1880 } |
1881 | 1881 |
1882 fwrite(gbRam, | 1882 fwrite(gbRam, |
1883 1, | 1883 1, |
1884 gbRamSize, | 1884 gbRamSize, |
1885 gzFile); | 1885 gzFile); |
1886 | 1886 |
1887 fclose(gzFile); | 1887 fclose(gzFile); |
1888 } | 1888 } |
1889 | 1889 |
1890 void gbWriteSaveMBC2(const char *name) | 1890 void gbWriteSaveMBC2(const char *name) |
1891 { | 1891 { |
1892 FILE *file = fopen(name, "wb"); | 1892 FILE *file = fopen(name, "wb"); |
1893 | 1893 |
1894 if (file == NULL) | 1894 if (file == NULL) |
1895 { | 1895 { |
1896 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | 1896 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); |
1897 return; | 1897 return; |
1898 } | 1898 } |
1899 | 1899 |
1900 fwrite(&gbMemory[0xa000], | 1900 fwrite(&gbMemory[0xa000], |
1901 1, | 1901 1, |
1902 256, | 1902 256, |
1903 file); | 1903 file); |
1904 | 1904 |
1905 fclose(file); | 1905 fclose(file); |
1906 } | 1906 } |
1907 | 1907 |
1908 void gbWriteSaveMBC3(const char *name, bool extendedSave) | 1908 void gbWriteSaveMBC3(const char *name, bool extendedSave) |
1909 { | 1909 { |
1910 FILE *gzFile = fopen(name, "wb"); | 1910 FILE *gzFile = fopen(name, "wb"); |
1911 | 1911 |
1912 if (gzFile == NULL) | 1912 if (gzFile == NULL) |
1913 { | 1913 { |
1914 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | 1914 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); |
1915 return; | 1915 return; |
1916 } | 1916 } |
1917 | 1917 |
1918 fwrite(gbRam, | 1918 fwrite(gbRam, |
1919 1, | 1919 1, |
1920 gbRamSize, | 1920 gbRamSize, |
1921 gzFile); | 1921 gzFile); |
1922 | 1922 |
1923 if (extendedSave) | 1923 if (extendedSave) |
1924 { | 1924 { |
1925 //assert(sizeof(time_t) == 4); | 1925 //assert(sizeof(time_t) == 4); |
1926 fwrite(&gbDataMBC3.mapperSeconds, | 1926 fwrite(&gbDataMBC3.mapperSeconds, |
1927 1, | 1927 1, |
1928 10 * sizeof(int32) + /*sizeof(time_t)*/4, | 1928 10 * sizeof(int32) + /*sizeof(time_t)*/4, |
1929 gzFile); | 1929 gzFile); |
1930 } | 1930 } |
1931 | 1931 |
1932 fclose(gzFile); | 1932 fclose(gzFile); |
1933 } | 1933 } |
1934 | 1934 |
1935 void gbWriteSaveMBC5(const char *name) | 1935 void gbWriteSaveMBC5(const char *name) |
1936 { | 1936 { |
1937 FILE *gzFile = fopen(name, "wb"); | 1937 FILE *gzFile = fopen(name, "wb"); |
1938 | 1938 |
1939 if (gzFile == NULL) | 1939 if (gzFile == NULL) |
1940 { | 1940 { |
1941 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | 1941 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); |
1942 return; | 1942 return; |
1943 } | 1943 } |
1944 | 1944 |
1945 fwrite(gbRam, | 1945 fwrite(gbRam, |
1946 1, | 1946 1, |
1947 gbRamSize, | 1947 gbRamSize, |
1948 gzFile); | 1948 gzFile); |
1949 | 1949 |
1950 fclose(gzFile); | 1950 fclose(gzFile); |
1951 } | 1951 } |
1952 | 1952 |
1953 void gbWriteSaveMBC7(const char *name) | 1953 void gbWriteSaveMBC7(const char *name) |
1954 { | 1954 { |
1955 FILE *file = fopen(name, "wb"); | 1955 FILE *file = fopen(name, "wb"); |
1956 | 1956 |
1957 if (file == NULL) | 1957 if (file == NULL) |
1958 { | 1958 { |
1959 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | 1959 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); |
1960 return; | 1960 return; |
1961 } | 1961 } |
1962 | 1962 |
1963 fwrite(&gbMemory[0xa000], | 1963 fwrite(&gbMemory[0xa000], |
1964 1, | 1964 1, |
1965 256, | 1965 256, |
1966 file); | 1966 file); |
1967 | 1967 |
1968 fclose(file); | 1968 fclose(file); |
1969 } | 1969 } |
1970 | 1970 |
1971 bool gbReadSaveMBC1(const char *name) | 1971 bool gbReadSaveMBC1(const char *name) |
1972 { | 1972 { |
1973 gzFile gzFile = gzopen(name, "rb"); | 1973 gzFile gzFile = gzopen(name, "rb"); |
1974 | 1974 |
1975 if (gzFile == NULL) | 1975 if (gzFile == NULL) |
1976 { | 1976 { |
1977 return false; | 1977 return false; |
1978 } | 1978 } |
1979 | 1979 |
1980 int read = gzread(gzFile, | 1980 int read = gzread(gzFile, |
1981 gbRam, | 1981 gbRam, |
1982 gbRamSize); | 1982 gbRamSize); |
1983 | 1983 |
1984 if (read != gbRamSize) | 1984 if (read != gbRamSize) |
1985 { | 1985 { |
1986 systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read); | 1986 systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read); |
1987 gzclose(gzFile); | 1987 gzclose(gzFile); |
1988 return false; | 1988 return false; |
1989 } | 1989 } |
1990 | 1990 |
1991 gzclose(gzFile); | 1991 gzclose(gzFile); |
1992 return true; | 1992 return true; |
1993 } | 1993 } |
1994 | 1994 |
1995 bool gbReadSaveMBC2(const char *name) | 1995 bool gbReadSaveMBC2(const char *name) |
1996 { | 1996 { |
1997 FILE *file = fopen(name, "rb"); | 1997 FILE *file = fopen(name, "rb"); |
1998 | 1998 |
1999 if (file == NULL) | 1999 if (file == NULL) |
2000 { | 2000 { |
2001 return false; | 2001 return false; |
2002 } | 2002 } |
2003 | 2003 |
2004 int read = fread(&gbMemory[0xa000], | 2004 int read = fread(&gbMemory[0xa000], |
2005 1, | 2005 1, |
2006 256, | 2006 256, |
2007 file); | 2007 file); |
2008 | 2008 |
2009 if (read != 256) | 2009 if (read != 256) |
2010 { | 2010 { |
2011 systemMessage(MSG_FAILED_TO_READ_SGM, | 2011 systemMessage(MSG_FAILED_TO_READ_SGM, |
2012 N_("Failed to read complete save game %s (%d)"), name, read); | 2012 N_("Failed to read complete save game %s (%d)"), name, read); |
2013 fclose(file); | 2013 fclose(file); |
2014 return false; | 2014 return false; |
2015 } | 2015 } |
2016 | 2016 |
2017 fclose(file); | 2017 fclose(file); |
2018 return true; | 2018 return true; |
2019 } | 2019 } |
2020 | 2020 |
2021 bool gbReadSaveMBC3(const char *name) | 2021 bool gbReadSaveMBC3(const char *name) |
2022 { | 2022 { |
2023 gzFile gzFile = gzopen(name, "rb"); | 2023 gzFile gzFile = gzopen(name, "rb"); |
2024 | 2024 |
2025 if (gzFile == NULL) | 2025 if (gzFile == NULL) |
2026 { | 2026 { |
2027 return false; | 2027 return false; |
2028 } | 2028 } |
2029 | 2029 |
2030 int read = gzread(gzFile, | 2030 int read = gzread(gzFile, |
2031 gbRam, | 2031 gbRam, |
2032 gbRamSize); | 2032 gbRamSize); |
2033 | 2033 |
2034 bool res = true; | 2034 bool res = true; |
2035 | 2035 |
2036 if (read != gbRamSize) | 2036 if (read != gbRamSize) |
2037 { | 2037 { |
2038 systemMessage(MSG_FAILED_TO_READ_SGM, | 2038 systemMessage(MSG_FAILED_TO_READ_SGM, |
2039 N_("Failed to read complete save game %s (%d)"), name, read); | 2039 N_("Failed to read complete save game %s (%d)"), name, read); |
2040 } | 2040 } |
2041 else | 2041 else |
2042 { | 2042 { |
2043 //assert(sizeof(time_t) == 4); | 2043 //assert(sizeof(time_t) == 4); |
2044 read = gzread(gzFile, | 2044 read = gzread(gzFile, |
2045 &gbDataMBC3.mapperSeconds, | 2045 &gbDataMBC3.mapperSeconds, |
2046 sizeof(int32) * 10 + /*sizeof(time_t)*/4); | 2046 sizeof(int32) * 10 + /*sizeof(time_t)*/4); |
2047 | 2047 |
2048 if (read != (sizeof(int32) * 10 + /*sizeof(time_t)*/4) && read != 0) | 2048 if (read != (sizeof(int32) * 10 + /*sizeof(time_t)*/4) && read != 0) |
2049 { | 2049 { |
2050 systemMessage(MSG_FAILED_TO_READ_RTC, | 2050 systemMessage(MSG_FAILED_TO_READ_RTC, |
2051 N_("Failed to read RTC from save game %s (continuing)"), | 2051 N_("Failed to read RTC from save game %s (continuing)"), |
2052 name); | 2052 name); |
2053 res = false; | 2053 res = false; |
2054 } | 2054 } |
2055 } | 2055 } |
2056 | 2056 |
2057 gzclose(gzFile); | 2057 gzclose(gzFile); |
2058 return res; | 2058 return res; |
2059 } | 2059 } |
2060 | 2060 |
2061 bool gbReadSaveMBC5(const char *name) | 2061 bool gbReadSaveMBC5(const char *name) |
2062 { | 2062 { |
2063 gzFile gzFile = gzopen(name, "rb"); | 2063 gzFile gzFile = gzopen(name, "rb"); |
2064 | 2064 |
2065 if (gzFile == NULL) | 2065 if (gzFile == NULL) |
2066 { | 2066 { |
2067 return false; | 2067 return false; |
2068 } | 2068 } |
2069 | 2069 |
2070 int read = gzread(gzFile, | 2070 int read = gzread(gzFile, |
2071 gbRam, | 2071 gbRam, |
2072 gbRamSize); | 2072 gbRamSize); |
2073 | 2073 |
2074 if (read != gbRamSize) | 2074 if (read != gbRamSize) |
2075 { | 2075 { |
2076 systemMessage(MSG_FAILED_TO_READ_SGM, | 2076 systemMessage(MSG_FAILED_TO_READ_SGM, |
2077 N_("Failed to read complete save game %s (%d)"), name, read); | 2077 N_("Failed to read complete save game %s (%d)"), name, read); |
2078 gzclose(gzFile); | 2078 gzclose(gzFile); |
2079 return false; | 2079 return false; |
2080 } | 2080 } |
2081 | 2081 |
2082 gzclose(gzFile); | 2082 gzclose(gzFile); |
2083 return true; | 2083 return true; |
2084 } | 2084 } |
2085 | 2085 |
2086 bool gbReadSaveMBC7(const char *name) | 2086 bool gbReadSaveMBC7(const char *name) |
2087 { | 2087 { |
2088 FILE *file = fopen(name, "rb"); | 2088 FILE *file = fopen(name, "rb"); |
2089 | 2089 |
2090 if (file == NULL) | 2090 if (file == NULL) |
2091 { | 2091 { |
2092 return false; | 2092 return false; |
2093 } | 2093 } |
2094 | 2094 |
2095 int read = fread(&gbMemory[0xa000], | 2095 int read = fread(&gbMemory[0xa000], |
2096 1, | 2096 1, |
2097 256, | 2097 256, |
2098 file); | 2098 file); |
2099 | 2099 |
2100 if (read != 256) | 2100 if (read != 256) |
2101 { | 2101 { |
2102 systemMessage(MSG_FAILED_TO_READ_SGM, | 2102 systemMessage(MSG_FAILED_TO_READ_SGM, |
2103 N_("Failed to read complete save game %s (%d)"), name, read); | 2103 N_("Failed to read complete save game %s (%d)"), name, read); |
2104 fclose(file); | 2104 fclose(file); |
2105 return false; | 2105 return false; |
2106 } | 2106 } |
2107 | 2107 |
2108 fclose(file); | 2108 fclose(file); |
2109 return true; | 2109 return true; |
2110 } | 2110 } |
2111 | 2111 |
2112 #if 0 | 2112 #if 0 |
2113 bool gbLoadBIOS(const char *biosFileName, bool useBiosFile) | 2113 bool gbLoadBIOS(const char *biosFileName, bool useBiosFile) |
2114 { | 2114 { |
2115 useBios = false; | 2115 useBios = false; |
2116 if (useBiosFile) | 2116 if (useBiosFile) |
2117 { | 2117 { |
2118 useBios = utilLoadBIOS(bios, biosFileName, gbEmulatorType); | 2118 useBios = utilLoadBIOS(bios, biosFileName, gbEmulatorType); |
2119 if (!useBios) | 2119 if (!useBios) |
2120 { | 2120 { |
2121 systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file")); | 2121 systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file")); |
2122 } | 2122 } |
2123 } | 2123 } |
2124 return useBios; | 2124 return useBios; |
2125 } | 2125 } |
2126 #endif | 2126 #endif |
2127 | 2127 |
2128 void gbInit() | 2128 void gbInit() |
2129 { | 2129 { |
2130 gbGenFilter(); | 2130 gbGenFilter(); |
2131 gbSgbInit(); // calls gbSgbReset()... whatever | 2131 gbSgbInit(); // calls gbSgbReset()... whatever |
2132 | 2132 |
2133 gbMemory = (u8 *)malloc(65536 + 4); | 2133 gbMemory = (u8 *)malloc(65536 + 4); |
2134 memset(gbMemory, 0, 65536 + 4); | 2134 memset(gbMemory, 0, 65536 + 4); |
2135 memset(gbPalette, 0, 2 * 128); | 2135 memset(gbPalette, 0, 2 * 128); |
2136 | 2136 |
2137 // HACK: +4 at start to accomodate the 2xSaI filter reading out of bounds of the leftmost pixel | 2137 // HACK: +4 at start to accomodate the 2xSaI filter reading out of bounds of the leftmost pixel |
2138 origPix = (u8 *)calloc(1, 4 * 257 * 226 + 4); | 2138 origPix = (u8 *)calloc(1, 4 * 257 * 226 + 4); |
2139 pix = origPix + 4; | 2139 pix = origPix + 4; |
2140 | 2140 |
2141 gbLineBuffer = (u16 *)malloc(160 * sizeof(u16)); | 2141 gbLineBuffer = (u16 *)malloc(160 * sizeof(u16)); |
2142 } | 2142 } |
2143 | 2143 |
2144 bool gbWriteBatteryFile(const char *file, bool extendedSave) | 2144 bool gbWriteBatteryFile(const char *file, bool extendedSave) |
2145 { | 2145 { |
2146 if (gbBattery) | 2146 if (gbBattery) |
2147 { | 2147 { |
2148 int type = gbRom[0x147]; | 2148 int type = gbRom[0x147]; |
2149 | 2149 |
2150 switch (type) | 2150 switch (type) |
2151 { | |
2152 case 0x03: | |
2153 gbWriteSaveMBC1(file); | |
2154 break; | |
2155 case 0x06: | |
2156 gbWriteSaveMBC2(file); | |
2157 break; | |
2158 case 0x0f: | |
2159 case 0x10: | |
2160 case 0x13: | |
2161 gbWriteSaveMBC3(file, extendedSave); | |
2162 break; | |
2163 case 0x1b: | |
2164 case 0x1e: | |
2165 gbWriteSaveMBC5(file); | |
2166 break; | |
2167 case 0x22: | |
2168 gbWriteSaveMBC7(file); | |
2169 break; | |
2170 case 0xff: | |
2171 gbWriteSaveMBC1(file); | |
2172 break; | |
2173 } | |
2174 } | |
2175 return true; | |
2176 } | |
2177 | |
2178 bool gbWriteBatteryFile(const char *file) | |
2179 { | |
2180 gbWriteBatteryFile(file, true); | |
2181 return true; | |
2182 } | |
2183 | |
2184 bool gbWriteBatteryToStream(gzFile gzfile) | |
2185 { | |
2186 // the GB save code is ugly, so rather than convert it all to use gzFiles, just save it to a temp file... | |
2187 #define TEMP_SAVE_FNAME ("tempvbawrite.sav") | |
2188 bool retVal = gbWriteBatteryFile(TEMP_SAVE_FNAME, true); | |
2189 | |
2190 // ...open the temp file and figure out its size... | |
2191 FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "rb"); | |
2192 if (fileTemp == NULL) | |
2193 return false; | |
2194 fseek(fileTemp, 0, SEEK_END); | |
2195 int len = (int) ftell(fileTemp); | |
2196 | |
2197 // ...copy over the temp file... | |
2198 char *temp = new char [len]; | |
2199 fseek(fileTemp, 0, SEEK_SET); | |
2200 if (fread(temp, len, 1, fileTemp) != 1) | |
2201 { | |
2202 delete [] temp; | |
2203 fclose(fileTemp); | |
2204 return false; | |
2205 } | |
2206 fclose(fileTemp); | |
2207 utilGzWrite(gzfile, temp, len); | |
2208 delete [] temp; | |
2209 | |
2210 // ... and delete the temp file | |
2211 remove(TEMP_SAVE_FNAME); | |
2212 #undef TEMP_SAVE_FNAME | |
2213 | |
2214 return retVal; | |
2215 } | |
2216 | |
2217 bool gbReadBatteryFile(const char *file) | |
2218 { | |
2219 bool res = false; | |
2220 if (gbBattery) | |
2221 { | |
2222 int type = gbRom[0x147]; | |
2223 | |
2224 switch (type) | |
2225 { | |
2226 case 0x03: | |
2227 res = gbReadSaveMBC1(file); | |
2228 break; | |
2229 case 0x06: | |
2230 res = gbReadSaveMBC2(file); | |
2231 break; | |
2232 case 0x0f: | |
2233 case 0x10: | |
2234 case 0x13: | |
2235 if (!gbReadSaveMBC3(file)) | |
2236 { | |
2237 struct tm *lt; | |
2238 time_t tmp; //Small kludge to get it working on some systems where time_t has size 8. | |
2239 | |
2240 if (VBAMovieActive() || VBAMovieLoading()) | |
2241 { | |
2242 gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter() / 60; | |
2243 lt = gmtime(&tmp); | |
2244 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2245 } | |
2246 else | |
2247 { | |
2248 time(&tmp); | |
2249 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2250 lt = localtime(&tmp); | |
2251 } | |
2252 systemScreenMessage(ctime(&tmp), 4); | |
2253 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2254 | |
2255 gbDataMBC3.mapperSeconds = lt->tm_sec; | |
2256 gbDataMBC3.mapperMinutes = lt->tm_min; | |
2257 gbDataMBC3.mapperHours = lt->tm_hour; | |
2258 gbDataMBC3.mapperDays = lt->tm_yday & 255; | |
2259 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | | |
2260 (lt->tm_yday > 255 ? 1 : 0); | |
2261 res = false; | |
2262 break; | |
2263 } | |
2264 time_t tmp; | |
2265 systemScreenMessage(ctime(&tmp), 4); | |
2266 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2267 res = true; | |
2268 break; | |
2269 case 0x1b: | |
2270 case 0x1e: | |
2271 res = gbReadSaveMBC5(file); | |
2272 break; | |
2273 case 0x22: | |
2274 res = gbReadSaveMBC7(file); | |
2275 case 0xff: | |
2276 res = gbReadSaveMBC1(file); | |
2277 break; | |
2278 } | |
2279 } | |
2280 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
2281 return res; | |
2282 } | |
2283 | |
2284 bool gbReadBatteryFromStream(gzFile gzfile) | |
2285 { | |
2286 // the GB save code is ugly, so rather than convert it all to use gzFiles, just copy it to temp RAM... | |
2287 #define TEMP_SAVE_FNAME ("tempvbaread.sav") | |
2288 int pos = gztell(gzfile); | |
2289 int buflen = 1024; | |
2290 // ...make a temp file and write it there... | |
2291 FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "wb"); | |
2292 if (fileTemp == NULL) | |
2293 return false; | |
2294 int gzDeflated; | |
2295 char *temp = new char [buflen]; | |
2296 while ((gzDeflated = utilGzRead(gzfile, temp, buflen)) != 0) | |
2297 { | |
2298 if (gzDeflated == -1 || fwrite(temp, gzDeflated, 1, fileTemp) != 1) | |
2299 { | |
2300 delete [] temp; | |
2301 fclose(fileTemp); | |
2302 gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that | |
2303 // calls this right now does a seek afterwards so it doesn't matter for now, but it's | |
2304 // still bad) | |
2305 return false; | |
2306 } | |
2307 } | |
2308 gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that calls this | |
2309 // right now does a seek afterwards so it doesn't matter for now, but it's still bad) | |
2310 fclose(fileTemp); | |
2311 delete [] temp; | |
2312 | |
2313 // ... load from the temp file... | |
2314 bool retVal = gbReadBatteryFile(TEMP_SAVE_FNAME); | |
2315 | |
2316 // ... and delete the temp file | |
2317 remove(TEMP_SAVE_FNAME); | |
2318 #undef TEMP_SAVE_FNAME | |
2319 | |
2320 return retVal; | |
2321 } | |
2322 | |
2323 bool gbReadGSASnapshot(const char *fileName) | |
2324 { | |
2325 FILE *file = fopen(fileName, "rb"); | |
2326 | |
2327 if (!file) | |
2328 { | |
2329 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); | |
2330 return false; | |
2331 } | |
2332 | |
2333 // long size = ftell(file); | |
2334 fseek(file, 0x4, SEEK_SET); | |
2335 char buffer[16]; | |
2336 char buffer2[16]; | |
2337 fread(buffer, 1, 15, file); | |
2338 buffer[15] = 0; | |
2339 memcpy(buffer2, &gbRom[0x134], 15); | |
2340 buffer2[15] = 0; | |
2341 if (memcmp(buffer, buffer2, 15)) | |
2342 { | |
2343 systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, | |
2344 N_("Cannot import snapshot for %s. Current game is %s"), | |
2345 buffer, | |
2346 buffer2); | |
2347 fclose(file); | |
2348 return false; | |
2349 } | |
2350 fseek(file, 0x13, SEEK_SET); | |
2351 int read = 0; | |
2352 int toRead = 0; | |
2353 switch (gbRom[0x147]) | |
2354 { | 2151 { |
2355 case 0x03: | 2152 case 0x03: |
2153 gbWriteSaveMBC1(file); | |
2154 break; | |
2155 case 0x06: | |
2156 gbWriteSaveMBC2(file); | |
2157 break; | |
2356 case 0x0f: | 2158 case 0x0f: |
2357 case 0x10: | 2159 case 0x10: |
2358 case 0x13: | 2160 case 0x13: |
2161 gbWriteSaveMBC3(file, extendedSave); | |
2162 break; | |
2359 case 0x1b: | 2163 case 0x1b: |
2360 case 0x1e: | 2164 case 0x1e: |
2165 gbWriteSaveMBC5(file); | |
2166 break; | |
2167 case 0x22: | |
2168 gbWriteSaveMBC7(file); | |
2169 break; | |
2361 case 0xff: | 2170 case 0xff: |
2362 read = fread(gbRam, 1, gbRamSize, file); | 2171 gbWriteSaveMBC1(file); |
2363 toRead = gbRamSize; | 2172 break; |
2364 break; | 2173 } |
2174 } | |
2175 return true; | |
2176 } | |
2177 | |
2178 bool gbWriteBatteryFile(const char *file) | |
2179 { | |
2180 gbWriteBatteryFile(file, true); | |
2181 return true; | |
2182 } | |
2183 | |
2184 bool gbWriteBatteryToStream(gzFile gzfile) | |
2185 { | |
2186 // the GB save code is ugly, so rather than convert it all to use gzFiles, just save it to a temp file... | |
2187 #define TEMP_SAVE_FNAME ("tempvbawrite.sav") | |
2188 bool retVal = gbWriteBatteryFile(TEMP_SAVE_FNAME, true); | |
2189 | |
2190 // ...open the temp file and figure out its size... | |
2191 FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "rb"); | |
2192 if (fileTemp == NULL) | |
2193 return false; | |
2194 fseek(fileTemp, 0, SEEK_END); | |
2195 int len = (int) ftell(fileTemp); | |
2196 | |
2197 // ...copy over the temp file... | |
2198 char *temp = new char [len]; | |
2199 fseek(fileTemp, 0, SEEK_SET); | |
2200 if (fread(temp, len, 1, fileTemp) != 1) | |
2201 { | |
2202 delete [] temp; | |
2203 fclose(fileTemp); | |
2204 return false; | |
2205 } | |
2206 fclose(fileTemp); | |
2207 utilGzWrite(gzfile, temp, len); | |
2208 delete [] temp; | |
2209 | |
2210 // ... and delete the temp file | |
2211 remove(TEMP_SAVE_FNAME); | |
2212 #undef TEMP_SAVE_FNAME | |
2213 | |
2214 return retVal; | |
2215 } | |
2216 | |
2217 bool gbReadBatteryFile(const char *file) | |
2218 { | |
2219 bool res = false; | |
2220 if (gbBattery) | |
2221 { | |
2222 int type = gbRom[0x147]; | |
2223 | |
2224 switch (type) | |
2225 { | |
2226 case 0x03: | |
2227 res = gbReadSaveMBC1(file); | |
2228 break; | |
2365 case 0x06: | 2229 case 0x06: |
2230 res = gbReadSaveMBC2(file); | |
2231 break; | |
2232 case 0x0f: | |
2233 case 0x10: | |
2234 case 0x13: | |
2235 if (!gbReadSaveMBC3(file)) | |
2236 { | |
2237 struct tm *lt; | |
2238 time_t tmp; //Small kludge to get it working on some systems where time_t has size 8. | |
2239 | |
2240 if (VBAMovieActive() || VBAMovieLoading()) | |
2241 { | |
2242 gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter() / 60; | |
2243 lt = gmtime(&tmp); | |
2244 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2245 } | |
2246 else | |
2247 { | |
2248 time(&tmp); | |
2249 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2250 lt = localtime(&tmp); | |
2251 } | |
2252 systemScreenMessage(ctime(&tmp), 4); | |
2253 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2254 | |
2255 gbDataMBC3.mapperSeconds = lt->tm_sec; | |
2256 gbDataMBC3.mapperMinutes = lt->tm_min; | |
2257 gbDataMBC3.mapperHours = lt->tm_hour; | |
2258 gbDataMBC3.mapperDays = lt->tm_yday & 255; | |
2259 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) | | |
2260 (lt->tm_yday > 255 ? 1 : 0); | |
2261 res = false; | |
2262 break; | |
2263 } | |
2264 time_t tmp; | |
2265 systemScreenMessage(ctime(&tmp), 4); | |
2266 gbDataMBC3.mapperLastTime=(u32)tmp; | |
2267 res = true; | |
2268 break; | |
2269 case 0x1b: | |
2270 case 0x1e: | |
2271 res = gbReadSaveMBC5(file); | |
2272 break; | |
2366 case 0x22: | 2273 case 0x22: |
2367 read = fread(&gbMemory[0xa000], 1, 256, file); | 2274 res = gbReadSaveMBC7(file); |
2368 toRead = 256; | 2275 case 0xff: |
2369 break; | 2276 res = gbReadSaveMBC1(file); |
2370 default: | 2277 break; |
2371 systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE, | 2278 } |
2372 N_("Unsupported snapshot file %s"), | 2279 } |
2373 fileName); | 2280 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; |
2374 fclose(file); | 2281 return res; |
2375 return false; | 2282 } |
2376 } | 2283 |
2377 fclose(file); | 2284 bool gbReadBatteryFromStream(gzFile gzfile) |
2378 gbReset(); | 2285 { |
2379 return true; | 2286 // the GB save code is ugly, so rather than convert it all to use gzFiles, just copy it to temp RAM... |
2287 #define TEMP_SAVE_FNAME ("tempvbaread.sav") | |
2288 int pos = gztell(gzfile); | |
2289 int buflen = 1024; | |
2290 // ...make a temp file and write it there... | |
2291 FILE *fileTemp = fopen(TEMP_SAVE_FNAME, "wb"); | |
2292 if (fileTemp == NULL) | |
2293 return false; | |
2294 int gzDeflated; | |
2295 char *temp = new char [buflen]; | |
2296 while ((gzDeflated = utilGzRead(gzfile, temp, buflen)) != 0) | |
2297 { | |
2298 if (gzDeflated == -1 || fwrite(temp, gzDeflated, 1, fileTemp) != 1) | |
2299 { | |
2300 delete [] temp; | |
2301 fclose(fileTemp); | |
2302 gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that | |
2303 // calls this right now does a seek afterwards so it doesn't matter for now, but it's | |
2304 // still bad) | |
2305 return false; | |
2306 } | |
2307 } | |
2308 gzseek(gzfile, pos, SEEK_SET); /// FIXME: leaves pos in gzfile before save instead of after it (everything that calls this | |
2309 // right now does a seek afterwards so it doesn't matter for now, but it's still bad) | |
2310 fclose(fileTemp); | |
2311 delete [] temp; | |
2312 | |
2313 // ... load from the temp file... | |
2314 bool retVal = gbReadBatteryFile(TEMP_SAVE_FNAME); | |
2315 | |
2316 // ... and delete the temp file | |
2317 remove(TEMP_SAVE_FNAME); | |
2318 #undef TEMP_SAVE_FNAME | |
2319 | |
2320 return retVal; | |
2321 } | |
2322 | |
2323 bool gbReadGSASnapshot(const char *fileName) | |
2324 { | |
2325 FILE *file = fopen(fileName, "rb"); | |
2326 | |
2327 if (!file) | |
2328 { | |
2329 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName); | |
2330 return false; | |
2331 } | |
2332 | |
2333 // long size = ftell(file); | |
2334 fseek(file, 0x4, SEEK_SET); | |
2335 char buffer[16]; | |
2336 char buffer2[16]; | |
2337 fread(buffer, 1, 15, file); | |
2338 buffer[15] = 0; | |
2339 memcpy(buffer2, &gbRom[0x134], 15); | |
2340 buffer2[15] = 0; | |
2341 if (memcmp(buffer, buffer2, 15)) | |
2342 { | |
2343 systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR, | |
2344 N_("Cannot import snapshot for %s. Current game is %s"), | |
2345 buffer, | |
2346 buffer2); | |
2347 fclose(file); | |
2348 return false; | |
2349 } | |
2350 fseek(file, 0x13, SEEK_SET); | |
2351 int read = 0; | |
2352 int toRead = 0; | |
2353 switch (gbRom[0x147]) | |
2354 { | |
2355 case 0x03: | |
2356 case 0x0f: | |
2357 case 0x10: | |
2358 case 0x13: | |
2359 case 0x1b: | |
2360 case 0x1e: | |
2361 case 0xff: | |
2362 read = fread(gbRam, 1, gbRamSize, file); | |
2363 toRead = gbRamSize; | |
2364 break; | |
2365 case 0x06: | |
2366 case 0x22: | |
2367 read = fread(&gbMemory[0xa000], 1, 256, file); | |
2368 toRead = 256; | |
2369 break; | |
2370 default: | |
2371 systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE, | |
2372 N_("Unsupported snapshot file %s"), | |
2373 fileName); | |
2374 fclose(file); | |
2375 return false; | |
2376 } | |
2377 fclose(file); | |
2378 gbReset(); | |
2379 return true; | |
2380 } | 2380 } |
2381 | 2381 |
2382 variable_desc gbSaveGameStruct[] = | 2382 variable_desc gbSaveGameStruct[] = |
2383 { | 2383 { |
2384 { &PC.W, sizeof(u16) }, | 2384 { &PC.W, sizeof(u16) }, |
2385 { &SP.W, sizeof(u16) }, | 2385 { &SP.W, sizeof(u16) }, |
2386 { &AF.W, sizeof(u16) }, | 2386 { &AF.W, sizeof(u16) }, |
2387 { &BC.W, sizeof(u16) }, | 2387 { &BC.W, sizeof(u16) }, |
2388 { &DE.W, sizeof(u16) }, | 2388 { &DE.W, sizeof(u16) }, |
2389 { &HL.W, sizeof(u16) }, | 2389 { &HL.W, sizeof(u16) }, |
2390 { &IFF, sizeof(u8) }, | 2390 { &IFF, sizeof(u8) }, |
2391 { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int32) }, | 2391 { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int32) }, |
2392 { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int32) }, | 2392 { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int32) }, |
2393 { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int32) }, | 2393 { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int32) }, |
2394 { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int32) }, | 2394 { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int32) }, |
2395 { &GBDIV_CLOCK_TICKS, sizeof(int32) }, | 2395 { &GBDIV_CLOCK_TICKS, sizeof(int32) }, |
2396 { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int32) }, | 2396 { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int32) }, |
2397 { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int32) }, | 2397 { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int32) }, |
2398 { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int32) }, | 2398 { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int32) }, |
2399 { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int32) }, | 2399 { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int32) }, |
2400 { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int32) }, | 2400 { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int32) }, |
2401 { &GBSERIAL_CLOCK_TICKS, sizeof(int32) }, | 2401 { &GBSERIAL_CLOCK_TICKS, sizeof(int32) }, |
2402 { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int32) }, | 2402 { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int32) }, |
2403 { &gbDivTicks, sizeof(int32) }, | 2403 { &gbDivTicks, sizeof(int32) }, |
2404 { &gbLcdMode, sizeof(int32) }, | 2404 { &gbLcdMode, sizeof(int32) }, |
2405 { &gbLcdTicks, sizeof(int32) }, | 2405 { &gbLcdTicks, sizeof(int32) }, |
2406 { &gbLcdLYIncrementTicks, sizeof(int32) }, | 2406 { &gbLcdLYIncrementTicks, sizeof(int32) }, |
2407 { &gbTimerTicks, sizeof(int32) }, | 2407 { &gbTimerTicks, sizeof(int32) }, |
2408 { &gbTimerClockTicks, sizeof(int32) }, | 2408 { &gbTimerClockTicks, sizeof(int32) }, |
2409 { &gbSerialTicks, sizeof(int32) }, | 2409 { &gbSerialTicks, sizeof(int32) }, |
2410 { &gbSerialBits, sizeof(int32) }, | 2410 { &gbSerialBits, sizeof(int32) }, |
2411 { &gbInterrupt, sizeof(int32) }, | 2411 { &gbInterrupt, sizeof(int32) }, |
2412 { &gbInterruptWait, sizeof(int32) }, | 2412 { &gbInterruptWait, sizeof(int32) }, |
2413 { &gbSynchronizeTicks, sizeof(int32) }, | 2413 { &gbSynchronizeTicks, sizeof(int32) }, |
2414 { &gbTimerOn, sizeof(int32) }, | 2414 { &gbTimerOn, sizeof(int32) }, |
2415 { &gbTimerMode, sizeof(int32) }, | 2415 { &gbTimerMode, sizeof(int32) }, |
2416 { &gbSerialOn, sizeof(int32) }, | 2416 { &gbSerialOn, sizeof(int32) }, |
2417 { &gbWindowLine, sizeof(int32) }, | 2417 { &gbWindowLine, sizeof(int32) }, |
2418 { &gbCgbMode, sizeof(int32) }, | 2418 { &gbCgbMode, sizeof(int32) }, |
2419 { &gbVramBank, sizeof(int32) }, | 2419 { &gbVramBank, sizeof(int32) }, |
2420 { &gbWramBank, sizeof(int32) }, | 2420 { &gbWramBank, sizeof(int32) }, |
2421 { &gbHdmaSource, sizeof(int32) }, | 2421 { &gbHdmaSource, sizeof(int32) }, |
2422 { &gbHdmaDestination, sizeof(int32) }, | 2422 { &gbHdmaDestination, sizeof(int32) }, |
2423 { &gbHdmaBytes, sizeof(int32) }, | 2423 { &gbHdmaBytes, sizeof(int32) }, |
2424 { &gbHdmaOn, sizeof(int32) }, | 2424 { &gbHdmaOn, sizeof(int32) }, |
2425 { &gbSpeed, sizeof(int32) }, | 2425 { &gbSpeed, sizeof(int32) }, |
2426 { &gbSgbMode, sizeof(int32) }, | 2426 { &gbSgbMode, sizeof(int32) }, |
2427 { ®ister_DIV, sizeof(u8) }, | 2427 { ®ister_DIV, sizeof(u8) }, |
2428 { ®ister_TIMA, sizeof(u8) }, | 2428 { ®ister_TIMA, sizeof(u8) }, |
2429 { ®ister_TMA, sizeof(u8) }, | 2429 { ®ister_TMA, sizeof(u8) }, |
2430 { ®ister_TAC, sizeof(u8) }, | 2430 { ®ister_TAC, sizeof(u8) }, |
2431 { ®ister_IF, sizeof(u8) }, | 2431 { ®ister_IF, sizeof(u8) }, |
2432 { ®ister_LCDC, sizeof(u8) }, | 2432 { ®ister_LCDC, sizeof(u8) }, |
2433 { ®ister_STAT, sizeof(u8) }, | 2433 { ®ister_STAT, sizeof(u8) }, |
2434 { ®ister_SCY, sizeof(u8) }, | 2434 { ®ister_SCY, sizeof(u8) }, |
2435 { ®ister_SCX, sizeof(u8) }, | 2435 { ®ister_SCX, sizeof(u8) }, |
2436 { ®ister_LY, sizeof(u8) }, | 2436 { ®ister_LY, sizeof(u8) }, |
2437 { ®ister_LYC, sizeof(u8) }, | 2437 { ®ister_LYC, sizeof(u8) }, |
2438 { ®ister_DMA, sizeof(u8) }, | 2438 { ®ister_DMA, sizeof(u8) }, |
2439 { ®ister_WY, sizeof(u8) }, | 2439 { ®ister_WY, sizeof(u8) }, |
2440 { ®ister_WX, sizeof(u8) }, | 2440 { ®ister_WX, sizeof(u8) }, |
2441 { ®ister_VBK, sizeof(u8) }, | 2441 { ®ister_VBK, sizeof(u8) }, |
2442 { ®ister_HDMA1, sizeof(u8) }, | 2442 { ®ister_HDMA1, sizeof(u8) }, |
2443 { ®ister_HDMA2, sizeof(u8) }, | 2443 { ®ister_HDMA2, sizeof(u8) }, |
2444 { ®ister_HDMA3, sizeof(u8) }, | 2444 { ®ister_HDMA3, sizeof(u8) }, |
2445 { ®ister_HDMA4, sizeof(u8) }, | 2445 { ®ister_HDMA4, sizeof(u8) }, |
2446 { ®ister_HDMA5, sizeof(u8) }, | 2446 { ®ister_HDMA5, sizeof(u8) }, |
2447 { ®ister_SVBK, sizeof(u8) }, | 2447 { ®ister_SVBK, sizeof(u8) }, |
2448 { ®ister_IE, sizeof(u8) }, | 2448 { ®ister_IE, sizeof(u8) }, |
2449 { &gbBgp[0], sizeof(u8) }, | 2449 { &gbBgp[0], sizeof(u8) }, |
2450 { &gbBgp[1], sizeof(u8) }, | 2450 { &gbBgp[1], sizeof(u8) }, |
2451 { &gbBgp[2], sizeof(u8) }, | 2451 { &gbBgp[2], sizeof(u8) }, |
2452 { &gbBgp[3], sizeof(u8) }, | 2452 { &gbBgp[3], sizeof(u8) }, |
2453 { &gbObp0[0], sizeof(u8) }, | 2453 { &gbObp0[0], sizeof(u8) }, |
2454 { &gbObp0[1], sizeof(u8) }, | 2454 { &gbObp0[1], sizeof(u8) }, |
2455 { &gbObp0[2], sizeof(u8) }, | 2455 { &gbObp0[2], sizeof(u8) }, |
2456 { &gbObp0[3], sizeof(u8) }, | 2456 { &gbObp0[3], sizeof(u8) }, |
2457 { &gbObp1[0], sizeof(u8) }, | 2457 { &gbObp1[0], sizeof(u8) }, |
2458 { &gbObp1[1], sizeof(u8) }, | 2458 { &gbObp1[1], sizeof(u8) }, |
2459 { &gbObp1[2], sizeof(u8) }, | 2459 { &gbObp1[2], sizeof(u8) }, |
2460 { &gbObp1[3], sizeof(u8) }, | 2460 { &gbObp1[3], sizeof(u8) }, |
2461 { NULL, 0 } | 2461 { NULL, 0 } |
2462 }; | 2462 }; |
2463 | 2463 |
2464 bool gbWriteSaveStateToStream(gzFile gzFile) | 2464 bool gbWriteSaveStateToStream(gzFile gzFile) |
2465 { | 2465 { |
2466 utilWriteInt(gzFile, GBSAVE_GAME_VERSION); | 2466 utilWriteInt(gzFile, GBSAVE_GAME_VERSION); |
2467 | 2467 |
2468 utilGzWrite(gzFile, &gbRom[0x134], 15); | 2468 utilGzWrite(gzFile, &gbRom[0x134], 15); |
2469 | 2469 |
2470 utilWriteData(gzFile, gbSaveGameStruct); | 2470 utilWriteData(gzFile, gbSaveGameStruct); |
2471 | 2471 |
2472 utilGzWrite(gzFile, &IFF, 2); | 2472 utilGzWrite(gzFile, &IFF, 2); |
2473 | 2473 |
2474 if (gbSgbMode) | 2474 if (gbSgbMode) |
2475 { | 2475 { |
2476 gbSgbSaveGame(gzFile); | 2476 gbSgbSaveGame(gzFile); |
2477 } | 2477 } |
2478 | 2478 |
2479 utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); | 2479 utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); |
2480 utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); | 2480 utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); |
2481 //assert(sizeof(time_t) == 4); | 2481 //assert(sizeof(time_t) == 4); |
2482 utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); | 2482 utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); |
2483 utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); | 2483 utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); |
2484 utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); | 2484 utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); |
2485 utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); | 2485 utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); |
2486 | 2486 |
2487 // yes, this definitely needs to be saved, or loading paused games will show a black screen | 2487 // yes, this definitely needs to be saved, or loading paused games will show a black screen |
2488 // this is also necessary to be consistent with what the GBA saving does | 2488 // this is also necessary to be consistent with what the GBA saving does |
2489 utilGzWrite(gzFile, pix, 4 * 257 * 226); | 2489 utilGzWrite(gzFile, pix, 4 * 257 * 226); |
2490 | 2490 |
2491 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); | 2491 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); |
2492 // todo: remove | 2492 // todo: remove |
2493 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); | 2493 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); |
2494 | 2494 |
2495 utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); | 2495 utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); |
2496 | 2496 |
2497 if (gbRamSize && gbRam) | 2497 if (gbRamSize && gbRam) |
2498 { | 2498 { |
2499 utilGzWrite(gzFile, gbRam, gbRamSize); | 2499 utilGzWrite(gzFile, gbRam, gbRamSize); |
2500 } | 2500 } |
2501 | 2501 |
2502 if (gbCgbMode) | 2502 if (gbCgbMode) |
2503 { | 2503 { |
2504 utilGzWrite(gzFile, gbVram, 0x4000); | 2504 utilGzWrite(gzFile, gbVram, 0x4000); |
2505 utilGzWrite(gzFile, gbWram, 0x8000); | 2505 utilGzWrite(gzFile, gbWram, 0x8000); |
2506 } | 2506 } |
2507 | 2507 |
2508 gbSoundSaveGame(gzFile); | 2508 gbSoundSaveGame(gzFile); |
2509 | 2509 |
2510 gbCheatsSaveGame(gzFile); | 2510 gbCheatsSaveGame(gzFile); |
2511 | 2511 |
2512 // new to re-recording version: | 2512 // new to re-recording version: |
2513 { | 2513 { |
2514 extern int32 sensorX, sensorY; | 2514 extern int32 sensorX, sensorY; |
2515 utilGzWrite(gzFile, &sensorX, sizeof(sensorX)); | 2515 utilGzWrite(gzFile, &sensorX, sizeof(sensorX)); |
2516 utilGzWrite(gzFile, &sensorY, sizeof(sensorY)); | 2516 utilGzWrite(gzFile, &sensorY, sizeof(sensorY)); |
2517 utilGzWrite(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get | 2517 utilGzWrite(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get |
2518 // carried | 2518 // carried |
2519 // back on loading a snapshot! | 2519 // back on loading a snapshot! |
2520 | 2520 |
2521 bool8 movieActive = VBAMovieActive(); | 2521 bool8 movieActive = VBAMovieActive(); |
2522 utilGzWrite(gzFile, &movieActive, sizeof(movieActive)); | 2522 utilGzWrite(gzFile, &movieActive, sizeof(movieActive)); |
2523 if (movieActive) | 2523 if (movieActive) |
2524 { | 2524 { |
2525 uint8 *movie_freeze_buf = NULL; | 2525 uint8 *movie_freeze_buf = NULL; |
2526 uint32 movie_freeze_size = 0; | 2526 uint32 movie_freeze_size = 0; |
2527 | 2527 |
2528 VBAMovieFreeze(&movie_freeze_buf, &movie_freeze_size); | 2528 VBAMovieFreeze(&movie_freeze_buf, &movie_freeze_size); |
2529 if (movie_freeze_buf) | 2529 if (movie_freeze_buf) |
2530 { | 2530 { |
2531 utilGzWrite(gzFile, &movie_freeze_size, sizeof(movie_freeze_size)); | 2531 utilGzWrite(gzFile, &movie_freeze_size, sizeof(movie_freeze_size)); |
2532 utilGzWrite(gzFile, movie_freeze_buf, movie_freeze_size); | 2532 utilGzWrite(gzFile, movie_freeze_buf, movie_freeze_size); |
2533 delete [] movie_freeze_buf; | 2533 delete [] movie_freeze_buf; |
2534 } | 2534 } |
2535 else | 2535 else |
2536 { | 2536 { |
2537 systemMessage(0, N_("Failed to save movie snapshot.")); | 2537 systemMessage(0, N_("Failed to save movie snapshot.")); |
2538 return false; | 2538 return false; |
2539 } | 2539 } |
2540 } | 2540 } |
2541 utilGzWrite(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); | 2541 utilGzWrite(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); |
2542 } | 2542 } |
2543 | 2543 |
2544 // new to rerecording 19.4 wip (svn r22+): | 2544 // new to rerecording 19.4 wip (svn r22+): |
2545 { | 2545 { |
2546 utilGzWrite(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); | 2546 utilGzWrite(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); |
2547 utilGzWrite(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); | 2547 utilGzWrite(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); |
2548 utilGzWrite(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); | 2548 utilGzWrite(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); |
2549 } | 2549 } |
2550 | 2550 |
2551 return true; | 2551 return true; |
2552 } | 2552 } |
2553 | 2553 |
2554 bool gbWriteMemSaveState(char *memory, int available) | 2554 bool gbWriteMemSaveState(char *memory, int available) |
2555 { | 2555 { |
2556 gzFile gzFile = utilMemGzOpen(memory, available, "w"); | 2556 gzFile gzFile = utilMemGzOpen(memory, available, "w"); |
2557 | 2557 |
2558 if (gzFile == NULL) | 2558 if (gzFile == NULL) |
2559 { | 2559 { |
2560 return false; | 2560 return false; |
2561 } | 2561 } |
2562 | 2562 |
2563 bool res = gbWriteSaveStateToStream(gzFile); | 2563 bool res = gbWriteSaveStateToStream(gzFile); |
2564 | 2564 |
2565 long pos = utilGzTell(gzFile) + 8; | 2565 long pos = utilGzTell(gzFile) + 8; |
2566 | 2566 |
2567 if (pos >= (available)) | 2567 if (pos >= (available)) |
2568 res = false; | 2568 res = false; |
2569 | 2569 |
2570 utilGzClose(gzFile); | 2570 utilGzClose(gzFile); |
2571 | 2571 |
2572 return res; | 2572 return res; |
2573 } | 2573 } |
2574 | 2574 |
2575 bool gbWriteSaveState(const char *name) | 2575 bool gbWriteSaveState(const char *name) |
2576 { | 2576 { |
2577 gzFile gzFile = utilGzOpen(name, "wb"); | 2577 gzFile gzFile = utilGzOpen(name, "wb"); |
2578 | 2578 |
2579 if (gzFile == NULL) | 2579 if (gzFile == NULL) |
2580 return false; | 2580 return false; |
2581 | 2581 |
2582 bool res = gbWriteSaveStateToStream(gzFile); | 2582 bool res = gbWriteSaveStateToStream(gzFile); |
2583 | 2583 |
2584 utilGzClose(gzFile); | 2584 utilGzClose(gzFile); |
2585 return res; | 2585 return res; |
2586 } | 2586 } |
2587 | 2587 |
2588 static int tempStateID = 0; | 2588 static int tempStateID = 0; |
2589 static int tempFailCount = 0; | 2589 static int tempFailCount = 0; |
2590 static bool backupSafe = true; | 2590 static bool backupSafe = true; |
2591 | 2591 |
2592 bool gbReadSaveStateFromStream(gzFile gzFile) | 2592 bool gbReadSaveStateFromStream(gzFile gzFile) |
2593 { | 2593 { |
2594 int type; | 2594 int type; |
2595 char tempBackupName [128]; | 2595 char tempBackupName [128]; |
2596 if (backupSafe) | 2596 if (backupSafe) |
2597 { | 2597 { |
2598 sprintf(tempBackupName, "gbatempsave%d.sav", tempStateID++); | 2598 sprintf(tempBackupName, "gbatempsave%d.sav", tempStateID++); |
2599 gbWriteSaveState(tempBackupName); | 2599 gbWriteSaveState(tempBackupName); |
2600 } | 2600 } |
2601 | 2601 |
2602 int version = utilReadInt(gzFile); | 2602 int version = utilReadInt(gzFile); |
2603 | 2603 |
2604 if (version > GBSAVE_GAME_VERSION || version < 0) | 2604 if (version > GBSAVE_GAME_VERSION || version < 0) |
2605 { | 2605 { |
2606 systemMessage(MSG_UNSUPPORTED_VB_SGM, | 2606 systemMessage(MSG_UNSUPPORTED_VB_SGM, |
2607 N_("Unsupported VisualBoy save game version %d"), version); | 2607 N_("Unsupported VisualBoy save game version %d"), version); |
2608 goto failedLoadGB; | 2608 goto failedLoadGB; |
2609 } | 2609 } |
2610 | 2610 |
2611 u8 romname[20]; | 2611 u8 romname[20]; |
2612 | 2612 |
2613 utilGzRead(gzFile, romname, 15); | 2613 utilGzRead(gzFile, romname, 15); |
2614 | 2614 |
2615 if (memcmp(&gbRom[0x134], romname, 15) != 0) | 2615 if (memcmp(&gbRom[0x134], romname, 15) != 0) |
2616 { | 2616 { |
2617 systemMessage(MSG_CANNOT_LOAD_SGM_FOR, | 2617 systemMessage(MSG_CANNOT_LOAD_SGM_FOR, |
2618 N_("Cannot load save game for %s. Playing %s"), | 2618 N_("Cannot load save game for %s. Playing %s"), |
2619 romname, &gbRom[0x134]); | 2619 romname, &gbRom[0x134]); |
2620 goto failedLoadGB; | 2620 goto failedLoadGB; |
2621 } | 2621 } |
2622 | 2622 |
2623 utilReadData(gzFile, gbSaveGameStruct); | 2623 utilReadData(gzFile, gbSaveGameStruct); |
2624 | 2624 |
2625 if (version >= GBSAVE_GAME_VERSION_7) | 2625 if (version >= GBSAVE_GAME_VERSION_7) |
2626 { | 2626 { |
2627 utilGzRead(gzFile, &IFF, 2); | 2627 utilGzRead(gzFile, &IFF, 2); |
2628 } | 2628 } |
2629 | 2629 |
2630 if (gbSgbMode) | 2630 if (gbSgbMode) |
2631 { | 2631 { |
2632 gbSgbReadGame(gzFile, version); | 2632 gbSgbReadGame(gzFile, version); |
2633 } | 2633 } |
2634 else | 2634 else |
2635 { | 2635 { |
2636 gbSgbMask = 0; // loading a game at the wrong time causes no display | 2636 gbSgbMask = 0; // loading a game at the wrong time causes no display |
2637 } | 2637 } |
2638 | 2638 |
2639 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); | 2639 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); |
2640 utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); | 2640 utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); |
2641 if (version < GBSAVE_GAME_VERSION_4) | 2641 if (version < GBSAVE_GAME_VERSION_4) |
2642 // prior to version 4, there was no adjustment for the time the game | 2642 // prior to version 4, there was no adjustment for the time the game |
2643 // was last played, so we have less to read. This needs update if the | 2643 // was last played, so we have less to read. This needs update if the |
2644 // structure changes again. | 2644 // structure changes again. |
2645 utilGzRead(gzFile, &gbDataMBC3, sizeof(int32) * 10); | 2645 utilGzRead(gzFile, &gbDataMBC3, sizeof(int32) * 10); |
2646 else | 2646 else |
2647 { | 2647 { |
2648 //assert(sizeof(time_t) == 4); | 2648 //assert(sizeof(time_t) == 4); |
2649 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); | 2649 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); |
2650 } | 2650 } |
2651 utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); | 2651 utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); |
2652 utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); | 2652 utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); |
2653 utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); | 2653 utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); |
2654 | 2654 |
2655 if (version >= GBSAVE_GAME_VERSION_12) | 2655 if (version >= GBSAVE_GAME_VERSION_12) |
2656 { | 2656 { |
2657 utilGzRead(gzFile, pix, 4 * 257 * 226); | 2657 utilGzRead(gzFile, pix, 4 * 257 * 226); |
2658 } | 2658 } |
2659 else | 2659 else |
2660 { | 2660 { |
2661 memset(pix, 0, 257 * 226 * sizeof(u32)); | 2661 memset(pix, 0, 257 * 226 * sizeof(u32)); |
2662 // if(version < GBSAVE_GAME_VERSION_5) | 2662 // if(version < GBSAVE_GAME_VERSION_5) |
2663 // utilGzRead(gzFile, pix, 256*224*sizeof(u16)); | 2663 // utilGzRead(gzFile, pix, 256*224*sizeof(u16)); |
2664 } | 2664 } |
2665 | 2665 |
2666 if (version < GBSAVE_GAME_VERSION_6) | 2666 if (version < GBSAVE_GAME_VERSION_6) |
2667 { | 2667 { |
2668 utilGzRead(gzFile, gbPalette, 64 * sizeof(u16)); | 2668 utilGzRead(gzFile, gbPalette, 64 * sizeof(u16)); |
2669 } | 2669 } |
2670 else | 2670 else |
2671 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); | 2671 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); |
2672 | 2672 |
2673 // todo: remove | 2673 // todo: remove |
2674 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); | 2674 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); |
2675 | 2675 |
2676 if (version < GBSAVE_GAME_VERSION_10) | 2676 if (version < GBSAVE_GAME_VERSION_10) |
2677 { | 2677 { |
2678 if (!gbCgbMode && !gbSgbMode) | 2678 if (!gbCgbMode && !gbSgbMode) |
2679 { | |
2680 for (int i = 0; i < 8; i++) | |
2681 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; | |
2682 } | |
2683 } | |
2684 | |
2685 utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); | |
2686 | |
2687 if (gbRamSize && gbRam) | |
2688 { | |
2689 utilGzRead(gzFile, gbRam, gbRamSize); | |
2690 } | |
2691 | |
2692 gbMemoryMap[0x00] = &gbRom[0x0000]; | |
2693 gbMemoryMap[0x01] = &gbRom[0x1000]; | |
2694 gbMemoryMap[0x02] = &gbRom[0x2000]; | |
2695 gbMemoryMap[0x03] = &gbRom[0x3000]; | |
2696 gbMemoryMap[0x04] = &gbRom[0x4000]; | |
2697 gbMemoryMap[0x05] = &gbRom[0x5000]; | |
2698 gbMemoryMap[0x06] = &gbRom[0x6000]; | |
2699 gbMemoryMap[0x07] = &gbRom[0x7000]; | |
2700 gbMemoryMap[0x08] = &gbMemory[0x8000]; | |
2701 gbMemoryMap[0x09] = &gbMemory[0x9000]; | |
2702 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | |
2703 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | |
2704 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | |
2705 gbMemoryMap[0x0d] = &gbMemory[0xd000]; | |
2706 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | |
2707 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | |
2708 | |
2709 type = gbRom[0x147]; | |
2710 | |
2711 switch (type) | |
2712 { | |
2713 case 0x00: | |
2714 case 0x01: | |
2715 case 0x02: | |
2716 case 0x03: | |
2717 // MBC 1 | |
2718 memoryUpdateMapMBC1(); | |
2719 break; | |
2720 case 0x05: | |
2721 case 0x06: | |
2722 // MBC2 | |
2723 memoryUpdateMapMBC2(); | |
2724 break; | |
2725 case 0x0f: | |
2726 case 0x10: | |
2727 case 0x11: | |
2728 case 0x12: | |
2729 case 0x13: | |
2730 // MBC 3 | |
2731 memoryUpdateMapMBC3(); | |
2732 break; | |
2733 case 0x19: | |
2734 case 0x1a: | |
2735 case 0x1b: | |
2736 // MBC5 | |
2737 memoryUpdateMapMBC5(); | |
2738 break; | |
2739 case 0x1c: | |
2740 case 0x1d: | |
2741 case 0x1e: | |
2742 // MBC 5 Rumble | |
2743 memoryUpdateMapMBC5(); | |
2744 break; | |
2745 case 0x22: | |
2746 // MBC 7 | |
2747 memoryUpdateMapMBC7(); | |
2748 break; | |
2749 case 0xfe: | |
2750 // HuC3 | |
2751 memoryUpdateMapHuC3(); | |
2752 break; | |
2753 case 0xff: | |
2754 // HuC1 | |
2755 memoryUpdateMapHuC1(); | |
2756 break; | |
2757 } | |
2758 | |
2759 if (gbCgbMode) | |
2760 { | |
2761 if (!gbVram) | |
2762 gbVram = (u8 *)malloc(0x4000 + 4); | |
2763 if (!gbWram) | |
2764 gbWram = (u8 *)malloc(0x8000 + 4); | |
2765 utilGzRead(gzFile, gbVram, 0x4000); | |
2766 utilGzRead(gzFile, gbWram, 0x8000); | |
2767 | |
2768 int value = register_SVBK; | |
2769 if (value == 0) | |
2770 value = 1; | |
2771 | |
2772 gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000]; | |
2773 gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000]; | |
2774 gbMemoryMap[0x0d] = &gbWram[value * 0x1000]; | |
2775 } | |
2776 else | |
2777 { | |
2778 if (gbVram) | |
2779 { | |
2780 free(gbVram); | |
2781 gbVram = NULL; | |
2782 } | |
2783 if (gbWram) | |
2784 { | |
2785 free(gbWram); | |
2786 gbWram = NULL; | |
2787 } | |
2788 } | |
2789 | |
2790 gbSoundReadGame(version, gzFile); | |
2791 | |
2792 #if 0 | |
2793 if (gbBorderOn) | |
2794 { | |
2795 gbSgbRenderBorder(); | |
2796 } | |
2797 | |
2798 systemRefreshScreen(); | |
2799 #endif | |
2800 | |
2801 if (version > GBSAVE_GAME_VERSION_1) | |
2802 gbCheatsReadGame(gzFile, version); | |
2803 | |
2804 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
2805 | |
2806 if (version >= GBSAVE_GAME_VERSION_11) // new to re-recording version: | |
2807 { | |
2808 extern int32 sensorX, sensorY; // from SDL.cpp | |
2809 utilGzRead(gzFile, &sensorX, sizeof(sensorX)); | |
2810 utilGzRead(gzFile, &sensorY, sizeof(sensorY)); | |
2811 utilGzRead(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get carried | |
2812 // back on loading a snapshot! | |
2813 | |
2814 bool8 movieSnapshot; | |
2815 utilGzRead(gzFile, &movieSnapshot, sizeof(movieSnapshot)); | |
2816 if (VBAMovieActive() && !movieSnapshot) | |
2817 { | |
2818 systemMessage(0, N_("Can't load a non-movie snapshot while a movie is active.")); | |
2819 goto failedLoadGB; | |
2820 } | |
2821 | |
2822 if (movieSnapshot) // even if a movie isn't active we still want to parse through this in case other stuff is added | |
2823 // later on in the save format | |
2824 { | |
2825 uint32 movieInputDataSize = 0; | |
2826 utilGzRead(gzFile, &movieInputDataSize, sizeof(movieInputDataSize)); | |
2827 uint8 *local_movie_data = new uint8 [movieInputDataSize]; | |
2828 int readBytes = utilGzRead(gzFile, local_movie_data, movieInputDataSize); | |
2829 if (readBytes != movieInputDataSize) | |
2830 { | |
2831 systemMessage(0, N_("Corrupt movie snapshot.")); | |
2832 if (local_movie_data) | |
2833 delete [] local_movie_data; | |
2834 goto failedLoadGB; | |
2835 } | |
2836 int code = VBAMovieUnfreeze(local_movie_data, movieInputDataSize); | |
2837 if (local_movie_data) | |
2838 delete [] local_movie_data; | |
2839 if (code != MOVIE_SUCCESS && VBAMovieActive()) | |
2840 { | |
2841 char errStr [1024]; | |
2842 strcpy(errStr, "Failed to load movie snapshot"); | |
2843 switch (code) | |
2679 { | 2844 { |
2680 for (int i = 0; i < 8; i++) | 2845 case MOVIE_NOT_FROM_THIS_MOVIE: |
2681 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; | 2846 strcat(errStr, ";\nSnapshot not from this movie"); break; |
2847 case MOVIE_NOT_FROM_A_MOVIE: | |
2848 strcat(errStr, ";\nNot a movie snapshot"); break; // shouldn't get here... | |
2849 case MOVIE_SNAPSHOT_INCONSISTENT: | |
2850 strcat(errStr, ";\nSnapshot inconsistent with movie"); break; | |
2851 case MOVIE_WRONG_FORMAT: | |
2852 strcat(errStr, ";\nWrong format"); break; | |
2682 } | 2853 } |
2683 } | 2854 strcat(errStr, "."); |
2684 | 2855 systemMessage(0, N_(errStr)); |
2685 utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); | 2856 goto failedLoadGB; |
2686 | 2857 } |
2687 if (gbRamSize && gbRam) | 2858 } |
2688 { | 2859 utilGzRead(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); |
2689 utilGzRead(gzFile, gbRam, gbRamSize); | 2860 } |
2690 } | 2861 |
2691 | 2862 if (version >= GBSAVE_GAME_VERSION_13) // new to rerecording 19.4 wip (svn r22+): |
2692 gbMemoryMap[0x00] = &gbRom[0x0000]; | 2863 { |
2693 gbMemoryMap[0x01] = &gbRom[0x1000]; | 2864 utilGzRead(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); |
2694 gbMemoryMap[0x02] = &gbRom[0x2000]; | 2865 utilGzRead(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); |
2695 gbMemoryMap[0x03] = &gbRom[0x3000]; | 2866 utilGzRead(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); |
2696 gbMemoryMap[0x04] = &gbRom[0x4000]; | 2867 } |
2697 gbMemoryMap[0x05] = &gbRom[0x5000]; | 2868 |
2698 gbMemoryMap[0x06] = &gbRom[0x6000]; | 2869 if (backupSafe) |
2699 gbMemoryMap[0x07] = &gbRom[0x7000]; | 2870 { |
2700 gbMemoryMap[0x08] = &gbMemory[0x8000]; | 2871 remove(tempBackupName); |
2701 gbMemoryMap[0x09] = &gbMemory[0x9000]; | 2872 tempFailCount = 0; |
2702 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | 2873 } |
2703 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | 2874 |
2704 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | 2875 for (int i = 0; i < 4; ++i) |
2705 gbMemoryMap[0x0d] = &gbMemory[0xd000]; | 2876 systemSetJoypad(i, gbJoymask[i] & 0xFFFF); |
2706 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | 2877 |
2707 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | 2878 // FIXME: horrible kludge |
2708 | 2879 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); |
2709 type = gbRom[0x147]; | 2880 |
2710 | 2881 VBAUpdateButtonPressDisplay(); |
2711 switch (type) | 2882 VBAUpdateFrameCountDisplay(); |
2712 { | 2883 systemRefreshScreen(); |
2713 case 0x00: | 2884 return true; |
2714 case 0x01: | 2885 |
2715 case 0x02: | 2886 failedLoadGB: |
2716 case 0x03: | 2887 if (backupSafe) |
2717 // MBC 1 | 2888 { |
2718 memoryUpdateMapMBC1(); | 2889 tempFailCount++; |
2719 break; | 2890 if (tempFailCount < 3) // fail no more than 2 times in a row |
2720 case 0x05: | 2891 gbReadSaveState(tempBackupName); |
2721 case 0x06: | 2892 remove(tempBackupName); |
2722 // MBC2 | 2893 } |
2723 memoryUpdateMapMBC2(); | 2894 return false; |
2724 break; | 2895 } |
2725 case 0x0f: | 2896 |
2726 case 0x10: | 2897 bool gbReadMemSaveState(char *memory, int available) |
2727 case 0x11: | 2898 { |
2728 case 0x12: | 2899 gzFile gzFile = utilMemGzOpen(memory, available, "r"); |
2729 case 0x13: | 2900 |
2730 // MBC 3 | 2901 backupSafe = false; |
2731 memoryUpdateMapMBC3(); | 2902 bool res = gbReadSaveStateFromStream(gzFile); |
2732 break; | 2903 backupSafe = true; |
2733 case 0x19: | 2904 |
2734 case 0x1a: | 2905 utilGzClose(gzFile); |
2735 case 0x1b: | 2906 |
2736 // MBC5 | 2907 return res; |
2737 memoryUpdateMapMBC5(); | 2908 } |
2738 break; | 2909 |
2739 case 0x1c: | 2910 bool gbReadSaveState(const char *name) |
2740 case 0x1d: | 2911 { |
2741 case 0x1e: | 2912 gzFile gzFile = utilGzOpen(name, "rb"); |
2742 // MBC 5 Rumble | 2913 |
2743 memoryUpdateMapMBC5(); | 2914 if (gzFile == NULL) |
2744 break; | 2915 { |
2745 case 0x22: | 2916 return false; |
2746 // MBC 7 | 2917 } |
2747 memoryUpdateMapMBC7(); | 2918 |
2748 break; | 2919 bool res = gbReadSaveStateFromStream(gzFile); |
2749 case 0xfe: | 2920 |
2750 // HuC3 | 2921 utilGzClose(gzFile); |
2751 memoryUpdateMapHuC3(); | 2922 |
2752 break; | 2923 return res; |
2753 case 0xff: | 2924 } |
2754 // HuC1 | 2925 |
2755 memoryUpdateMapHuC1(); | 2926 bool gbWritePNGFile(const char *fileName) |
2756 break; | 2927 { |
2757 } | 2928 if (gbBorderOn) |
2758 | 2929 return utilWritePNGFile(fileName, 256, 224, pix); |
2759 if (gbCgbMode) | 2930 return utilWritePNGFile(fileName, 160, 144, pix); |
2760 { | 2931 } |
2761 if (!gbVram) | 2932 |
2762 gbVram = (u8 *)malloc(0x4000 + 4); | 2933 bool gbWriteBMPFile(const char *fileName) |
2763 if (!gbWram) | 2934 { |
2764 gbWram = (u8 *)malloc(0x8000 + 4); | 2935 if (gbBorderOn) |
2765 utilGzRead(gzFile, gbVram, 0x4000); | 2936 return utilWriteBMPFile(fileName, 256, 224, pix); |
2766 utilGzRead(gzFile, gbWram, 0x8000); | 2937 return utilWriteBMPFile(fileName, 160, 144, pix); |
2767 | 2938 } |
2768 int value = register_SVBK; | 2939 |
2769 if (value == 0) | 2940 void gbCleanUp() |
2770 value = 1; | 2941 { |
2771 | 2942 newFrame = true; |
2772 gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000]; | 2943 |
2773 gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000]; | 2944 GBSystemCounters.frameCount = 0; |
2774 gbMemoryMap[0x0d] = &gbWram[value * 0x1000]; | 2945 GBSystemCounters.lagCount = 0; |
2775 } | 2946 GBSystemCounters.extraCount = 0; |
2776 else | 2947 GBSystemCounters.lagged = true; |
2777 { | 2948 GBSystemCounters.laggedLast = true; |
2778 if (gbVram) | 2949 |
2950 if (gbRam != NULL) | |
2951 { | |
2952 free(gbRam); | |
2953 gbRam = NULL; | |
2954 } | |
2955 | |
2956 if (gbRom != NULL) | |
2957 { | |
2958 free(gbRom); | |
2959 gbRom = NULL; | |
2960 } | |
2961 | |
2962 if (gbMemory != NULL) | |
2963 { | |
2964 free(gbMemory); | |
2965 gbMemory = NULL; | |
2966 } | |
2967 | |
2968 if (gbLineBuffer != NULL) | |
2969 { | |
2970 free(gbLineBuffer); | |
2971 gbLineBuffer = NULL; | |
2972 } | |
2973 | |
2974 if (origPix != NULL) | |
2975 { | |
2976 free(origPix); | |
2977 origPix = NULL; | |
2978 } | |
2979 pix = NULL; | |
2980 | |
2981 gbSgbShutdown(); | |
2982 | |
2983 if (gbVram != NULL) | |
2984 { | |
2985 free(gbVram); | |
2986 gbVram = NULL; | |
2987 } | |
2988 | |
2989 if (gbWram != NULL) | |
2990 { | |
2991 free(gbWram); | |
2992 gbWram = NULL; | |
2993 } | |
2994 | |
2995 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
2996 | |
2997 memset(gbJoymask, 0, sizeof(gbJoymask)); | |
2998 // FIXME: horrible kludge | |
2999 memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); | |
3000 | |
3001 systemClearJoypads(); | |
3002 systemResetSensor(); | |
3003 | |
3004 // gbLastTime = gbFrameCount = 0; | |
3005 systemRefreshScreen(); | |
3006 } | |
3007 | |
3008 bool gbLoadRom(const char *szFile) | |
3009 { | |
3010 int size = 0; | |
3011 | |
3012 if (gbRom != NULL) | |
3013 { | |
3014 gbCleanUp(); | |
3015 } | |
3016 | |
3017 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
3018 | |
3019 gbRom = utilLoad(szFile, | |
3020 utilIsGBImage, | |
3021 NULL, | |
3022 size); | |
3023 if (!gbRom) | |
3024 return false; | |
3025 | |
3026 gbRomSize = size; | |
3027 | |
3028 return gbUpdateSizes(); | |
3029 } | |
3030 | |
3031 bool gbUpdateSizes() | |
3032 { | |
3033 if (gbRom[0x148] > 8) | |
3034 { | |
3035 systemMessage(MSG_UNSUPPORTED_ROM_SIZE, | |
3036 N_("Unsupported rom size %02x"), gbRom[0x148]); | |
3037 return false; | |
3038 } | |
3039 | |
3040 if (gbRomSize < gbRomSizes[gbRom[0x148]]) | |
3041 { | |
3042 gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); | |
3043 } | |
3044 gbRomSize = gbRomSizes[gbRom[0x148]]; | |
3045 gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]]; | |
3046 | |
3047 if (gbRom[0x149] > 5) | |
3048 { | |
3049 systemMessage(MSG_UNSUPPORTED_RAM_SIZE, | |
3050 N_("Unsupported ram size %02x"), gbRom[0x149]); | |
3051 return false; | |
3052 } | |
3053 | |
3054 gbRamSize = gbRamSizes[gbRom[0x149]]; | |
3055 gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]]; | |
3056 | |
3057 if (gbRamSize) | |
3058 { | |
3059 gbRam = (u8 *)malloc(gbRamSize + 4); | |
3060 memset(gbRam, 0xFF, gbRamSize + 4); | |
3061 } | |
3062 | |
3063 int type = gbRom[0x147]; | |
3064 | |
3065 mapperReadRAM = NULL; | |
3066 | |
3067 switch (type) | |
3068 { | |
3069 case 0x00: | |
3070 case 0x01: | |
3071 case 0x02: | |
3072 case 0x03: | |
3073 // MBC 1 | |
3074 mapper = mapperMBC1ROM; | |
3075 mapperRAM = mapperMBC1RAM; | |
3076 break; | |
3077 case 0x05: | |
3078 case 0x06: | |
3079 // MBC2 | |
3080 mapper = mapperMBC2ROM; | |
3081 mapperRAM = mapperMBC2RAM; | |
3082 gbRamSize = 0x200; | |
3083 gbRamSizeMask = 0x1ff; | |
3084 break; | |
3085 case 0x0f: | |
3086 case 0x10: | |
3087 case 0x11: | |
3088 case 0x12: | |
3089 case 0x13: | |
3090 // MBC 3 | |
3091 mapper = mapperMBC3ROM; | |
3092 mapperRAM = mapperMBC3RAM; | |
3093 mapperReadRAM = mapperMBC3ReadRAM; | |
3094 break; | |
3095 case 0x19: | |
3096 case 0x1a: | |
3097 case 0x1b: | |
3098 // MBC5 | |
3099 mapper = mapperMBC5ROM; | |
3100 mapperRAM = mapperMBC5RAM; | |
3101 break; | |
3102 case 0x1c: | |
3103 case 0x1d: | |
3104 case 0x1e: | |
3105 // MBC 5 Rumble | |
3106 mapper = mapperMBC5ROM; | |
3107 mapperRAM = mapperMBC5RAM; | |
3108 break; | |
3109 case 0x22: | |
3110 // MBC 7 | |
3111 mapper = mapperMBC7ROM; | |
3112 mapperRAM = mapperMBC7RAM; | |
3113 mapperReadRAM = mapperMBC7ReadRAM; | |
3114 break; | |
3115 case 0xfe: | |
3116 // HuC3 | |
3117 mapper = mapperHuC3ROM; | |
3118 mapperRAM = mapperHuC3RAM; | |
3119 mapperReadRAM = mapperHuC3ReadRAM; | |
3120 break; | |
3121 case 0xff: | |
3122 // HuC1 | |
3123 mapper = mapperHuC1ROM; | |
3124 mapperRAM = mapperHuC1RAM; | |
3125 break; | |
3126 default: | |
3127 systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE, | |
3128 N_("Unknown cartridge type %02x"), type); | |
3129 return false; | |
3130 } | |
3131 | |
3132 switch (type) | |
3133 { | |
3134 case 0x03: | |
3135 case 0x06: | |
3136 case 0x0f: | |
3137 case 0x10: | |
3138 case 0x13: | |
3139 case 0x1b: | |
3140 case 0x1d: | |
3141 case 0x1e: | |
3142 case 0x22: | |
3143 case 0xff: | |
3144 gbBattery = 1; | |
3145 break; | |
3146 } | |
3147 | |
3148 gbInit(); | |
3149 gbReset(); | |
3150 | |
3151 return true; | |
3152 } | |
3153 | |
3154 void gbEmulate(int ticksToStop) | |
3155 { | |
3156 printf("RLM: Inside the GB!\n"); | |
3157 gbRegister tempRegister; | |
3158 u8 tempValue; | |
3159 s8 offset; | |
3160 | |
3161 int clockTicks = 0; | |
3162 gbDmaTicks = 0; | |
3163 | |
3164 register int opcode = 0; | |
3165 | |
3166 u32 newmask = 0; | |
3167 printf("RLM: newframe = %d\n", newFrame); | |
3168 if (newFrame) | |
3169 { | |
3170 extern void VBAOnExitingFrameBoundary(); | |
3171 VBAOnExitingFrameBoundary(); | |
3172 printf("RLM: exiting frame boundary?\n"); | |
3173 // update joystick information | |
3174 systemReadJoypads(); | |
3175 | |
3176 bool sensor = (gbRom[0x147] == 0x22); | |
3177 | |
3178 // read joystick | |
3179 if (gbSgbMode && gbSgbMultiplayer) | |
3180 { | |
3181 if (gbSgbFourPlayers) | |
3182 { | |
3183 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3184 gbJoymask[1] = systemGetJoypad(1, false); | |
3185 gbJoymask[2] = systemGetJoypad(2, false); | |
3186 gbJoymask[3] = systemGetJoypad(3, false); | |
3187 } | |
3188 else | |
3189 { | |
3190 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3191 gbJoymask[1] = systemGetJoypad(1, false); | |
3192 } | |
3193 } | |
3194 else | |
3195 { | |
3196 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3197 } | |
3198 | |
3199 // FIXME: horrible kludge | |
3200 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | |
3201 | |
3202 // if (sensor) | |
3203 // systemUpdateMotionSensor(0); | |
3204 | |
3205 newmask = gbJoymask[0]; | |
3206 if (newmask & 0xFF) | |
3207 { | |
3208 gbInterrupt |= 16; | |
3209 } | |
3210 | |
3211 extButtons = (newmask >> 18); | |
3212 speedup = (extButtons & 1) != 0; | |
3213 | |
3214 VBAMovieResetIfRequested(); | |
3215 printf("RLM: before Lua functions\n"); | |
3216 //CallRegisteredLuaFunctions(LUACALL_BEFOREEMULATION); | |
3217 printf("RLM: after Lua functions\n"); | |
3218 newFrame = false; | |
3219 } | |
3220 | |
3221 | |
3222 for (;; ) | |
3223 { | |
3224 #ifndef FINAL_VERSION | |
3225 if (systemDebug) | |
3226 { | |
3227 if (!(IFF & 0x80)) | |
3228 { | |
3229 if (systemDebug > 1) | |
2779 { | 3230 { |
2780 free(gbVram); | 3231 sprintf(gbBuffer, "PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n", |
2781 gbVram = NULL; | 3232 PC.W, AF.W, BC.W, DE.W, HL.W, SP.W, IFF); |
2782 } | 3233 } |
2783 if (gbWram) | 3234 else |
2784 { | 3235 { |
2785 free(gbWram); | 3236 sprintf(gbBuffer, "PC=%04x I=%02x\n", PC.W, IFF); |
2786 gbWram = NULL; | |
2787 } | 3237 } |
2788 } | 3238 log(gbBuffer); |
2789 | 3239 } |
2790 gbSoundReadGame(version, gzFile); | 3240 } |
2791 | |
2792 #if 0 | |
2793 if (gbBorderOn) | |
2794 { | |
2795 gbSgbRenderBorder(); | |
2796 } | |
2797 | |
2798 systemRefreshScreen(); | |
2799 #endif | 3241 #endif |
2800 | 3242 if (IFF & 0x80) |
2801 if (version > GBSAVE_GAME_VERSION_1) | 3243 { |
2802 gbCheatsReadGame(gzFile, version); | 3244 if (register_LCDC & 0x80) |
2803 | 3245 { |
2804 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | 3246 clockTicks = gbLcdTicks; |
2805 | 3247 } |
2806 if (version >= GBSAVE_GAME_VERSION_11) // new to re-recording version: | 3248 else |
2807 { | 3249 clockTicks = 100; |
2808 extern int32 sensorX, sensorY; // from SDL.cpp | 3250 |
2809 utilGzRead(gzFile, &sensorX, sizeof(sensorX)); | 3251 if (gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks)) |
2810 utilGzRead(gzFile, &sensorY, sizeof(sensorY)); | 3252 clockTicks = gbLcdLYIncrementTicks; |
2811 utilGzRead(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get carried | 3253 |
2812 // back on loading a snapshot! | 3254 if (gbSerialOn && (gbSerialTicks < clockTicks)) |
2813 | 3255 clockTicks = gbSerialTicks; |
2814 bool8 movieSnapshot; | 3256 |
2815 utilGzRead(gzFile, &movieSnapshot, sizeof(movieSnapshot)); | 3257 if (gbTimerOn && (gbTimerTicks < clockTicks)) |
2816 if (VBAMovieActive() && !movieSnapshot) | 3258 clockTicks = gbTimerTicks; |
3259 | |
3260 if (soundTicks && (soundTicks < clockTicks)) | |
3261 clockTicks = soundTicks; | |
3262 } | |
3263 else | |
3264 { | |
3265 opcode = gbReadOpcode(PC.W); | |
3266 CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); | |
3267 PC.W++; | |
3268 | |
3269 if (IFF & 0x100) | |
3270 { | |
3271 IFF &= 0xff; | |
3272 PC.W--; | |
3273 } | |
3274 | |
3275 clockTicks = gbCycles[opcode]; | |
3276 | |
3277 switch (opcode) | |
3278 { | |
3279 case 0xCB: | |
3280 // extended opcode | |
3281 //CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); // is this desired? | |
3282 opcode = gbReadOpcode(PC.W++); | |
3283 clockTicks = gbCyclesCB[opcode]; | |
3284 switch (opcode) | |
2817 { | 3285 { |
2818 systemMessage(0, N_("Can't load a non-movie snapshot while a movie is active.")); | 3286 #include "gbCodesCB.h" |
2819 goto failedLoadGB; | |
2820 } | 3287 } |
2821 | 3288 break; |
2822 if (movieSnapshot) // even if a movie isn't active we still want to parse through this in case other stuff is added | 3289 #include "gbCodes.h" |
2823 // later on in the save format | 3290 } |
3291 } | |
3292 | |
3293 if (!emulating) | |
3294 return; | |
3295 | |
3296 if (gbDmaTicks) | |
3297 { | |
3298 clockTicks += gbDmaTicks; | |
3299 gbDmaTicks = 0; | |
3300 } | |
3301 | |
3302 if (gbSgbMode) | |
3303 { | |
3304 if (gbSgbPacketTimeout) | |
3305 { | |
3306 gbSgbPacketTimeout -= clockTicks; | |
3307 | |
3308 if (gbSgbPacketTimeout <= 0) | |
3309 gbSgbResetPacketState(); | |
3310 } | |
3311 } | |
3312 | |
3313 ticksToStop -= clockTicks; | |
3314 | |
3315 // DIV register emulation | |
3316 gbDivTicks -= clockTicks; | |
3317 while (gbDivTicks <= 0) | |
3318 { | |
3319 register_DIV++; | |
3320 gbDivTicks += GBDIV_CLOCK_TICKS; | |
3321 } | |
3322 | |
3323 if (register_LCDC & 0x80) | |
3324 { | |
3325 // LCD stuff | |
3326 gbLcdTicks -= clockTicks; | |
3327 if (gbLcdMode == 1) | |
3328 { | |
3329 // during V-BLANK,we need to increment LY at the same rate! | |
3330 gbLcdLYIncrementTicks -= clockTicks; | |
3331 while (gbLcdLYIncrementTicks <= 0) | |
2824 { | 3332 { |
2825 uint32 movieInputDataSize = 0; | 3333 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; |
2826 utilGzRead(gzFile, &movieInputDataSize, sizeof(movieInputDataSize)); | 3334 |
2827 uint8 *local_movie_data = new uint8 [movieInputDataSize]; | 3335 if (register_LY < 153) |
2828 int readBytes = utilGzRead(gzFile, local_movie_data, movieInputDataSize); | 3336 { |
2829 if (readBytes != movieInputDataSize) | 3337 register_LY++; |
3338 | |
3339 gbCompareLYToLYC(); | |
3340 | |
3341 if (register_LY >= 153) | |
3342 gbLcdLYIncrementTicks = 6; | |
3343 } | |
3344 else | |
3345 { | |
3346 register_LY = 0x00; | |
3347 // reset the window line | |
3348 gbWindowLine = -1; | |
3349 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2; | |
3350 gbCompareLYToLYC(); | |
3351 } | |
3352 } | |
3353 } | |
3354 | |
3355 // our counter is off, see what we need to do | |
3356 while (gbLcdTicks <= 0) | |
3357 { | |
3358 int framesToSkip = systemFramesToSkip(); | |
3359 | |
3360 switch (gbLcdMode) | |
3361 { | |
3362 case 0: | |
3363 // H-Blank | |
3364 register_LY++; | |
3365 | |
3366 gbCompareLYToLYC(); | |
3367 | |
3368 // check if we reached the V-Blank period | |
3369 if (register_LY == 144) | |
3370 { | |
3371 // Yes, V-Blank | |
3372 // set the LY increment counter | |
3373 gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS; | |
3374 gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; | |
3375 gbLcdMode = 1; | |
3376 if (register_LCDC & 0x80) | |
2830 { | 3377 { |
2831 systemMessage(0, N_("Corrupt movie snapshot.")); | 3378 gbInterrupt |= 1; // V-Blank interrupt |
2832 if (local_movie_data) | 3379 gbInterruptWait = 6; |
2833 delete [] local_movie_data; | 3380 if (register_STAT & 0x10) |
2834 goto failedLoadGB; | 3381 gbInterrupt |= 2; |
2835 } | 3382 } |
2836 int code = VBAMovieUnfreeze(local_movie_data, movieInputDataSize); | 3383 |
2837 if (local_movie_data) | 3384 systemFrame(); |
2838 delete [] local_movie_data; | 3385 |
2839 if (code != MOVIE_SUCCESS && VBAMovieActive()) | 3386 ++gbFrameCount; |
3387 u32 currentTime = systemGetClock(); | |
3388 if (currentTime - gbLastTime >= 1000) | |
2840 { | 3389 { |
2841 char errStr [1024]; | 3390 systemShowSpeed(int(float(gbFrameCount) * 100000 / (float(currentTime - gbLastTime) * 60) + .5f)); |
2842 strcpy(errStr, "Failed to load movie snapshot"); | 3391 gbLastTime = currentTime; |
2843 switch (code) | 3392 gbFrameCount = 0; |
3393 } | |
3394 | |
3395 ++GBSystemCounters.frameCount; | |
3396 if (GBSystemCounters.lagged) | |
3397 { | |
3398 ++GBSystemCounters.lagCount; | |
3399 } | |
3400 GBSystemCounters.laggedLast = GBSystemCounters.lagged; | |
3401 GBSystemCounters.lagged = true; | |
3402 | |
3403 extern void VBAOnEnteringFrameBoundary(); | |
3404 VBAOnEnteringFrameBoundary(); | |
3405 | |
3406 newFrame = true; | |
3407 | |
3408 pauseAfterFrameAdvance = systemPauseOnFrame(); | |
3409 | |
3410 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) | |
3411 { | |
3412 if (gbBorderOn) | |
3413 gbSgbRenderBorder(); // clear unnecessary things on border (e.g. in-game text message) | |
3414 | |
3415 systemRenderFrame(); | |
3416 gbFrameSkipCount = 0; | |
3417 | |
3418 bool capturePressed = (extButtons & 2) != 0; | |
3419 if (capturePressed && !capturePrevious) | |
3420 { | |
3421 captureNumber = systemScreenCapture(captureNumber); | |
3422 } | |
3423 capturePrevious = capturePressed && !pauseAfterFrameAdvance; | |
3424 } | |
3425 else | |
3426 { | |
3427 ++gbFrameSkipCount; | |
3428 } | |
3429 | |
3430 if (pauseAfterFrameAdvance) | |
3431 { | |
3432 systemSetPause(true); | |
3433 } | |
3434 } | |
3435 else | |
3436 { | |
3437 // go the the OAM being accessed mode | |
3438 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; | |
3439 gbLcdMode = 2; | |
3440 | |
3441 // only one LCD interrupt per line. may need to generalize... | |
3442 if (!(register_STAT & 0x40) || | |
3443 (register_LY != register_LYC)) | |
3444 { | |
3445 if ((register_STAT & 0x28) == 0x20) | |
3446 gbInterrupt |= 2; | |
3447 } | |
3448 } | |
3449 | |
3450 break; | |
3451 case 1: | |
3452 // V-Blank | |
3453 // next mode is OAM being accessed mode | |
3454 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; | |
3455 gbLcdMode = 2; | |
3456 if (!(register_STAT & 0x40) || | |
3457 (register_LY != register_LYC)) | |
3458 { | |
3459 if ((register_STAT & 0x28) == 0x20) | |
3460 gbInterrupt |= 2; | |
3461 } | |
3462 break; | |
3463 case 2: | |
3464 // OAM being accessed mode | |
3465 | |
3466 // next mode is OAM and VRAM in use | |
3467 gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS; | |
3468 gbLcdMode = 3; | |
3469 break; | |
3470 case 3: | |
3471 // OAM and VRAM in use | |
3472 // next mode is H-Blank | |
3473 if (register_LY < 144) | |
3474 { | |
3475 if (!gbSgbMask) | |
3476 { | |
3477 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) | |
3478 { | |
3479 gbRenderLine(); | |
3480 gbDrawSprites(); | |
3481 | |
3482 switch (systemColorDepth) | |
2844 { | 3483 { |
2845 case MOVIE_NOT_FROM_THIS_MOVIE: | 3484 case 16: |
2846 strcat(errStr, ";\nSnapshot not from this movie"); break; | 3485 |
2847 case MOVIE_NOT_FROM_A_MOVIE: | 3486 { |
2848 strcat(errStr, ";\nNot a movie snapshot"); break; // shouldn't get here... | 3487 u16 *dest = (u16 *)pix + |
2849 case MOVIE_SNAPSHOT_INCONSISTENT: | 3488 (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1) |
2850 strcat(errStr, ";\nSnapshot inconsistent with movie"); break; | 3489 + gbBorderColumnSkip; |
2851 case MOVIE_WRONG_FORMAT: | 3490 for (int x = 0; x < 160; ) |
2852 strcat(errStr, ";\nWrong format"); break; | 3491 { |
3492 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3493 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3494 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3495 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3496 | |
3497 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3498 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3499 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3500 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3501 | |
3502 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3503 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3504 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3505 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3506 | |
3507 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3508 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3509 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3510 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3511 } | |
3512 if (gbBorderOn) | |
3513 dest += gbBorderColumnSkip; | |
3514 *dest++ = 0; // for filters that read one pixel more | |
3515 break; | |
3516 } | |
3517 case 24: | |
3518 | |
3519 { | |
3520 u8 *dest = (u8 *)pix + | |
3521 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) + | |
3522 gbBorderColumnSkip); | |
3523 for (int x = 0; x < 160; ) | |
3524 { | |
3525 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3526 dest += 3; | |
3527 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3528 dest += 3; | |
3529 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3530 dest += 3; | |
3531 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3532 dest += 3; | |
3533 | |
3534 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3535 dest += 3; | |
3536 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3537 dest += 3; | |
3538 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3539 dest += 3; | |
3540 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3541 dest += 3; | |
3542 | |
3543 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3544 dest += 3; | |
3545 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3546 dest += 3; | |
3547 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3548 dest += 3; | |
3549 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3550 dest += 3; | |
3551 | |
3552 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3553 dest += 3; | |
3554 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3555 dest += 3; | |
3556 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3557 dest += 3; | |
3558 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3559 dest += 3; | |
3560 } | |
3561 break; | |
3562 } | |
3563 case 32: | |
3564 | |
3565 { | |
3566 u32 *dest = (u32 *)pix + | |
3567 (gbBorderLineSkip + 1) * (register_LY + gbBorderRowSkip + 1) | |
3568 + gbBorderColumnSkip; | |
3569 for (int x = 0; x < 160; ) | |
3570 { | |
3571 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3572 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3573 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3574 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3575 | |
3576 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3577 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3578 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3579 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3580 | |
3581 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3582 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3583 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3584 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3585 | |
3586 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3587 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3588 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3589 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3590 } | |
3591 break; | |
3592 } | |
2853 } | 3593 } |
2854 strcat(errStr, "."); | 3594 } |
2855 systemMessage(0, N_(errStr)); | |
2856 goto failedLoadGB; | |
2857 } | 3595 } |
3596 } | |
3597 gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS; | |
3598 gbLcdMode = 0; | |
3599 // only one LCD interrupt per line. may need to generalize... | |
3600 if (!(register_STAT & 0x40) || | |
3601 (register_LY != register_LYC)) | |
3602 { | |
3603 if (register_STAT & 0x08) | |
3604 gbInterrupt |= 2; | |
3605 } | |
3606 if (gbHdmaOn) | |
3607 { | |
3608 gbDoHdma(); | |
3609 } | |
3610 break; | |
2858 } | 3611 } |
2859 utilGzRead(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); | 3612 // mark the correct lcd mode on STAT register |
2860 } | 3613 register_STAT = (register_STAT & 0xfc) | gbLcdMode; |
2861 | 3614 } |
2862 if (version >= GBSAVE_GAME_VERSION_13) // new to rerecording 19.4 wip (svn r22+): | 3615 } |
2863 { | 3616 |
2864 utilGzRead(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); | 3617 // serial emulation |
2865 utilGzRead(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); | 3618 if (gbSerialOn) |
2866 utilGzRead(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); | 3619 { |
2867 } | 3620 #ifdef LINK_EMULATION |
2868 | 3621 if (linkConnected) |
2869 if (backupSafe) | 3622 { |
2870 { | 3623 gbSerialTicks -= clockTicks; |
2871 remove(tempBackupName); | 3624 |
2872 tempFailCount = 0; | 3625 while (gbSerialTicks <= 0) |
2873 } | |
2874 | |
2875 for (int i = 0; i < 4; ++i) | |
2876 systemSetJoypad(i, gbJoymask[i] & 0xFFFF); | |
2877 | |
2878 // FIXME: horrible kludge | |
2879 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | |
2880 | |
2881 VBAUpdateButtonPressDisplay(); | |
2882 VBAUpdateFrameCountDisplay(); | |
2883 systemRefreshScreen(); | |
2884 return true; | |
2885 | |
2886 failedLoadGB: | |
2887 if (backupSafe) | |
2888 { | |
2889 tempFailCount++; | |
2890 if (tempFailCount < 3) // fail no more than 2 times in a row | |
2891 gbReadSaveState(tempBackupName); | |
2892 remove(tempBackupName); | |
2893 } | |
2894 return false; | |
2895 } | |
2896 | |
2897 bool gbReadMemSaveState(char *memory, int available) | |
2898 { | |
2899 gzFile gzFile = utilMemGzOpen(memory, available, "r"); | |
2900 | |
2901 backupSafe = false; | |
2902 bool res = gbReadSaveStateFromStream(gzFile); | |
2903 backupSafe = true; | |
2904 | |
2905 utilGzClose(gzFile); | |
2906 | |
2907 return res; | |
2908 } | |
2909 | |
2910 bool gbReadSaveState(const char *name) | |
2911 { | |
2912 gzFile gzFile = utilGzOpen(name, "rb"); | |
2913 | |
2914 if (gzFile == NULL) | |
2915 { | |
2916 return false; | |
2917 } | |
2918 | |
2919 bool res = gbReadSaveStateFromStream(gzFile); | |
2920 | |
2921 utilGzClose(gzFile); | |
2922 | |
2923 return res; | |
2924 } | |
2925 | |
2926 bool gbWritePNGFile(const char *fileName) | |
2927 { | |
2928 if (gbBorderOn) | |
2929 return utilWritePNGFile(fileName, 256, 224, pix); | |
2930 return utilWritePNGFile(fileName, 160, 144, pix); | |
2931 } | |
2932 | |
2933 bool gbWriteBMPFile(const char *fileName) | |
2934 { | |
2935 if (gbBorderOn) | |
2936 return utilWriteBMPFile(fileName, 256, 224, pix); | |
2937 return utilWriteBMPFile(fileName, 160, 144, pix); | |
2938 } | |
2939 | |
2940 void gbCleanUp() | |
2941 { | |
2942 newFrame = true; | |
2943 | |
2944 GBSystemCounters.frameCount = 0; | |
2945 GBSystemCounters.lagCount = 0; | |
2946 GBSystemCounters.extraCount = 0; | |
2947 GBSystemCounters.lagged = true; | |
2948 GBSystemCounters.laggedLast = true; | |
2949 | |
2950 if (gbRam != NULL) | |
2951 { | |
2952 free(gbRam); | |
2953 gbRam = NULL; | |
2954 } | |
2955 | |
2956 if (gbRom != NULL) | |
2957 { | |
2958 free(gbRom); | |
2959 gbRom = NULL; | |
2960 } | |
2961 | |
2962 if (gbMemory != NULL) | |
2963 { | |
2964 free(gbMemory); | |
2965 gbMemory = NULL; | |
2966 } | |
2967 | |
2968 if (gbLineBuffer != NULL) | |
2969 { | |
2970 free(gbLineBuffer); | |
2971 gbLineBuffer = NULL; | |
2972 } | |
2973 | |
2974 if (origPix != NULL) | |
2975 { | |
2976 free(origPix); | |
2977 origPix = NULL; | |
2978 } | |
2979 pix = NULL; | |
2980 | |
2981 gbSgbShutdown(); | |
2982 | |
2983 if (gbVram != NULL) | |
2984 { | |
2985 free(gbVram); | |
2986 gbVram = NULL; | |
2987 } | |
2988 | |
2989 if (gbWram != NULL) | |
2990 { | |
2991 free(gbWram); | |
2992 gbWram = NULL; | |
2993 } | |
2994 | |
2995 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
2996 | |
2997 memset(gbJoymask, 0, sizeof(gbJoymask)); | |
2998 // FIXME: horrible kludge | |
2999 memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); | |
3000 | |
3001 systemClearJoypads(); | |
3002 systemResetSensor(); | |
3003 | |
3004 // gbLastTime = gbFrameCount = 0; | |
3005 systemRefreshScreen(); | |
3006 } | |
3007 | |
3008 bool gbLoadRom(const char *szFile) | |
3009 { | |
3010 int size = 0; | |
3011 | |
3012 if (gbRom != NULL) | |
3013 { | |
3014 gbCleanUp(); | |
3015 } | |
3016 | |
3017 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
3018 | |
3019 gbRom = utilLoad(szFile, | |
3020 utilIsGBImage, | |
3021 NULL, | |
3022 size); | |
3023 if (!gbRom) | |
3024 return false; | |
3025 | |
3026 gbRomSize = size; | |
3027 | |
3028 return gbUpdateSizes(); | |
3029 } | |
3030 | |
3031 bool gbUpdateSizes() | |
3032 { | |
3033 if (gbRom[0x148] > 8) | |
3034 { | |
3035 systemMessage(MSG_UNSUPPORTED_ROM_SIZE, | |
3036 N_("Unsupported rom size %02x"), gbRom[0x148]); | |
3037 return false; | |
3038 } | |
3039 | |
3040 if (gbRomSize < gbRomSizes[gbRom[0x148]]) | |
3041 { | |
3042 gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]); | |
3043 } | |
3044 gbRomSize = gbRomSizes[gbRom[0x148]]; | |
3045 gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]]; | |
3046 | |
3047 if (gbRom[0x149] > 5) | |
3048 { | |
3049 systemMessage(MSG_UNSUPPORTED_RAM_SIZE, | |
3050 N_("Unsupported ram size %02x"), gbRom[0x149]); | |
3051 return false; | |
3052 } | |
3053 | |
3054 gbRamSize = gbRamSizes[gbRom[0x149]]; | |
3055 gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]]; | |
3056 | |
3057 if (gbRamSize) | |
3058 { | |
3059 gbRam = (u8 *)malloc(gbRamSize + 4); | |
3060 memset(gbRam, 0xFF, gbRamSize + 4); | |
3061 } | |
3062 | |
3063 int type = gbRom[0x147]; | |
3064 | |
3065 mapperReadRAM = NULL; | |
3066 | |
3067 switch (type) | |
3068 { | |
3069 case 0x00: | |
3070 case 0x01: | |
3071 case 0x02: | |
3072 case 0x03: | |
3073 // MBC 1 | |
3074 mapper = mapperMBC1ROM; | |
3075 mapperRAM = mapperMBC1RAM; | |
3076 break; | |
3077 case 0x05: | |
3078 case 0x06: | |
3079 // MBC2 | |
3080 mapper = mapperMBC2ROM; | |
3081 mapperRAM = mapperMBC2RAM; | |
3082 gbRamSize = 0x200; | |
3083 gbRamSizeMask = 0x1ff; | |
3084 break; | |
3085 case 0x0f: | |
3086 case 0x10: | |
3087 case 0x11: | |
3088 case 0x12: | |
3089 case 0x13: | |
3090 // MBC 3 | |
3091 mapper = mapperMBC3ROM; | |
3092 mapperRAM = mapperMBC3RAM; | |
3093 mapperReadRAM = mapperMBC3ReadRAM; | |
3094 break; | |
3095 case 0x19: | |
3096 case 0x1a: | |
3097 case 0x1b: | |
3098 // MBC5 | |
3099 mapper = mapperMBC5ROM; | |
3100 mapperRAM = mapperMBC5RAM; | |
3101 break; | |
3102 case 0x1c: | |
3103 case 0x1d: | |
3104 case 0x1e: | |
3105 // MBC 5 Rumble | |
3106 mapper = mapperMBC5ROM; | |
3107 mapperRAM = mapperMBC5RAM; | |
3108 break; | |
3109 case 0x22: | |
3110 // MBC 7 | |
3111 mapper = mapperMBC7ROM; | |
3112 mapperRAM = mapperMBC7RAM; | |
3113 mapperReadRAM = mapperMBC7ReadRAM; | |
3114 break; | |
3115 case 0xfe: | |
3116 // HuC3 | |
3117 mapper = mapperHuC3ROM; | |
3118 mapperRAM = mapperHuC3RAM; | |
3119 mapperReadRAM = mapperHuC3ReadRAM; | |
3120 break; | |
3121 case 0xff: | |
3122 // HuC1 | |
3123 mapper = mapperHuC1ROM; | |
3124 mapperRAM = mapperHuC1RAM; | |
3125 break; | |
3126 default: | |
3127 systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE, | |
3128 N_("Unknown cartridge type %02x"), type); | |
3129 return false; | |
3130 } | |
3131 | |
3132 switch (type) | |
3133 { | |
3134 case 0x03: | |
3135 case 0x06: | |
3136 case 0x0f: | |
3137 case 0x10: | |
3138 case 0x13: | |
3139 case 0x1b: | |
3140 case 0x1d: | |
3141 case 0x1e: | |
3142 case 0x22: | |
3143 case 0xff: | |
3144 gbBattery = 1; | |
3145 break; | |
3146 } | |
3147 | |
3148 gbInit(); | |
3149 gbReset(); | |
3150 | |
3151 return true; | |
3152 } | |
3153 | |
3154 void gbEmulate(int ticksToStop) | |
3155 { | |
3156 gbRegister tempRegister; | |
3157 u8 tempValue; | |
3158 s8 offset; | |
3159 | |
3160 int clockTicks = 0; | |
3161 gbDmaTicks = 0; | |
3162 | |
3163 register int opcode = 0; | |
3164 | |
3165 u32 newmask = 0; | |
3166 if (newFrame) | |
3167 { | |
3168 extern void VBAOnExitingFrameBoundary(); | |
3169 VBAOnExitingFrameBoundary(); | |
3170 | |
3171 // update joystick information | |
3172 systemReadJoypads(); | |
3173 | |
3174 bool sensor = (gbRom[0x147] == 0x22); | |
3175 | |
3176 // read joystick | |
3177 if (gbSgbMode && gbSgbMultiplayer) | |
3178 { | 3626 { |
3179 if (gbSgbFourPlayers) | 3627 // increment number of shifted bits |
3628 gbSerialBits++; | |
3629 linkProc(); | |
3630 if (gbSerialOn && (gbMemory[0xff02] & 1)) | |
3631 { | |
3632 if (gbSerialBits == 8) | |
3180 { | 3633 { |
3181 gbJoymask[0] = systemGetJoypad(0, sensor); | 3634 gbSerialBits = 0; |
3182 gbJoymask[1] = systemGetJoypad(1, false); | 3635 gbMemory[0xff01] = 0xff; |
3183 gbJoymask[2] = systemGetJoypad(2, false); | 3636 gbMemory[0xff02] &= 0x7f; |
3184 gbJoymask[3] = systemGetJoypad(3, false); | 3637 gbSerialOn = 0; |
3638 gbInterrupt |= 8; | |
3639 gbSerialTicks = 0; | |
3185 } | 3640 } |
3186 else | 3641 } |
3642 gbSerialTicks += GBSERIAL_CLOCK_TICKS; | |
3643 } | |
3644 } | |
3645 else | |
3646 { | |
3647 #endif | |
3648 if (gbMemory[0xff02] & 1) | |
3649 { | |
3650 gbSerialTicks -= clockTicks; | |
3651 | |
3652 // overflow | |
3653 while (gbSerialTicks <= 0) | |
3654 { | |
3655 // shift serial byte to right and put a 1 bit in its place | |
3656 // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1); | |
3657 // increment number of shifted bits | |
3658 gbSerialBits++; | |
3659 if (gbSerialBits == 8) | |
3187 { | 3660 { |
3188 gbJoymask[0] = systemGetJoypad(0, sensor); | 3661 // end of transmission |
3189 gbJoymask[1] = systemGetJoypad(1, false); | 3662 if (gbSerialFunction) // external device |
3663 gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); | |
3664 else | |
3665 gbMemory[0xff01] = 0xff; | |
3666 gbSerialTicks = 0; | |
3667 gbMemory[0xff02] &= 0x7f; | |
3668 gbSerialOn = 0; | |
3669 gbInterrupt |= 8; | |
3670 gbSerialBits = 0; | |
3190 } | 3671 } |
3672 else | |
3673 gbSerialTicks += GBSERIAL_CLOCK_TICKS; | |
3674 } | |
3191 } | 3675 } |
3192 else | 3676 #ifdef LINK_EMULATION |
3677 } | |
3678 #endif | |
3679 } | |
3680 | |
3681 // timer emulation | |
3682 if (gbTimerOn) | |
3683 { | |
3684 gbTimerTicks -= clockTicks; | |
3685 | |
3686 while (gbTimerTicks <= 0) | |
3687 { | |
3688 register_TIMA++; | |
3689 | |
3690 if (register_TIMA == 0) | |
3193 { | 3691 { |
3194 gbJoymask[0] = systemGetJoypad(0, sensor); | 3692 // timer overflow! |
3693 | |
3694 // reload timer modulo | |
3695 register_TIMA = register_TMA; | |
3696 | |
3697 // flag interrupt | |
3698 gbInterrupt |= 4; | |
3195 } | 3699 } |
3196 | 3700 |
3197 // FIXME: horrible kludge | 3701 gbTimerTicks += gbTimerClockTicks; |
3198 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | 3702 } |
3199 | 3703 } |
3200 // if (sensor) | 3704 |
3201 // systemUpdateMotionSensor(0); | 3705 /* |
3202 | 3706 if(soundOffFlag) |
3203 newmask = gbJoymask[0]; | 3707 { |
3204 if (newmask & 0xFF) | 3708 if(synchronize && !speedup) |
3709 { | |
3710 synchronizeTicks -= clockTicks; | |
3711 | |
3712 while(synchronizeTicks < 0) | |
3713 { | |
3714 synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS; | |
3715 | |
3716 DWORD now = timeGetTime(); | |
3717 gbElapsedTime += (now - timeNow); | |
3718 | |
3719 if(gbElapsedTime < 50) | |
3720 { | |
3721 DWORD diff = 50 - gbElapsedTime; | |
3722 Sleep(diff); | |
3723 timeNow = timeGetTime(); | |
3724 elapsedTime = timeNow - now - diff; | |
3725 if((int)elapsedTime < 0) | |
3726 elapsedTime = 0; | |
3727 } else | |
3728 { | |
3729 timeNow = timeGetTime(); | |
3730 elapsedTime = 0; | |
3731 } | |
3732 } | |
3733 } | |
3734 } | |
3735 */ | |
3736 | |
3737 soundTicks -= clockTicks; | |
3738 while (soundTicks < 0) // must be < 1 when soundtick_t is real data type | |
3739 { | |
3740 soundTicks += SOUND_CLOCK_TICKS; | |
3741 | |
3742 gbSoundTick(); | |
3743 } | |
3744 | |
3745 register_IF = gbInterrupt; | |
3746 | |
3747 if (IFF & 0x20) | |
3748 { | |
3749 IFF &= 0xdf; | |
3750 IFF |= 0x01; | |
3751 gbInterruptWait = 0; | |
3752 } | |
3753 else if (gbInterrupt) | |
3754 { | |
3755 if (gbInterruptWait == 0) | |
3756 { | |
3757 // gbInterruptWait = 0; | |
3758 | |
3759 if (IFF & 0x01) | |
3205 { | 3760 { |
3206 gbInterrupt |= 16; | 3761 if ((gbInterrupt & 1) && (register_IE & 1)) |
3762 { | |
3763 gbVblank_interrupt(); | |
3764 continue; | |
3765 } | |
3766 | |
3767 if ((gbInterrupt & 2) && (register_IE & 2)) | |
3768 { | |
3769 gbLcd_interrupt(); | |
3770 continue; | |
3771 } | |
3772 | |
3773 if ((gbInterrupt & 4) && (register_IE & 4)) | |
3774 { | |
3775 gbTimer_interrupt(); | |
3776 continue; | |
3777 } | |
3778 | |
3779 if ((gbInterrupt & 8) && (register_IE & 8)) | |
3780 { | |
3781 gbSerial_interrupt(); | |
3782 continue; | |
3783 } | |
3784 | |
3785 if ((gbInterrupt & 16) && (register_IE & 16)) | |
3786 { | |
3787 gbJoypad_interrupt(); | |
3788 continue; | |
3789 } | |
3207 } | 3790 } |
3208 | 3791 } |
3209 extButtons = (newmask >> 18); | 3792 else |
3210 speedup = (extButtons & 1) != 0; | 3793 { |
3211 | 3794 gbInterruptWait -= clockTicks; |
3212 VBAMovieResetIfRequested(); | 3795 if (gbInterruptWait < 0) |
3213 | 3796 gbInterruptWait = 0; |
3214 CallRegisteredLuaFunctions(LUACALL_BEFOREEMULATION); | 3797 } |
3215 | 3798 } |
3216 newFrame = false; | 3799 |
3217 } | 3800 if (useOldFrameTiming) |
3218 | 3801 { |
3219 for (;; ) | 3802 // old timing code |
3220 { | 3803 if (ticksToStop > 0) |
3221 #ifndef FINAL_VERSION | 3804 continue; |
3222 if (systemDebug) | 3805 } |
3806 else | |
3807 { | |
3808 if (!newFrame && (register_LCDC & 0x80) != 0) | |
3809 continue; | |
3810 } | |
3811 | |
3812 if (!(register_LCDC & 0x80)) | |
3813 { | |
3814 if (!useOldFrameTiming) | |
3815 { | |
3816 // FIXME: since register_LY can be reset to 0 by some games, frame length is variable | |
3817 // and infinite loops can occurr | |
3818 // for now, it IS necessary to do something on this condition or games like | |
3819 // Megaman would freeze upon low-level restart interrupt sequence (Start+Select+A+B). | |
3820 // the only sensible way to fix this issue is to implement the RIGHT frame timing | |
3821 #ifdef WANTS_INCOMPLETE_WORKAROUND | |
3822 if (systemReadJoypads()) | |
3223 { | 3823 { |
3224 if (!(IFF & 0x80)) | 3824 if (gbSgbMode && gbSgbMultiplayer) |
3825 { | |
3826 if (gbSgbFourPlayers) | |
3225 { | 3827 { |
3226 if (systemDebug > 1) | 3828 gbJoymask[0] = systemGetJoypad(0, false); |
3227 { | 3829 gbJoymask[1] = systemGetJoypad(1, false); |
3228 sprintf(gbBuffer, "PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n", | 3830 gbJoymask[2] = systemGetJoypad(2, false); |
3229 PC.W, AF.W, BC.W, DE.W, HL.W, SP.W, IFF); | 3831 gbJoymask[3] = systemGetJoypad(3, false); |
3230 } | |
3231 else | |
3232 { | |
3233 sprintf(gbBuffer, "PC=%04x I=%02x\n", PC.W, IFF); | |
3234 } | |
3235 log(gbBuffer); | |
3236 } | 3832 } |
3833 else | |
3834 { | |
3835 gbJoymask[0] = systemGetJoypad(0, false); | |
3836 gbJoymask[1] = systemGetJoypad(1, false); | |
3837 } | |
3838 } | |
3839 else | |
3840 { | |
3841 gbJoymask[0] = systemGetJoypad(0, false); | |
3842 } | |
3237 } | 3843 } |
3238 #endif | 3844 else |
3239 if (IFF & 0x80) | 3845 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; |
3240 { | |
3241 if (register_LCDC & 0x80) | |
3242 { | |
3243 clockTicks = gbLcdTicks; | |
3244 } | |
3245 else | |
3246 clockTicks = 100; | |
3247 | |
3248 if (gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks)) | |
3249 clockTicks = gbLcdLYIncrementTicks; | |
3250 | |
3251 if (gbSerialOn && (gbSerialTicks < clockTicks)) | |
3252 clockTicks = gbSerialTicks; | |
3253 | |
3254 if (gbTimerOn && (gbTimerTicks < clockTicks)) | |
3255 clockTicks = gbTimerTicks; | |
3256 | |
3257 if (soundTicks && (soundTicks < clockTicks)) | |
3258 clockTicks = soundTicks; | |
3259 } | |
3260 else | |
3261 { | |
3262 opcode = gbReadOpcode(PC.W); | |
3263 CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); | |
3264 PC.W++; | |
3265 | |
3266 if (IFF & 0x100) | |
3267 { | |
3268 IFF &= 0xff; | |
3269 PC.W--; | |
3270 } | |
3271 | |
3272 clockTicks = gbCycles[opcode]; | |
3273 | |
3274 switch (opcode) | |
3275 { | |
3276 case 0xCB: | |
3277 // extended opcode | |
3278 //CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); // is this desired? | |
3279 opcode = gbReadOpcode(PC.W++); | |
3280 clockTicks = gbCyclesCB[opcode]; | |
3281 switch (opcode) | |
3282 { | |
3283 #include "gbCodesCB.h" | |
3284 } | |
3285 break; | |
3286 #include "gbCodes.h" | |
3287 } | |
3288 } | |
3289 | |
3290 if (!emulating) | |
3291 return; | |
3292 | |
3293 if (gbDmaTicks) | |
3294 { | |
3295 clockTicks += gbDmaTicks; | |
3296 gbDmaTicks = 0; | |
3297 } | |
3298 | |
3299 if (gbSgbMode) | |
3300 { | |
3301 if (gbSgbPacketTimeout) | |
3302 { | |
3303 gbSgbPacketTimeout -= clockTicks; | |
3304 | |
3305 if (gbSgbPacketTimeout <= 0) | |
3306 gbSgbResetPacketState(); | |
3307 } | |
3308 } | |
3309 | |
3310 ticksToStop -= clockTicks; | |
3311 | |
3312 // DIV register emulation | |
3313 gbDivTicks -= clockTicks; | |
3314 while (gbDivTicks <= 0) | |
3315 { | |
3316 register_DIV++; | |
3317 gbDivTicks += GBDIV_CLOCK_TICKS; | |
3318 } | |
3319 | |
3320 if (register_LCDC & 0x80) | |
3321 { | |
3322 // LCD stuff | |
3323 gbLcdTicks -= clockTicks; | |
3324 if (gbLcdMode == 1) | |
3325 { | |
3326 // during V-BLANK,we need to increment LY at the same rate! | |
3327 gbLcdLYIncrementTicks -= clockTicks; | |
3328 while (gbLcdLYIncrementTicks <= 0) | |
3329 { | |
3330 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS; | |
3331 | |
3332 if (register_LY < 153) | |
3333 { | |
3334 register_LY++; | |
3335 | |
3336 gbCompareLYToLYC(); | |
3337 | |
3338 if (register_LY >= 153) | |
3339 gbLcdLYIncrementTicks = 6; | |
3340 } | |
3341 else | |
3342 { | |
3343 register_LY = 0x00; | |
3344 // reset the window line | |
3345 gbWindowLine = -1; | |
3346 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2; | |
3347 gbCompareLYToLYC(); | |
3348 } | |
3349 } | |
3350 } | |
3351 | |
3352 // our counter is off, see what we need to do | |
3353 while (gbLcdTicks <= 0) | |
3354 { | |
3355 int framesToSkip = systemFramesToSkip(); | |
3356 | |
3357 switch (gbLcdMode) | |
3358 { | |
3359 case 0: | |
3360 // H-Blank | |
3361 register_LY++; | |
3362 | |
3363 gbCompareLYToLYC(); | |
3364 | |
3365 // check if we reached the V-Blank period | |
3366 if (register_LY == 144) | |
3367 { | |
3368 // Yes, V-Blank | |
3369 // set the LY increment counter | |
3370 gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS; | |
3371 gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS; | |
3372 gbLcdMode = 1; | |
3373 if (register_LCDC & 0x80) | |
3374 { | |
3375 gbInterrupt |= 1; // V-Blank interrupt | |
3376 gbInterruptWait = 6; | |
3377 if (register_STAT & 0x10) | |
3378 gbInterrupt |= 2; | |
3379 } | |
3380 | |
3381 systemFrame(); | |
3382 | |
3383 ++gbFrameCount; | |
3384 u32 currentTime = systemGetClock(); | |
3385 if (currentTime - gbLastTime >= 1000) | |
3386 { | |
3387 systemShowSpeed(int(float(gbFrameCount) * 100000 / (float(currentTime - gbLastTime) * 60) + .5f)); | |
3388 gbLastTime = currentTime; | |
3389 gbFrameCount = 0; | |
3390 } | |
3391 | |
3392 ++GBSystemCounters.frameCount; | |
3393 if (GBSystemCounters.lagged) | |
3394 { | |
3395 ++GBSystemCounters.lagCount; | |
3396 } | |
3397 GBSystemCounters.laggedLast = GBSystemCounters.lagged; | |
3398 GBSystemCounters.lagged = true; | |
3399 | |
3400 extern void VBAOnEnteringFrameBoundary(); | |
3401 VBAOnEnteringFrameBoundary(); | |
3402 | |
3403 newFrame = true; | |
3404 | |
3405 pauseAfterFrameAdvance = systemPauseOnFrame(); | |
3406 | |
3407 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) | |
3408 { | |
3409 if (gbBorderOn) | |
3410 gbSgbRenderBorder(); // clear unnecessary things on border (e.g. in-game text message) | |
3411 | |
3412 systemRenderFrame(); | |
3413 gbFrameSkipCount = 0; | |
3414 | |
3415 bool capturePressed = (extButtons & 2) != 0; | |
3416 if (capturePressed && !capturePrevious) | |
3417 { | |
3418 captureNumber = systemScreenCapture(captureNumber); | |
3419 } | |
3420 capturePrevious = capturePressed && !pauseAfterFrameAdvance; | |
3421 } | |
3422 else | |
3423 { | |
3424 ++gbFrameSkipCount; | |
3425 } | |
3426 | |
3427 if (pauseAfterFrameAdvance) | |
3428 { | |
3429 systemSetPause(true); | |
3430 } | |
3431 } | |
3432 else | |
3433 { | |
3434 // go the the OAM being accessed mode | |
3435 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; | |
3436 gbLcdMode = 2; | |
3437 | |
3438 // only one LCD interrupt per line. may need to generalize... | |
3439 if (!(register_STAT & 0x40) || | |
3440 (register_LY != register_LYC)) | |
3441 { | |
3442 if ((register_STAT & 0x28) == 0x20) | |
3443 gbInterrupt |= 2; | |
3444 } | |
3445 } | |
3446 | |
3447 break; | |
3448 case 1: | |
3449 // V-Blank | |
3450 // next mode is OAM being accessed mode | |
3451 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS; | |
3452 gbLcdMode = 2; | |
3453 if (!(register_STAT & 0x40) || | |
3454 (register_LY != register_LYC)) | |
3455 { | |
3456 if ((register_STAT & 0x28) == 0x20) | |
3457 gbInterrupt |= 2; | |
3458 } | |
3459 break; | |
3460 case 2: | |
3461 // OAM being accessed mode | |
3462 | |
3463 // next mode is OAM and VRAM in use | |
3464 gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS; | |
3465 gbLcdMode = 3; | |
3466 break; | |
3467 case 3: | |
3468 // OAM and VRAM in use | |
3469 // next mode is H-Blank | |
3470 if (register_LY < 144) | |
3471 { | |
3472 if (!gbSgbMask) | |
3473 { | |
3474 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance) | |
3475 { | |
3476 gbRenderLine(); | |
3477 gbDrawSprites(); | |
3478 | |
3479 switch (systemColorDepth) | |
3480 { | |
3481 case 16: | |
3482 | |
3483 { | |
3484 u16 *dest = (u16 *)pix + | |
3485 (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1) | |
3486 + gbBorderColumnSkip; | |
3487 for (int x = 0; x < 160; ) | |
3488 { | |
3489 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3490 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3491 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3492 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3493 | |
3494 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3495 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3496 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3497 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3498 | |
3499 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3500 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3501 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3502 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3503 | |
3504 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3505 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3506 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3507 *dest++ = systemColorMap16[gbLineMix[x++]]; | |
3508 } | |
3509 if (gbBorderOn) | |
3510 dest += gbBorderColumnSkip; | |
3511 *dest++ = 0; // for filters that read one pixel more | |
3512 break; | |
3513 } | |
3514 case 24: | |
3515 | |
3516 { | |
3517 u8 *dest = (u8 *)pix + | |
3518 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) + | |
3519 gbBorderColumnSkip); | |
3520 for (int x = 0; x < 160; ) | |
3521 { | |
3522 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3523 dest += 3; | |
3524 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3525 dest += 3; | |
3526 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3527 dest += 3; | |
3528 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3529 dest += 3; | |
3530 | |
3531 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3532 dest += 3; | |
3533 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3534 dest += 3; | |
3535 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3536 dest += 3; | |
3537 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3538 dest += 3; | |
3539 | |
3540 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3541 dest += 3; | |
3542 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3543 dest += 3; | |
3544 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3545 dest += 3; | |
3546 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3547 dest += 3; | |
3548 | |
3549 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3550 dest += 3; | |
3551 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3552 dest += 3; | |
3553 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3554 dest += 3; | |
3555 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]]; | |
3556 dest += 3; | |
3557 } | |
3558 break; | |
3559 } | |
3560 case 32: | |
3561 | |
3562 { | |
3563 u32 *dest = (u32 *)pix + | |
3564 (gbBorderLineSkip + 1) * (register_LY + gbBorderRowSkip + 1) | |
3565 + gbBorderColumnSkip; | |
3566 for (int x = 0; x < 160; ) | |
3567 { | |
3568 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3569 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3570 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3571 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3572 | |
3573 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3574 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3575 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3576 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3577 | |
3578 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3579 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3580 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3581 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3582 | |
3583 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3584 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3585 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3586 *dest++ = systemColorMap32[gbLineMix[x++]]; | |
3587 } | |
3588 break; | |
3589 } | |
3590 } | |
3591 } | |
3592 } | |
3593 } | |
3594 gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS; | |
3595 gbLcdMode = 0; | |
3596 // only one LCD interrupt per line. may need to generalize... | |
3597 if (!(register_STAT & 0x40) || | |
3598 (register_LY != register_LYC)) | |
3599 { | |
3600 if (register_STAT & 0x08) | |
3601 gbInterrupt |= 2; | |
3602 } | |
3603 if (gbHdmaOn) | |
3604 { | |
3605 gbDoHdma(); | |
3606 } | |
3607 break; | |
3608 } | |
3609 // mark the correct lcd mode on STAT register | |
3610 register_STAT = (register_STAT & 0xfc) | gbLcdMode; | |
3611 } | |
3612 } | |
3613 | |
3614 // serial emulation | |
3615 if (gbSerialOn) | |
3616 { | |
3617 #ifdef LINK_EMULATION | |
3618 if (linkConnected) | |
3619 { | |
3620 gbSerialTicks -= clockTicks; | |
3621 | |
3622 while (gbSerialTicks <= 0) | |
3623 { | |
3624 // increment number of shifted bits | |
3625 gbSerialBits++; | |
3626 linkProc(); | |
3627 if (gbSerialOn && (gbMemory[0xff02] & 1)) | |
3628 { | |
3629 if (gbSerialBits == 8) | |
3630 { | |
3631 gbSerialBits = 0; | |
3632 gbMemory[0xff01] = 0xff; | |
3633 gbMemory[0xff02] &= 0x7f; | |
3634 gbSerialOn = 0; | |
3635 gbInterrupt |= 8; | |
3636 gbSerialTicks = 0; | |
3637 } | |
3638 } | |
3639 gbSerialTicks += GBSERIAL_CLOCK_TICKS; | |
3640 } | |
3641 } | |
3642 else | |
3643 { | |
3644 #endif | |
3645 if (gbMemory[0xff02] & 1) | |
3646 { | |
3647 gbSerialTicks -= clockTicks; | |
3648 | |
3649 // overflow | |
3650 while (gbSerialTicks <= 0) | |
3651 { | |
3652 // shift serial byte to right and put a 1 bit in its place | |
3653 // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1); | |
3654 // increment number of shifted bits | |
3655 gbSerialBits++; | |
3656 if (gbSerialBits == 8) | |
3657 { | |
3658 // end of transmission | |
3659 if (gbSerialFunction) // external device | |
3660 gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); | |
3661 else | |
3662 gbMemory[0xff01] = 0xff; | |
3663 gbSerialTicks = 0; | |
3664 gbMemory[0xff02] &= 0x7f; | |
3665 gbSerialOn = 0; | |
3666 gbInterrupt |= 8; | |
3667 gbSerialBits = 0; | |
3668 } | |
3669 else | |
3670 gbSerialTicks += GBSERIAL_CLOCK_TICKS; | |
3671 } | |
3672 } | |
3673 #ifdef LINK_EMULATION | |
3674 } | |
3675 #endif | |
3676 } | |
3677 | |
3678 // timer emulation | |
3679 if (gbTimerOn) | |
3680 { | |
3681 gbTimerTicks -= clockTicks; | |
3682 | |
3683 while (gbTimerTicks <= 0) | |
3684 { | |
3685 register_TIMA++; | |
3686 | |
3687 if (register_TIMA == 0) | |
3688 { | |
3689 // timer overflow! | |
3690 | |
3691 // reload timer modulo | |
3692 register_TIMA = register_TMA; | |
3693 | |
3694 // flag interrupt | |
3695 gbInterrupt |= 4; | |
3696 } | |
3697 | |
3698 gbTimerTicks += gbTimerClockTicks; | |
3699 } | |
3700 } | |
3701 | |
3702 /* | |
3703 if(soundOffFlag) | |
3704 { | |
3705 if(synchronize && !speedup) | |
3706 { | |
3707 synchronizeTicks -= clockTicks; | |
3708 | |
3709 while(synchronizeTicks < 0) | |
3710 { | |
3711 synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS; | |
3712 | |
3713 DWORD now = timeGetTime(); | |
3714 gbElapsedTime += (now - timeNow); | |
3715 | |
3716 if(gbElapsedTime < 50) | |
3717 { | |
3718 DWORD diff = 50 - gbElapsedTime; | |
3719 Sleep(diff); | |
3720 timeNow = timeGetTime(); | |
3721 elapsedTime = timeNow - now - diff; | |
3722 if((int)elapsedTime < 0) | |
3723 elapsedTime = 0; | |
3724 } else | |
3725 { | |
3726 timeNow = timeGetTime(); | |
3727 elapsedTime = 0; | |
3728 } | |
3729 } | |
3730 } | |
3731 } | |
3732 */ | |
3733 | |
3734 soundTicks -= clockTicks; | |
3735 while (soundTicks < 0) // must be < 1 when soundtick_t is real data type | |
3736 { | |
3737 soundTicks += SOUND_CLOCK_TICKS; | |
3738 | |
3739 gbSoundTick(); | |
3740 } | |
3741 | |
3742 register_IF = gbInterrupt; | |
3743 | |
3744 if (IFF & 0x20) | |
3745 { | |
3746 IFF &= 0xdf; | |
3747 IFF |= 0x01; | |
3748 gbInterruptWait = 0; | |
3749 } | |
3750 else if (gbInterrupt) | |
3751 { | |
3752 if (gbInterruptWait == 0) | |
3753 { | |
3754 // gbInterruptWait = 0; | |
3755 | |
3756 if (IFF & 0x01) | |
3757 { | |
3758 if ((gbInterrupt & 1) && (register_IE & 1)) | |
3759 { | |
3760 gbVblank_interrupt(); | |
3761 continue; | |
3762 } | |
3763 | |
3764 if ((gbInterrupt & 2) && (register_IE & 2)) | |
3765 { | |
3766 gbLcd_interrupt(); | |
3767 continue; | |
3768 } | |
3769 | |
3770 if ((gbInterrupt & 4) && (register_IE & 4)) | |
3771 { | |
3772 gbTimer_interrupt(); | |
3773 continue; | |
3774 } | |
3775 | |
3776 if ((gbInterrupt & 8) && (register_IE & 8)) | |
3777 { | |
3778 gbSerial_interrupt(); | |
3779 continue; | |
3780 } | |
3781 | |
3782 if ((gbInterrupt & 16) && (register_IE & 16)) | |
3783 { | |
3784 gbJoypad_interrupt(); | |
3785 continue; | |
3786 } | |
3787 } | |
3788 } | |
3789 else | |
3790 { | |
3791 gbInterruptWait -= clockTicks; | |
3792 if (gbInterruptWait < 0) | |
3793 gbInterruptWait = 0; | |
3794 } | |
3795 } | |
3796 | |
3797 if (useOldFrameTiming) | |
3798 { | |
3799 // old timing code | |
3800 if (ticksToStop > 0) | |
3801 continue; | |
3802 } | |
3803 else | |
3804 { | |
3805 if (!newFrame && (register_LCDC & 0x80) != 0) | |
3806 continue; | |
3807 } | |
3808 | |
3809 if (!(register_LCDC & 0x80)) | |
3810 { | |
3811 if (!useOldFrameTiming) | |
3812 { | |
3813 // FIXME: since register_LY can be reset to 0 by some games, frame length is variable | |
3814 // and infinite loops can occurr | |
3815 // for now, it IS necessary to do something on this condition or games like | |
3816 // Megaman would freeze upon low-level restart interrupt sequence (Start+Select+A+B). | |
3817 // the only sensible way to fix this issue is to implement the RIGHT frame timing | |
3818 #ifdef WANTS_INCOMPLETE_WORKAROUND | |
3819 if (systemReadJoypads()) | |
3820 { | |
3821 if (gbSgbMode && gbSgbMultiplayer) | |
3822 { | |
3823 if (gbSgbFourPlayers) | |
3824 { | |
3825 gbJoymask[0] = systemGetJoypad(0, false); | |
3826 gbJoymask[1] = systemGetJoypad(1, false); | |
3827 gbJoymask[2] = systemGetJoypad(2, false); | |
3828 gbJoymask[3] = systemGetJoypad(3, false); | |
3829 } | |
3830 else | |
3831 { | |
3832 gbJoymask[0] = systemGetJoypad(0, false); | |
3833 gbJoymask[1] = systemGetJoypad(1, false); | |
3834 } | |
3835 } | |
3836 else | |
3837 { | |
3838 gbJoymask[0] = systemGetJoypad(0, false); | |
3839 } | |
3840 } | |
3841 else | |
3842 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; | |
3843 #else | 3846 #else |
3844 #endif | 3847 #endif |
3845 } | 3848 } |
3846 } | 3849 } |
3847 | 3850 |
3848 // makes sure frames are really divided across input sampling boundaries which occur at a constant rate | 3851 // makes sure frames are really divided across input sampling boundaries which occur at a constant rate |
3849 if (newFrame || useOldFrameTiming) | 3852 if (newFrame || useOldFrameTiming) |
3850 { | 3853 { |
3851 /// extern void VBAOnEnteringFrameBoundary(); | 3854 /// extern void VBAOnEnteringFrameBoundary(); |
3852 /// VBAOnEnteringFrameBoundary(); | 3855 /// VBAOnEnteringFrameBoundary(); |
3853 | 3856 |
3854 break; | 3857 break; |
3855 } | 3858 } |
3856 } | 3859 } |
3857 } | 3860 } |
3858 | 3861 |
3859 struct EmulatedSystem GBSystem = | 3862 struct EmulatedSystem GBSystem = |
3860 { | 3863 { |
3861 // emuMain | 3864 // emuMain |
3862 gbEmulate, | 3865 gbEmulate, |
3863 // emuReset | 3866 // emuReset |
3864 gbReset, | 3867 gbReset, |
3865 // emuCleanUp | 3868 // emuCleanUp |
3866 gbCleanUp, | 3869 gbCleanUp, |
3867 // emuReadBattery | 3870 // emuReadBattery |
3868 gbReadBatteryFile, | 3871 gbReadBatteryFile, |
3869 // emuWriteBattery | 3872 // emuWriteBattery |
3870 gbWriteBatteryFile, | 3873 gbWriteBatteryFile, |
3871 // emuReadBatteryFromStream | 3874 // emuReadBatteryFromStream |
3872 gbReadBatteryFromStream, | 3875 gbReadBatteryFromStream, |
3873 // emuWriteBatteryToStream | 3876 // emuWriteBatteryToStream |
3874 gbWriteBatteryToStream, | 3877 gbWriteBatteryToStream, |
3875 // emuReadState | 3878 // emuReadState |
3876 gbReadSaveState, | 3879 gbReadSaveState, |
3877 // emuWriteState | 3880 // emuWriteState |
3878 gbWriteSaveState, | 3881 gbWriteSaveState, |
3879 // emuReadStateFromStream | 3882 // emuReadStateFromStream |
3880 gbReadSaveStateFromStream, | 3883 gbReadSaveStateFromStream, |
3881 // emuWriteStateToStream | 3884 // emuWriteStateToStream |
3882 gbWriteSaveStateToStream, | 3885 gbWriteSaveStateToStream, |
3883 // emuReadMemState | 3886 // emuReadMemState |
3884 gbReadMemSaveState, | 3887 gbReadMemSaveState, |
3885 // emuWriteMemState | 3888 // emuWriteMemState |
3886 gbWriteMemSaveState, | 3889 gbWriteMemSaveState, |
3887 // emuWritePNG | 3890 // emuWritePNG |
3888 gbWritePNGFile, | 3891 gbWritePNGFile, |
3889 // emuWriteBMP | 3892 // emuWriteBMP |
3890 gbWriteBMPFile, | 3893 gbWriteBMPFile, |
3891 // emuUpdateCPSR | 3894 // emuUpdateCPSR |
3892 NULL, | 3895 NULL, |
3893 // emuHasDebugger | 3896 // emuHasDebugger |
3894 false, | 3897 false, |
3895 // emuCount | 3898 // emuCount |
3896 #ifdef FINAL_VERSION | 3899 #ifdef FINAL_VERSION |
3897 70000 / 4, | 3900 70000 / 4, |
3898 #else | 3901 #else |
3899 1000, | 3902 1000, |
3900 #endif | 3903 #endif |
3901 }; | 3904 }; |
3902 | 3905 |
3903 // is there a reason to use more than one set of counters? | 3906 // is there a reason to use more than one set of counters? |
3904 EmulatedSystemCounters &GBSystemCounters = systemCounters; | 3907 EmulatedSystemCounters &GBSystemCounters = systemCounters; |
3905 | 3908 |
3906 /* | 3909 /* |
3907 EmulatedSystemCounters GBSystemCounters = | 3910 EmulatedSystemCounters GBSystemCounters = |
3908 { | 3911 { |
3909 // frameCount | 3912 // frameCount |
3910 0, | 3913 0, |
3911 // lagCount | 3914 // lagCount |
3912 0, | 3915 0, |
3913 // lagged | 3916 // lagged |
3914 true, | 3917 true, |
3915 // laggedLast | 3918 // laggedLast |
3916 true, | 3919 true, |
3917 }; | 3920 }; |
3918 */ | 3921 */ |