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 { &register_DIV, sizeof(u8) }, 2427 { &register_DIV, sizeof(u8) },
2428 { &register_TIMA, sizeof(u8) }, 2428 { &register_TIMA, sizeof(u8) },
2429 { &register_TMA, sizeof(u8) }, 2429 { &register_TMA, sizeof(u8) },
2430 { &register_TAC, sizeof(u8) }, 2430 { &register_TAC, sizeof(u8) },
2431 { &register_IF, sizeof(u8) }, 2431 { &register_IF, sizeof(u8) },
2432 { &register_LCDC, sizeof(u8) }, 2432 { &register_LCDC, sizeof(u8) },
2433 { &register_STAT, sizeof(u8) }, 2433 { &register_STAT, sizeof(u8) },
2434 { &register_SCY, sizeof(u8) }, 2434 { &register_SCY, sizeof(u8) },
2435 { &register_SCX, sizeof(u8) }, 2435 { &register_SCX, sizeof(u8) },
2436 { &register_LY, sizeof(u8) }, 2436 { &register_LY, sizeof(u8) },
2437 { &register_LYC, sizeof(u8) }, 2437 { &register_LYC, sizeof(u8) },
2438 { &register_DMA, sizeof(u8) }, 2438 { &register_DMA, sizeof(u8) },
2439 { &register_WY, sizeof(u8) }, 2439 { &register_WY, sizeof(u8) },
2440 { &register_WX, sizeof(u8) }, 2440 { &register_WX, sizeof(u8) },
2441 { &register_VBK, sizeof(u8) }, 2441 { &register_VBK, sizeof(u8) },
2442 { &register_HDMA1, sizeof(u8) }, 2442 { &register_HDMA1, sizeof(u8) },
2443 { &register_HDMA2, sizeof(u8) }, 2443 { &register_HDMA2, sizeof(u8) },
2444 { &register_HDMA3, sizeof(u8) }, 2444 { &register_HDMA3, sizeof(u8) },
2445 { &register_HDMA4, sizeof(u8) }, 2445 { &register_HDMA4, sizeof(u8) },
2446 { &register_HDMA5, sizeof(u8) }, 2446 { &register_HDMA5, sizeof(u8) },
2447 { &register_SVBK, sizeof(u8) }, 2447 { &register_SVBK, sizeof(u8) },
2448 { &register_IE, sizeof(u8) }, 2448 { &register_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 */