Mercurial > vba-linux
comparison src/gb/GB.cpp @ 17:75e5bb1e0aa1
going to now integrate the gb src tree since it has no dependencies
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:44:47 -0600 |
parents | f9f4f1b99eed |
children | 44974c3e093b |
comparison
equal
deleted
inserted
replaced
16:9e598342e182 | 17:75e5bb1e0aa1 |
---|---|
1 #include <cstdio> | |
2 #include <cstdlib> | |
3 #include <cstring> | |
4 #include <cassert> | |
5 | |
6 #include "../Port.h" | |
7 #include "../NLS.h" | |
8 #include "GB.h" | |
9 #include "gbCheats.h" | |
10 #include "gbGlobals.h" | |
11 #include "gbMemory.h" | |
12 #include "gbSGB.h" | |
13 #include "gbSound.h" | |
14 #include "../common/unzip.h" | |
15 #include "../common/Util.h" | |
16 #include "../common/System.h" | |
17 #include "../common/movie.h" | |
18 #include "../common/vbalua.h" | |
19 | |
20 #ifdef __GNUC__ | |
21 #define _stricmp strcasecmp | |
22 #endif | |
23 | |
24 // FIXME: constant (GB) or boolean (GBA)?! | |
25 #define C_FLAG 0x10 | |
26 #define H_FLAG 0x20 | |
27 #define N_FLAG 0x40 | |
28 #define Z_FLAG 0x80 | |
29 extern soundtick_t GB_USE_TICKS_AS; | |
30 | |
31 u8 * origPix = NULL; | |
32 extern u8 * pix; | |
33 extern u32 extButtons; | |
34 extern bool8 capturePrevious; | |
35 extern int32 captureNumber; | |
36 extern bool8 speedup; | |
37 | |
38 bool gbUpdateSizes(); | |
39 | |
40 // debugging | |
41 bool memorydebug = false; | |
42 char gbBuffer[2048]; | |
43 | |
44 extern u16 gbLineMix[160]; | |
45 | |
46 // mappers | |
47 void (*mapper)(u16, u8) = NULL; | |
48 void (*mapperRAM)(u16, u8) = NULL; | |
49 u8 (*mapperReadRAM)(u16) = NULL; | |
50 | |
51 // registers | |
52 gbRegister PC; | |
53 gbRegister SP; | |
54 gbRegister AF; | |
55 gbRegister BC; | |
56 gbRegister DE; | |
57 gbRegister HL; | |
58 u16 IFF; | |
59 // 0xff04 | |
60 u8 register_DIV = 0; | |
61 // 0xff05 | |
62 u8 register_TIMA = 0; | |
63 // 0xff06 | |
64 u8 register_TMA = 0; | |
65 // 0xff07 | |
66 u8 register_TAC = 0; | |
67 // 0xff0f | |
68 u8 register_IF = 0; | |
69 // 0xff40 | |
70 u8 register_LCDC = 0; | |
71 // 0xff41 | |
72 u8 register_STAT = 0; | |
73 // 0xff42 | |
74 u8 register_SCY = 0; | |
75 // 0xff43 | |
76 u8 register_SCX = 0; | |
77 // 0xff44 | |
78 u8 register_LY = 0; | |
79 // 0xff45 | |
80 u8 register_LYC = 0; | |
81 // 0xff46 | |
82 u8 register_DMA = 0; | |
83 // 0xff4a | |
84 u8 register_WY = 0; | |
85 // 0xff4b | |
86 u8 register_WX = 0; | |
87 // 0xff4f | |
88 u8 register_VBK = 0; | |
89 // 0xff51 | |
90 u8 register_HDMA1 = 0; | |
91 // 0xff52 | |
92 u8 register_HDMA2 = 0; | |
93 // 0xff53 | |
94 u8 register_HDMA3 = 0; | |
95 // 0xff54 | |
96 u8 register_HDMA4 = 0; | |
97 // 0xff55 | |
98 u8 register_HDMA5 = 0; | |
99 // 0xff70 | |
100 u8 register_SVBK = 0; | |
101 // 0xffff | |
102 u8 register_IE = 0; | |
103 | |
104 // ticks definition | |
105 int32 GBDIV_CLOCK_TICKS = 64; | |
106 int32 GBLCD_MODE_0_CLOCK_TICKS = 51; | |
107 int32 GBLCD_MODE_1_CLOCK_TICKS = 1140; | |
108 int32 GBLCD_MODE_2_CLOCK_TICKS = 20; | |
109 int32 GBLCD_MODE_3_CLOCK_TICKS = 43; | |
110 int32 GBLY_INCREMENT_CLOCK_TICKS = 114; | |
111 int32 GBTIMER_MODE_0_CLOCK_TICKS = 256; | |
112 int32 GBTIMER_MODE_1_CLOCK_TICKS = 4; | |
113 int32 GBTIMER_MODE_2_CLOCK_TICKS = 16; | |
114 int32 GBTIMER_MODE_3_CLOCK_TICKS = 64; | |
115 int32 GBSERIAL_CLOCK_TICKS = 128; | |
116 int32 GBSYNCHRONIZE_CLOCK_TICKS = 52920; | |
117 | |
118 // state variables | |
119 | |
120 // interrupt | |
121 int32 gbInterrupt = 0; | |
122 int32 gbInterruptWait = 0; | |
123 // serial | |
124 int32 gbSerialOn = 0; | |
125 int32 gbSerialTicks = 0; | |
126 int32 gbSerialBits = 0; | |
127 // timer | |
128 int32 gbTimerOn = 0; | |
129 int32 gbTimerTicks = 0; | |
130 int32 gbTimerClockTicks = 0; | |
131 int32 gbTimerMode = 0; | |
132 // lcd | |
133 int32 gbLcdMode = 2; | |
134 int32 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; | |
135 int32 gbLcdLYIncrementTicks = 0; | |
136 // div | |
137 int32 gbDivTicks = GBDIV_CLOCK_TICKS; | |
138 // cgb | |
139 int32 gbVramBank = 0; | |
140 int32 gbWramBank = 1; | |
141 int32 gbHdmaSource = 0x0000; | |
142 int32 gbHdmaDestination = 0x8000; | |
143 int32 gbHdmaBytes = 0x0000; | |
144 int32 gbHdmaOn = 0; | |
145 int32 gbSpeed = 0; | |
146 // frame counting | |
147 int32 gbFrameCount = 0; | |
148 int32 gbFrameSkip = 0; | |
149 int32 gbFrameSkipCount = 0; | |
150 // timing | |
151 u32 gbLastTime = 0; | |
152 u32 gbElapsedTime = 0; | |
153 u32 gbTimeNow = 0; | |
154 int32 gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; | |
155 int32 gbDMASpeedVersion = 1; | |
156 // emulator features | |
157 int32 gbBattery = 0; | |
158 int32 gbJoymask[4] = { 0, 0, 0, 0 }; | |
159 | |
160 int32 gbEchoRAMFixOn = 1; | |
161 | |
162 static bool newFrame = true; | |
163 static bool pauseAfterFrameAdvance = false; | |
164 | |
165 int32 gbRomSizes[] = { 0x00008000, // 32K | |
166 0x00010000, // 64K | |
167 0x00020000, // 128K | |
168 0x00040000, // 256K | |
169 0x00080000, // 512K | |
170 0x00100000, // 1024K | |
171 0x00200000, // 2048K | |
172 0x00400000, // 4096K | |
173 0x00800000 // 8192K | |
174 }; | |
175 int32 gbRomSizesMasks[] = { 0x00007fff, | |
176 0x0000ffff, | |
177 0x0001ffff, | |
178 0x0003ffff, | |
179 0x0007ffff, | |
180 0x000fffff, | |
181 0x001fffff, | |
182 0x003fffff, | |
183 0x007fffff }; | |
184 | |
185 int32 gbRamSizes[6] = { 0x00000000, // 0K | |
186 0x00000800, // 2K | |
187 0x00002000, // 8K | |
188 0x00008000, // 32K | |
189 0x00020000, // 128K | |
190 0x00010000 // 64K | |
191 }; | |
192 | |
193 int32 gbRamSizesMasks[6] = { 0x00000000, | |
194 0x000007ff, | |
195 0x00001fff, | |
196 0x00007fff, | |
197 0x0001ffff, | |
198 0x0000ffff }; | |
199 | |
200 int32 gbCycles[] = | |
201 { | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
218 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4 // f | |
219 }; | |
220 | |
221 int32 gbCyclesCB[] = | |
222 { | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
239 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2 // f | |
240 }; | |
241 | |
242 u16 DAATable[] = | |
243 { | |
244 0x0080, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, | |
245 0x0800, 0x0900, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, | |
246 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, | |
247 0x1800, 0x1900, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, | |
248 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2600, 0x2700, | |
249 0x2800, 0x2900, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, | |
250 0x3000, 0x3100, 0x3200, 0x3300, 0x3400, 0x3500, 0x3600, 0x3700, | |
251 0x3800, 0x3900, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, | |
252 0x4000, 0x4100, 0x4200, 0x4300, 0x4400, 0x4500, 0x4600, 0x4700, | |
253 0x4800, 0x4900, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, | |
254 0x5000, 0x5100, 0x5200, 0x5300, 0x5400, 0x5500, 0x5600, 0x5700, | |
255 0x5800, 0x5900, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, | |
256 0x6000, 0x6100, 0x6200, 0x6300, 0x6400, 0x6500, 0x6600, 0x6700, | |
257 0x6800, 0x6900, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, | |
258 0x7000, 0x7100, 0x7200, 0x7300, 0x7400, 0x7500, 0x7600, 0x7700, | |
259 0x7800, 0x7900, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, | |
260 0x8000, 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, | |
261 0x8800, 0x8900, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, | |
262 0x9000, 0x9100, 0x9200, 0x9300, 0x9400, 0x9500, 0x9600, 0x9700, | |
263 0x9800, 0x9900, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | |
264 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, | |
265 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | |
266 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, | |
267 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | |
268 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, | |
269 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | |
270 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, | |
271 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | |
272 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, | |
273 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | |
274 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, | |
275 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | |
276 0x6010, 0x6110, 0x6210, 0x6310, 0x6410, 0x6510, 0x6610, 0x6710, | |
277 0x6810, 0x6910, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, | |
278 0x7010, 0x7110, 0x7210, 0x7310, 0x7410, 0x7510, 0x7610, 0x7710, | |
279 0x7810, 0x7910, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, | |
280 0x8010, 0x8110, 0x8210, 0x8310, 0x8410, 0x8510, 0x8610, 0x8710, | |
281 0x8810, 0x8910, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, | |
282 0x9010, 0x9110, 0x9210, 0x9310, 0x9410, 0x9510, 0x9610, 0x9710, | |
283 0x9810, 0x9910, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, | |
284 0xA010, 0xA110, 0xA210, 0xA310, 0xA410, 0xA510, 0xA610, 0xA710, | |
285 0xA810, 0xA910, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, | |
286 0xB010, 0xB110, 0xB210, 0xB310, 0xB410, 0xB510, 0xB610, 0xB710, | |
287 0xB810, 0xB910, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, | |
288 0xC010, 0xC110, 0xC210, 0xC310, 0xC410, 0xC510, 0xC610, 0xC710, | |
289 0xC810, 0xC910, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, | |
290 0xD010, 0xD110, 0xD210, 0xD310, 0xD410, 0xD510, 0xD610, 0xD710, | |
291 0xD810, 0xD910, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, | |
292 0xE010, 0xE110, 0xE210, 0xE310, 0xE410, 0xE510, 0xE610, 0xE710, | |
293 0xE810, 0xE910, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, | |
294 0xF010, 0xF110, 0xF210, 0xF310, 0xF410, 0xF510, 0xF610, 0xF710, | |
295 0xF810, 0xF910, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | |
296 0x0090, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710, | |
297 0x0810, 0x0910, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | |
298 0x1010, 0x1110, 0x1210, 0x1310, 0x1410, 0x1510, 0x1610, 0x1710, | |
299 0x1810, 0x1910, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | |
300 0x2010, 0x2110, 0x2210, 0x2310, 0x2410, 0x2510, 0x2610, 0x2710, | |
301 0x2810, 0x2910, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | |
302 0x3010, 0x3110, 0x3210, 0x3310, 0x3410, 0x3510, 0x3610, 0x3710, | |
303 0x3810, 0x3910, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | |
304 0x4010, 0x4110, 0x4210, 0x4310, 0x4410, 0x4510, 0x4610, 0x4710, | |
305 0x4810, 0x4910, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | |
306 0x5010, 0x5110, 0x5210, 0x5310, 0x5410, 0x5510, 0x5610, 0x5710, | |
307 0x5810, 0x5910, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | |
308 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, | |
309 0x0E00, 0x0F00, 0x1020, 0x1120, 0x1220, 0x1320, 0x1420, 0x1520, | |
310 0x1600, 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00, 0x1C00, 0x1D00, | |
311 0x1E00, 0x1F00, 0x2020, 0x2120, 0x2220, 0x2320, 0x2420, 0x2520, | |
312 0x2600, 0x2700, 0x2800, 0x2900, 0x2A00, 0x2B00, 0x2C00, 0x2D00, | |
313 0x2E00, 0x2F00, 0x3020, 0x3120, 0x3220, 0x3320, 0x3420, 0x3520, | |
314 0x3600, 0x3700, 0x3800, 0x3900, 0x3A00, 0x3B00, 0x3C00, 0x3D00, | |
315 0x3E00, 0x3F00, 0x4020, 0x4120, 0x4220, 0x4320, 0x4420, 0x4520, | |
316 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, 0x4B00, 0x4C00, 0x4D00, | |
317 0x4E00, 0x4F00, 0x5020, 0x5120, 0x5220, 0x5320, 0x5420, 0x5520, | |
318 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x5C00, 0x5D00, | |
319 0x5E00, 0x5F00, 0x6020, 0x6120, 0x6220, 0x6320, 0x6420, 0x6520, | |
320 0x6600, 0x6700, 0x6800, 0x6900, 0x6A00, 0x6B00, 0x6C00, 0x6D00, | |
321 0x6E00, 0x6F00, 0x7020, 0x7120, 0x7220, 0x7320, 0x7420, 0x7520, | |
322 0x7600, 0x7700, 0x7800, 0x7900, 0x7A00, 0x7B00, 0x7C00, 0x7D00, | |
323 0x7E00, 0x7F00, 0x8020, 0x8120, 0x8220, 0x8320, 0x8420, 0x8520, | |
324 0x8600, 0x8700, 0x8800, 0x8900, 0x8A00, 0x8B00, 0x8C00, 0x8D00, | |
325 0x8E00, 0x8F00, 0x9020, 0x9120, 0x9220, 0x9320, 0x9420, 0x9520, | |
326 0x9600, 0x9700, 0x9800, 0x9900, 0x9A00, 0x9B00, 0x9C00, 0x9D00, | |
327 0x9E00, 0x9F00, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | |
328 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, | |
329 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | |
330 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, | |
331 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | |
332 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, | |
333 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | |
334 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, | |
335 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | |
336 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, | |
337 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | |
338 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, | |
339 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | |
340 0x6610, 0x6710, 0x6810, 0x6910, 0x6A10, 0x6B10, 0x6C10, 0x6D10, | |
341 0x6E10, 0x6F10, 0x7030, 0x7130, 0x7230, 0x7330, 0x7430, 0x7530, | |
342 0x7610, 0x7710, 0x7810, 0x7910, 0x7A10, 0x7B10, 0x7C10, 0x7D10, | |
343 0x7E10, 0x7F10, 0x8030, 0x8130, 0x8230, 0x8330, 0x8430, 0x8530, | |
344 0x8610, 0x8710, 0x8810, 0x8910, 0x8A10, 0x8B10, 0x8C10, 0x8D10, | |
345 0x8E10, 0x8F10, 0x9030, 0x9130, 0x9230, 0x9330, 0x9430, 0x9530, | |
346 0x9610, 0x9710, 0x9810, 0x9910, 0x9A10, 0x9B10, 0x9C10, 0x9D10, | |
347 0x9E10, 0x9F10, 0xA030, 0xA130, 0xA230, 0xA330, 0xA430, 0xA530, | |
348 0xA610, 0xA710, 0xA810, 0xA910, 0xAA10, 0xAB10, 0xAC10, 0xAD10, | |
349 0xAE10, 0xAF10, 0xB030, 0xB130, 0xB230, 0xB330, 0xB430, 0xB530, | |
350 0xB610, 0xB710, 0xB810, 0xB910, 0xBA10, 0xBB10, 0xBC10, 0xBD10, | |
351 0xBE10, 0xBF10, 0xC030, 0xC130, 0xC230, 0xC330, 0xC430, 0xC530, | |
352 0xC610, 0xC710, 0xC810, 0xC910, 0xCA10, 0xCB10, 0xCC10, 0xCD10, | |
353 0xCE10, 0xCF10, 0xD030, 0xD130, 0xD230, 0xD330, 0xD430, 0xD530, | |
354 0xD610, 0xD710, 0xD810, 0xD910, 0xDA10, 0xDB10, 0xDC10, 0xDD10, | |
355 0xDE10, 0xDF10, 0xE030, 0xE130, 0xE230, 0xE330, 0xE430, 0xE530, | |
356 0xE610, 0xE710, 0xE810, 0xE910, 0xEA10, 0xEB10, 0xEC10, 0xED10, | |
357 0xEE10, 0xEF10, 0xF030, 0xF130, 0xF230, 0xF330, 0xF430, 0xF530, | |
358 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, 0xFC10, 0xFD10, | |
359 0xFE10, 0xFF10, 0x00B0, 0x0130, 0x0230, 0x0330, 0x0430, 0x0530, | |
360 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, 0x0C10, 0x0D10, | |
361 0x0E10, 0x0F10, 0x1030, 0x1130, 0x1230, 0x1330, 0x1430, 0x1530, | |
362 0x1610, 0x1710, 0x1810, 0x1910, 0x1A10, 0x1B10, 0x1C10, 0x1D10, | |
363 0x1E10, 0x1F10, 0x2030, 0x2130, 0x2230, 0x2330, 0x2430, 0x2530, | |
364 0x2610, 0x2710, 0x2810, 0x2910, 0x2A10, 0x2B10, 0x2C10, 0x2D10, | |
365 0x2E10, 0x2F10, 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, | |
366 0x3610, 0x3710, 0x3810, 0x3910, 0x3A10, 0x3B10, 0x3C10, 0x3D10, | |
367 0x3E10, 0x3F10, 0x4030, 0x4130, 0x4230, 0x4330, 0x4430, 0x4530, | |
368 0x4610, 0x4710, 0x4810, 0x4910, 0x4A10, 0x4B10, 0x4C10, 0x4D10, | |
369 0x4E10, 0x4F10, 0x5030, 0x5130, 0x5230, 0x5330, 0x5430, 0x5530, | |
370 0x5610, 0x5710, 0x5810, 0x5910, 0x5A10, 0x5B10, 0x5C10, 0x5D10, | |
371 0x5E10, 0x5F10, 0x6030, 0x6130, 0x6230, 0x6330, 0x6430, 0x6530, | |
372 0x00C0, 0x0140, 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, | |
373 0x0840, 0x0940, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, | |
374 0x1040, 0x1140, 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, | |
375 0x1840, 0x1940, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, | |
376 0x2040, 0x2140, 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, | |
377 0x2840, 0x2940, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, | |
378 0x3040, 0x3140, 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, | |
379 0x3840, 0x3940, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, | |
380 0x4040, 0x4140, 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, | |
381 0x4840, 0x4940, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, | |
382 0x5040, 0x5140, 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, | |
383 0x5840, 0x5940, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, | |
384 0x6040, 0x6140, 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, | |
385 0x6840, 0x6940, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, | |
386 0x7040, 0x7140, 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, | |
387 0x7840, 0x7940, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, | |
388 0x8040, 0x8140, 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, | |
389 0x8840, 0x8940, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, | |
390 0x9040, 0x9140, 0x9240, 0x9340, 0x9440, 0x9540, 0x9640, 0x9740, | |
391 0x9840, 0x9940, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | |
392 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, | |
393 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | |
394 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, | |
395 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | |
396 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, | |
397 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | |
398 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, | |
399 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | |
400 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, | |
401 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | |
402 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, | |
403 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | |
404 0xA050, 0xA150, 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, | |
405 0xA850, 0xA950, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, | |
406 0xB050, 0xB150, 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, | |
407 0xB850, 0xB950, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, | |
408 0xC050, 0xC150, 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, | |
409 0xC850, 0xC950, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, | |
410 0xD050, 0xD150, 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, | |
411 0xD850, 0xD950, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, | |
412 0xE050, 0xE150, 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, | |
413 0xE850, 0xE950, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, | |
414 0xF050, 0xF150, 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, | |
415 0xF850, 0xF950, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, | |
416 0x00D0, 0x0150, 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, | |
417 0x0850, 0x0950, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, | |
418 0x1050, 0x1150, 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, | |
419 0x1850, 0x1950, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, | |
420 0x2050, 0x2150, 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, | |
421 0x2850, 0x2950, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, | |
422 0x3050, 0x3150, 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, | |
423 0x3850, 0x3950, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | |
424 0x4050, 0x4150, 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, | |
425 0x4850, 0x4950, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | |
426 0x5050, 0x5150, 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, | |
427 0x5850, 0x5950, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | |
428 0x6050, 0x6150, 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, | |
429 0x6850, 0x6950, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | |
430 0x7050, 0x7150, 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, | |
431 0x7850, 0x7950, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | |
432 0x8050, 0x8150, 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, | |
433 0x8850, 0x8950, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | |
434 0x9050, 0x9150, 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, | |
435 0x9850, 0x9950, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | |
436 0xFA60, 0xFB60, 0xFC60, 0xFD60, 0xFE60, 0xFF60, 0x00C0, 0x0140, | |
437 0x0240, 0x0340, 0x0440, 0x0540, 0x0640, 0x0740, 0x0840, 0x0940, | |
438 0x0A60, 0x0B60, 0x0C60, 0x0D60, 0x0E60, 0x0F60, 0x1040, 0x1140, | |
439 0x1240, 0x1340, 0x1440, 0x1540, 0x1640, 0x1740, 0x1840, 0x1940, | |
440 0x1A60, 0x1B60, 0x1C60, 0x1D60, 0x1E60, 0x1F60, 0x2040, 0x2140, | |
441 0x2240, 0x2340, 0x2440, 0x2540, 0x2640, 0x2740, 0x2840, 0x2940, | |
442 0x2A60, 0x2B60, 0x2C60, 0x2D60, 0x2E60, 0x2F60, 0x3040, 0x3140, | |
443 0x3240, 0x3340, 0x3440, 0x3540, 0x3640, 0x3740, 0x3840, 0x3940, | |
444 0x3A60, 0x3B60, 0x3C60, 0x3D60, 0x3E60, 0x3F60, 0x4040, 0x4140, | |
445 0x4240, 0x4340, 0x4440, 0x4540, 0x4640, 0x4740, 0x4840, 0x4940, | |
446 0x4A60, 0x4B60, 0x4C60, 0x4D60, 0x4E60, 0x4F60, 0x5040, 0x5140, | |
447 0x5240, 0x5340, 0x5440, 0x5540, 0x5640, 0x5740, 0x5840, 0x5940, | |
448 0x5A60, 0x5B60, 0x5C60, 0x5D60, 0x5E60, 0x5F60, 0x6040, 0x6140, | |
449 0x6240, 0x6340, 0x6440, 0x6540, 0x6640, 0x6740, 0x6840, 0x6940, | |
450 0x6A60, 0x6B60, 0x6C60, 0x6D60, 0x6E60, 0x6F60, 0x7040, 0x7140, | |
451 0x7240, 0x7340, 0x7440, 0x7540, 0x7640, 0x7740, 0x7840, 0x7940, | |
452 0x7A60, 0x7B60, 0x7C60, 0x7D60, 0x7E60, 0x7F60, 0x8040, 0x8140, | |
453 0x8240, 0x8340, 0x8440, 0x8540, 0x8640, 0x8740, 0x8840, 0x8940, | |
454 0x8A60, 0x8B60, 0x8C60, 0x8D60, 0x8E60, 0x8F60, 0x9040, 0x9140, | |
455 0x9240, 0x9340, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | |
456 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, | |
457 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | |
458 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, | |
459 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | |
460 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, | |
461 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | |
462 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, | |
463 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | |
464 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, | |
465 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | |
466 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, | |
467 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | |
468 0x9A70, 0x9B70, 0x9C70, 0x9D70, 0x9E70, 0x9F70, 0xA050, 0xA150, | |
469 0xA250, 0xA350, 0xA450, 0xA550, 0xA650, 0xA750, 0xA850, 0xA950, | |
470 0xAA70, 0xAB70, 0xAC70, 0xAD70, 0xAE70, 0xAF70, 0xB050, 0xB150, | |
471 0xB250, 0xB350, 0xB450, 0xB550, 0xB650, 0xB750, 0xB850, 0xB950, | |
472 0xBA70, 0xBB70, 0xBC70, 0xBD70, 0xBE70, 0xBF70, 0xC050, 0xC150, | |
473 0xC250, 0xC350, 0xC450, 0xC550, 0xC650, 0xC750, 0xC850, 0xC950, | |
474 0xCA70, 0xCB70, 0xCC70, 0xCD70, 0xCE70, 0xCF70, 0xD050, 0xD150, | |
475 0xD250, 0xD350, 0xD450, 0xD550, 0xD650, 0xD750, 0xD850, 0xD950, | |
476 0xDA70, 0xDB70, 0xDC70, 0xDD70, 0xDE70, 0xDF70, 0xE050, 0xE150, | |
477 0xE250, 0xE350, 0xE450, 0xE550, 0xE650, 0xE750, 0xE850, 0xE950, | |
478 0xEA70, 0xEB70, 0xEC70, 0xED70, 0xEE70, 0xEF70, 0xF050, 0xF150, | |
479 0xF250, 0xF350, 0xF450, 0xF550, 0xF650, 0xF750, 0xF850, 0xF950, | |
480 0xFA70, 0xFB70, 0xFC70, 0xFD70, 0xFE70, 0xFF70, 0x00D0, 0x0150, | |
481 0x0250, 0x0350, 0x0450, 0x0550, 0x0650, 0x0750, 0x0850, 0x0950, | |
482 0x0A70, 0x0B70, 0x0C70, 0x0D70, 0x0E70, 0x0F70, 0x1050, 0x1150, | |
483 0x1250, 0x1350, 0x1450, 0x1550, 0x1650, 0x1750, 0x1850, 0x1950, | |
484 0x1A70, 0x1B70, 0x1C70, 0x1D70, 0x1E70, 0x1F70, 0x2050, 0x2150, | |
485 0x2250, 0x2350, 0x2450, 0x2550, 0x2650, 0x2750, 0x2850, 0x2950, | |
486 0x2A70, 0x2B70, 0x2C70, 0x2D70, 0x2E70, 0x2F70, 0x3050, 0x3150, | |
487 0x3250, 0x3350, 0x3450, 0x3550, 0x3650, 0x3750, 0x3850, 0x3950, | |
488 0x3A70, 0x3B70, 0x3C70, 0x3D70, 0x3E70, 0x3F70, 0x4050, 0x4150, | |
489 0x4250, 0x4350, 0x4450, 0x4550, 0x4650, 0x4750, 0x4850, 0x4950, | |
490 0x4A70, 0x4B70, 0x4C70, 0x4D70, 0x4E70, 0x4F70, 0x5050, 0x5150, | |
491 0x5250, 0x5350, 0x5450, 0x5550, 0x5650, 0x5750, 0x5850, 0x5950, | |
492 0x5A70, 0x5B70, 0x5C70, 0x5D70, 0x5E70, 0x5F70, 0x6050, 0x6150, | |
493 0x6250, 0x6350, 0x6450, 0x6550, 0x6650, 0x6750, 0x6850, 0x6950, | |
494 0x6A70, 0x6B70, 0x6C70, 0x6D70, 0x6E70, 0x6F70, 0x7050, 0x7150, | |
495 0x7250, 0x7350, 0x7450, 0x7550, 0x7650, 0x7750, 0x7850, 0x7950, | |
496 0x7A70, 0x7B70, 0x7C70, 0x7D70, 0x7E70, 0x7F70, 0x8050, 0x8150, | |
497 0x8250, 0x8350, 0x8450, 0x8550, 0x8650, 0x8750, 0x8850, 0x8950, | |
498 0x8A70, 0x8B70, 0x8C70, 0x8D70, 0x8E70, 0x8F70, 0x9050, 0x9150, | |
499 0x9250, 0x9350, 0x9450, 0x9550, 0x9650, 0x9750, 0x9850, 0x9950, | |
500 }; | |
501 | |
502 u8 ZeroTable[] = | |
503 { | |
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, | |
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, | |
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, | |
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, | |
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, | |
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, | |
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, | |
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 | |
520 }; | |
521 | |
522 #define GBSAVE_GAME_VERSION_1 1 | |
523 #define GBSAVE_GAME_VERSION_2 2 | |
524 #define GBSAVE_GAME_VERSION_3 3 | |
525 #define GBSAVE_GAME_VERSION_4 4 | |
526 #define GBSAVE_GAME_VERSION_5 5 | |
527 #define GBSAVE_GAME_VERSION_6 6 | |
528 #define GBSAVE_GAME_VERSION_7 7 | |
529 #define GBSAVE_GAME_VERSION_8 8 | |
530 #define GBSAVE_GAME_VERSION_9 9 | |
531 #define GBSAVE_GAME_VERSION_10 10 | |
532 #define GBSAVE_GAME_VERSION_11 11 | |
533 #define GBSAVE_GAME_VERSION_12 12 | |
534 #define GBSAVE_GAME_VERSION_13 13 | |
535 #define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_13 | |
536 | |
537 int inline gbGetValue(int min, int max, int v) | |
538 { | |
539 return (int)(min + (float)(max - min) * (2.0 * (v / 31.0) - (v / 31.0) * (v / 31.0))); | |
540 } | |
541 | |
542 void gbGenFilter() | |
543 { | |
544 for (int r = 0; r < 32; r++) | |
545 { | |
546 for (int g = 0; g < 32; g++) | |
547 { | |
548 for (int b = 0; b < 32; b++) | |
549 { | |
550 int nr = gbGetValue(gbGetValue(4, 14, g), | |
551 gbGetValue(24, 29, g), r) - 4; | |
552 int ng = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), | |
553 14 + gbGetValue(0, 3, r), b), | |
554 gbGetValue(24 + gbGetValue(0, 3, r), | |
555 29 + gbGetValue(0, 1, r), b), g) - 4; | |
556 int nb = gbGetValue(gbGetValue(4 + gbGetValue(0, 5, r), | |
557 14 + gbGetValue(0, 3, r), g), | |
558 gbGetValue(24 + gbGetValue(0, 3, r), | |
559 29 + gbGetValue(0, 1, r), g), b) - 4; | |
560 gbColorFilter[(b << 10) | (g << 5) | r] = (nb << 10) | (ng << 5) | nr; | |
561 } | |
562 } | |
563 } | |
564 } | |
565 | |
566 void gbCopyMemory(u16 d, u16 s, int count) | |
567 { | |
568 while (count) | |
569 { | |
570 gbWriteMemoryQuick(d, gbReadMemoryQuick(s)); | |
571 s++; | |
572 d++; | |
573 count--; | |
574 } | |
575 } | |
576 | |
577 void gbDoHdma() | |
578 { | |
579 gbCopyMemory(gbHdmaDestination, gbHdmaSource, 0x10); | |
580 | |
581 gbHdmaDestination += 0x10; | |
582 gbHdmaSource += 0x10; | |
583 | |
584 register_HDMA2 = (register_HDMA2 + 0x10) & 0xFF; | |
585 if (register_HDMA2 == 0x00) | |
586 register_HDMA1++; | |
587 | |
588 register_HDMA4 = (register_HDMA4 + 0x10) & 0xFF; | |
589 if (register_HDMA4 == 0x00) | |
590 register_HDMA3++; | |
591 | |
592 if (gbHdmaDestination == 0x96b0) | |
593 gbHdmaBytes = gbHdmaBytes; | |
594 gbHdmaBytes -= 0x10; | |
595 register_HDMA5--; | |
596 if (register_HDMA5 == 0xff) | |
597 gbHdmaOn = 0; | |
598 } | |
599 | |
600 // fix for Harley and Lego Racers | |
601 void gbCompareLYToLYC() | |
602 { | |
603 if (register_LY == register_LYC) | |
604 { | |
605 // mark that we have a match | |
606 register_STAT |= 4; | |
607 | |
608 // check if we need an interrupt | |
609 if ((register_STAT & 0x40) && (register_IE & 2)) | |
610 gbInterrupt |= 2; | |
611 } | |
612 else // no match | |
613 register_STAT &= 0xfb; | |
614 } | |
615 | |
616 // FIXME: horrible kludge to workaround the frame timing bug | |
617 static int32 s_gbJoymask[4] = { 0, 0, 0, 0 }; | |
618 | |
619 void gbWriteMemoryWrapped(register u16 address, register u8 value) | |
620 { | |
621 if (address < 0x8000) | |
622 { | |
623 #ifndef FINAL_VERSION | |
624 if (memorydebug && (address > 0x3fff || address < 0x2000)) | |
625 { | |
626 log("Memory register write %04x=%02x PC=%04x\n", | |
627 address, | |
628 value, | |
629 PC.W); | |
630 } | |
631 #endif | |
632 if (mapper) | |
633 (*mapper)(address, value); | |
634 return; | |
635 } | |
636 | |
637 if (address < 0xa000) | |
638 { | |
639 gbWriteMemoryQuick(address, value); | |
640 return; | |
641 } | |
642 | |
643 if (address < 0xc000) | |
644 { | |
645 #ifndef FINAL_VERSION | |
646 if (memorydebug) | |
647 { | |
648 log("Memory register write %04x=%02x PC=%04x\n", | |
649 address, | |
650 value, | |
651 PC.W); | |
652 } | |
653 #endif | |
654 | |
655 if (mapper) | |
656 (*mapperRAM)(address, value); | |
657 return; | |
658 } | |
659 | |
660 if (address < 0xfe00) | |
661 { | |
662 gbWriteMemoryQuick(address, value); | |
663 return; | |
664 } | |
665 | |
666 if (address < 0xff00) | |
667 { | |
668 gbMemory[address] = value; | |
669 return; | |
670 } | |
671 | |
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) | |
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 } | |
1464 | |
1465 void gbVblank_interrupt() | |
1466 { | |
1467 if (IFF & 0x80) | |
1468 { | |
1469 PC.W++; | |
1470 IFF &= 0x7f; | |
1471 } | |
1472 gbInterrupt &= 0xfe; | |
1473 | |
1474 IFF &= 0x7e; | |
1475 register_IF &= 0xfe; | |
1476 | |
1477 gbWriteMemory(--SP.W, PC.B.B1); | |
1478 gbWriteMemory(--SP.W, PC.B.B0); | |
1479 PC.W = 0x40; | |
1480 } | |
1481 | |
1482 void gbLcd_interrupt() | |
1483 { | |
1484 if (IFF & 0x80) | |
1485 { | |
1486 PC.W++; | |
1487 IFF &= 0x7f; | |
1488 } | |
1489 gbInterrupt &= 0xfd; | |
1490 IFF &= 0x7e; | |
1491 register_IF &= 0xfd; | |
1492 | |
1493 gbWriteMemory(--SP.W, PC.B.B1); | |
1494 gbWriteMemory(--SP.W, PC.B.B0); | |
1495 | |
1496 PC.W = 0x48; | |
1497 } | |
1498 | |
1499 void gbTimer_interrupt() | |
1500 { | |
1501 if (IFF & 0x80) | |
1502 { | |
1503 PC.W++; | |
1504 IFF &= 0x7f; | |
1505 } | |
1506 IFF &= 0x7e; | |
1507 gbInterrupt &= 0xfb; | |
1508 register_IF &= 0xfb; | |
1509 | |
1510 gbWriteMemory(--SP.W, PC.B.B1); | |
1511 gbWriteMemory(--SP.W, PC.B.B0); | |
1512 | |
1513 PC.W = 0x50; | |
1514 } | |
1515 | |
1516 void gbSerial_interrupt() | |
1517 { | |
1518 if (IFF & 0x80) | |
1519 { | |
1520 PC.W++; | |
1521 IFF &= 0x7f; | |
1522 } | |
1523 IFF &= 0x7e; | |
1524 gbInterrupt &= 0xf7; | |
1525 register_IF &= 0xf7; | |
1526 | |
1527 gbWriteMemory(--SP.W, PC.B.B1); | |
1528 gbWriteMemory(--SP.W, PC.B.B0); | |
1529 | |
1530 PC.W = 0x58; | |
1531 } | |
1532 | |
1533 void gbJoypad_interrupt() | |
1534 { | |
1535 if (IFF & 0x80) | |
1536 { | |
1537 PC.W++; | |
1538 IFF &= 0x7f; | |
1539 } | |
1540 IFF &= 0x7e; | |
1541 gbInterrupt &= 0xef; | |
1542 register_IF &= 0xef; | |
1543 | |
1544 gbWriteMemory(--SP.W, PC.B.B1); | |
1545 gbWriteMemory(--SP.W, PC.B.B0); | |
1546 | |
1547 PC.W = 0x60; | |
1548 } | |
1549 | |
1550 void gbSpeedSwitch() | |
1551 { | |
1552 if (gbSpeed == 0) | |
1553 { | |
1554 gbSpeed = 1; | |
1555 GBLCD_MODE_0_CLOCK_TICKS = 51 * 2; //127; //51 * 2; | |
1556 GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2; | |
1557 GBLCD_MODE_2_CLOCK_TICKS = 20 * 2; //52; //20 * 2; | |
1558 GBLCD_MODE_3_CLOCK_TICKS = 43 * 2; //99; //43 * 2; | |
1559 GBDIV_CLOCK_TICKS = 64 * 2; | |
1560 GBLY_INCREMENT_CLOCK_TICKS = 114 * 2; | |
1561 GBTIMER_MODE_0_CLOCK_TICKS = 256; //256*2; | |
1562 GBTIMER_MODE_1_CLOCK_TICKS = 4; //4*2; | |
1563 GBTIMER_MODE_2_CLOCK_TICKS = 16; //16*2; | |
1564 GBTIMER_MODE_3_CLOCK_TICKS = 64; //64*2; | |
1565 GBSERIAL_CLOCK_TICKS = 128 * 2; | |
1566 gbDivTicks *= 2; | |
1567 gbLcdTicks *= 2; | |
1568 gbLcdLYIncrementTicks *= 2; | |
1569 // timerTicks *= 2; | |
1570 // timerClockTicks *= 2; | |
1571 gbSerialTicks *= 2; | |
1572 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS * 2; | |
1573 soundTicks *= 2; | |
1574 // synchronizeTicks *= 2; | |
1575 // SYNCHRONIZE_CLOCK_TICKS *= 2; | |
1576 } | |
1577 else | |
1578 { | |
1579 gbSpeed = 0; | |
1580 GBLCD_MODE_0_CLOCK_TICKS = 51; | |
1581 GBLCD_MODE_1_CLOCK_TICKS = 1140; | |
1582 GBLCD_MODE_2_CLOCK_TICKS = 20; | |
1583 GBLCD_MODE_3_CLOCK_TICKS = 43; | |
1584 GBDIV_CLOCK_TICKS = 64; | |
1585 GBLY_INCREMENT_CLOCK_TICKS = 114; | |
1586 GBTIMER_MODE_0_CLOCK_TICKS = 256; | |
1587 GBTIMER_MODE_1_CLOCK_TICKS = 4; | |
1588 GBTIMER_MODE_2_CLOCK_TICKS = 16; | |
1589 GBTIMER_MODE_3_CLOCK_TICKS = 64; | |
1590 GBSERIAL_CLOCK_TICKS = 128; | |
1591 gbDivTicks /= 2; | |
1592 gbLcdTicks /= 2; | |
1593 gbLcdLYIncrementTicks /= 2; | |
1594 // timerTicks /= 2; | |
1595 // timerClockTicks /= 2; | |
1596 gbSerialTicks /= 2; | |
1597 SOUND_CLOCK_TICKS = soundQuality * GB_USE_TICKS_AS; | |
1598 soundTicks /= 2; | |
1599 // synchronizeTicks /= 2; | |
1600 // SYNCHRONIZE_CLOCK_TICKS /= 2; | |
1601 } | |
1602 } | |
1603 | |
1604 void gbGetHardwareType() | |
1605 { | |
1606 gbCgbMode = 0; | |
1607 if (gbRom[0x143] & 0x80) | |
1608 { | |
1609 if (gbEmulatorType == 0 || | |
1610 gbEmulatorType == 1 || | |
1611 gbEmulatorType == 4 || | |
1612 gbEmulatorType == 5 || | |
1613 (gbRom[0x146] != 0x03 && (gbEmulatorType == 2))) | |
1614 { | |
1615 gbCgbMode = 1; | |
1616 } | |
1617 } | |
1618 | |
1619 if (gbSgbMode == 2) | |
1620 { | |
1621 gbSgbMode = 0; | |
1622 return; | |
1623 } | |
1624 | |
1625 gbSgbMode = 0; | |
1626 if (gbRom[0x146] == 0x03) | |
1627 { | |
1628 if (gbEmulatorType == 0 || | |
1629 gbEmulatorType == 2 || | |
1630 gbEmulatorType == 5 || | |
1631 (!(gbRom[0x143] & 0x80) && (gbEmulatorType == 1 || gbEmulatorType == 4))) | |
1632 gbSgbMode = 1; | |
1633 } | |
1634 } | |
1635 | |
1636 void gbReset(bool userReset) | |
1637 { | |
1638 // movie must be closed while opening/creating a movie | |
1639 if (userReset && VBAMovieRecording()) | |
1640 { | |
1641 VBAMovieSignalReset(); | |
1642 return; | |
1643 } | |
1644 | |
1645 if (!VBAMovieActive()) | |
1646 { | |
1647 GBSystemCounters.frameCount = 0; | |
1648 GBSystemCounters.lagCount = 0; | |
1649 GBSystemCounters.extraCount = 0; | |
1650 GBSystemCounters.lagged = true; | |
1651 GBSystemCounters.laggedLast = true; | |
1652 } | |
1653 | |
1654 SP.W = 0xfffe; | |
1655 AF.W = 0x01b0; | |
1656 BC.W = 0x0013; | |
1657 DE.W = 0x00d8; | |
1658 HL.W = 0x014d; | |
1659 PC.W = 0x0100; | |
1660 IFF = 0; | |
1661 gbInterrupt = 1; | |
1662 gbInterruptWait = 0; | |
1663 | |
1664 register_DIV = 0; | |
1665 register_TIMA = 0; | |
1666 register_TMA = 0; | |
1667 register_TAC = 0; | |
1668 register_IF = 1; | |
1669 register_LCDC = 0x91; | |
1670 register_STAT = 0; | |
1671 register_SCY = 0; | |
1672 register_SCX = 0; | |
1673 register_LY = 0; | |
1674 register_LYC = 0; | |
1675 register_DMA = 0; | |
1676 register_WY = 0; | |
1677 register_WX = 0; | |
1678 register_VBK = 0; | |
1679 register_HDMA1 = 0; | |
1680 register_HDMA2 = 0; | |
1681 register_HDMA3 = 0; | |
1682 register_HDMA4 = 0; | |
1683 register_HDMA5 = 0; | |
1684 register_SVBK = 0; | |
1685 register_IE = 0; | |
1686 | |
1687 gbGetHardwareType(); | |
1688 if (gbCgbMode) | |
1689 { | |
1690 if (!gbVram) | |
1691 gbVram = (u8 *)malloc(0x4000 + 4); | |
1692 if (!gbWram) | |
1693 gbWram = (u8 *)malloc(0x8000 + 4); | |
1694 memset(gbVram, 0, 0x4000 + 4); | |
1695 memset(gbWram, 0, 0x8000 + 4); | |
1696 } | |
1697 else | |
1698 { | |
1699 if (gbVram) | |
1700 { | |
1701 free(gbVram); | |
1702 gbVram = NULL; | |
1703 } | |
1704 if (gbWram) | |
1705 { | |
1706 free(gbWram); | |
1707 gbWram = NULL; | |
1708 } | |
1709 } | |
1710 | |
1711 // clean LineBuffer | |
1712 if (gbLineBuffer) | |
1713 memset(gbLineBuffer, 0, 160 * sizeof(u16)); | |
1714 // clean Pix | |
1715 if (pix) | |
1716 memset(pix, 0, 4 * 257 * 226); | |
1717 | |
1718 if (gbCgbMode) | |
1719 { | |
1720 if (gbSgbMode) | |
1721 { | |
1722 if (gbEmulatorType == 5) | |
1723 AF.W = 0xffb0; | |
1724 else | |
1725 AF.W = 0x01b0; | |
1726 BC.W = 0x0013; | |
1727 DE.W = 0x00d8; | |
1728 HL.W = 0x014d; | |
1729 } | |
1730 else | |
1731 { | |
1732 AF.W = 0x11b0; | |
1733 BC.W = 0x0000; | |
1734 DE.W = 0xff56; | |
1735 HL.W = 0x000d; | |
1736 } | |
1737 if (gbEmulatorType == 4) | |
1738 BC.B.B1 |= 0x01; | |
1739 | |
1740 register_HDMA5 = 0xff; | |
1741 gbMemory[0xff68] = 0xc0; | |
1742 gbMemory[0xff6a] = 0xc0; | |
1743 | |
1744 for (int i = 0; i < 64; i++) | |
1745 gbPalette[i] = 0x7fff; | |
1746 } | |
1747 else | |
1748 { | |
1749 for (int i = 0; i < 8; i++) | |
1750 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i]; | |
1751 } | |
1752 | |
1753 if (gbSpeed) | |
1754 { | |
1755 gbSpeedSwitch(); | |
1756 gbMemory[0xff4d] = 0; | |
1757 } | |
1758 | |
1759 gbDivTicks = GBDIV_CLOCK_TICKS; | |
1760 gbLcdMode = 2; | |
1761 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS; | |
1762 gbLcdLYIncrementTicks = 0; | |
1763 gbTimerTicks = 0; | |
1764 gbTimerClockTicks = 0; | |
1765 gbSerialTicks = 0; | |
1766 gbSerialBits = 0; | |
1767 gbSerialOn = 0; | |
1768 gbWindowLine = -1; | |
1769 gbTimerOn = 0; | |
1770 gbTimerMode = 0; | |
1771 // gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS; | |
1772 gbSpeed = 0; | |
1773 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0; | |
1774 | |
1775 // FIXME: horrible kludge | |
1776 memset(s_gbJoymask, 0, sizeof(s_gbJoymask)); | |
1777 | |
1778 if (gbCgbMode) | |
1779 { | |
1780 gbSpeed = 0; | |
1781 gbHdmaOn = 0; | |
1782 gbHdmaSource = 0x0000; | |
1783 gbHdmaDestination = 0x8000; | |
1784 gbVramBank = 0; | |
1785 gbWramBank = 1; | |
1786 register_LY = 0x90; | |
1787 gbLcdMode = 1; | |
1788 } | |
1789 | |
1790 if (gbSgbMode) | |
1791 { | |
1792 gbSgbReset(); | |
1793 } | |
1794 | |
1795 for (int i = 0; i < 4; i++) | |
1796 gbBgp[i] = gbObp0[i] = gbObp1[i] = i; | |
1797 | |
1798 memset(&gbDataMBC1, 0, sizeof(gbDataMBC1)); | |
1799 gbDataMBC1.mapperROMBank = 1; | |
1800 | |
1801 gbDataMBC2.mapperRAMEnable = 0; | |
1802 gbDataMBC2.mapperROMBank = 1; | |
1803 | |
1804 memset(&gbDataMBC3, 0, 6 * sizeof(int32)); | |
1805 gbDataMBC3.mapperROMBank = 1; | |
1806 | |
1807 memset(&gbDataMBC5, 0, sizeof(gbDataMBC5)); | |
1808 gbDataMBC5.mapperROMBank = 1; | |
1809 switch (gbRom[0x147]) | |
1810 { | |
1811 case 0x1c: | |
1812 case 0x1d: | |
1813 case 0x1e: | |
1814 gbDataMBC5.isRumbleCartridge = 1; | |
1815 } | |
1816 | |
1817 memset(&gbDataHuC1, 0, sizeof(gbDataHuC1)); | |
1818 gbDataHuC1.mapperROMBank = 1; | |
1819 | |
1820 memset(&gbDataHuC3, 0, sizeof(gbDataHuC3)); | |
1821 gbDataHuC3.mapperROMBank = 1; | |
1822 | |
1823 gbMemoryMap[0x00] = &gbRom[0x0000]; | |
1824 gbMemoryMap[0x01] = &gbRom[0x1000]; | |
1825 gbMemoryMap[0x02] = &gbRom[0x2000]; | |
1826 gbMemoryMap[0x03] = &gbRom[0x3000]; | |
1827 gbMemoryMap[0x04] = &gbRom[0x4000]; | |
1828 gbMemoryMap[0x05] = &gbRom[0x5000]; | |
1829 gbMemoryMap[0x06] = &gbRom[0x6000]; | |
1830 gbMemoryMap[0x07] = &gbRom[0x7000]; | |
1831 if (gbCgbMode) | |
1832 { | |
1833 gbMemoryMap[0x08] = &gbVram[0x0000]; | |
1834 gbMemoryMap[0x09] = &gbVram[0x1000]; | |
1835 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | |
1836 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | |
1837 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | |
1838 gbMemoryMap[0x0d] = &gbWram[0x1000]; | |
1839 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | |
1840 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | |
1841 } | |
1842 else | |
1843 { | |
1844 gbMemoryMap[0x08] = &gbMemory[0x8000]; | |
1845 gbMemoryMap[0x09] = &gbMemory[0x9000]; | |
1846 gbMemoryMap[0x0a] = &gbMemory[0xa000]; | |
1847 gbMemoryMap[0x0b] = &gbMemory[0xb000]; | |
1848 gbMemoryMap[0x0c] = &gbMemory[0xc000]; | |
1849 gbMemoryMap[0x0d] = &gbMemory[0xd000]; | |
1850 gbMemoryMap[0x0e] = &gbMemory[0xe000]; | |
1851 gbMemoryMap[0x0f] = &gbMemory[0xf000]; | |
1852 } | |
1853 | |
1854 if (gbRam) | |
1855 { | |
1856 gbMemoryMap[0x0a] = &gbRam[0x0000]; | |
1857 gbMemoryMap[0x0b] = &gbRam[0x1000]; | |
1858 } | |
1859 | |
1860 gbSoundReset(); | |
1861 | |
1862 systemResetSensor(); | |
1863 | |
1864 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
1865 | |
1866 gbLastTime = systemGetClock(); | |
1867 gbFrameCount = 0; | |
1868 | |
1869 systemRefreshScreen(); | |
1870 } | |
1871 | |
1872 void gbWriteSaveMBC1(const char *name) | |
1873 { | |
1874 FILE *gzFile = fopen(name, "wb"); | |
1875 | |
1876 if (gzFile == NULL) | |
1877 { | |
1878 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | |
1879 return; | |
1880 } | |
1881 | |
1882 fwrite(gbRam, | |
1883 1, | |
1884 gbRamSize, | |
1885 gzFile); | |
1886 | |
1887 fclose(gzFile); | |
1888 } | |
1889 | |
1890 void gbWriteSaveMBC2(const char *name) | |
1891 { | |
1892 FILE *file = fopen(name, "wb"); | |
1893 | |
1894 if (file == NULL) | |
1895 { | |
1896 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | |
1897 return; | |
1898 } | |
1899 | |
1900 fwrite(&gbMemory[0xa000], | |
1901 1, | |
1902 256, | |
1903 file); | |
1904 | |
1905 fclose(file); | |
1906 } | |
1907 | |
1908 void gbWriteSaveMBC3(const char *name, bool extendedSave) | |
1909 { | |
1910 FILE *gzFile = fopen(name, "wb"); | |
1911 | |
1912 if (gzFile == NULL) | |
1913 { | |
1914 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | |
1915 return; | |
1916 } | |
1917 | |
1918 fwrite(gbRam, | |
1919 1, | |
1920 gbRamSize, | |
1921 gzFile); | |
1922 | |
1923 if (extendedSave) | |
1924 { | |
1925 //assert(sizeof(time_t) == 4); | |
1926 fwrite(&gbDataMBC3.mapperSeconds, | |
1927 1, | |
1928 10 * sizeof(int32) + /*sizeof(time_t)*/4, | |
1929 gzFile); | |
1930 } | |
1931 | |
1932 fclose(gzFile); | |
1933 } | |
1934 | |
1935 void gbWriteSaveMBC5(const char *name) | |
1936 { | |
1937 FILE *gzFile = fopen(name, "wb"); | |
1938 | |
1939 if (gzFile == NULL) | |
1940 { | |
1941 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | |
1942 return; | |
1943 } | |
1944 | |
1945 fwrite(gbRam, | |
1946 1, | |
1947 gbRamSize, | |
1948 gzFile); | |
1949 | |
1950 fclose(gzFile); | |
1951 } | |
1952 | |
1953 void gbWriteSaveMBC7(const char *name) | |
1954 { | |
1955 FILE *file = fopen(name, "wb"); | |
1956 | |
1957 if (file == NULL) | |
1958 { | |
1959 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name); | |
1960 return; | |
1961 } | |
1962 | |
1963 fwrite(&gbMemory[0xa000], | |
1964 1, | |
1965 256, | |
1966 file); | |
1967 | |
1968 fclose(file); | |
1969 } | |
1970 | |
1971 bool gbReadSaveMBC1(const char *name) | |
1972 { | |
1973 gzFile gzFile = gzopen(name, "rb"); | |
1974 | |
1975 if (gzFile == NULL) | |
1976 { | |
1977 return false; | |
1978 } | |
1979 | |
1980 int read = gzread(gzFile, | |
1981 gbRam, | |
1982 gbRamSize); | |
1983 | |
1984 if (read != gbRamSize) | |
1985 { | |
1986 systemMessage(MSG_FAILED_TO_READ_SGM, N_("Failed to read complete save game %s (%d)"), name, read); | |
1987 gzclose(gzFile); | |
1988 return false; | |
1989 } | |
1990 | |
1991 gzclose(gzFile); | |
1992 return true; | |
1993 } | |
1994 | |
1995 bool gbReadSaveMBC2(const char *name) | |
1996 { | |
1997 FILE *file = fopen(name, "rb"); | |
1998 | |
1999 if (file == NULL) | |
2000 { | |
2001 return false; | |
2002 } | |
2003 | |
2004 int read = fread(&gbMemory[0xa000], | |
2005 1, | |
2006 256, | |
2007 file); | |
2008 | |
2009 if (read != 256) | |
2010 { | |
2011 systemMessage(MSG_FAILED_TO_READ_SGM, | |
2012 N_("Failed to read complete save game %s (%d)"), name, read); | |
2013 fclose(file); | |
2014 return false; | |
2015 } | |
2016 | |
2017 fclose(file); | |
2018 return true; | |
2019 } | |
2020 | |
2021 bool gbReadSaveMBC3(const char *name) | |
2022 { | |
2023 gzFile gzFile = gzopen(name, "rb"); | |
2024 | |
2025 if (gzFile == NULL) | |
2026 { | |
2027 return false; | |
2028 } | |
2029 | |
2030 int read = gzread(gzFile, | |
2031 gbRam, | |
2032 gbRamSize); | |
2033 | |
2034 bool res = true; | |
2035 | |
2036 if (read != gbRamSize) | |
2037 { | |
2038 systemMessage(MSG_FAILED_TO_READ_SGM, | |
2039 N_("Failed to read complete save game %s (%d)"), name, read); | |
2040 } | |
2041 else | |
2042 { | |
2043 //assert(sizeof(time_t) == 4); | |
2044 read = gzread(gzFile, | |
2045 &gbDataMBC3.mapperSeconds, | |
2046 sizeof(int32) * 10 + /*sizeof(time_t)*/4); | |
2047 | |
2048 if (read != (sizeof(int32) * 10 + /*sizeof(time_t)*/4) && read != 0) | |
2049 { | |
2050 systemMessage(MSG_FAILED_TO_READ_RTC, | |
2051 N_("Failed to read RTC from save game %s (continuing)"), | |
2052 name); | |
2053 res = false; | |
2054 } | |
2055 } | |
2056 | |
2057 gzclose(gzFile); | |
2058 return res; | |
2059 } | |
2060 | |
2061 bool gbReadSaveMBC5(const char *name) | |
2062 { | |
2063 gzFile gzFile = gzopen(name, "rb"); | |
2064 | |
2065 if (gzFile == NULL) | |
2066 { | |
2067 return false; | |
2068 } | |
2069 | |
2070 int read = gzread(gzFile, | |
2071 gbRam, | |
2072 gbRamSize); | |
2073 | |
2074 if (read != gbRamSize) | |
2075 { | |
2076 systemMessage(MSG_FAILED_TO_READ_SGM, | |
2077 N_("Failed to read complete save game %s (%d)"), name, read); | |
2078 gzclose(gzFile); | |
2079 return false; | |
2080 } | |
2081 | |
2082 gzclose(gzFile); | |
2083 return true; | |
2084 } | |
2085 | |
2086 bool gbReadSaveMBC7(const char *name) | |
2087 { | |
2088 FILE *file = fopen(name, "rb"); | |
2089 | |
2090 if (file == NULL) | |
2091 { | |
2092 return false; | |
2093 } | |
2094 | |
2095 int read = fread(&gbMemory[0xa000], | |
2096 1, | |
2097 256, | |
2098 file); | |
2099 | |
2100 if (read != 256) | |
2101 { | |
2102 systemMessage(MSG_FAILED_TO_READ_SGM, | |
2103 N_("Failed to read complete save game %s (%d)"), name, read); | |
2104 fclose(file); | |
2105 return false; | |
2106 } | |
2107 | |
2108 fclose(file); | |
2109 return true; | |
2110 } | |
2111 | |
2112 #if 0 | |
2113 bool gbLoadBIOS(const char *biosFileName, bool useBiosFile) | |
2114 { | |
2115 useBios = false; | |
2116 if (useBiosFile) | |
2117 { | |
2118 useBios = utilLoadBIOS(bios, biosFileName, gbEmulatorType); | |
2119 if (!useBios) | |
2120 { | |
2121 systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file")); | |
2122 } | |
2123 } | |
2124 return useBios; | |
2125 } | |
2126 #endif | |
2127 | |
2128 void gbInit() | |
2129 { | |
2130 gbGenFilter(); | |
2131 gbSgbInit(); // calls gbSgbReset()... whatever | |
2132 | |
2133 gbMemory = (u8 *)malloc(65536 + 4); | |
2134 memset(gbMemory, 0, 65536 + 4); | |
2135 memset(gbPalette, 0, 2 * 128); | |
2136 | |
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); | |
2139 pix = origPix + 4; | |
2140 | |
2141 gbLineBuffer = (u16 *)malloc(160 * sizeof(u16)); | |
2142 } | |
2143 | |
2144 bool gbWriteBatteryFile(const char *file, bool extendedSave) | |
2145 { | |
2146 if (gbBattery) | |
2147 { | |
2148 int type = gbRom[0x147]; | |
2149 | |
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 { | |
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 } | |
2381 | |
2382 variable_desc gbSaveGameStruct[] = | |
2383 { | |
2384 { &PC.W, sizeof(u16) }, | |
2385 { &SP.W, sizeof(u16) }, | |
2386 { &AF.W, sizeof(u16) }, | |
2387 { &BC.W, sizeof(u16) }, | |
2388 { &DE.W, sizeof(u16) }, | |
2389 { &HL.W, sizeof(u16) }, | |
2390 { &IFF, sizeof(u8) }, | |
2391 { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int32) }, | |
2392 { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int32) }, | |
2393 { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int32) }, | |
2394 { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int32) }, | |
2395 { &GBDIV_CLOCK_TICKS, sizeof(int32) }, | |
2396 { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int32) }, | |
2397 { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int32) }, | |
2398 { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int32) }, | |
2399 { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int32) }, | |
2400 { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int32) }, | |
2401 { &GBSERIAL_CLOCK_TICKS, sizeof(int32) }, | |
2402 { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int32) }, | |
2403 { &gbDivTicks, sizeof(int32) }, | |
2404 { &gbLcdMode, sizeof(int32) }, | |
2405 { &gbLcdTicks, sizeof(int32) }, | |
2406 { &gbLcdLYIncrementTicks, sizeof(int32) }, | |
2407 { &gbTimerTicks, sizeof(int32) }, | |
2408 { &gbTimerClockTicks, sizeof(int32) }, | |
2409 { &gbSerialTicks, sizeof(int32) }, | |
2410 { &gbSerialBits, sizeof(int32) }, | |
2411 { &gbInterrupt, sizeof(int32) }, | |
2412 { &gbInterruptWait, sizeof(int32) }, | |
2413 { &gbSynchronizeTicks, sizeof(int32) }, | |
2414 { &gbTimerOn, sizeof(int32) }, | |
2415 { &gbTimerMode, sizeof(int32) }, | |
2416 { &gbSerialOn, sizeof(int32) }, | |
2417 { &gbWindowLine, sizeof(int32) }, | |
2418 { &gbCgbMode, sizeof(int32) }, | |
2419 { &gbVramBank, sizeof(int32) }, | |
2420 { &gbWramBank, sizeof(int32) }, | |
2421 { &gbHdmaSource, sizeof(int32) }, | |
2422 { &gbHdmaDestination, sizeof(int32) }, | |
2423 { &gbHdmaBytes, sizeof(int32) }, | |
2424 { &gbHdmaOn, sizeof(int32) }, | |
2425 { &gbSpeed, sizeof(int32) }, | |
2426 { &gbSgbMode, sizeof(int32) }, | |
2427 { ®ister_DIV, sizeof(u8) }, | |
2428 { ®ister_TIMA, sizeof(u8) }, | |
2429 { ®ister_TMA, sizeof(u8) }, | |
2430 { ®ister_TAC, sizeof(u8) }, | |
2431 { ®ister_IF, sizeof(u8) }, | |
2432 { ®ister_LCDC, sizeof(u8) }, | |
2433 { ®ister_STAT, sizeof(u8) }, | |
2434 { ®ister_SCY, sizeof(u8) }, | |
2435 { ®ister_SCX, sizeof(u8) }, | |
2436 { ®ister_LY, sizeof(u8) }, | |
2437 { ®ister_LYC, sizeof(u8) }, | |
2438 { ®ister_DMA, sizeof(u8) }, | |
2439 { ®ister_WY, sizeof(u8) }, | |
2440 { ®ister_WX, sizeof(u8) }, | |
2441 { ®ister_VBK, sizeof(u8) }, | |
2442 { ®ister_HDMA1, sizeof(u8) }, | |
2443 { ®ister_HDMA2, sizeof(u8) }, | |
2444 { ®ister_HDMA3, sizeof(u8) }, | |
2445 { ®ister_HDMA4, sizeof(u8) }, | |
2446 { ®ister_HDMA5, sizeof(u8) }, | |
2447 { ®ister_SVBK, sizeof(u8) }, | |
2448 { ®ister_IE, sizeof(u8) }, | |
2449 { &gbBgp[0], sizeof(u8) }, | |
2450 { &gbBgp[1], sizeof(u8) }, | |
2451 { &gbBgp[2], sizeof(u8) }, | |
2452 { &gbBgp[3], sizeof(u8) }, | |
2453 { &gbObp0[0], sizeof(u8) }, | |
2454 { &gbObp0[1], sizeof(u8) }, | |
2455 { &gbObp0[2], sizeof(u8) }, | |
2456 { &gbObp0[3], sizeof(u8) }, | |
2457 { &gbObp1[0], sizeof(u8) }, | |
2458 { &gbObp1[1], sizeof(u8) }, | |
2459 { &gbObp1[2], sizeof(u8) }, | |
2460 { &gbObp1[3], sizeof(u8) }, | |
2461 { NULL, 0 } | |
2462 }; | |
2463 | |
2464 bool gbWriteSaveStateToStream(gzFile gzFile) | |
2465 { | |
2466 utilWriteInt(gzFile, GBSAVE_GAME_VERSION); | |
2467 | |
2468 utilGzWrite(gzFile, &gbRom[0x134], 15); | |
2469 | |
2470 utilWriteData(gzFile, gbSaveGameStruct); | |
2471 | |
2472 utilGzWrite(gzFile, &IFF, 2); | |
2473 | |
2474 if (gbSgbMode) | |
2475 { | |
2476 gbSgbSaveGame(gzFile); | |
2477 } | |
2478 | |
2479 utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); | |
2480 utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); | |
2481 //assert(sizeof(time_t) == 4); | |
2482 utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); | |
2483 utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); | |
2484 utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); | |
2485 utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); | |
2486 | |
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 | |
2489 utilGzWrite(gzFile, pix, 4 * 257 * 226); | |
2490 | |
2491 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); | |
2492 // todo: remove | |
2493 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); | |
2494 | |
2495 utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); | |
2496 | |
2497 if (gbRamSize && gbRam) | |
2498 { | |
2499 utilGzWrite(gzFile, gbRam, gbRamSize); | |
2500 } | |
2501 | |
2502 if (gbCgbMode) | |
2503 { | |
2504 utilGzWrite(gzFile, gbVram, 0x4000); | |
2505 utilGzWrite(gzFile, gbWram, 0x8000); | |
2506 } | |
2507 | |
2508 gbSoundSaveGame(gzFile); | |
2509 | |
2510 gbCheatsSaveGame(gzFile); | |
2511 | |
2512 // new to re-recording version: | |
2513 { | |
2514 extern int32 sensorX, sensorY; | |
2515 utilGzWrite(gzFile, &sensorX, sizeof(sensorX)); | |
2516 utilGzWrite(gzFile, &sensorY, sizeof(sensorY)); | |
2517 utilGzWrite(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get | |
2518 // carried | |
2519 // back on loading a snapshot! | |
2520 | |
2521 bool8 movieActive = VBAMovieActive(); | |
2522 utilGzWrite(gzFile, &movieActive, sizeof(movieActive)); | |
2523 if (movieActive) | |
2524 { | |
2525 uint8 *movie_freeze_buf = NULL; | |
2526 uint32 movie_freeze_size = 0; | |
2527 | |
2528 VBAMovieFreeze(&movie_freeze_buf, &movie_freeze_size); | |
2529 if (movie_freeze_buf) | |
2530 { | |
2531 utilGzWrite(gzFile, &movie_freeze_size, sizeof(movie_freeze_size)); | |
2532 utilGzWrite(gzFile, movie_freeze_buf, movie_freeze_size); | |
2533 delete [] movie_freeze_buf; | |
2534 } | |
2535 else | |
2536 { | |
2537 systemMessage(0, N_("Failed to save movie snapshot.")); | |
2538 return false; | |
2539 } | |
2540 } | |
2541 utilGzWrite(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); | |
2542 } | |
2543 | |
2544 // new to rerecording 19.4 wip (svn r22+): | |
2545 { | |
2546 utilGzWrite(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); | |
2547 utilGzWrite(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); | |
2548 utilGzWrite(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); | |
2549 } | |
2550 | |
2551 return true; | |
2552 } | |
2553 | |
2554 bool gbWriteMemSaveState(char *memory, int available) | |
2555 { | |
2556 gzFile gzFile = utilMemGzOpen(memory, available, "w"); | |
2557 | |
2558 if (gzFile == NULL) | |
2559 { | |
2560 return false; | |
2561 } | |
2562 | |
2563 bool res = gbWriteSaveStateToStream(gzFile); | |
2564 | |
2565 long pos = utilGzTell(gzFile) + 8; | |
2566 | |
2567 if (pos >= (available)) | |
2568 res = false; | |
2569 | |
2570 utilGzClose(gzFile); | |
2571 | |
2572 return res; | |
2573 } | |
2574 | |
2575 bool gbWriteSaveState(const char *name) | |
2576 { | |
2577 gzFile gzFile = utilGzOpen(name, "wb"); | |
2578 | |
2579 if (gzFile == NULL) | |
2580 return false; | |
2581 | |
2582 bool res = gbWriteSaveStateToStream(gzFile); | |
2583 | |
2584 utilGzClose(gzFile); | |
2585 return res; | |
2586 } | |
2587 | |
2588 static int tempStateID = 0; | |
2589 static int tempFailCount = 0; | |
2590 static bool backupSafe = true; | |
2591 | |
2592 bool gbReadSaveStateFromStream(gzFile gzFile) | |
2593 { | |
2594 int type; | |
2595 char tempBackupName [128]; | |
2596 if (backupSafe) | |
2597 { | |
2598 sprintf(tempBackupName, "gbatempsave%d.sav", tempStateID++); | |
2599 gbWriteSaveState(tempBackupName); | |
2600 } | |
2601 | |
2602 int version = utilReadInt(gzFile); | |
2603 | |
2604 if (version > GBSAVE_GAME_VERSION || version < 0) | |
2605 { | |
2606 systemMessage(MSG_UNSUPPORTED_VB_SGM, | |
2607 N_("Unsupported VisualBoy save game version %d"), version); | |
2608 goto failedLoadGB; | |
2609 } | |
2610 | |
2611 u8 romname[20]; | |
2612 | |
2613 utilGzRead(gzFile, romname, 15); | |
2614 | |
2615 if (memcmp(&gbRom[0x134], romname, 15) != 0) | |
2616 { | |
2617 systemMessage(MSG_CANNOT_LOAD_SGM_FOR, | |
2618 N_("Cannot load save game for %s. Playing %s"), | |
2619 romname, &gbRom[0x134]); | |
2620 goto failedLoadGB; | |
2621 } | |
2622 | |
2623 utilReadData(gzFile, gbSaveGameStruct); | |
2624 | |
2625 if (version >= GBSAVE_GAME_VERSION_7) | |
2626 { | |
2627 utilGzRead(gzFile, &IFF, 2); | |
2628 } | |
2629 | |
2630 if (gbSgbMode) | |
2631 { | |
2632 gbSgbReadGame(gzFile, version); | |
2633 } | |
2634 else | |
2635 { | |
2636 gbSgbMask = 0; // loading a game at the wrong time causes no display | |
2637 } | |
2638 | |
2639 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1)); | |
2640 utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2)); | |
2641 if (version < GBSAVE_GAME_VERSION_4) | |
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 | |
2644 // structure changes again. | |
2645 utilGzRead(gzFile, &gbDataMBC3, sizeof(int32) * 10); | |
2646 else | |
2647 { | |
2648 //assert(sizeof(time_t) == 4); | |
2649 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)); | |
2650 } | |
2651 utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5)); | |
2652 utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1)); | |
2653 utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3)); | |
2654 | |
2655 if (version >= GBSAVE_GAME_VERSION_12) | |
2656 { | |
2657 utilGzRead(gzFile, pix, 4 * 257 * 226); | |
2658 } | |
2659 else | |
2660 { | |
2661 memset(pix, 0, 257 * 226 * sizeof(u32)); | |
2662 // if(version < GBSAVE_GAME_VERSION_5) | |
2663 // utilGzRead(gzFile, pix, 256*224*sizeof(u16)); | |
2664 } | |
2665 | |
2666 if (version < GBSAVE_GAME_VERSION_6) | |
2667 { | |
2668 utilGzRead(gzFile, gbPalette, 64 * sizeof(u16)); | |
2669 } | |
2670 else | |
2671 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); | |
2672 | |
2673 // todo: remove | |
2674 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16)); | |
2675 | |
2676 if (version < GBSAVE_GAME_VERSION_10) | |
2677 { | |
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) | |
2844 { | |
2845 case MOVIE_NOT_FROM_THIS_MOVIE: | |
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; | |
2853 } | |
2854 strcat(errStr, "."); | |
2855 systemMessage(0, N_(errStr)); | |
2856 goto failedLoadGB; | |
2857 } | |
2858 } | |
2859 utilGzRead(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount)); | |
2860 } | |
2861 | |
2862 if (version >= GBSAVE_GAME_VERSION_13) // new to rerecording 19.4 wip (svn r22+): | |
2863 { | |
2864 utilGzRead(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount)); | |
2865 utilGzRead(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged)); | |
2866 utilGzRead(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast)); | |
2867 } | |
2868 | |
2869 if (backupSafe) | |
2870 { | |
2871 remove(tempBackupName); | |
2872 tempFailCount = 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 { | |
3179 if (gbSgbFourPlayers) | |
3180 { | |
3181 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3182 gbJoymask[1] = systemGetJoypad(1, false); | |
3183 gbJoymask[2] = systemGetJoypad(2, false); | |
3184 gbJoymask[3] = systemGetJoypad(3, false); | |
3185 } | |
3186 else | |
3187 { | |
3188 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3189 gbJoymask[1] = systemGetJoypad(1, false); | |
3190 } | |
3191 } | |
3192 else | |
3193 { | |
3194 gbJoymask[0] = systemGetJoypad(0, sensor); | |
3195 } | |
3196 | |
3197 // FIXME: horrible kludge | |
3198 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask)); | |
3199 | |
3200 // if (sensor) | |
3201 // systemUpdateMotionSensor(0); | |
3202 | |
3203 newmask = gbJoymask[0]; | |
3204 if (newmask & 0xFF) | |
3205 { | |
3206 gbInterrupt |= 16; | |
3207 } | |
3208 | |
3209 extButtons = (newmask >> 18); | |
3210 speedup = (extButtons & 1) != 0; | |
3211 | |
3212 VBAMovieResetIfRequested(); | |
3213 | |
3214 CallRegisteredLuaFunctions(LUACALL_BEFOREEMULATION); | |
3215 | |
3216 newFrame = false; | |
3217 } | |
3218 | |
3219 for (;; ) | |
3220 { | |
3221 #ifndef FINAL_VERSION | |
3222 if (systemDebug) | |
3223 { | |
3224 if (!(IFF & 0x80)) | |
3225 { | |
3226 if (systemDebug > 1) | |
3227 { | |
3228 sprintf(gbBuffer, "PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n", | |
3229 PC.W, AF.W, BC.W, DE.W, HL.W, SP.W, IFF); | |
3230 } | |
3231 else | |
3232 { | |
3233 sprintf(gbBuffer, "PC=%04x I=%02x\n", PC.W, IFF); | |
3234 } | |
3235 log(gbBuffer); | |
3236 } | |
3237 } | |
3238 #endif | |
3239 if (IFF & 0x80) | |
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 | |
3844 #endif | |
3845 } | |
3846 } | |
3847 | |
3848 // makes sure frames are really divided across input sampling boundaries which occur at a constant rate | |
3849 if (newFrame || useOldFrameTiming) | |
3850 { | |
3851 /// extern void VBAOnEnteringFrameBoundary(); | |
3852 /// VBAOnEnteringFrameBoundary(); | |
3853 | |
3854 break; | |
3855 } | |
3856 } | |
3857 } | |
3858 | |
3859 struct EmulatedSystem GBSystem = | |
3860 { | |
3861 // emuMain | |
3862 gbEmulate, | |
3863 // emuReset | |
3864 gbReset, | |
3865 // emuCleanUp | |
3866 gbCleanUp, | |
3867 // emuReadBattery | |
3868 gbReadBatteryFile, | |
3869 // emuWriteBattery | |
3870 gbWriteBatteryFile, | |
3871 // emuReadBatteryFromStream | |
3872 gbReadBatteryFromStream, | |
3873 // emuWriteBatteryToStream | |
3874 gbWriteBatteryToStream, | |
3875 // emuReadState | |
3876 gbReadSaveState, | |
3877 // emuWriteState | |
3878 gbWriteSaveState, | |
3879 // emuReadStateFromStream | |
3880 gbReadSaveStateFromStream, | |
3881 // emuWriteStateToStream | |
3882 gbWriteSaveStateToStream, | |
3883 // emuReadMemState | |
3884 gbReadMemSaveState, | |
3885 // emuWriteMemState | |
3886 gbWriteMemSaveState, | |
3887 // emuWritePNG | |
3888 gbWritePNGFile, | |
3889 // emuWriteBMP | |
3890 gbWriteBMPFile, | |
3891 // emuUpdateCPSR | |
3892 NULL, | |
3893 // emuHasDebugger | |
3894 false, | |
3895 // emuCount | |
3896 #ifdef FINAL_VERSION | |
3897 70000 / 4, | |
3898 #else | |
3899 1000, | |
3900 #endif | |
3901 }; | |
3902 | |
3903 // is there a reason to use more than one set of counters? | |
3904 EmulatedSystemCounters &GBSystemCounters = systemCounters; | |
3905 | |
3906 /* | |
3907 EmulatedSystemCounters GBSystemCounters = | |
3908 { | |
3909 // frameCount | |
3910 0, | |
3911 // lagCount | |
3912 0, | |
3913 // lagged | |
3914 true, | |
3915 // laggedLast | |
3916 true, | |
3917 }; | |
3918 */ |