1 //#include "../win32/stdafx.h" // would fix LNK2005 linker errors for MSVC
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <memory.h>
6 #include <assert.h>
7
8 #include "../System.h"
9 #include "../NLS.h"
10 #include "gb.h"
11 #include "gbCheats.h"
12 #include "gbGlobals.h"
13 #include "gbMemory.h"
14 #include "gbSGB.h"
15 #include "gbSound.h"
16 #include "../Util.h"
17 #include "../gba/GBALink.h"
18 #include "../common/ConfigManager.h"
19
20 #ifdef __GNUC__
21 #define _stricmp strcasecmp
22 #endif
23
24 extern u8 *pix;
25 bool gbUpdateSizes();
26 bool inBios = false;
27
28 // debugging
29 bool memorydebug = false;
30 char gbBuffer[2048];
31
32 extern u16 gbLineMix[160];
33
34 // mappers
35 void (*mapper)(u16,u8) = NULL;
36 void (*mapperRAM)(u16,u8) = NULL;
37 u8 (*mapperReadRAM)(u16) = NULL;
38 void (*mapperUpdateClock)() = NULL;
39
40 // registers
41 gbRegister PC;
42 gbRegister SP;
43 gbRegister AF;
44 gbRegister BC;
45 gbRegister DE;
46 gbRegister HL;
47 u16 IFF = 0;
48 // 0xff04
49 u8 register_DIV = 0;
50 // 0xff05
51 u8 register_TIMA = 0;
52 // 0xff06
53 u8 register_TMA = 0;
54 // 0xff07
55 u8 register_TAC = 0;
56 // 0xff0f
57 u8 register_IF = 0;
58 // 0xff40
59 u8 register_LCDC = 0;
60 // 0xff41
61 u8 register_STAT = 0;
62 // 0xff42
63 u8 register_SCY = 0;
64 // 0xff43
65 u8 register_SCX = 0;
66 // 0xff44
67 u8 register_LY = 0;
68 // 0xff45
69 u8 register_LYC = 0;
70 // 0xff46
71 u8 register_DMA = 0;
72 // 0xff4a
73 u8 register_WY = 0;
74 // 0xff4b
75 u8 register_WX = 0;
76 // 0xff4f
77 u8 register_VBK = 0;
78 // 0xff51
79 u8 register_HDMA1 = 0;
80 // 0xff52
81 u8 register_HDMA2 = 0;
82 // 0xff53
83 u8 register_HDMA3 = 0;
84 // 0xff54
85 u8 register_HDMA4 = 0;
86 // 0xff55
87 u8 register_HDMA5 = 0;
88 // 0xff70
89 u8 register_SVBK = 0;
90 // 0xffff
91 u8 register_IE = 0;
92
93 // ticks definition
94 int GBDIV_CLOCK_TICKS = 64;
95 int GBLCD_MODE_0_CLOCK_TICKS = 51;
96 int GBLCD_MODE_1_CLOCK_TICKS = 1140;
97 int GBLCD_MODE_2_CLOCK_TICKS = 20;
98 int GBLCD_MODE_3_CLOCK_TICKS = 43;
99 int GBLY_INCREMENT_CLOCK_TICKS = 114;
100 int GBTIMER_MODE_0_CLOCK_TICKS = 256;
101 int GBTIMER_MODE_1_CLOCK_TICKS = 4;
102 int GBTIMER_MODE_2_CLOCK_TICKS = 16;
103 int GBTIMER_MODE_3_CLOCK_TICKS = 64;
104 int GBSERIAL_CLOCK_TICKS = 128;
105 int GBSYNCHRONIZE_CLOCK_TICKS = 52920;
106
107 // state variables
108
109 // general
110 int clockTicks = 0;
111 bool gbSystemMessage = false;
112 int gbGBCColorType = 0;
113 int gbHardware = 0;
114 int gbRomType = 0;
115 int gbRemainingClockTicks = 0;
116 int gbOldClockTicks = 0;
117 int gbIntBreak = 0;
118 int gbInterruptLaunched = 0;
119 u8 gbCheatingDevice = 0; // 1 = GS, 2 = GG
120 // breakpoint
121 bool breakpoint = false;
122 // interrupt
123 int gbInt48Signal = 0;
124 int gbInterruptWait = 0;
125 // serial
126 int gbSerialOn = 0;
127 int gbSerialTicks = 0;
128 int gbSerialBits = 0;
129 // timer
130 bool gbTimerOn = false;
131 int gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;
132 int gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
133 int gbTimerMode = 0;
134 bool gbIncreased = false;
135 // The internal timer is always active, and it is
136 // not reset by writing to register_TIMA/TMA, but by
137 // writing to register_DIV...
138 int gbInternalTimer = 0x55;
139 const u8 gbTimerMask [4] = {0xff, 0x3, 0xf, 0x3f};
140 const u8 gbTimerBug [8] = {0x80, 0x80, 0x02, 0x02, 0x0, 0xff, 0x0, 0xff};
141 bool gbTimerModeChange = false;
142 bool gbTimerOnChange = false;
143 // lcd
144 bool gbScreenOn = true;
145 int gbLcdMode = 2;
146 int gbLcdModeDelayed = 2;
147 int gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS-1;
148 int gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS;
149 int gbLcdLYIncrementTicks = 114;
150 int gbLcdLYIncrementTicksDelayed = 115;
151 int gbScreenTicks = 0;
152 u8 gbSCYLine[300];
153 u8 gbSCXLine[300];
154 u8 gbBgpLine[300];
155 u8 gbObp0Line [300];
156 u8 gbObp1Line [300];
157 u8 gbSpritesTicks [300];
158 u8 oldRegister_WY;
159 bool gbLYChangeHappened = false;
160 bool gbLCDChangeHappened = false;
161 int gbLine99Ticks = 1;
162 int gbRegisterLYLCDCOffOn = 0;
163 int inUseRegister_WY = 0;
164
165 // Used to keep track of the line that ellapse
166 // when screen is off
167 int gbWhiteScreen = 0;
168 bool gbBlackScreen = false;
169 int register_LCDCBusy = 0;
170
171 // div
172 int gbDivTicks = GBDIV_CLOCK_TICKS;
173 // cgb
174 int gbVramBank = 0;
175 int gbWramBank = 1;
176 //sgb
177 bool gbSgbResetFlag = false;
178 // gbHdmaDestination is 0x99d0 on startup (tested on HW)
179 // but I'm not sure what gbHdmaSource is...
180 int gbHdmaSource = 0x99d0;
181 int gbHdmaDestination = 0x99d0;
182 int gbHdmaBytes = 0x0000;
183 int gbHdmaOn = 0;
184 int gbSpeed = 0;
185 // frame counting
186 int gbFrameCount = 0;
187 int gbFrameSkip = 0;
188 int gbFrameSkipCount = 0;
189 // timing
190 u32 gbLastTime = 0;
191 u32 gbElapsedTime = 0;
192 u32 gbTimeNow = 0;
193 int gbSynchronizeTicks = GBSYNCHRONIZE_CLOCK_TICKS;
194 // emulator features
195 int gbBattery = 0;
196 bool gbBatteryError = false;
197 int gbCaptureNumber = 0;
198 bool gbCapture = false;
199 bool gbCapturePrevious = false;
200 int gbJoymask[4] = { 0, 0, 0, 0 };
201
202 u8 gbRamFill = 0xff;
203
204 int gbRomSizes[] = { 0x00008000, // 32K
205 0x00010000, // 64K
206 0x00020000, // 128K
207 0x00040000, // 256K
208 0x00080000, // 512K
209 0x00100000, // 1024K
210 0x00200000, // 2048K
211 0x00400000, // 4096K
212 0x00800000 // 8192K
213 };
214 int gbRomSizesMasks[] = { 0x00007fff,
215 0x0000ffff,
216 0x0001ffff,
217 0x0003ffff,
218 0x0007ffff,
219 0x000fffff,
220 0x001fffff,
221 0x003fffff,
222 0x007fffff
223 };
224
225 int gbRamSizes[6] = { 0x00000000, // 0K
226 0x00002000, // 2K // Changed to 2000 to avoid problems with gbMemoryMap...
227 0x00002000, // 8K
228 0x00008000, // 32K
229 0x00020000, // 128K
230 0x00010000 // 64K
231 };
232
233 int gbRamSizesMasks[6] = { 0x00000000,
234 0x000007ff,
235 0x00001fff,
236 0x00007fff,
237 0x0001ffff,
238 0x0000ffff
239 };
240
241 int gbCycles[] = {
242 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
243 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1, // 0
244 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1, // 1
245 2, 3, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 2
246 2, 3, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 1, 1, 2, 1, // 3
247 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 4
248 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 5
249 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 6
250 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, // 7
251 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 8
252 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 9
253 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // a
254 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, // b
255 2, 3, 3, 4, 3, 4, 2, 4, 2, 4, 3, 2, 3, 6, 2, 4, // c
256 2, 3, 3, 1, 3, 4, 2, 4, 2, 4, 3, 1, 3, 1, 2, 4, // d
257 3, 3, 2, 1, 1, 4, 2, 4, 4, 1, 4, 1, 1, 1, 2, 4, // e
258 3, 3, 2, 1, 1, 4, 2, 4, 3, 2, 4, 1, 0, 1, 2, 4 // f
259 };
260
261 int gbCyclesCB[] = {
262 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
263 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 0
264 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 1
265 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 2
266 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 3
267 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 4
268 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 5
269 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 6
270 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, // 7
271 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 8
272 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // 9
273 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // a
274 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // b
275 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // c
276 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // d
277 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2, // e
278 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2 // f
279 };
280
281 u16 DAATable[] = {
282 0x0080,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700,
283 0x0800,0x0900,0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,
284 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700,
285 0x1800,0x1900,0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,
286 0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,0x2600,0x2700,
287 0x2800,0x2900,0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,
288 0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,0x3600,0x3700,
289 0x3800,0x3900,0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,
290 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700,
291 0x4800,0x4900,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,
292 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700,
293 0x5800,0x5900,0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,
294 0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,
295 0x6800,0x6900,0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,
296 0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,0x7600,0x7700,
297 0x7800,0x7900,0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,
298 0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,0x8600,0x8700,
299 0x8800,0x8900,0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,
300 0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,0x9600,0x9700,
301 0x9800,0x9900,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,
302 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
303 0x0810,0x0910,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,
304 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
305 0x1810,0x1910,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,
306 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
307 0x2810,0x2910,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,
308 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
309 0x3810,0x3910,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,
310 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
311 0x4810,0x4910,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,
312 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
313 0x5810,0x5910,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,
314 0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,0x6610,0x6710,
315 0x6810,0x6910,0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,
316 0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,0x7610,0x7710,
317 0x7810,0x7910,0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,
318 0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,0x8610,0x8710,
319 0x8810,0x8910,0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,
320 0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,0x9610,0x9710,
321 0x9810,0x9910,0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,
322 0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,0xA610,0xA710,
323 0xA810,0xA910,0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,
324 0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,0xB610,0xB710,
325 0xB810,0xB910,0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,
326 0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,0xC610,0xC710,
327 0xC810,0xC910,0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,
328 0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,0xD610,0xD710,
329 0xD810,0xD910,0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,
330 0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,0xE610,0xE710,
331 0xE810,0xE910,0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,
332 0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,0xF610,0xF710,
333 0xF810,0xF910,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,
334 0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,0x0610,0x0710,
335 0x0810,0x0910,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,
336 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710,
337 0x1810,0x1910,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,
338 0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,0x2610,0x2710,
339 0x2810,0x2910,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,
340 0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,0x3610,0x3710,
341 0x3810,0x3910,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,
342 0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,0x4610,0x4710,
343 0x4810,0x4910,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,
344 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710,
345 0x5810,0x5910,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,
346 0x0600,0x0700,0x0800,0x0900,0x0A00,0x0B00,0x0C00,0x0D00,
347 0x0E00,0x0F00,0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,
348 0x1600,0x1700,0x1800,0x1900,0x1A00,0x1B00,0x1C00,0x1D00,
349 0x1E00,0x1F00,0x2000,0x2100,0x2200,0x2300,0x2400,0x2500,
350 0x2600,0x2700,0x2800,0x2900,0x2A00,0x2B00,0x2C00,0x2D00,
351 0x2E00,0x2F00,0x3000,0x3100,0x3200,0x3300,0x3400,0x3500,
352 0x3600,0x3700,0x3800,0x3900,0x3A00,0x3B00,0x3C00,0x3D00,
353 0x3E00,0x3F00,0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,
354 0x4600,0x4700,0x4800,0x4900,0x4A00,0x4B00,0x4C00,0x4D00,
355 0x4E00,0x4F00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,
356 0x5600,0x5700,0x5800,0x5900,0x5A00,0x5B00,0x5C00,0x5D00,
357 0x5E00,0x5F00,0x6000,0x6100,0x6200,0x6300,0x6400,0x6500,
358 0x6600,0x6700,0x6800,0x6900,0x6A00,0x6B00,0x6C00,0x6D00,
359 0x6E00,0x6F00,0x7000,0x7100,0x7200,0x7300,0x7400,0x7500,
360 0x7600,0x7700,0x7800,0x7900,0x7A00,0x7B00,0x7C00,0x7D00,
361 0x7E00,0x7F00,0x8000,0x8100,0x8200,0x8300,0x8400,0x8500,
362 0x8600,0x8700,0x8800,0x8900,0x8A00,0x8B00,0x8C00,0x8D00,
363 0x8E00,0x8F00,0x9000,0x9100,0x9200,0x9300,0x9400,0x9500,
364 0x9600,0x9700,0x9800,0x9900,0x9A00,0x9B00,0x9C00,0x9D00,
365 0x9E00,0x9F00,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,
366 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
367 0x0E10,0x0F10,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,
368 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
369 0x1E10,0x1F10,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,
370 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
371 0x2E10,0x2F10,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,
372 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
373 0x3E10,0x3F10,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,
374 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
375 0x4E10,0x4F10,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,
376 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
377 0x5E10,0x5F10,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,
378 0x6610,0x6710,0x6810,0x6910,0x6A10,0x6B10,0x6C10,0x6D10,
379 0x6E10,0x6F10,0x7010,0x7110,0x7210,0x7310,0x7410,0x7510,
380 0x7610,0x7710,0x7810,0x7910,0x7A10,0x7B10,0x7C10,0x7D10,
381 0x7E10,0x7F10,0x8010,0x8110,0x8210,0x8310,0x8410,0x8510,
382 0x8610,0x8710,0x8810,0x8910,0x8A10,0x8B10,0x8C10,0x8D10,
383 0x8E10,0x8F10,0x9010,0x9110,0x9210,0x9310,0x9410,0x9510,
384 0x9610,0x9710,0x9810,0x9910,0x9A10,0x9B10,0x9C10,0x9D10,
385 0x9E10,0x9F10,0xA010,0xA110,0xA210,0xA310,0xA410,0xA510,
386 0xA610,0xA710,0xA810,0xA910,0xAA10,0xAB10,0xAC10,0xAD10,
387 0xAE10,0xAF10,0xB010,0xB110,0xB210,0xB310,0xB410,0xB510,
388 0xB610,0xB710,0xB810,0xB910,0xBA10,0xBB10,0xBC10,0xBD10,
389 0xBE10,0xBF10,0xC010,0xC110,0xC210,0xC310,0xC410,0xC510,
390 0xC610,0xC710,0xC810,0xC910,0xCA10,0xCB10,0xCC10,0xCD10,
391 0xCE10,0xCF10,0xD010,0xD110,0xD210,0xD310,0xD410,0xD510,
392 0xD610,0xD710,0xD810,0xD910,0xDA10,0xDB10,0xDC10,0xDD10,
393 0xDE10,0xDF10,0xE010,0xE110,0xE210,0xE310,0xE410,0xE510,
394 0xE610,0xE710,0xE810,0xE910,0xEA10,0xEB10,0xEC10,0xED10,
395 0xEE10,0xEF10,0xF010,0xF110,0xF210,0xF310,0xF410,0xF510,
396 0xF610,0xF710,0xF810,0xF910,0xFA10,0xFB10,0xFC10,0xFD10,
397 0xFE10,0xFF10,0x0090,0x0110,0x0210,0x0310,0x0410,0x0510,
398 0x0610,0x0710,0x0810,0x0910,0x0A10,0x0B10,0x0C10,0x0D10,
399 0x0E10,0x0F10,0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,
400 0x1610,0x1710,0x1810,0x1910,0x1A10,0x1B10,0x1C10,0x1D10,
401 0x1E10,0x1F10,0x2010,0x2110,0x2210,0x2310,0x2410,0x2510,
402 0x2610,0x2710,0x2810,0x2910,0x2A10,0x2B10,0x2C10,0x2D10,
403 0x2E10,0x2F10,0x3010,0x3110,0x3210,0x3310,0x3410,0x3510,
404 0x3610,0x3710,0x3810,0x3910,0x3A10,0x3B10,0x3C10,0x3D10,
405 0x3E10,0x3F10,0x4010,0x4110,0x4210,0x4310,0x4410,0x4510,
406 0x4610,0x4710,0x4810,0x4910,0x4A10,0x4B10,0x4C10,0x4D10,
407 0x4E10,0x4F10,0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,
408 0x5610,0x5710,0x5810,0x5910,0x5A10,0x5B10,0x5C10,0x5D10,
409 0x5E10,0x5F10,0x6010,0x6110,0x6210,0x6310,0x6410,0x6510,
410 0x00C0,0x0140,0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,
411 0x0840,0x0940,0x0A40,0x0B40,0x0C40,0x0D40,0x0E40,0x0F40,
412 0x1040,0x1140,0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,
413 0x1840,0x1940,0x1A40,0x1B40,0x1C40,0x1D40,0x1E40,0x1F40,
414 0x2040,0x2140,0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,
415 0x2840,0x2940,0x2A40,0x2B40,0x2C40,0x2D40,0x2E40,0x2F40,
416 0x3040,0x3140,0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,
417 0x3840,0x3940,0x3A40,0x3B40,0x3C40,0x3D40,0x3E40,0x3F40,
418 0x4040,0x4140,0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,
419 0x4840,0x4940,0x4A40,0x4B40,0x4C40,0x4D40,0x4E40,0x4F40,
420 0x5040,0x5140,0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,
421 0x5840,0x5940,0x5A40,0x5B40,0x5C40,0x5D40,0x5E40,0x5F40,
422 0x6040,0x6140,0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,
423 0x6840,0x6940,0x6A40,0x6B40,0x6C40,0x6D40,0x6E40,0x6F40,
424 0x7040,0x7140,0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,
425 0x7840,0x7940,0x7A40,0x7B40,0x7C40,0x7D40,0x7E40,0x7F40,
426 0x8040,0x8140,0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,
427 0x8840,0x8940,0x8A40,0x8B40,0x8C40,0x8D40,0x8E40,0x8F40,
428 0x9040,0x9140,0x9240,0x9340,0x9440,0x9540,0x9640,0x9740,
429 0x9840,0x9940,0x9A40,0x9B40,0x9C40,0x9D40,0x9E40,0x9F40,
430 0xA040,0xA140,0xA240,0xA340,0xA440,0xA540,0xA640,0xA740,
431 0xA840,0xA940,0xAA40,0xAB40,0xAC40,0xAD40,0xAE40,0xAF40,
432 0xB040,0xB140,0xB240,0xB340,0xB440,0xB540,0xB640,0xB740,
433 0xB840,0xB940,0xBA40,0xBB40,0xBC40,0xBD40,0xBE40,0xBF40,
434 0xC040,0xC140,0xC240,0xC340,0xC440,0xC540,0xC640,0xC740,
435 0xC840,0xC940,0xCA40,0xCB40,0xCC40,0xCD40,0xCE40,0xCF40,
436 0xD040,0xD140,0xD240,0xD340,0xD440,0xD540,0xD640,0xD740,
437 0xD840,0xD940,0xDA40,0xDB40,0xDC40,0xDD40,0xDE40,0xDF40,
438 0xE040,0xE140,0xE240,0xE340,0xE440,0xE540,0xE640,0xE740,
439 0xE840,0xE940,0xEA40,0xEB40,0xEC40,0xED40,0xEE40,0xEF40,
440 0xF040,0xF140,0xF240,0xF340,0xF440,0xF540,0xF640,0xF740,
441 0xF840,0xF940,0xFA40,0xFB40,0xFC40,0xFD40,0xFE40,0xFF40,
442 0xA050,0xA150,0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,
443 0xA850,0xA950,0xAA50,0xAB50,0xAC50,0xAD50,0xAE50,0xAF50,
444 0xB050,0xB150,0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,
445 0xB850,0xB950,0xBA50,0xBB50,0xBC50,0xBD50,0xBE50,0xBF50,
446 0xC050,0xC150,0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,
447 0xC850,0xC950,0xCA50,0xCB50,0xCC50,0xCD50,0xCE50,0xCF50,
448 0xD050,0xD150,0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,
449 0xD850,0xD950,0xDA50,0xDB50,0xDC50,0xDD50,0xDE50,0xDF50,
450 0xE050,0xE150,0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,
451 0xE850,0xE950,0xEA50,0xEB50,0xEC50,0xED50,0xEE50,0xEF50,
452 0xF050,0xF150,0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,
453 0xF850,0xF950,0xFA50,0xFB50,0xFC50,0xFD50,0xFE50,0xFF50,
454 0x00D0,0x0150,0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,
455 0x0850,0x0950,0x0A50,0x0B50,0x0C50,0x0D50,0x0E50,0x0F50,
456 0x1050,0x1150,0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,
457 0x1850,0x1950,0x1A50,0x1B50,0x1C50,0x1D50,0x1E50,0x1F50,
458 0x2050,0x2150,0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,
459 0x2850,0x2950,0x2A50,0x2B50,0x2C50,0x2D50,0x2E50,0x2F50,
460 0x3050,0x3150,0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,
461 0x3850,0x3950,0x3A50,0x3B50,0x3C50,0x3D50,0x3E50,0x3F50,
462 0x4050,0x4150,0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,
463 0x4850,0x4950,0x4A50,0x4B50,0x4C50,0x4D50,0x4E50,0x4F50,
464 0x5050,0x5150,0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,
465 0x5850,0x5950,0x5A50,0x5B50,0x5C50,0x5D50,0x5E50,0x5F50,
466 0x6050,0x6150,0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,
467 0x6850,0x6950,0x6A50,0x6B50,0x6C50,0x6D50,0x6E50,0x6F50,
468 0x7050,0x7150,0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,
469 0x7850,0x7950,0x7A50,0x7B50,0x7C50,0x7D50,0x7E50,0x7F50,
470 0x8050,0x8150,0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,
471 0x8850,0x8950,0x8A50,0x8B50,0x8C50,0x8D50,0x8E50,0x8F50,
472 0x9050,0x9150,0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,
473 0x9850,0x9950,0x9A50,0x9B50,0x9C50,0x9D50,0x9E50,0x9F50,
474 0xFA40,0xFB40,0xFC40,0xFD40,0xFE40,0xFF40,0x00C0,0x0140,
475 0x0240,0x0340,0x0440,0x0540,0x0640,0x0740,0x0840,0x0940,
476 0x0A40,0x0B40,0x0C40,0x0D40,0x0E40,0x0F40,0x1040,0x1140,
477 0x1240,0x1340,0x1440,0x1540,0x1640,0x1740,0x1840,0x1940,
478 0x1A40,0x1B40,0x1C40,0x1D40,0x1E40,0x1F40,0x2040,0x2140,
479 0x2240,0x2340,0x2440,0x2540,0x2640,0x2740,0x2840,0x2940,
480 0x2A40,0x2B40,0x2C40,0x2D40,0x2E40,0x2F40,0x3040,0x3140,
481 0x3240,0x3340,0x3440,0x3540,0x3640,0x3740,0x3840,0x3940,
482 0x3A40,0x3B40,0x3C40,0x3D40,0x3E40,0x3F40,0x4040,0x4140,
483 0x4240,0x4340,0x4440,0x4540,0x4640,0x4740,0x4840,0x4940,
484 0x4A40,0x4B40,0x4C40,0x4D40,0x4E40,0x4F40,0x5040,0x5140,
485 0x5240,0x5340,0x5440,0x5540,0x5640,0x5740,0x5840,0x5940,
486 0x5A40,0x5B40,0x5C40,0x5D40,0x5E40,0x5F40,0x6040,0x6140,
487 0x6240,0x6340,0x6440,0x6540,0x6640,0x6740,0x6840,0x6940,
488 0x6A40,0x6B40,0x6C40,0x6D40,0x6E40,0x6F40,0x7040,0x7140,
489 0x7240,0x7340,0x7440,0x7540,0x7640,0x7740,0x7840,0x7940,
490 0x7A40,0x7B40,0x7C40,0x7D40,0x7E40,0x7F40,0x8040,0x8140,
491 0x8240,0x8340,0x8440,0x8540,0x8640,0x8740,0x8840,0x8940,
492 0x8A40,0x8B40,0x8C40,0x8D40,0x8E40,0x8F40,0x9040,0x9140,
493 0x9240,0x9340,0x9440,0x9540,0x9640,0x9740,0x9840,0x9940,
494 0x9A40,0x9B40,0x9C40,0x9D40,0x9E40,0x9F40,0xA040,0xA140,
495 0xA240,0xA340,0xA440,0xA540,0xA640,0xA740,0xA840,0xA940,
496 0xAA40,0xAB40,0xAC40,0xAD40,0xAE40,0xAF40,0xB040,0xB140,
497 0xB240,0xB340,0xB440,0xB540,0xB640,0xB740,0xB840,0xB940,
498 0xBA40,0xBB40,0xBC40,0xBD40,0xBE40,0xBF40,0xC040,0xC140,
499 0xC240,0xC340,0xC440,0xC540,0xC640,0xC740,0xC840,0xC940,
500 0xCA40,0xCB40,0xCC40,0xCD40,0xCE40,0xCF40,0xD040,0xD140,
501 0xD240,0xD340,0xD440,0xD540,0xD640,0xD740,0xD840,0xD940,
502 0xDA40,0xDB40,0xDC40,0xDD40,0xDE40,0xDF40,0xE040,0xE140,
503 0xE240,0xE340,0xE440,0xE540,0xE640,0xE740,0xE840,0xE940,
504 0xEA40,0xEB40,0xEC40,0xED40,0xEE40,0xEF40,0xF040,0xF140,
505 0xF240,0xF340,0xF440,0xF540,0xF640,0xF740,0xF840,0xF940,
506 0x9A50,0x9B50,0x9C50,0x9D50,0x9E50,0x9F50,0xA050,0xA150,
507 0xA250,0xA350,0xA450,0xA550,0xA650,0xA750,0xA850,0xA950,
508 0xAA50,0xAB50,0xAC50,0xAD50,0xAE50,0xAF50,0xB050,0xB150,
509 0xB250,0xB350,0xB450,0xB550,0xB650,0xB750,0xB850,0xB950,
510 0xBA50,0xBB50,0xBC50,0xBD50,0xBE50,0xBF50,0xC050,0xC150,
511 0xC250,0xC350,0xC450,0xC550,0xC650,0xC750,0xC850,0xC950,
512 0xCA50,0xCB50,0xCC50,0xCD50,0xCE50,0xCF50,0xD050,0xD150,
513 0xD250,0xD350,0xD450,0xD550,0xD650,0xD750,0xD850,0xD950,
514 0xDA50,0xDB50,0xDC50,0xDD50,0xDE50,0xDF50,0xE050,0xE150,
515 0xE250,0xE350,0xE450,0xE550,0xE650,0xE750,0xE850,0xE950,
516 0xEA50,0xEB50,0xEC50,0xED50,0xEE50,0xEF50,0xF050,0xF150,
517 0xF250,0xF350,0xF450,0xF550,0xF650,0xF750,0xF850,0xF950,
518 0xFA50,0xFB50,0xFC50,0xFD50,0xFE50,0xFF50,0x00D0,0x0150,
519 0x0250,0x0350,0x0450,0x0550,0x0650,0x0750,0x0850,0x0950,
520 0x0A50,0x0B50,0x0C50,0x0D50,0x0E50,0x0F50,0x1050,0x1150,
521 0x1250,0x1350,0x1450,0x1550,0x1650,0x1750,0x1850,0x1950,
522 0x1A50,0x1B50,0x1C50,0x1D50,0x1E50,0x1F50,0x2050,0x2150,
523 0x2250,0x2350,0x2450,0x2550,0x2650,0x2750,0x2850,0x2950,
524 0x2A50,0x2B50,0x2C50,0x2D50,0x2E50,0x2F50,0x3050,0x3150,
525 0x3250,0x3350,0x3450,0x3550,0x3650,0x3750,0x3850,0x3950,
526 0x3A50,0x3B50,0x3C50,0x3D50,0x3E50,0x3F50,0x4050,0x4150,
527 0x4250,0x4350,0x4450,0x4550,0x4650,0x4750,0x4850,0x4950,
528 0x4A50,0x4B50,0x4C50,0x4D50,0x4E50,0x4F50,0x5050,0x5150,
529 0x5250,0x5350,0x5450,0x5550,0x5650,0x5750,0x5850,0x5950,
530 0x5A50,0x5B50,0x5C50,0x5D50,0x5E50,0x5F50,0x6050,0x6150,
531 0x6250,0x6350,0x6450,0x6550,0x6650,0x6750,0x6850,0x6950,
532 0x6A50,0x6B50,0x6C50,0x6D50,0x6E50,0x6F50,0x7050,0x7150,
533 0x7250,0x7350,0x7450,0x7550,0x7650,0x7750,0x7850,0x7950,
534 0x7A50,0x7B50,0x7C50,0x7D50,0x7E50,0x7F50,0x8050,0x8150,
535 0x8250,0x8350,0x8450,0x8550,0x8650,0x8750,0x8850,0x8950,
536 0x8A50,0x8B50,0x8C50,0x8D50,0x8E50,0x8F50,0x9050,0x9150,
537 0x9250,0x9350,0x9450,0x9550,0x9650,0x9750,0x9850,0x9950,
538 };
539
540 u8 ZeroTable[256] = {
541 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
542 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
543 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
544 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
545 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
546 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
547 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
548 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
549 0,0,0,0,0,0,0,0,
550 0,0,0,0,0,0,0,0,
551 0,0,0,0,0,0,0,0,
552 0,0,0,0,0,0,0,0,
553 0,0,0,0,0,0,0,0,
554 0,0,0,0,0,0,0,0,
555 0,0,0,0,0,0,0,0,
556 0,0,0,0,0,0,0,0,
557 0,0,0,0,0,0,0,0,
558 0,0,0,0,0,0,0,0,
559 0,0,0,0,0,0,0,0,
560 0,0,0,0,0,0,0,0,
561 0,0,0,0,0,0,0,0,
562 0,0,0,0,0,0,0,0,
563 0,0,0,0,0,0,0,0,
564 0,0,0,0,0,0,0,0
565 };
566
567 // Title checksums that are treated specially by the CGB boot ROM
568 static const u8 gbColorizationChecksums[79] = {
569 0x00, 0x88, 0x16, 0x36, 0xD1, 0xDB, 0xF2, 0x3C, 0x8C, 0x92, 0x3D, 0x5C,
570 0x58, 0xC9, 0x3E, 0x70, 0x1D, 0x59, 0x69, 0x19, 0x35, 0xA8, 0x14, 0xAA,
571 0x75, 0x95, 0x99, 0x34, 0x6F, 0x15, 0xFF, 0x97, 0x4B, 0x90, 0x17, 0x10,
572 0x39, 0xF7, 0xF6, 0xA2, 0x49, 0x4E, 0x43, 0x68, 0xE0, 0x8B, 0xF0, 0xCE,
573 0x0C, 0x29, 0xE8, 0xB7, 0x86, 0x9A, 0x52, 0x01, 0x9D, 0x71, 0x9C, 0xBD,
574 0x5D, 0x6D, 0x67, 0x3F, 0x6B, 0xB3, 0x46, 0x28, 0xA5, 0xC6, 0xD3, 0x27,
575 0x61, 0x18, 0x66, 0x6A, 0xBF, 0x0D, 0xF4
576 };
577
578 // For titles with colliding checksums, the fourth character of the game title
579 // for disambiguation.
580 static const u8 gbColorizationDisambigChars[29] = {
581 'B', 'E', 'F', 'A', 'A', 'R', 'B', 'E',
582 'K', 'E', 'K', ' ', 'R', '-', 'U', 'R',
583 'A', 'R', ' ', 'I', 'N', 'A', 'I', 'L',
584 'I', 'C', 'E', ' ', 'R'
585 };
586
587 // Palette ID | (Flags << 5)
588 static const u8 gbColorizationPaletteInfo[94] = {
589 0x7C, 0x08, 0x12, 0xA3, 0xA2, 0x07, 0x87, 0x4B, 0x20, 0x12, 0x65, 0xA8,
590 0x16, 0xA9, 0x86, 0xB1, 0x68, 0xA0, 0x87, 0x66, 0x12, 0xA1, 0x30, 0x3C,
591 0x12, 0x85, 0x12, 0x64, 0x1B, 0x07, 0x06, 0x6F, 0x6E, 0x6E, 0xAE, 0xAF,
592 0x6F, 0xB2, 0xAF, 0xB2, 0xA8, 0xAB, 0x6F, 0xAF, 0x86, 0xAE, 0xA2, 0xA2,
593 0x12, 0xAF, 0x13, 0x12, 0xA1, 0x6E, 0xAF, 0xAF, 0xAD, 0x06, 0x4C, 0x6E,
594 0xAF, 0xAF, 0x12, 0x7C, 0xAC, 0xA8, 0x6A, 0x6E, 0x13, 0xA0, 0x2D, 0xA8,
595 0x2B, 0xAC, 0x64, 0xAC, 0x6D, 0x87, 0xBC, 0x60, 0xB4, 0x13, 0x72, 0x7C,
596 0xB5, 0xAE, 0xAE, 0x7C, 0x7C, 0x65, 0xA2, 0x6C, 0x64, 0x85
597 };
598
599
600 // Uncompressed palette data from the CGB boot ROM
601 static const u16 gbColorizationPaletteData[32][3][4] = {
602 {
603 { 0x7FFF, 0x01DF, 0x0112, 0x0000 },
604 { 0x7FFF, 0x7EEB, 0x001F, 0x7C00 },
605 { 0x7FFF, 0x42B5, 0x3DC8, 0x0000 },
606 },
607 {
608 { 0x231F, 0x035F, 0x00F2, 0x0009 },
609 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
610 { 0x4FFF, 0x7ED2, 0x3A4C, 0x1CE0 },
611 },
612 {
613 { 0x7FFF, 0x7FFF, 0x7E8C, 0x7C00 },
614 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
615 { 0x03ED, 0x7FFF, 0x255F, 0x0000 },
616 },
617 {
618 { 0x7FFF, 0x7FFF, 0x7E8C, 0x7C00 },
619 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
620 { 0x036A, 0x021F, 0x03FF, 0x7FFF },
621 },
622 {
623 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
624 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
625 { 0x7FFF, 0x03EF, 0x01D6, 0x0000 },
626 },
627 {
628 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
629 { 0x7FFF, 0x7EEB, 0x001F, 0x7C00 },
630 { 0x7FFF, 0x03EA, 0x011F, 0x0000 },
631 },
632 {
633 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
634 { 0x7FFF, 0x7EEB, 0x001F, 0x7C00 },
635 { 0x7FFF, 0x027F, 0x001F, 0x0000 },
636 },
637 {
638 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
639 { 0x7FFF, 0x7EEB, 0x001F, 0x7C00 },
640 { 0x7FFF, 0x03FF, 0x001F, 0x0000 },
641 },
642 {
643 { 0x299F, 0x001A, 0x000C, 0x0000 },
644 { 0x7C00, 0x7FFF, 0x3FFF, 0x7E00 },
645 { 0x7E74, 0x03FF, 0x0180, 0x0000 },
646 },
647 {
648 { 0x7FFF, 0x01DF, 0x0112, 0x0000 },
649 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
650 { 0x67FF, 0x77AC, 0x1A13, 0x2D6B },
651 },
652 {
653 { 0x0000, 0x7FFF, 0x421F, 0x1CF2 },
654 { 0x0000, 0x7FFF, 0x421F, 0x1CF2 },
655 { 0x7ED6, 0x4BFF, 0x2175, 0x0000 },
656 },
657 {
658 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
659 { 0x7FFF, 0x3FFF, 0x7E00, 0x001F },
660 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
661 },
662 {
663 { 0x231F, 0x035F, 0x00F2, 0x0009 },
664 { 0x7FFF, 0x7EEB, 0x001F, 0x7C00 },
665 { 0x7FFF, 0x6E31, 0x454A, 0x0000 },
666 },
667 {
668 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
669 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
670 { 0x7FFF, 0x6E31, 0x454A, 0x0000 },
671 },
672 {
673 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
674 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
675 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
676 },
677 {
678 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
679 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
680 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
681 },
682 {
683 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
684 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
685 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
686 },
687 {
688 { 0x7FFF, 0x03E0, 0x0206, 0x0120 },
689 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
690 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
691 },
692 {
693 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
694 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
695 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
696 },
697 {
698 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
699 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
700 { 0x0000, 0x4200, 0x037F, 0x7FFF },
701 },
702 {
703 { 0x03FF, 0x001F, 0x000C, 0x0000 },
704 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
705 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
706 },
707 {
708 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
709 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
710 { 0x7FFF, 0x42B5, 0x3DC8, 0x0000 },
711 },
712 {
713 { 0x7FFF, 0x5294, 0x294A, 0x0000 },
714 { 0x7FFF, 0x5294, 0x294A, 0x0000 },
715 { 0x7FFF, 0x5294, 0x294A, 0x0000 },
716 },
717 {
718 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
719 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
720 { 0x53FF, 0x4A5F, 0x7E52, 0x0000 },
721 },
722 {
723 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
724 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
725 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
726 },
727 {
728 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
729 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
730 { 0x639F, 0x4279, 0x15B0, 0x04CB },
731 },
732 {
733 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
734 { 0x7FFF, 0x1BEF, 0x0200, 0x0000 },
735 { 0x7FFF, 0x03FF, 0x012F, 0x0000 },
736 },
737 {
738 { 0x7FFF, 0x033F, 0x0193, 0x0000 },
739 { 0x7FFF, 0x033F, 0x0193, 0x0000 },
740 { 0x7FFF, 0x033F, 0x0193, 0x0000 },
741 },
742 {
743 { 0x7FFF, 0x421F, 0x1CF2, 0x0000 },
744 { 0x7FFF, 0x7E8C, 0x7C00, 0x0000 },
745 { 0x7FFF, 0x1BEF, 0x6180, 0x0000 },
746 },
747 {
748 { 0x2120, 0x8022, 0x8281, 0x1110 },
749 { 0xFF7F, 0xDF7F, 0x1201, 0x0001 },
750 { 0xFF00, 0xFF7F, 0x1F03, 0x0000 },
751 },
752 {
753 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
754 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
755 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
756 },
757 {
758 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
759 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
760 { 0x7FFF, 0x32BF, 0x00D0, 0x0000 },
761 }
762 };
763
764
765
766 #define GBSAVE_GAME_VERSION_1 1
767 #define GBSAVE_GAME_VERSION_2 2
768 #define GBSAVE_GAME_VERSION_3 3
769 #define GBSAVE_GAME_VERSION_4 4
770 #define GBSAVE_GAME_VERSION_5 5
771 #define GBSAVE_GAME_VERSION_6 6
772 #define GBSAVE_GAME_VERSION_7 7
773 #define GBSAVE_GAME_VERSION_8 8
774 #define GBSAVE_GAME_VERSION_9 9
775 #define GBSAVE_GAME_VERSION_10 10
776 #define GBSAVE_GAME_VERSION_11 11
777 #define GBSAVE_GAME_VERSION_12 12
778 #define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_12
779
gbGetValue(int min,int max,int v)780 int inline gbGetValue(int min,int max,int v)
781 {
782 return (int)(min+(float)(max-min)*(2.0*(v/31.0)-(v/31.0)*(v/31.0)));
783 }
784
gbGenFilter()785 void gbGenFilter()
786 {
787 for (int r=0;r<32;r++) {
788 for (int g=0;g<32;g++) {
789 for (int b=0;b<32;b++) {
790 int nr=gbGetValue(gbGetValue(4,14,g),
791 gbGetValue(24,29,g),r)-4;
792 int ng=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
793 14+gbGetValue(0,3,r),b),
794 gbGetValue(24+gbGetValue(0,3,r),
795 29+gbGetValue(0,1,r),b),g)-4;
796 int nb=gbGetValue(gbGetValue(4+gbGetValue(0,5,r),
797 14+gbGetValue(0,3,r),g),
798 gbGetValue(24+gbGetValue(0,3,r),
799 29+gbGetValue(0,1,r),g),b)-4;
800 gbColorFilter[(b<<10)|(g<<5)|r]=(nb<<10)|(ng<<5)|nr;
801 }
802 }
803 }
804 }
805
gbIsGameboyRom(char * file)806 bool gbIsGameboyRom(char * file)
807 {
808 if(strlen(file) > 4) {
809 char * p = strrchr(file,'.');
810
811 if(p != NULL) {
812 if(_stricmp(p, ".gb") == 0)
813 return true;
814 if(_stricmp(p, ".dmg") == 0)
815 return true;
816 if(_stricmp(p, ".gbc") == 0)
817 return true;
818 if(_stricmp(p, ".cgb") == 0)
819 return true;
820 if(_stricmp(p, ".sgb") == 0)
821 return true;
822 }
823 }
824
825 return false;
826 }
827
gbCopyMemory(u16 d,u16 s,int count)828 void gbCopyMemory(u16 d, u16 s, int count)
829 {
830 while(count) {
831 gbMemoryMap[d>>12][d & 0x0fff] = gbMemoryMap[s>>12][s & 0x0fff];
832 s++;
833 d++;
834 count--;
835 }
836 }
837
gbDoHdma()838 void gbDoHdma()
839 {
840
841 gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000,
842 gbHdmaSource & 0xfff0,
843 0x10);
844
845 gbHdmaDestination += 0x10;
846 if (gbHdmaDestination == 0xa000)
847 gbHdmaDestination = 0x8000;
848
849 gbHdmaSource += 0x10;
850 if (gbHdmaSource == 0x8000)
851 gbHdmaSource = 0xa000;
852
853 register_HDMA2 = gbHdmaSource & 0xff;
854 register_HDMA1 = gbHdmaSource>>8;
855
856 register_HDMA4 = gbHdmaDestination & 0xff;
857 register_HDMA3 = gbHdmaDestination>>8;
858
859 gbHdmaBytes -= 0x10;
860 gbMemory[0xff55] = --register_HDMA5;
861 if(register_HDMA5 == 0xff)
862 gbHdmaOn = 0;
863
864 // We need to add the dmaClockticks for HDMA !
865 if(gbSpeed)
866 gbDmaTicks = 17;
867 else
868 gbDmaTicks = 9;
869
870 if (IFF & 0x80)
871 gbDmaTicks++;
872
873 }
874
875 // fix for Harley and Lego Racers
gbCompareLYToLYC()876 void gbCompareLYToLYC()
877 {
878 if(register_LCDC & 0x80) {
879 if(register_LY == register_LYC) {
880
881 // mark that we have a match
882 register_STAT |= 4;
883
884 // check if we need an interrupt
885 if (register_STAT & 0x40)
886 {
887 // send LCD interrupt only if no interrupt 48h signal...
888 if (!gbInt48Signal)
889 {
890 register_IF |=2;
891 }
892 gbInt48Signal |= 8;
893 }
894 }
895 else // no match
896 {
897 register_STAT &= 0xfb;
898 gbInt48Signal &=~8;
899 }
900 }
901 }
902
gbWriteMemory(register u16 address,register u8 value)903 void gbWriteMemory(register u16 address, register u8 value)
904 {
905
906 if(address < 0x8000) {
907 #ifndef FINAL_VERSION
908 if(memorydebug && (address>0x3fff || address < 0x2000)) {
909 log("Memory register write %04x=%02x PC=%04x\n",
910 address,
911 value,
912 PC.W);
913 }
914
915 #endif
916 if(mapper)
917 (*mapper)(address, value);
918 return;
919
920 }
921
922 if(address < 0xa000) {
923 // No access to Vram during mode 3
924 // (used to emulate the gfx differences between GB & GBC-GBA/SP in Stunt Racer)
925 if ((gbLcdModeDelayed !=3) ||
926 // This part is used to emulate a small difference between hardwares
927 // (check 8-in-1's arrow on GBA/GBC to verify it)
928 ((register_LY == 0) && ((gbHardware & 0xa) && (gbScreenOn==false) &&
929 (register_LCDC & 0x80)) &&
930 (gbLcdLYIncrementTicksDelayed ==(GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS))))
931 gbMemoryMap[address>>12][address&0x0fff] = value;
932 return;
933 }
934
935 // Used for the mirroring of 0xC000 in 0xE000
936 if ((address >= 0xe000) && (address < 0xfe00))
937 address &= ~0x2000;
938
939 if(address < 0xc000) {
940 #ifndef FINAL_VERSION
941 if(memorydebug) {
942 log("Memory register write %04x=%02x PC=%04x\n",
943 address,
944 value,
945 PC.W);
946 }
947 #endif
948
949 // Is that a correct fix ??? (it used to be 'if (mapper)')...
950 if(mapperRAM)
951 (*mapperRAM)(address, value);
952 return;
953 }
954
955
956 if(address < 0xfe00) {
957 gbMemoryMap[address>>12][address & 0x0fff] = value;
958 return;
959 }
960
961 // OAM not accessible during mode 2 & 3.
962 if(address < 0xfea0)
963 {
964 if (((gbHardware & 0xa) && ((gbLcdMode | gbLcdModeDelayed) &2)) ||
965 ((gbHardware & 5) && (((gbLcdModeDelayed == 2) &&
966 (gbLcdTicksDelayed<=GBLCD_MODE_2_CLOCK_TICKS)) ||
967 (gbLcdModeDelayed == 3))))
968 return;
969 else
970 {
971 gbMemory[address] = value;
972 return;
973 }
974 }
975
976
977
978 if((address > 0xfea0) && (address < 0xff00)){ // GBC allows reading/writing to that area
979 gbMemory[address] = value;
980 return;
981 }
982
983 switch(address & 0x00ff) {
984
985 case 0x00: {
986 gbMemory[0xff00] = ((gbMemory[0xff00] & 0xcf) |
987 (value & 0x30) | 0xc0);
988 if(gbSgbMode) {
989 gbSgbDoBitTransfer(value);
990 }
991 return;
992 }
993
994 case 0x01: {
995 gbMemory[0xff01] = value;
996 return;
997 }
998
999 // serial control
1000 case 0x02: {
1001 gbSerialOn = (value & 0x80);
1002 #ifndef NO_LINK
1003 //trying to detect whether the game has exited multiplay mode, pokemon blue start w/ 0x7e while pocket racing start w/ 0x7c
1004 if (EmuReseted || (gbMemory[0xff02] & 0x7c) || (value & 0x7c) || (!(value & 0x81))) {
1005 LinkFirstTime = true;
1006 }
1007 EmuReseted = false;
1008 gbMemory[0xff02] = value;
1009 if (gbSerialOn && (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET || winGbPrinterEnabled)) {
1010 gbSerialTicks = GBSERIAL_CLOCK_TICKS;
1011
1012 LinkIsWaiting = true;
1013
1014 //Do data exchange, master initiate the transfer
1015 //may cause visual artifact if not processed immediately, is it due to IRQ stuff or invalid data being exchanged?
1016 if ((value & 1) ) { //internal clock
1017 if (gbSerialFunction) {
1018 gbSIO_SC = value;
1019 gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbSerialFunction/gbStartLink/gbPrinter
1020 }
1021 else gbMemory[0xff01] = 0xff;
1022 gbMemory[0xff02] &= 0x7f;
1023 gbSerialOn = 0;
1024 gbMemory[0xff0f] = register_IF |= 8;
1025 }
1026 #ifdef OLD_GB_LINK
1027 if (linkConnected) {
1028 if (value & 1) {
1029 linkSendByte(0x100 | gbMemory[0xFF01]);
1030 Sleep(5);
1031 }
1032 }
1033 #endif
1034 }
1035
1036 gbSerialBits = 0;
1037 return;
1038 #endif
1039 }
1040
1041 case 0x04: {
1042 // DIV register resets on any write
1043 // (not totally perfect, but better than nothing)
1044 gbMemory[0xff04] = register_DIV = 0;
1045 gbDivTicks = GBDIV_CLOCK_TICKS;
1046 // Another weird timer 'bug' :
1047 // Writing to DIV register resets the internal timer,
1048 // and can also increase TIMA/trigger an interrupt
1049 // in some cases...
1050 if (gbTimerOn && !(gbInternalTimer & (gbTimerClockTicks>>1)))
1051 {
1052 gbMemory[0xff05] = ++register_TIMA;
1053 if(register_TIMA == 0) {
1054 // timer overflow!
1055
1056 // reload timer modulo
1057 gbMemory[0xff05] = register_TIMA = register_TMA;
1058
1059 // flag interrupt
1060 gbMemory[0xff0f] = register_IF |= 4;
1061 }
1062 }
1063 gbInternalTimer = 0xff;
1064 return;
1065 }
1066 case 0x05:
1067 gbMemory[0xff05] = register_TIMA = value;
1068 return;
1069
1070 case 0x06:
1071 gbMemory[0xff06] = register_TMA = value;
1072 return;
1073
1074 // TIMER control
1075 case 0x07: {
1076
1077 gbTimerModeChange = (((value & 3) != (register_TAC&3)) && (value & register_TAC & 4)) ? true : false;
1078 gbTimerOnChange = (((value ^ register_TAC) & 4) == 4) ? true : false;
1079
1080 gbTimerOn = (value & 4) ? true : false;
1081
1082 if (gbTimerOnChange || gbTimerModeChange)
1083 {
1084 gbTimerMode = value & 3;
1085
1086 switch(gbTimerMode) {
1087 case 0:
1088 gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
1089 break;
1090 case 1:
1091 gbTimerClockTicks = GBTIMER_MODE_1_CLOCK_TICKS;
1092 break;
1093 case 2:
1094 gbTimerClockTicks = GBTIMER_MODE_2_CLOCK_TICKS;
1095 break;
1096 case 3:
1097 gbTimerClockTicks = GBTIMER_MODE_3_CLOCK_TICKS;
1098 break;
1099 }
1100 }
1101
1102
1103 // This looks weird, but this emulates a bug in which register_TIMA
1104 // is increased when writing to register_TAC
1105 // (This fixes Korodice's long-delay between menus bug).
1106
1107 if (gbTimerOnChange || gbTimerModeChange)
1108 {
1109 bool temp = false;
1110
1111 if ((gbTimerOn && !gbTimerModeChange) && (gbTimerMode & 2) &&
1112 !(gbInternalTimer & 0x80) && (gbInternalTimer & (gbTimerClockTicks>>1)) &&
1113 !(gbInternalTimer & (gbTimerClockTicks>>5)))
1114 temp = true;
1115 else if ((!gbTimerOn && !gbTimerModeChange && gbTimerOnChange ) && ((gbTimerTicks-1) < (gbTimerClockTicks>>1)))
1116 temp = true;
1117 else if (gbTimerOn && gbTimerModeChange && !gbTimerOnChange)
1118 {
1119 switch(gbTimerMode & 3)
1120 {
1121 case 0x00:
1122 temp = false;
1123 break;
1124 case 0x01:
1125 if (((gbInternalTimer & 0x82) == 2) && (gbTimerTicks>(clockTicks+1)))
1126 temp = true;
1127 break;
1128 case 0x02:
1129 if (((gbInternalTimer & 0x88) == 0x8) && (gbTimerTicks>(clockTicks+1)))
1130 temp = true;
1131 break;
1132 case 0x03:
1133 if (((gbInternalTimer & 0xA0) == 0x20) && (gbTimerTicks>(clockTicks+1)))
1134 temp = true;
1135 break;
1136 }
1137 }
1138
1139 if (temp)
1140 {
1141 gbMemory[0xff05] = ++register_TIMA;
1142 if((register_TIMA & 0xff) == 0) {
1143 // timer overflow!
1144
1145 // reload timer modulo
1146 gbMemory[0xff05] = register_TIMA = register_TMA;
1147
1148 // flag interrupt
1149 gbMemory[0xff0f] = register_IF |= 4;
1150 }
1151 }
1152 }
1153 gbMemory[0xff07] = register_TAC = value;
1154 return;
1155 }
1156
1157 case 0x0f: {
1158 gbMemory[0xff0f] = register_IF = value;
1159 //gbMemory[0xff0f] = register_IE |= value;
1160 return;
1161 }
1162
1163 case 0x10:
1164 case 0x11:
1165 case 0x12:
1166 case 0x13:
1167 case 0x14:
1168 case 0x16:
1169 case 0x17:
1170 case 0x18:
1171 case 0x19:
1172 case 0x1a:
1173 case 0x1b:
1174 case 0x1c:
1175 case 0x1d:
1176 case 0x1e:
1177 case 0x20:
1178 case 0x21:
1179 case 0x22:
1180 case 0x23:
1181 case 0x24:
1182 case 0x25: {
1183 if (gbMemory[NR52] & 0x80) {
1184 SOUND_EVENT(address,value);
1185 return;
1186 }
1187 }
1188
1189 case 0x26: {
1190 SOUND_EVENT(address,value);
1191 return;
1192 }
1193
1194 case 0x30:
1195 case 0x31:
1196 case 0x32:
1197 case 0x33:
1198 case 0x34:
1199 case 0x35:
1200 case 0x36:
1201 case 0x37:
1202 case 0x38:
1203 case 0x39:
1204 case 0x3a:
1205 case 0x3b:
1206 case 0x3c:
1207 case 0x3d:
1208 case 0x3e:
1209 case 0x3f: {
1210 SOUND_EVENT(address,value);
1211 //gbMemory[address] = value;
1212 return;
1213 }
1214
1215 case 0x40: {
1216 int lcdChange = (register_LCDC & 0x80) ^ (value & 0x80);
1217
1218 // don't draw the window if it was not enabled and not being drawn before
1219 if(!(register_LCDC & 0x20) && (value & 0x20) && gbWindowLine == -1 &&
1220 register_LY > register_WY)
1221 gbWindowLine = 146;
1222 // 007 fix : don't draw the first window's 1st line if it's enable 'too late'
1223 // (ie. if register_LY == register_WY when enabling it)
1224 // and move it to the next line
1225 else if (!(register_LCDC & 0x20) && (value & 0x20) && (register_LY == register_WY))
1226 gbWindowLine = -2;
1227
1228
1229 gbMemory[0xff40] = register_LCDC = value;
1230
1231
1232 if(lcdChange) {
1233 if((value & 0x80) && (!register_LCDCBusy)) {
1234
1235 // if (!gbWhiteScreen && !gbSgbMask)
1236
1237 // systemDrawScreen();
1238
1239
1240
1241 gbRegisterLYLCDCOffOn = (register_LY + 144) % 154;
1242
1243 gbLcdTicks = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 2 : 1);
1244 gbLcdTicksDelayed = GBLCD_MODE_2_CLOCK_TICKS - (gbSpeed ? 1 : 0);
1245 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 2 : 1);
1246 gbLcdLYIncrementTicksDelayed = GBLY_INCREMENT_CLOCK_TICKS - (gbSpeed ? 1 : 0);
1247 gbLcdMode = 2;
1248 gbLcdModeDelayed = 2;
1249 gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | 2;
1250 gbMemory[0xff44] = register_LY = 0x00;
1251 gbInt48Signal = 0;
1252 gbLYChangeHappened = false;
1253 gbLCDChangeHappened = false;
1254 gbWindowLine = 146;
1255 oldRegister_WY = 146;
1256
1257 // Fix for Namco Gallery Vol.2
1258 // (along with updating register_LCDC at the start of 'case 0x40') :
1259 if(register_STAT & 0x20)
1260 {
1261 // send LCD interrupt only if no interrupt 48h signal...
1262 if (!gbInt48Signal)
1263 {
1264 gbMemory[0xff0f] = register_IF |= 2;
1265 }
1266 gbInt48Signal |= 4;
1267 }
1268 gbCompareLYToLYC();
1269
1270 } else {
1271
1272 register_LCDCBusy = clockTicks+6;
1273
1274 //used to update the screen with white lines when it's off.
1275 //(it looks strange, but it's pretty accurate)
1276
1277 gbWhiteScreen = 0;
1278
1279 gbScreenTicks = ((150-register_LY)*GBLY_INCREMENT_CLOCK_TICKS +
1280 (49<<(gbSpeed ? 1 : 0)));
1281
1282 // disable the screen rendering
1283 gbScreenOn = false;
1284 gbLcdTicks = 0;
1285 gbLcdMode = 0;
1286 gbLcdModeDelayed = 0;
1287 gbMemory[0xff41] = register_STAT &= 0xfc;
1288 gbInt48Signal = 0;
1289 }
1290 }
1291 return;
1292 }
1293
1294 // STAT
1295 case 0x41: {
1296 //register_STAT = (register_STAT & 0x87) |
1297 // (value & 0x7c);
1298 gbMemory[0xff41] = register_STAT = (value & 0xf8) | (register_STAT & 0x07); // fix ?
1299 // GB bug from Devrs FAQ
1300 // proper fix
1301 gbInt48Signal &= ((register_STAT>>3) & 0xF);
1302
1303 if((register_LCDC & 0x80)) {
1304 if ((register_STAT & 0x08) && (gbLcdMode == 0))
1305 {
1306 if (!gbInt48Signal)
1307 {
1308 gbMemory[0xff0f] = register_IF |=2;
1309 }
1310 gbInt48Signal |= 1;
1311 }
1312 if ((register_STAT & 0x10) && (gbLcdMode == 1))
1313 {
1314 if (!gbInt48Signal)
1315 {
1316 gbMemory[0xff0f] = register_IF |=2;
1317 }
1318 gbInt48Signal |= 2;
1319 }
1320 if ((register_STAT & 0x20) && (gbLcdMode == 2))
1321 {
1322 if (!gbInt48Signal)
1323 {
1324 gbMemory[0xff0f] = register_IF |=2;
1325 }
1326 gbInt48Signal |= 4;
1327 }
1328 gbCompareLYToLYC();
1329
1330 gbMemory[0xff0f] = register_IF;
1331 gbMemory[0xff41] = register_STAT;
1332
1333 }
1334 return;
1335 }
1336
1337 // SCY
1338 case 0x42: {
1339 int temp = -1;
1340
1341 if ((gbLcdMode == 3) || (gbLcdModeDelayed == 3))
1342 temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
1343 gbLcdLYIncrementTicks);
1344
1345 if (temp >=0)
1346 {
1347 for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
1348 if (temp < 300)
1349 gbSCYLine[i] = value;
1350 }
1351
1352 else
1353 memset(gbSCYLine, value, sizeof(gbSCYLine));
1354
1355 gbMemory[0xff42] = register_SCY = value;
1356 return;
1357 }
1358
1359 // SCX
1360 case 0x43: {
1361 int temp = -1;
1362
1363 if (gbLcdModeDelayed == 3)
1364 temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
1365 gbLcdLYIncrementTicksDelayed);
1366
1367 if (temp >=0)
1368 {
1369 for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
1370 if (temp < 300)
1371 gbSCXLine[i] = value;
1372 }
1373
1374 else
1375 memset(gbSCXLine, value, sizeof(gbSCXLine));
1376
1377 gbMemory[0xff43] = register_SCX = value;
1378 return;
1379 }
1380
1381 // LY
1382 case 0x44: {
1383 // read only
1384 return;
1385 }
1386
1387 // LYC
1388 case 0x45: {
1389 if (register_LYC != value)
1390 {
1391 gbMemory[0xff45] = register_LYC = value;
1392 if(register_LCDC & 0x80) {
1393 gbCompareLYToLYC();
1394 }
1395 }
1396 return;
1397 }
1398
1399 // DMA!
1400 case 0x46: {
1401 int source = value * 0x0100;
1402
1403 gbCopyMemory(0xfe00,
1404 source,
1405 0xa0);
1406 gbMemory[0xff46] = register_DMA = value;
1407 return;
1408 }
1409
1410 // BGP
1411 case 0x47: {
1412
1413 int temp = -1;
1414
1415 gbMemory[0xff47] = value;
1416
1417 if (gbLcdModeDelayed == 3)
1418 temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
1419 gbLcdLYIncrementTicksDelayed);
1420
1421 if (temp >=0)
1422 {
1423 for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
1424 if (temp < 300)
1425 gbBgpLine[i] = value;
1426 }
1427 else
1428 memset(gbBgpLine,value,sizeof(gbBgpLine));
1429
1430 gbBgp[0] = value & 0x03;
1431 gbBgp[1] = (value & 0x0c)>>2;
1432 gbBgp[2] = (value & 0x30)>>4;
1433 gbBgp[3] = (value & 0xc0)>>6;
1434 break;
1435 }
1436
1437 // OBP0
1438 case 0x48: {
1439 int temp = -1;
1440
1441 gbMemory[0xff48] = value;
1442
1443 if (gbLcdModeDelayed == 3)
1444 temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
1445 gbLcdLYIncrementTicksDelayed);
1446
1447 if (temp >=0)
1448 {
1449 for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
1450 if (temp < 300)
1451 gbObp0Line[i] = value;
1452 }
1453 else
1454 memset(gbObp0Line,value,sizeof(gbObp0Line));
1455
1456 gbObp0[0] = value & 0x03;
1457 gbObp0[1] = (value & 0x0c)>>2;
1458 gbObp0[2] = (value & 0x30)>>4;
1459 gbObp0[3] = (value & 0xc0)>>6;
1460 break;
1461 }
1462
1463 // OBP1
1464 case 0x49: {
1465 int temp = -1;
1466
1467 gbMemory[0xff49] = value;
1468
1469 if (gbLcdModeDelayed == 3)
1470 temp = ((GBLY_INCREMENT_CLOCK_TICKS-GBLCD_MODE_2_CLOCK_TICKS) -
1471 gbLcdLYIncrementTicksDelayed);
1472
1473 if (temp >=0)
1474 {
1475 for (int i=temp<<(gbSpeed ? 1 : 2);i<300;i++)
1476 if (temp < 300)
1477 gbObp1Line[i] = value;
1478 }
1479 else
1480 memset(gbObp1Line,value,sizeof(gbObp1Line));
1481
1482 gbObp1[0] = value & 0x03;
1483 gbObp1[1] = (value & 0x0c)>>2;
1484 gbObp1[2] = (value & 0x30)>>4;
1485 gbObp1[3] = (value & 0xc0)>>6;
1486 break;
1487 }
1488
1489 // WY
1490 case 0x4a:
1491 gbMemory[0xff4a] = register_WY = value;
1492 if ((register_LY <= register_WY) && ((gbWindowLine < 0) || (gbWindowLine>=144)))
1493 {
1494 gbWindowLine = -1;
1495 oldRegister_WY = register_WY;
1496 }
1497 return;
1498
1499 // WX
1500 case 0x4b:
1501 gbMemory[0xff4b] = register_WX = value;
1502 return;
1503
1504 // KEY1
1505 case 0x4d: {
1506 if(gbCgbMode) {
1507 gbMemory[0xff4d] = (gbMemory[0xff4d] & 0x80) | (value & 1) | 0x7e;
1508 return;
1509 }
1510 }
1511 break;
1512
1513 // VBK
1514 case 0x4f: {
1515 if(gbCgbMode) {
1516 value = value & 1;
1517 if(value == gbVramBank)
1518 return;
1519
1520 int vramAddress = value * 0x2000;
1521 gbMemoryMap[0x08] = &gbVram[vramAddress];
1522 gbMemoryMap[0x09] = &gbVram[vramAddress + 0x1000];
1523
1524 gbVramBank = value;
1525 register_VBK = value;
1526 }
1527 return;
1528 }
1529 break;
1530
1531 // BOOTROM disable register (also gbCgbMode enabler if value & 0x10 ?)
1532 case 0x50 :
1533 {
1534 if (inBios && (value & 1))
1535 {
1536 gbMemoryMap[0x00] = &gbRom[0x0000];
1537 if (gbHardware & 5) {
1538 memcpy ((u8 *)(gbRom+0x100), (u8 *)(gbMemory + 0x100), 0xF00);
1539 }
1540 inBios = false;
1541 }
1542 }
1543
1544 // HDMA1
1545 case 0x51: {
1546 if(gbCgbMode) {
1547 if(value > 0x7f && value < 0xa0)
1548 value = 0;
1549
1550 gbHdmaSource = (value << 8) | (gbHdmaSource & 0xf0);
1551
1552 register_HDMA1 = value;
1553 return;
1554 }
1555 }
1556 break;
1557
1558 // HDMA2
1559 case 0x52: {
1560 if(gbCgbMode) {
1561 value = value & 0xf0;
1562
1563 gbHdmaSource = (gbHdmaSource & 0xff00) | (value);
1564
1565 register_HDMA2 = value;
1566 return;
1567 }
1568 }
1569 break;
1570
1571 // HDMA3
1572 case 0x53: {
1573 if(gbCgbMode) {
1574 value = value & 0x1f;
1575 gbHdmaDestination = (value << 8) | (gbHdmaDestination & 0xf0);
1576 gbHdmaDestination |= 0x8000;
1577 register_HDMA3 = value;
1578 return;
1579 }
1580 }
1581 break;
1582
1583 // HDMA4
1584 case 0x54: {
1585 if(gbCgbMode) {
1586 value = value & 0xf0;
1587 gbHdmaDestination = (gbHdmaDestination & 0x1f00) | value;
1588 gbHdmaDestination |= 0x8000;
1589 register_HDMA4 = value;
1590 return;
1591 }
1592 }
1593 break;
1594
1595 // HDMA5
1596 case 0x55: {
1597
1598 if(gbCgbMode) {
1599 gbHdmaBytes = 16 + (value & 0x7f) * 16;
1600 if(gbHdmaOn) {
1601 if(value & 0x80) {
1602 gbMemory[0xff55] = register_HDMA5 = (value & 0x7f);
1603 } else {
1604 register_HDMA5 = 0xff;
1605 gbHdmaOn = 0;
1606 }
1607 } else {
1608 if(value & 0x80) {
1609 gbHdmaOn = 1;
1610 gbMemory[0xff55] = register_HDMA5 = value & 0x7f;
1611 if(gbLcdModeDelayed == 0)
1612 gbDoHdma();
1613 } else {
1614 // we need to take the time it takes to complete the transfer into
1615 // account... according to GB DEV FAQs, the setup time is the same
1616 // for single and double speed, but the actual transfer takes the
1617 // same time
1618 if(gbSpeed)
1619 gbDmaTicks = 2+16 * ((value & 0x7f) +1);
1620 else
1621 gbDmaTicks = 1+8 * ((value & 0x7f)+1);
1622
1623 gbCopyMemory((gbHdmaDestination & 0x1ff0) | 0x8000,
1624 gbHdmaSource & 0xfff0,
1625 gbHdmaBytes);
1626 gbHdmaDestination += gbHdmaBytes;
1627 gbHdmaSource += gbHdmaBytes;
1628
1629 gbMemory[0xff51] = register_HDMA1 = 0xff;// = (gbHdmaSource >> 8) & 0xff;
1630 gbMemory[0xff52] = register_HDMA2 = 0xff;// = gbHdmaSource & 0xf0;
1631 gbMemory[0xff53] = register_HDMA3 = 0xff;// = ((gbHdmaDestination - 0x8000) >> 8) & 0x1f;
1632 gbMemory[0xff54] = register_HDMA4 = 0xff;// = gbHdmaDestination & 0xf0;
1633 gbMemory[0xff55] = register_HDMA5 = 0xff;
1634 }
1635 }
1636 return;
1637 }
1638 }
1639 break;
1640
1641 // BCPS
1642 case 0x68: {
1643 if(gbCgbMode) {
1644 int paletteIndex = (value & 0x3f) >> 1;
1645 int paletteHiLo = (value & 0x01);
1646
1647 gbMemory[0xff68] = value;
1648
1649 gbMemory[0xff69] = (paletteHiLo ?
1650 (gbPalette[paletteIndex] >> 8) :
1651 (gbPalette[paletteIndex] & 0x00ff));
1652 return;
1653 }
1654 }
1655 break;
1656
1657 // BCPD
1658 case 0x69: {
1659 if(gbCgbMode) {
1660 int v = gbMemory[0xff68];
1661 int paletteIndex = (v & 0x3f) >> 1;
1662 int paletteHiLo = (v & 0x01);
1663
1664 // No access to gbPalette during mode 3 (Color Panel Demo)
1665 if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
1666 (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
1667 ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
1668 ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
1669 {
1670 gbMemory[0xff69] = value;
1671 gbPalette[paletteIndex] = (paletteHiLo ?
1672 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
1673 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
1674 }
1675
1676
1677 if(gbMemory[0xff68] & 0x80) {
1678 int index = ((gbMemory[0xff68] & 0x3f) + 1) & 0x3f;
1679
1680 gbMemory[0xff68] = (gbMemory[0xff68] & 0x80) | index;
1681 gbMemory[0xff69] = (index & 1 ?
1682 (gbPalette[index>>1] >> 8) :
1683 (gbPalette[index>>1] & 0x00ff));
1684 }
1685 return;
1686 }
1687 }
1688 break;
1689
1690 // OCPS
1691 case 0x6a: {
1692 if(gbCgbMode) {
1693 int paletteIndex = (value & 0x3f) >> 1;
1694 int paletteHiLo = (value & 0x01);
1695
1696 paletteIndex += 32;
1697
1698 gbMemory[0xff6a] = value;
1699
1700 gbMemory[0xff6b] = (paletteHiLo ?
1701 (gbPalette[paletteIndex] >> 8) :
1702 (gbPalette[paletteIndex] & 0x00ff));
1703 return;
1704 }
1705 }
1706 break;
1707
1708 // OCPD
1709 case 0x6b: {
1710
1711 if(gbCgbMode) {
1712 int v = gbMemory[0xff6a];
1713 int paletteIndex = (v & 0x3f) >> 1;
1714 int paletteHiLo = (v & 0x01);
1715
1716 paletteIndex += 32;
1717
1718 // No access to gbPalette during mode 3 (Color Panel Demo)
1719 if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
1720 (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
1721 ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
1722 ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
1723 {
1724 gbMemory[0xff6b] = value;
1725 gbPalette[paletteIndex] = (paletteHiLo ?
1726 ((value << 8) | (gbPalette[paletteIndex] & 0xff)) :
1727 ((gbPalette[paletteIndex] & 0xff00) | (value))) & 0x7fff;
1728 }
1729
1730 if(gbMemory[0xff6a] & 0x80) {
1731 int index = ((gbMemory[0xff6a] & 0x3f) + 1) & 0x3f;
1732
1733 gbMemory[0xff6a] = (gbMemory[0xff6a] & 0x80) | index;
1734
1735 gbMemory[0xff6b] = (index & 1 ?
1736 (gbPalette[(index>>1) + 32] >> 8) :
1737 (gbPalette[(index>>1) + 32] & 0x00ff));
1738 }
1739 return;
1740 }
1741 }
1742 break;
1743
1744 case 0x6c: {
1745 gbMemory[0xff6c] = 0xfe | value;
1746 return;
1747 }
1748
1749
1750 // SVBK
1751 case 0x70: {
1752 if(gbCgbMode) {
1753 value = value & 7;
1754
1755 int bank = value;
1756 if(value == 0)
1757 bank = 1;
1758
1759 if(bank == gbWramBank)
1760 return;
1761
1762 int wramAddress = bank * 0x1000;
1763 gbMemoryMap[0x0d] = &gbWram[wramAddress];
1764
1765 gbWramBank = bank;
1766 gbMemory[0xff70] = register_SVBK = value;
1767 return;
1768 }
1769 }
1770
1771 case 0x75:{
1772 gbMemory[0xff75] = 0x8f | value;
1773 return;
1774 }
1775
1776 case 0xff: {
1777 gbMemory[0xffff] = register_IE = value;
1778 return;
1779 }
1780 }
1781
1782 if(address < 0xff80)
1783 {
1784 gbMemory[address] = value;
1785 return;
1786 }
1787
1788 gbMemory[address] = value;
1789 }
1790
gbReadOpcode(register u16 address)1791 u8 gbReadOpcode(register u16 address)
1792 {
1793 if(gbCheatMap[address])
1794 return gbCheatRead(address);
1795
1796 if(address < 0x8000)
1797 return gbMemoryMap[address>>12][address&0x0fff];
1798
1799 if (address < 0xa000)
1800 {
1801 // A lot of 'ugly' checks... But only way to emulate this particular behaviour...
1802 if (
1803 (
1804 (gbHardware & 0xa) &&
1805 (
1806 (gbLcdModeDelayed != 3) ||
1807 (
1808 ((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) &&
1809 (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))
1810 )
1811 )
1812 )
1813 ||
1814 (
1815 (gbHardware & 0x5) &&
1816 (gbLcdModeDelayed != 3) &&
1817 (
1818 (gbLcdMode != 3) ||
1819 ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) &&
1820 (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))
1821 )
1822 )
1823 )
1824 return gbMemoryMap[address >> 12][address & 0x0fff];
1825
1826 return 0xff;
1827 }
1828
1829 // Used for the mirroring of 0xC000 in 0xE000
1830 if ((address >= 0xe000) && (address < 0xfe00))
1831 address &= ~0x2000;
1832
1833 switch(address & 0xf000) {
1834 case 0x0a:
1835 case 0x0b:
1836 if(mapperReadRAM)
1837 return mapperReadRAM(address);
1838 break;
1839 case 0x0f:
1840 if(address > 0xff00) {
1841 switch(address & 0x00ff) {
1842 case 0x02:
1843 return (gbMemory[0xff02]);
1844 case 0x03:
1845 return (0xff);
1846 case 0x04:
1847 return register_DIV;
1848 case 0x05:
1849 return register_TIMA;
1850 case 0x06:
1851 return register_TMA;
1852 case 0x07:
1853 return (0xf8 | register_TAC);
1854 case 0x08:
1855 case 0x09:
1856 case 0x0a:
1857 case 0x0b:
1858 case 0x0c:
1859 case 0x0d:
1860 case 0x0e:
1861 return (0xff);
1862 case 0x0f:
1863 return (0xe0 | gbMemory[0xff0f]);
1864 case 0x40:
1865 return register_LCDC;
1866 case 0x41:
1867 // This is a GB/C only bug (ie. not GBA/SP).
1868 if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed))
1869 return (0x80 | (gbMemory[0xff41] & 0xFC));
1870 else
1871 return (0x80 | gbMemory[0xff41]);
1872 case 0x42:
1873 return register_SCY;
1874 case 0x43:
1875 return register_SCX;
1876 case 0x44:
1877 if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) ||
1878 (!(register_LCDC & 0x80)))
1879 return 0;
1880 else
1881 return register_LY;
1882 case 0x45:
1883 return register_LYC;
1884 case 0x46:
1885 return register_DMA;
1886 case 0x4a:
1887 return register_WY;
1888 case 0x4b:
1889 return register_WX;
1890 case 0x4c:
1891 return 0xff;
1892 case 0x4f:
1893 return (0xfe | register_VBK);
1894 case 0x51:
1895 return register_HDMA1;
1896 case 0x52:
1897 return register_HDMA2;
1898 case 0x53:
1899 return register_HDMA3;
1900 case 0x54:
1901 return register_HDMA4;
1902 case 0x55:
1903 return register_HDMA5;
1904 case 0x68:
1905 case 0x6a:
1906 if (gbCgbMode)
1907 return (0x40 | gbMemory[address]);
1908 else
1909 return 0xc0;
1910 case 0x69:
1911 case 0x6b:
1912 if (gbCgbMode)
1913 {
1914 // No access to gbPalette during mode 3 (Color Panel Demo)
1915 if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
1916 (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
1917 ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
1918 ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
1919 return (gbMemory[address]);
1920 else
1921 return 0xff;
1922 }
1923 else
1924 return 0xff;
1925 case 0x70:
1926 if (gbCgbMode)
1927 return (0xf8 | register_SVBK);
1928 else
1929 return 0xff;
1930 case 0xff:
1931 return register_IE;
1932 }
1933 }
1934 // OAM not accessible during mode 2 & 3.
1935 if(((address >= 0xfe00) && (address<0xfea0)) &&
1936 ((gbLcdMode | gbLcdModeDelayed) &2))
1937 return 0xff;
1938 break;
1939 }
1940
1941 if ((address >= 0xfea0) && (address < 0xff00))
1942 {
1943 if (gbHardware & 1)
1944 return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff );
1945 else if (gbHardware & 2)
1946 return gbMemoryMap[address>>12][address & 0x0fff];
1947 else if (gbHardware & 4)
1948 return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 );
1949 else if (gbHardware & 8)
1950 return ((address & 0xf0) |((address & 0xf0)>>4));
1951 }
1952
1953 return gbMemoryMap[address>>12][address & 0x0fff];
1954 }
1955
gbReadMemory(register u16 address)1956 u8 gbReadMemory(register u16 address)
1957 {
1958 if(gbCheatMap[address])
1959 return gbCheatRead(address);
1960
1961
1962 if(address < 0x8000)
1963 return gbMemoryMap[address>>12][address&0x0fff];
1964
1965
1966 if (address < 0xa000)
1967 {
1968 // A lot of 'ugly' checks... But only way to emulate this particular behaviour...
1969 if (
1970 (
1971 (gbHardware & 0xa) &&
1972 (
1973 (gbLcdModeDelayed != 3) ||
1974 (
1975 ((register_LY == 0) && (gbScreenOn == false) && (register_LCDC & 0x80)) &&
1976 (gbLcdLYIncrementTicksDelayed == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS))
1977 )
1978 )
1979 )
1980 ||
1981 (
1982 (gbHardware & 0x5) &&
1983 (gbLcdModeDelayed != 3) &&
1984 (
1985 (gbLcdMode != 3) ||
1986 ((register_LY == 0) && ((gbScreenOn == false) && (register_LCDC & 0x80)) &&
1987 (gbLcdLYIncrementTicks == (GBLY_INCREMENT_CLOCK_TICKS - GBLCD_MODE_2_CLOCK_TICKS)))
1988 )
1989 )
1990 )
1991 return gbMemoryMap[address >> 12][address & 0x0fff];
1992
1993 return 0xff;
1994 }
1995
1996 if ((address >= 0xe000) && (address < 0xfe00))
1997 address &= ~0x2000;
1998
1999 if(address < 0xc000) {
2000 #ifndef FINAL_VERSION
2001 if(memorydebug) {
2002 log("Memory register read %04x PC=%04x\n",
2003 address,
2004 PC.W);
2005 }
2006 #endif
2007
2008 // for the 2kb ram limit (fixes crash in shawu's story
2009 // but now its sram test fails, as the it expects 8kb and not 2kb...
2010 // So use the 'genericflashcard' option to fix it).
2011 if (address<=(0xa000+gbRamSizeMask))
2012 {
2013 if(mapperReadRAM)
2014 return mapperReadRAM(address);
2015 return gbMemoryMap[address>>12][address & 0x0fff];
2016 }
2017 return 0xff;
2018 }
2019
2020 if(address >= 0xff00) {
2021 if ( address >= 0xFF10 && address <= 0xFF3F )
2022 return gbSoundRead( address );
2023
2024 switch(address & 0x00ff) {
2025 case 0x00:
2026 {
2027 if(gbSgbMode) {
2028 gbSgbReadingController |= 4;
2029 gbSgbResetPacketState();
2030 }
2031
2032 int b = gbMemory[0xff00];
2033
2034 if((b & 0x30) == 0x20) {
2035 b &= 0xf0;
2036
2037 int joy = 0;
2038 if(gbSgbMode && gbSgbMultiplayer) {
2039 switch(gbSgbNextController) {
2040 case 0x0f:
2041 joy = 0;
2042 break;
2043 case 0x0e:
2044 joy = 1;
2045 break;
2046 case 0x0d:
2047 joy = 2;
2048 break;
2049 case 0x0c:
2050 joy = 3;
2051 break;
2052 default:
2053 joy = 0;
2054 }
2055 }
2056 int joystate = gbJoymask[joy];
2057 if(!(joystate & 128))
2058 b |= 0x08;
2059 if(!(joystate & 64))
2060 b |= 0x04;
2061 if(!(joystate & 32))
2062 b |= 0x02;
2063 if(!(joystate & 16))
2064 b |= 0x01;
2065
2066 gbMemory[0xff00] = b;
2067 } else if((b & 0x30) == 0x10) {
2068 b &= 0xf0;
2069
2070 int joy = 0;
2071 if(gbSgbMode && gbSgbMultiplayer) {
2072 switch(gbSgbNextController) {
2073 case 0x0f:
2074 joy = 0;
2075 break;
2076 case 0x0e:
2077 joy = 1;
2078 break;
2079 case 0x0d:
2080 joy = 2;
2081 break;
2082 case 0x0c:
2083 joy = 3;
2084 break;
2085 default:
2086 joy = 0;
2087 }
2088 }
2089 int joystate = gbJoymask[joy];
2090 if(!(joystate & 8))
2091 b |= 0x08;
2092 if(!(joystate & 4))
2093 b |= 0x04;
2094 if(!(joystate & 2))
2095 b |= 0x02;
2096 if(!(joystate & 1))
2097 b |= 0x01;
2098
2099 gbMemory[0xff00] = b;
2100 } else {
2101 if(gbSgbMode && gbSgbMultiplayer) {
2102 gbMemory[0xff00] = 0xf0 | gbSgbNextController;
2103 } else {
2104 gbMemory[0xff00] = 0xff;
2105 }
2106 }
2107 }
2108 return gbMemory[0xff00];
2109 break;
2110 case 0x01:
2111 return gbMemory[0xff01];
2112 case 0x02:
2113 return (gbMemory[0xff02]);
2114 case 0x04:
2115 return register_DIV;
2116 case 0x05:
2117 return register_TIMA;
2118 case 0x06:
2119 return register_TMA;
2120 case 0x07:
2121 return (0xf8 | register_TAC);
2122 case 0x0f:
2123 return (0xe0 | gbMemory[0xff0f]);
2124 case 0x30:
2125 case 0x31:
2126 case 0x32:
2127 case 0x33:
2128 case 0x34:
2129 case 0x35:
2130 case 0x36:
2131 case 0x37:
2132 case 0x38:
2133 case 0x39:
2134 case 0x3A:
2135 case 0x3B:
2136 case 0x3C:
2137 case 0x3D:
2138 case 0x3E:
2139 case 0x3F:
2140 if ((gbMemory[NR30] & 0x80) && (gbMemory[NR34] & 0x80))
2141 return 0xFF;
2142 else
2143 return gbMemoryMap[address>>12][address & 0x0fff];
2144 case 0x40:
2145 return register_LCDC;
2146 case 0x41:
2147 // This is a GB/C only bug (ie. not GBA/SP).
2148 if ((gbHardware & 7) && (gbLcdMode == 2) && (gbLcdModeDelayed == 1) && (!gbSpeed))
2149 return (0x80 | (gbMemory[0xff41] & 0xFC));
2150 else
2151 return (0x80 | gbMemory[0xff41]);
2152 case 0x42:
2153 return register_SCY;
2154 case 0x43:
2155 return register_SCX;
2156 case 0x44:
2157 if (((gbHardware & 7) && ((gbLcdMode == 1) && (gbLcdTicks == 0x71))) ||
2158 (!(register_LCDC & 0x80)))
2159 return (0);
2160 else
2161 return register_LY;
2162 case 0x45:
2163 return register_LYC;
2164 case 0x46:
2165 return register_DMA;
2166 case 0x4a:
2167 return register_WY;
2168 case 0x4b:
2169 return register_WX;
2170 case 0x4f:
2171 return (0xfe | register_VBK);
2172 case 0x51:
2173 return register_HDMA1;
2174 case 0x52:
2175 return register_HDMA2;
2176 case 0x53:
2177 return register_HDMA3;
2178 case 0x54:
2179 return register_HDMA4;
2180 case 0x55:
2181 return register_HDMA5;
2182 case 0x68:
2183 case 0x6a:
2184 if (gbCgbMode)
2185 return (0x40 | gbMemory[address]);
2186 else
2187 return 0xc0;
2188 case 0x69:
2189 case 0x6b:
2190 if (gbCgbMode)
2191 {
2192 // No access to gbPalette during mode 3 (Color Panel Demo)
2193 if (((gbLcdModeDelayed != 3) && (!((gbLcdMode == 0) && (gbLcdTicks>=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-1)))) && (!gbSpeed)) ||
2194 (gbSpeed && ((gbLcdMode == 1) || (gbLcdMode == 2) ||
2195 ((gbLcdMode == 3) && (gbLcdTicks>(GBLCD_MODE_3_CLOCK_TICKS-2))) ||
2196 ((gbLcdMode == 0) && (gbLcdTicks<=(GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299]-2))))))
2197 return (gbMemory[address]);
2198 else
2199 return 0xff;
2200 }
2201 else
2202 return 0xff;
2203 case 0x70:
2204 if (gbCgbMode)
2205 return (0xf8 | register_SVBK);
2206 else
2207 return 0xff;
2208 case 0xff:
2209 return register_IE;
2210 }
2211 }
2212 // OAM not accessible during mode 2 & 3.
2213 if(((address >= 0xfe00) && (address<0xfea0)) &&
2214 ((((gbLcdMode | gbLcdModeDelayed) & 2) &&
2215 (!(gbSpeed && (gbHardware & 0x2) && !(gbLcdModeDelayed & 2) && (gbLcdMode == 2)))) ||
2216 (gbSpeed && (gbHardware & 0x2) && (gbLcdModeDelayed == 0) && (gbLcdTicksDelayed == (GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299])))))
2217 return 0xff;
2218
2219 if ((address >= 0xfea0) && (address < 0xff00))
2220 {
2221 if (gbHardware & 1)
2222 return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0x00 : 0xff );
2223 else if (gbHardware & 2)
2224 return gbMemoryMap[address>>12][address & 0x0fff];
2225 else if (gbHardware & 4)
2226 return ((((address + ((address >> 4) - 0xfea)) >> 2) & 1) ? 0xff : 0x00 );
2227 else if (gbHardware & 8)
2228 return ((address & 0xf0) |((address & 0xf0)>>4));
2229 }
2230
2231 return gbMemoryMap[address>>12][address & 0x0fff];
2232 }
2233
gbVblank_interrupt()2234 void gbVblank_interrupt()
2235 {
2236 gbCheatWrite(false); // Emulates GS codes.
2237 gbMemory[0xff0f] = register_IF &= 0xfe;
2238 gbWriteMemory(--SP.W, PC.B.B1);
2239 gbWriteMemory(--SP.W, PC.B.B0);
2240 PC.W = 0x40;
2241 }
2242
gbLcd_interrupt()2243 void gbLcd_interrupt()
2244 {
2245 gbCheatWrite(false); // Emulates GS codes.
2246 gbMemory[0xff0f] = register_IF &= 0xfd;
2247 gbWriteMemory(--SP.W, PC.B.B1);
2248 gbWriteMemory(--SP.W, PC.B.B0);
2249 PC.W = 0x48;
2250 }
2251
gbTimer_interrupt()2252 void gbTimer_interrupt()
2253 {
2254 gbMemory[0xff0f] = register_IF &= 0xfb;
2255 gbWriteMemory(--SP.W, PC.B.B1);
2256 gbWriteMemory(--SP.W, PC.B.B0);
2257 PC.W = 0x50;
2258 }
2259
gbSerial_interrupt()2260 void gbSerial_interrupt()
2261 {
2262 gbMemory[0xff0f] = register_IF &= 0xf7;
2263 gbWriteMemory(--SP.W, PC.B.B1);
2264 gbWriteMemory(--SP.W, PC.B.B0);
2265 PC.W = 0x58;
2266 }
2267
gbJoypad_interrupt()2268 void gbJoypad_interrupt()
2269 {
2270 gbMemory[0xff0f] = register_IF &= 0xef;
2271 gbWriteMemory(--SP.W, PC.B.B1);
2272 gbWriteMemory(--SP.W, PC.B.B0);
2273 PC.W = 0x60;
2274 }
2275
gbSpeedSwitch()2276 void gbSpeedSwitch()
2277 {
2278 gbBlackScreen = true;
2279 if(gbSpeed == 0) {
2280 gbSpeed = 1;
2281 GBLCD_MODE_0_CLOCK_TICKS = 51 * 2;
2282 GBLCD_MODE_1_CLOCK_TICKS = 1140 * 2;
2283 GBLCD_MODE_2_CLOCK_TICKS = 20 * 2;
2284 GBLCD_MODE_3_CLOCK_TICKS = 43 * 2;
2285 GBLY_INCREMENT_CLOCK_TICKS = 114 * 2;
2286 GBDIV_CLOCK_TICKS = 64;
2287 GBTIMER_MODE_0_CLOCK_TICKS = 256;
2288 GBTIMER_MODE_1_CLOCK_TICKS = 4;
2289 GBTIMER_MODE_2_CLOCK_TICKS = 16;
2290 GBTIMER_MODE_3_CLOCK_TICKS = 64;
2291 GBSERIAL_CLOCK_TICKS = 128 * 2;
2292 gbLcdTicks *= 2;
2293 gbLcdTicksDelayed *=2;
2294 gbLcdTicksDelayed--;
2295 gbLcdLYIncrementTicks *= 2;
2296 gbLcdLYIncrementTicksDelayed *= 2;
2297 gbLcdLYIncrementTicksDelayed--;
2298 gbSerialTicks *= 2;
2299 //SOUND_CLOCK_TICKS = soundQuality * 24 * 2;
2300 //soundTicks *= 2;
2301 gbLine99Ticks = 3;
2302 } else {
2303 gbSpeed = 0;
2304 GBLCD_MODE_0_CLOCK_TICKS = 51;
2305 GBLCD_MODE_1_CLOCK_TICKS = 1140;
2306 GBLCD_MODE_2_CLOCK_TICKS = 20;
2307 GBLCD_MODE_3_CLOCK_TICKS = 43;
2308 GBLY_INCREMENT_CLOCK_TICKS = 114;
2309 GBDIV_CLOCK_TICKS = 64;
2310 GBTIMER_MODE_0_CLOCK_TICKS = 256;
2311 GBTIMER_MODE_1_CLOCK_TICKS = 4;
2312 GBTIMER_MODE_2_CLOCK_TICKS = 16;
2313 GBTIMER_MODE_3_CLOCK_TICKS = 64;
2314 GBSERIAL_CLOCK_TICKS = 128;
2315 gbLcdTicks >>= 1;
2316 gbLcdTicksDelayed++;
2317 gbLcdTicksDelayed >>=1;
2318 gbLcdLYIncrementTicks >>= 1;
2319 gbLcdLYIncrementTicksDelayed++;
2320 gbLcdLYIncrementTicksDelayed >>= 1;
2321 gbSerialTicks /= 2;
2322 //SOUND_CLOCK_TICKS = soundQuality * 24;
2323 //soundTicks /= 2;
2324 gbLine99Ticks = 1;
2325 if (gbHardware & 8)
2326 gbLine99Ticks++;
2327 }
2328 gbDmaTicks += (134)*GBLY_INCREMENT_CLOCK_TICKS + (37<<(gbSpeed ? 1 : 0));
2329 }
2330
CPUIsGBBios(const char * file)2331 bool CPUIsGBBios(const char * file)
2332 {
2333 if(strlen(file) > 4) {
2334 const char * p = strrchr(file,'.');
2335
2336 if(p != NULL) {
2337 if(_stricmp(p, ".gb") == 0)
2338 return true;
2339 if(_stricmp(p, ".bin") == 0)
2340 return true;
2341 if(_stricmp(p, ".bios") == 0)
2342 return true;
2343 if(_stricmp(p, ".rom") == 0)
2344 return true;
2345 }
2346 }
2347
2348 return false;
2349 }
2350
gbCPUInit(const char * biosFileName,bool useBiosFile)2351 void gbCPUInit(const char *biosFileName, bool useBiosFile)
2352 {
2353 // GB/GBC/SGB only at the moment
2354 if (!(gbHardware & 7))
2355 return;
2356
2357 useBios = false;
2358 if (useBiosFile)
2359 {
2360 int expectedSize = (gbHardware & 2) ? 0x900 : 0x100;
2361 int size = expectedSize;
2362 if(utilLoad(biosFileName,
2363 CPUIsGBBios,
2364 bios,
2365 size)) {
2366 if(size == expectedSize)
2367 useBios = true;
2368 else
2369 systemMessage(MSG_INVALID_BIOS_FILE_SIZE, N_("Invalid BOOTROM file size"));
2370 }
2371 }
2372 }
2373
gbGetHardwareType()2374 void gbGetHardwareType()
2375 {
2376 gbCgbMode = 0;
2377 gbSgbMode = 0;
2378 if((gbEmulatorType == 0 && (gbRom[0x143] & 0x80)) ||
2379 gbEmulatorType == 1 ||
2380 gbEmulatorType == 4) {
2381 gbCgbMode = 1;
2382 }
2383
2384 if((gbCgbMode == 0 ) && (gbRom[0x146] == 0x03)) {
2385 if(gbEmulatorType == 0 ||
2386 gbEmulatorType == 2 ||
2387 gbEmulatorType == 5)
2388 gbSgbMode = 1;
2389 }
2390
2391 gbHardware = 1; // GB
2392 if (((gbCgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 1))
2393 gbHardware = 2; // GBC
2394 else if (((gbSgbMode == 1) && (gbEmulatorType == 0)) || (gbEmulatorType == 2) || (gbEmulatorType == 5))
2395 gbHardware = 4; // SGB(2)
2396 else if (gbEmulatorType == 4)
2397 gbHardware = 8; // GBA
2398
2399 gbGBCColorType = 0;
2400 if (gbHardware & 8) // If GBA is selected, choose the GBA default settings.
2401 gbGBCColorType = 2; // (0 = GBC, 1 = GBA, 2 = GBASP)
2402 }
2403
gbSelectColorizationPalette()2404 static void gbSelectColorizationPalette()
2405 {
2406 int infoIdx = 0;
2407
2408 // Check if licensee is Nintendo. If not, use default palette.
2409 if (gbRom[0x014B] == 0x01 ||
2410 (gbRom[0x014B] == 0x33 && gbRom[0x0144] == 0x30 && gbRom[0x0145] == 0x31))
2411 {
2412 // Calculate the checksum over 16 title bytes.
2413 u8 checksum = 0;
2414 for (int i = 0; i < 16; i++)
2415 {
2416 checksum += gbRom[0x0134 + i];
2417 }
2418
2419 // Check if the checksum is in the list.
2420 int idx;
2421 for (idx = 0; idx < sizeof(gbColorizationChecksums); idx++)
2422 {
2423 if (gbColorizationChecksums[idx] == checksum)
2424 {
2425 break;
2426 }
2427 }
2428
2429 // Was the checksum found in the list?
2430 if (idx < sizeof(gbColorizationChecksums))
2431 {
2432 // Indexes above 0x40 have to be disambiguated.
2433 if (idx > 0x40)
2434 {
2435 // No idea how that works. But it works.
2436 for (int i = idx - 0x41, j = 0; i < sizeof(gbColorizationDisambigChars); i += 14, j += 14)
2437 {
2438 if (gbRom[0x0137] == gbColorizationDisambigChars[i])
2439 {
2440 infoIdx = idx + j;
2441 break;
2442 }
2443 }
2444 }
2445 else
2446 {
2447 // Lower indexes just use the index from the checksum list.
2448 infoIdx = idx;
2449 }
2450 }
2451 }
2452 u8 palette = gbColorizationPaletteInfo[infoIdx] & 0x1F;
2453 u8 flags = (gbColorizationPaletteInfo[infoIdx] & 0xE0) >> 5;
2454
2455
2456 // Normally the first palette is used as OBP0.
2457 // If bit 0 is zero, the third palette is used instead.
2458 const u16* obp0 = 0;
2459 if (flags & 1)
2460 {
2461 obp0 = gbColorizationPaletteData[palette][0];
2462 }
2463 else
2464 {
2465 obp0 = gbColorizationPaletteData[palette][2];
2466 }
2467
2468 memcpy(gbPalette + 32, obp0, sizeof(gbColorizationPaletteData[palette][0]));
2469
2470 // Normally the second palette is used as OBP1.
2471 // If bit 1 is set, the first palette is used instead.
2472 // If bit 2 is zero, the third palette is used instead.
2473 const u16* obp1 = 0;
2474 if (!(flags & 4))
2475 {
2476 obp1 = gbColorizationPaletteData[palette][2];
2477 }
2478 else if (flags & 2)
2479 {
2480 obp1 = gbColorizationPaletteData[palette][0];
2481 }
2482 else
2483 {
2484 obp1 = gbColorizationPaletteData[palette][1];
2485 }
2486
2487 memcpy(gbPalette + 36, obp1, sizeof(gbColorizationPaletteData[palette][0]));
2488
2489 // Third palette is always used for BGP.
2490 memcpy(gbPalette, gbColorizationPaletteData[palette][2], sizeof(gbColorizationPaletteData[palette][0]));
2491 }
2492
gbReset()2493 void gbReset()
2494 {
2495 #ifndef NO_LINK
2496 if (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET) {
2497 EmuReseted = true;
2498 gbInitLink();
2499 }
2500 #endif
2501
2502 gbGetHardwareType();
2503
2504 oldRegister_WY = 146;
2505 gbInterruptLaunched = 0;
2506
2507 if(gbCgbMode == 1) {
2508 if (gbVram == NULL)
2509 gbVram = (u8 *)malloc(0x4000);
2510 if (gbWram == NULL)
2511 gbWram = (u8 *)malloc(0x8000);
2512 memset(gbVram,0,0x4000);
2513 memset(gbPalette,0, 2*128);
2514 }
2515 else
2516 {
2517 if(gbVram != NULL) {
2518 free(gbVram);
2519 gbVram = NULL;
2520 }
2521 if(gbWram != NULL) {
2522 free(gbWram);
2523 gbWram = NULL;
2524 }
2525 }
2526
2527 gbLYChangeHappened = false;
2528 gbLCDChangeHappened = false;
2529 gbBlackScreen = false;
2530 gbInterruptWait = 0;
2531 gbDmaTicks = 0;
2532 clockTicks = 0;
2533
2534 // clean Wram
2535 // This kinda emulates the startup state of Wram on GB/C (not very accurate,
2536 // but way closer to the reality than filling it with 00es or FFes).
2537 // On GBA/GBASP, it's kinda filled with random data.
2538 // In all cases, most of the 2nd bank is filled with 00s.
2539 // The starting data are important for some 'buggy' games, like Buster Brothers or
2540 // Karamuchou ha Oosawagi!.
2541 if (gbMemory != NULL)
2542 {
2543 memset(gbMemory,0xff, 65536);
2544 for (int temp = 0xC000; temp < 0xE000; temp++)
2545 if ((temp & 0x8) ^((temp & 0x800)>>8))
2546 {
2547 if ((gbHardware & 0x02) && (gbGBCColorType == 0))
2548 gbMemory[temp] = 0x0;
2549 else
2550 gbMemory[temp] = 0x0f;
2551 }
2552
2553 else
2554 gbMemory[temp] = 0xff;
2555 }
2556
2557 if(gbSpeed) {
2558 gbSpeedSwitch();
2559 gbMemory[0xff4d] = 0;
2560 }
2561
2562 // GB bios set this memory area to 0
2563 // Fixes Pitman (J) title screen
2564 if (gbHardware & 0x1) {
2565 memset(&gbMemory[0x8000], 0x0, 0x2000);
2566 }
2567
2568 // clean LineBuffer
2569 if (gbLineBuffer != NULL)
2570 memset(gbLineBuffer, 0, sizeof(*gbLineBuffer));
2571 // clean Pix
2572 if (pix != NULL)
2573 memset(pix, 0, sizeof(*pix));
2574 // clean Vram
2575 if (gbVram != NULL)
2576 memset(gbVram, 0, 0x4000);
2577 // clean Wram 2
2578 // This kinda emulates the startup state of Wram on GBC (not very accurate,
2579 // but way closer to the reality than filling it with 00es or FFes).
2580 // On GBA/GBASP, it's kinda filled with random data.
2581 // In all cases, most of the 2nd bank is filled with 00s.
2582 // The starting data are important for some 'buggy' games, like Buster Brothers or
2583 // Karamuchou ha Oosawagi!
2584 if (gbWram != NULL)
2585 {
2586 for (int i = 0; i<8; i++)
2587 if (i != 2)
2588 memcpy ((u16 *)(gbWram+i*0x1000), (u16 *)(gbMemory+0xC000), 0x1000);
2589 }
2590
2591 memset(gbSCYLine,0,sizeof(gbSCYLine));
2592 memset(gbSCXLine,0,sizeof(gbSCXLine));
2593 memset(gbBgpLine,0xfc,sizeof(gbBgpLine));
2594 if (gbHardware & 5)
2595 {
2596 memset(gbObp0Line,0xff,sizeof(gbObp0Line));
2597 memset(gbObp1Line,0xff,sizeof(gbObp1Line));
2598 }
2599 else
2600 {
2601 memset(gbObp0Line,0x0,sizeof(gbObp0Line));
2602 memset(gbObp1Line,0x0,sizeof(gbObp1Line));
2603 }
2604 memset(gbSpritesTicks,0x0,sizeof(gbSpritesTicks));
2605
2606 SP.W = 0xfffe;
2607 AF.W = 0x01b0;
2608 BC.W = 0x0013;
2609 DE.W = 0x00d8;
2610 HL.W = 0x014d;
2611 PC.W = 0x0100;
2612 IFF = 0;
2613 gbInt48Signal = 0;
2614
2615 register_TIMA = 0;
2616 register_TMA = 0;
2617 register_TAC = 0;
2618 gbMemory[0xff0f] = register_IF = 1;
2619 gbMemory[0xff40] = register_LCDC = 0x91;
2620 gbMemory[0xff47] = 0xfc;
2621
2622 if (gbCgbMode)
2623 gbMemory[0xff4d] = 0x7e;
2624 else
2625 gbMemory[0xff4d] = 0xff;
2626
2627 if (!gbCgbMode)
2628 gbMemory[0xff70] = gbMemory[0xff74] = 0xff;
2629
2630 if (gbCgbMode)
2631 gbMemory[0xff56] = 0x3e;
2632 else
2633 gbMemory[0xff56] = 0xff;
2634
2635 register_SCY = 0;
2636 register_SCX = 0;
2637 register_LYC = 0;
2638 register_DMA = 0xff;
2639 register_WY = 0;
2640 register_WX = 0;
2641 register_VBK = 0;
2642 register_HDMA1 = 0xff;
2643 register_HDMA2 = 0xff;
2644 register_HDMA3 = 0xff;
2645 register_HDMA4 = 0xff;
2646 register_HDMA5 = 0xff;
2647 register_SVBK = 0;
2648 register_IE = 0;
2649
2650 if (gbCgbMode)
2651 gbMemory[0xff02] = 0x7c;
2652 else
2653 gbMemory[0xff02] = 0x7e;
2654
2655 gbMemory[0xff03] = 0xff;
2656 int i;
2657 for (i = 0x8; i<0xf; i++)
2658 gbMemory[0xff00+i] = 0xff;
2659
2660 gbMemory[0xff13] = 0xff;
2661 gbMemory[0xff15] = 0xff;
2662 gbMemory[0xff18] = 0xff;
2663 gbMemory[0xff1d] = 0xff;
2664 gbMemory[0xff1f] = 0xff;
2665
2666 for (i = 0x27; i<0x30; i++)
2667 gbMemory[0xff00+i] = 0xff;
2668
2669 gbMemory[0xff4c] = 0xff;
2670 gbMemory[0xff4e] = 0xff;
2671 gbMemory[0xff50] = 0xff;
2672
2673 for (i = 0x57; i<0x68; i++)
2674 gbMemory[0xff00+i] = 0xff;
2675
2676 for (i = 0x5d; i<0x70; i++)
2677 gbMemory[0xff00+i] = 0xff;
2678
2679 gbMemory[0xff71] = 0xff;
2680
2681 for (i = 0x78; i<0x80; i++)
2682 gbMemory[0xff00+i] = 0xff;
2683
2684 if (gbHardware & 0xa)
2685 {
2686
2687 if (gbHardware & 2)
2688 {
2689 AF.W = 0x1180;
2690 BC.W = 0x0000;
2691 }
2692 else
2693 {
2694 AF.W = 0x1100;
2695 BC.W = 0x0100; // GBA/SP have B = 0x01 (which means GBC & GBA/SP bootrom are different !)
2696 }
2697
2698 gbMemory[0xff26] = 0xf1;
2699 if (gbCgbMode)
2700 {
2701
2702 gbMemory[0xff31] = 0xff;
2703 gbMemory[0xff33] = 0xff;
2704 gbMemory[0xff35] = 0xff;
2705 gbMemory[0xff37] = 0xff;
2706 gbMemory[0xff39] = 0xff;
2707 gbMemory[0xff3b] = 0xff;
2708 gbMemory[0xff3d] = 0xff;
2709
2710 gbMemory[0xff44] = register_LY = 0x90;
2711 gbDivTicks = 0x19 + ((gbHardware & 2) >> 1);
2712 gbInternalTimer = 0x58 + ((gbHardware & 2) >> 1);
2713 gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS -
2714 (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 72 + ((gbHardware & 2) >> 1);
2715 gbLcdLYIncrementTicks = 72 + ((gbHardware & 2) >> 1);
2716 gbMemory[0xff04] = register_DIV = 0x1E;
2717 }
2718 else
2719 {
2720 gbMemory[0xff44] = register_LY = 0x94;
2721 gbDivTicks = 0x22 + ((gbHardware & 2) >> 1);
2722 gbInternalTimer = 0x61 + ((gbHardware & 2) >> 1);
2723 gbLcdTicks = GBLCD_MODE_1_CLOCK_TICKS -
2724 (register_LY-0x8F)*GBLY_INCREMENT_CLOCK_TICKS + 25 + ((gbHardware & 2) >> 1);
2725 gbLcdLYIncrementTicks = 25 + ((gbHardware & 2) >> 1);
2726 gbMemory[0xff04] = register_DIV = 0x26;
2727 }
2728
2729
2730 DE.W = 0xff56;
2731 HL.W = 0x000d;
2732
2733 register_HDMA5 = 0xff;
2734 gbMemory[0xff68] = 0xc0;
2735 gbMemory[0xff6a] = 0xc0;
2736
2737
2738 gbMemory[0xff41] = register_STAT = 0x81;
2739 gbLcdMode = 1;
2740 }
2741 else
2742 {
2743 if (gbHardware & 4)
2744 {
2745 if(gbEmulatorType == 5)
2746 AF.W = 0xffb0;
2747 else
2748 AF.W = 0x01b0;
2749 BC.W = 0x0013;
2750 DE.W = 0x00d8;
2751 HL.W = 0x014d;
2752 }
2753 gbDivTicks = 14;
2754 gbInternalTimer = gbDivTicks--;
2755 gbMemory[0xff04] = register_DIV = 0xAB;
2756 gbMemory[0xff41] = register_STAT = 0x85;
2757 gbMemory[0xff44] = register_LY = 0x00;
2758 gbLcdTicks = 15;
2759 gbLcdLYIncrementTicks = 114+gbLcdTicks;
2760 gbLcdMode = 1;
2761
2762 }
2763
2764 // used for the handling of the gb Boot Rom
2765 if ((gbHardware & 7) && (bios != NULL) && useBios && !skipBios)
2766 {
2767 if (gbHardware & 5)
2768 {
2769 memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000);
2770 memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100);
2771 }
2772 else
2773 {
2774 memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x900);
2775 memcpy ((u8 *)(gbMemory + 0x100), (u8 *)(gbRom + 0x100), 0x100);
2776 }
2777 gbWhiteScreen = 0;
2778
2779 gbInternalTimer = 0x3e;
2780 gbDivTicks = 0x3f;
2781 gbMemory[0xff04] = register_DIV = 0x00;
2782 PC.W = 0x0000;
2783 register_LCDC = 0x11;
2784 gbScreenOn = false;
2785 gbLcdTicks = 0;
2786 gbLcdMode = 0;
2787 gbLcdModeDelayed = 0;
2788 gbMemory[0xff41] = register_STAT &= 0xfc;
2789 gbInt48Signal = 0;
2790 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS;
2791 gbMemory[0xff6c] = 0xfe;
2792
2793 inBios = true;
2794 }
2795 else if (gbHardware & 0xa)
2796 {
2797 // Set compatibility mode if it is a DMG ROM.
2798 gbMemory[0xff6c] = 0xfe | (u8)!(gbRom[0x143] & 0x80);
2799 }
2800
2801
2802 gbLine99Ticks = 1;
2803 if (gbHardware & 8)
2804 gbLine99Ticks++;
2805
2806 gbLcdModeDelayed = gbLcdMode;
2807 gbLcdTicksDelayed = gbLcdTicks+1;
2808 gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks+1;
2809
2810
2811 gbTimerModeChange = false;
2812 gbTimerOnChange = false;
2813 gbTimerOn = false;
2814
2815 if(gbCgbMode) {
2816 for (i = 0; i<0x20; i++)
2817 gbPalette[i] = 0x7fff;
2818
2819 // This is just to show that the starting values of the OBJ palettes are different
2820 // between the 3 consoles, and that they 'kinda' stay the same at each reset
2821 // (they can slightly change, somehow (randomly?)).
2822 // You can check the effects of gbGBCColorType on the "Vila Caldan Color" gbc demo.
2823 // Note that you could also check the Div register to check on which system the game
2824 // is running (GB,GBC and GBA(SP) have different startup values).
2825 // Unfortunatly, I don't have any SGB system, so I can't get their starting values.
2826
2827 if (gbGBCColorType == 0) // GBC Hardware
2828 {
2829 gbPalette[0x20] = 0x0600;
2830 gbPalette[0x21] = 0xfdf3;
2831 gbPalette[0x22] = 0x041c;
2832 gbPalette[0x23] = 0xf5db;
2833 gbPalette[0x24] = 0x4419;
2834 gbPalette[0x25] = 0x57ea;
2835 gbPalette[0x26] = 0x2808;
2836 gbPalette[0x27] = 0x9b75;
2837 gbPalette[0x28] = 0x129b;
2838 gbPalette[0x29] = 0xfce0;
2839 gbPalette[0x2a] = 0x22da;
2840 gbPalette[0x2b] = 0x4ac5;
2841 gbPalette[0x2c] = 0x2d71;
2842 gbPalette[0x2d] = 0xf0c2;
2843 gbPalette[0x2e] = 0x5137;
2844 gbPalette[0x2f] = 0x2d41;
2845 gbPalette[0x30] = 0x6b2d;
2846 gbPalette[0x31] = 0x2215;
2847 gbPalette[0x32] = 0xbe0a;
2848 gbPalette[0x33] = 0xc053;
2849 gbPalette[0x34] = 0xfe5f;
2850 gbPalette[0x35] = 0xe000;
2851 gbPalette[0x36] = 0xbe10;
2852 gbPalette[0x37] = 0x914d;
2853 gbPalette[0x38] = 0x7f91;
2854 gbPalette[0x39] = 0x02b5;
2855 gbPalette[0x3a] = 0x77ac;
2856 gbPalette[0x3b] = 0x14e5;
2857 gbPalette[0x3c] = 0xcf89;
2858 gbPalette[0x3d] = 0xa03d;
2859 gbPalette[0x3e] = 0xfd50;
2860 gbPalette[0x3f] = 0x91ff;
2861 }
2862 else if (gbGBCColorType == 1) // GBA Hardware
2863 {
2864 gbPalette[0x20] = 0xbe00;
2865 gbPalette[0x21] = 0xfdfd;
2866 gbPalette[0x22] = 0xbd69;
2867 gbPalette[0x23] = 0x7baf;
2868 gbPalette[0x24] = 0xf5ff;
2869 gbPalette[0x25] = 0x3f8f;
2870 gbPalette[0x26] = 0xcee5;
2871 gbPalette[0x27] = 0x5bf7;
2872 gbPalette[0x28] = 0xb35b;
2873 gbPalette[0x29] = 0xef97;
2874 gbPalette[0x2a] = 0xef9f;
2875 gbPalette[0x2b] = 0x97f7;
2876 gbPalette[0x2c] = 0x82bf;
2877 gbPalette[0x2d] = 0x9f3d;
2878 gbPalette[0x2e] = 0xddde;
2879 gbPalette[0x2f] = 0xbad5;
2880 gbPalette[0x30] = 0x3cba;
2881 gbPalette[0x31] = 0xdfd7;
2882 gbPalette[0x32] = 0xedea;
2883 gbPalette[0x33] = 0xfeda;
2884 gbPalette[0x34] = 0xf7f9;
2885 gbPalette[0x35] = 0xfdee;
2886 gbPalette[0x36] = 0x6d2f;
2887 gbPalette[0x37] = 0xf0e6;
2888 gbPalette[0x38] = 0xf7f0;
2889 gbPalette[0x39] = 0xf296;
2890 gbPalette[0x3a] = 0x3bf1;
2891 gbPalette[0x3b] = 0xe211;
2892 gbPalette[0x3c] = 0x69ba;
2893 gbPalette[0x3d] = 0x3d0d;
2894 gbPalette[0x3e] = 0xdfd3;
2895 gbPalette[0x3f] = 0xa6ba;
2896 }
2897 else if (gbGBCColorType == 2) // GBASP Hardware
2898 {
2899 gbPalette[0x20] = 0x9c00;
2900 gbPalette[0x21] = 0x6340;
2901 gbPalette[0x22] = 0x10c6;
2902 gbPalette[0x23] = 0xdb97;
2903 gbPalette[0x24] = 0x7622;
2904 gbPalette[0x25] = 0x3e57;
2905 gbPalette[0x26] = 0x2e12;
2906 gbPalette[0x27] = 0x95c3;
2907 gbPalette[0x28] = 0x1095;
2908 gbPalette[0x29] = 0x488c;
2909 gbPalette[0x2a] = 0x8241;
2910 gbPalette[0x2b] = 0xde8c;
2911 gbPalette[0x2c] = 0xfabc;
2912 gbPalette[0x2d] = 0x0e81;
2913 gbPalette[0x2e] = 0x7675;
2914 gbPalette[0x2f] = 0xfdec;
2915 gbPalette[0x30] = 0xddfd;
2916 gbPalette[0x31] = 0x5995;
2917 gbPalette[0x32] = 0x066a;
2918 gbPalette[0x33] = 0xed1e;
2919 gbPalette[0x34] = 0x1e84;
2920 gbPalette[0x35] = 0x1d14;
2921 gbPalette[0x36] = 0x11c3;
2922 gbPalette[0x37] = 0x2749;
2923 gbPalette[0x38] = 0xa727;
2924 gbPalette[0x39] = 0x6266;
2925 gbPalette[0x3a] = 0xe27b;
2926 gbPalette[0x3b] = 0xe3fc;
2927 gbPalette[0x3c] = 0x1f76;
2928 gbPalette[0x3d] = 0xf158;
2929 gbPalette[0x3e] = 0x468e;
2930 gbPalette[0x3f] = 0xa540;
2931 }
2932
2933 // The CGB BIOS palette selection has to be done by VBA if BIOS is skipped.
2934 if (!(gbRom[0x143] & 0x80) && !inBios) {
2935 gbSelectColorizationPalette();
2936 }
2937
2938 } else {
2939 if(gbSgbMode) {
2940 for(i = 0; i < 8; i++)
2941 gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
2942
2943 }
2944 for(i = 0; i < 8; i++)
2945 gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
2946 }
2947
2948 GBTIMER_MODE_0_CLOCK_TICKS = 256;
2949 GBTIMER_MODE_1_CLOCK_TICKS = 4;
2950 GBTIMER_MODE_2_CLOCK_TICKS = 16;
2951 GBTIMER_MODE_3_CLOCK_TICKS = 64;
2952
2953 GBLY_INCREMENT_CLOCK_TICKS = 114;
2954 gbTimerTicks = GBTIMER_MODE_0_CLOCK_TICKS;
2955 gbTimerClockTicks = GBTIMER_MODE_0_CLOCK_TICKS;
2956 gbSerialTicks = 0;
2957 gbSerialBits = 0;
2958 gbSerialOn = 0;
2959 gbWindowLine = -1;
2960 gbTimerOn = false;
2961 gbTimerMode = 0;
2962 gbSpeed = 0;
2963 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0;
2964
2965 if(gbCgbMode) {
2966 gbSpeed = 0;
2967 gbHdmaOn = 0;
2968 gbHdmaSource = 0x99d0;
2969 gbHdmaDestination = 0x99d0;
2970 gbVramBank = 0;
2971 gbWramBank = 1;
2972
2973 }
2974
2975 // used to clean the borders
2976 if (gbSgbMode)
2977 {
2978 gbSgbResetFlag = true;
2979 gbSgbReset();
2980 if (gbBorderOn)
2981 gbSgbRenderBorder();
2982 gbSgbResetFlag = false;
2983 }
2984
2985 for(i = 0; i < 4; i++)
2986 gbBgp[i] = gbObp0[i] = gbObp1[i] = i;
2987
2988 memset(&gbDataMBC1,0, sizeof(gbDataMBC1));
2989 gbDataMBC1.mapperROMBank = 1;
2990
2991 gbDataMBC2.mapperRAMEnable = 0;
2992 gbDataMBC2.mapperROMBank = 1;
2993
2994 memset(&gbDataMBC3,0, 6 * sizeof(int));
2995 gbDataMBC3.mapperROMBank = 1;
2996
2997 memset(&gbDataMBC5, 0, sizeof(gbDataMBC5));
2998 gbDataMBC5.mapperROMBank = 1;
2999
3000 memset(&gbDataHuC1, 0, sizeof(gbDataHuC1));
3001 gbDataHuC1.mapperROMBank = 1;
3002
3003 memset(&gbDataHuC3, 0, sizeof(gbDataHuC3));
3004 gbDataHuC3.mapperROMBank = 1;
3005
3006 memset(&gbDataTAMA5,0, 26*sizeof(int));
3007 gbDataTAMA5.mapperROMBank = 1;
3008
3009 memset(&gbDataMMM01,0, sizeof(gbDataMMM01));
3010 gbDataMMM01.mapperROMBank = 1;
3011
3012 if (inBios)
3013 {
3014 gbMemoryMap[0x00] = &gbMemory[0x0000];
3015 }
3016 else
3017 {
3018 gbMemoryMap[0x00] = &gbRom[0x0000];
3019 }
3020
3021 gbMemoryMap[0x01] = &gbRom[0x1000];
3022 gbMemoryMap[0x02] = &gbRom[0x2000];
3023 gbMemoryMap[0x03] = &gbRom[0x3000];
3024 gbMemoryMap[0x04] = &gbRom[0x4000];
3025 gbMemoryMap[0x05] = &gbRom[0x5000];
3026 gbMemoryMap[0x06] = &gbRom[0x6000];
3027 gbMemoryMap[0x07] = &gbRom[0x7000];
3028 if(gbCgbMode) {
3029 gbMemoryMap[0x08] = &gbVram[0x0000];
3030 gbMemoryMap[0x09] = &gbVram[0x1000];
3031 gbMemoryMap[0x0a] = &gbMemory[0xa000];
3032 gbMemoryMap[0x0b] = &gbMemory[0xb000];
3033 gbMemoryMap[0x0c] = &gbMemory[0xc000];
3034 gbMemoryMap[0x0d] = &gbWram[0x1000];
3035 gbMemoryMap[0x0e] = &gbMemory[0xe000];
3036 gbMemoryMap[0x0f] = &gbMemory[0xf000];
3037 } else {
3038 gbMemoryMap[0x08] = &gbMemory[0x8000];
3039 gbMemoryMap[0x09] = &gbMemory[0x9000];
3040 gbMemoryMap[0x0a] = &gbMemory[0xa000];
3041 gbMemoryMap[0x0b] = &gbMemory[0xb000];
3042 gbMemoryMap[0x0c] = &gbMemory[0xc000];
3043 gbMemoryMap[0x0d] = &gbMemory[0xd000];
3044 gbMemoryMap[0x0e] = &gbMemory[0xe000];
3045 gbMemoryMap[0x0f] = &gbMemory[0xf000];
3046 }
3047
3048 if(gbRam) {
3049 gbMemoryMap[0x0a] = &gbRam[0x0000];
3050 gbMemoryMap[0x0b] = &gbRam[0x1000];
3051 }
3052
3053 gbSoundReset();
3054
3055 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
3056
3057 gbLastTime = systemGetClock();
3058 gbFrameCount = 0;
3059
3060 gbScreenOn = true;
3061 gbSystemMessage = false;
3062
3063 gbCheatWrite(true); // Emulates GS codes.
3064
3065 }
3066
gbWriteSaveMBC1(const char * name)3067 void gbWriteSaveMBC1(const char * name)
3068 {
3069 if (gbRam)
3070 {
3071 FILE *gzFile = fopen(name,"wb");
3072
3073 if(gzFile == NULL) {
3074 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3075 return;
3076 }
3077
3078 fwrite(gbRam,
3079 1,
3080 (gbRamSizeMask+1),
3081 gzFile);
3082
3083 fclose(gzFile);
3084 }
3085 }
3086
gbWriteSaveMBC2(const char * name)3087 void gbWriteSaveMBC2(const char * name)
3088 {
3089 if (gbRam)
3090 {
3091 FILE *file = fopen(name, "wb");
3092
3093 if(file == NULL) {
3094 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3095 return;
3096 }
3097
3098 fwrite(gbMemoryMap[0x0a],
3099 1,
3100 512,
3101 file);
3102
3103 fclose(file);
3104 }
3105 }
3106
gbWriteSaveMBC3(const char * name,bool extendedSave)3107 void gbWriteSaveMBC3(const char * name, bool extendedSave)
3108 {
3109 if (gbRam || extendedSave)
3110 {
3111 FILE *gzFile = fopen(name,"wb");
3112 if (gbRam)
3113 {
3114
3115 if(gzFile == NULL) {
3116 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3117 return;
3118 }
3119
3120 fwrite(gbRam,
3121 1,
3122 (gbRamSizeMask+1),
3123 gzFile);
3124 }
3125
3126 if(extendedSave)
3127 fwrite(&gbDataMBC3.mapperSeconds,
3128 1,
3129 10*sizeof(int) + sizeof(time_t),
3130 gzFile);
3131
3132 fclose(gzFile);
3133 }
3134 }
3135
gbWriteSaveMBC5(const char * name)3136 void gbWriteSaveMBC5(const char * name)
3137 {
3138 if (gbRam)
3139 {
3140 FILE *gzFile = fopen(name,"wb");
3141
3142 if(gzFile == NULL) {
3143 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3144 return;
3145 }
3146
3147 fwrite(gbRam,
3148 1,
3149 (gbRamSizeMask+1),
3150 gzFile);
3151
3152 fclose(gzFile);
3153 }
3154 }
3155
gbWriteSaveMBC7(const char * name)3156 void gbWriteSaveMBC7(const char * name)
3157 {
3158 if (gbRam)
3159 {
3160 FILE *file = fopen(name, "wb");
3161
3162 if(file == NULL) {
3163 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3164 return;
3165 }
3166
3167 fwrite(&gbMemory[0xa000],
3168 1,
3169 256,
3170 file);
3171
3172 fclose(file);
3173 }
3174 }
3175
gbWriteSaveTAMA5(const char * name,bool extendedSave)3176 void gbWriteSaveTAMA5(const char * name, bool extendedSave)
3177 {
3178 FILE *gzFile = fopen(name,"wb");
3179
3180 if(gzFile == NULL) {
3181 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3182 return;
3183 }
3184 if (gbRam)
3185 fwrite(gbRam,
3186 1,
3187 (gbRamSizeMask+1),
3188 gzFile);
3189
3190 fwrite(gbTAMA5ram,
3191 1,
3192 (gbTAMA5ramSize),
3193 gzFile);
3194
3195 if(extendedSave)
3196 fwrite(&gbDataTAMA5.mapperSeconds,
3197 1,
3198 14*sizeof(int) + sizeof(time_t),
3199 gzFile);
3200
3201 fclose(gzFile);
3202 }
3203
gbWriteSaveMMM01(const char * name)3204 void gbWriteSaveMMM01(const char * name)
3205 {
3206 if (gbRam)
3207 {
3208 FILE *gzFile = fopen(name,"wb");
3209
3210 if(gzFile == NULL) {
3211 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
3212 return;
3213 }
3214
3215 fwrite(gbRam,
3216 1,
3217 (gbRamSizeMask+1),
3218 gzFile);
3219
3220 fclose(gzFile);
3221 }
3222 }
3223
3224
gbReadSaveMBC1(const char * name)3225 bool gbReadSaveMBC1(const char * name)
3226 {
3227 if (gbRam)
3228 {
3229 gzFile gzFile = gzopen(name, "rb");
3230
3231 if(gzFile == NULL) {
3232 return false;
3233 }
3234
3235 int read = gzread(gzFile,
3236 gbRam,
3237 (gbRamSizeMask+1));
3238
3239 if(read != (gbRamSizeMask+1)) {
3240 systemMessage(MSG_FAILED_TO_READ_SGM,
3241 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3242 gzclose(gzFile);
3243 gbBatteryError = true;
3244 return false;
3245 }
3246
3247 // Also checks if the battery file it bigger than gbRamSizeMask+1 !
3248 u8 data[1];
3249 data[0] = 0;
3250
3251 read = gzread(gzFile,
3252 data,
3253 1);
3254 if(read >0) {
3255 systemMessage(MSG_FAILED_TO_READ_SGM,
3256 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3257 gzclose(gzFile);
3258 gbBatteryError = true;
3259 return false;
3260 }
3261
3262 gzclose(gzFile);
3263 return true;
3264 }
3265 else
3266 return false;
3267 }
3268
3269
gbReadSaveMBC2(const char * name)3270 bool gbReadSaveMBC2(const char * name)
3271 {
3272 if (gbRam)
3273 {
3274 FILE *file = fopen(name, "rb");
3275
3276 if(file == NULL) {
3277 return false;
3278 }
3279
3280 size_t read = fread(gbMemoryMap[0x0a],
3281 1,
3282 512,
3283 file);
3284
3285 if(read != 512) {
3286 systemMessage(MSG_FAILED_TO_READ_SGM,
3287 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3288 fclose(file);
3289 gbBatteryError = true;
3290 return false;
3291 }
3292
3293 // Also checks if the battery file it bigger than gbRamSizeMask+1 !
3294 u8 data[1];
3295 data[0] = 0;
3296
3297 read = fread(&data[0],
3298 1,
3299 1,
3300 file);
3301 if(read > 0) {
3302 systemMessage(MSG_FAILED_TO_READ_SGM,
3303 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3304 fclose(file);
3305 gbBatteryError = true;
3306 return false;
3307 }
3308
3309 fclose(file);
3310 return true;
3311 }
3312 else
3313 return false;
3314 }
3315
gbReadSaveMBC3(const char * name)3316 bool gbReadSaveMBC3(const char * name)
3317 {
3318 gzFile gzFile = gzopen(name, "rb");
3319
3320 if(gzFile == NULL) {
3321 return false;
3322 }
3323
3324 int read = 0;
3325
3326 if (gbRam)
3327 read = gzread(gzFile,
3328 gbRam,
3329 (gbRamSizeMask+1));
3330 else
3331 read = (gbRamSizeMask+1);
3332
3333
3334 bool res = true;
3335
3336 if(read != (gbRamSizeMask+1)) {
3337 systemMessage(MSG_FAILED_TO_READ_SGM,
3338 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3339 gbBatteryError = true;
3340 res = false;
3341 } else if ((gbRomType == 0xf) || (gbRomType == 0x10)){
3342 read = gzread(gzFile,
3343 &gbDataMBC3.mapperSeconds,
3344 sizeof(int)*10 + sizeof(time_t));
3345
3346 if(read != (sizeof(int)*10 + sizeof(time_t)) && read != 0) {
3347 systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
3348 name);
3349 res = false;
3350 }
3351 else if (read == 0)
3352 {
3353 systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
3354 name);
3355 res = false;
3356 }
3357 else
3358 {
3359 // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
3360 u8 data[1];
3361 data[0] = 0;
3362
3363 read = gzread(gzFile,
3364 data,
3365 1);
3366 if(read >0) {
3367 systemMessage(MSG_FAILED_TO_READ_SGM,
3368 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3369 gbBatteryError = true;
3370 res = false;
3371 }
3372 }
3373 }
3374
3375 gzclose(gzFile);
3376 return res;
3377 }
3378
gbReadSaveMBC5(const char * name)3379 bool gbReadSaveMBC5(const char * name)
3380 {
3381 if (gbRam)
3382 {
3383 gzFile gzFile = gzopen(name, "rb");
3384
3385 if(gzFile == NULL) {
3386 return false;
3387 }
3388
3389 int read = gzread(gzFile,
3390 gbRam,
3391 (gbRamSizeMask+1));
3392
3393 if(read != (gbRamSizeMask+1)) {
3394 systemMessage(MSG_FAILED_TO_READ_SGM,
3395 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3396 gzclose(gzFile);
3397 gbBatteryError = true;
3398 return false;
3399 }
3400
3401
3402 // Also checks if the battery file it bigger than gbRamSizeMask+1 !
3403 u8 data[1];
3404 data[0] = 0;
3405
3406 read = gzread(gzFile,
3407 data,
3408 1);
3409 if(read >0) {
3410 systemMessage(MSG_FAILED_TO_READ_SGM,
3411 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3412 gzclose(gzFile);
3413 gbBatteryError = true;
3414 return false;
3415 }
3416
3417 gzclose(gzFile);
3418 return true;
3419 }
3420 else
3421 return false;
3422 }
3423
gbReadSaveMBC7(const char * name)3424 bool gbReadSaveMBC7(const char * name)
3425 {
3426 if (gbRam)
3427 {
3428 FILE *file = fopen(name, "rb");
3429
3430 if(file == NULL) {
3431 return false;
3432 }
3433
3434 size_t read = fread(&gbMemory[0xa000],
3435 1,
3436 256,
3437 file);
3438
3439 if(read != 256) {
3440 systemMessage(MSG_FAILED_TO_READ_SGM,
3441 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3442 fclose(file);
3443 gbBatteryError = true;
3444 return false;
3445 }
3446
3447 // Also checks if the battery file it bigger than gbRamSizeMask+1 !
3448 u8 data[1];
3449 data[0] = 0;
3450
3451 read = fread(&data[0],
3452 1,
3453 1,
3454 file);
3455 if(read > 0) {
3456 systemMessage(MSG_FAILED_TO_READ_SGM,
3457 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3458 fclose(file);
3459 gbBatteryError = true;
3460 return false;
3461 }
3462
3463 fclose(file);
3464 return true;
3465 }
3466 else
3467 return false;
3468 }
3469
gbReadSaveTAMA5(const char * name)3470 bool gbReadSaveTAMA5(const char * name)
3471 {
3472 gzFile gzFile = gzopen(name, "rb");
3473
3474 if(gzFile == NULL) {
3475 return false;
3476 }
3477
3478 int read = 0;
3479
3480 if (gbRam)
3481 read = gzread(gzFile,
3482 gbRam,
3483 (gbRamSizeMask+1));
3484 else
3485 read = gbRamSizeMask;
3486
3487 read += gzread(gzFile,
3488 gbTAMA5ram,
3489 gbTAMA5ramSize);
3490
3491 bool res = true;
3492
3493 if(read != (gbRamSizeMask+gbTAMA5ramSize+1)) {
3494 systemMessage(MSG_FAILED_TO_READ_SGM,
3495 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3496 gbBatteryError = true;
3497 res = false;
3498 } else {
3499 read = gzread(gzFile,
3500 &gbDataTAMA5.mapperSeconds,
3501 sizeof(int)*14 + sizeof(time_t));
3502
3503 if(read != (sizeof(int)*14 + sizeof(time_t)) && read != 0) {
3504 systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
3505 name);
3506 res = false;
3507 }
3508 else if (read == 0)
3509 {
3510 systemMessage(MSG_FAILED_TO_READ_RTC,N_("Failed to read RTC from save game %s (continuing)"),
3511 name);
3512 res = false;
3513 }
3514 else
3515 {
3516 // Also checks if the battery file it bigger than gbRamSizeMask+1+RTC !
3517 u8 data[1];
3518 data[0] = 0;
3519
3520 read = gzread(gzFile,
3521 data,
3522 1);
3523 if(read >0) {
3524 systemMessage(MSG_FAILED_TO_READ_SGM,
3525 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3526 gbBatteryError = true;
3527 res = false;
3528 }
3529 }
3530 }
3531
3532 gzclose(gzFile);
3533 return res;
3534 }
3535
3536
gbReadSaveMMM01(const char * name)3537 bool gbReadSaveMMM01(const char * name)
3538 {
3539 if (gbRam)
3540 {
3541 gzFile gzFile = gzopen(name, "rb");
3542
3543 if(gzFile == NULL) {
3544 return false;
3545 }
3546
3547 int read = gzread(gzFile,
3548 gbRam,
3549 (gbRamSizeMask+1));
3550
3551 if(read != (gbRamSizeMask+1)) {
3552 systemMessage(MSG_FAILED_TO_READ_SGM,
3553 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3554 gzclose(gzFile);
3555 gbBatteryError = true;
3556 return false;
3557 }
3558
3559 // Also checks if the battery file it bigger than gbRamSizeMask+1 !
3560 u8 data[1];
3561 data[0] = 0;
3562
3563 read = gzread(gzFile,
3564 data,
3565 1);
3566 if(read >0) {
3567 systemMessage(MSG_FAILED_TO_READ_SGM,
3568 N_("Battery file's size incompatible with the rom settings %s (%d).\nWarning : save of the battery file is now disabled !"), name, read);
3569 gzclose(gzFile);
3570 gbBatteryError = true;
3571 return false;
3572 }
3573
3574 gzclose(gzFile);
3575 return true;
3576 }
3577 else
3578 return false;
3579 }
3580
gbInit()3581 void gbInit()
3582 {
3583 gbGenFilter();
3584 gbSgbInit();
3585
3586 gbMemory = (u8 *)malloc(65536);
3587
3588 pix = (u8 *)calloc(1,4*257*226);
3589
3590 gbLineBuffer = (u16 *)malloc(160 * sizeof(u16));
3591 }
3592
gbWriteBatteryFile(const char * file,bool extendedSave)3593 bool gbWriteBatteryFile(const char *file, bool extendedSave)
3594 {
3595 if(gbBattery) {
3596 switch(gbRomType) {
3597 case 0x03:
3598 gbWriteSaveMBC1(file);
3599 break;
3600 case 0x06:
3601 gbWriteSaveMBC2(file);
3602 break;
3603 case 0x0d:
3604 gbWriteSaveMMM01(file);
3605 break;
3606 case 0x0f:
3607 case 0x10:
3608 gbWriteSaveMBC3(file, extendedSave);
3609 break;
3610 case 0x13:
3611 case 0xfc:
3612 gbWriteSaveMBC3(file, false);
3613 break;
3614 case 0x1b:
3615 case 0x1e:
3616 gbWriteSaveMBC5(file);
3617 break;
3618 case 0x22:
3619 gbWriteSaveMBC7(file);
3620 break;
3621 case 0xfd:
3622 gbWriteSaveTAMA5(file, extendedSave);
3623 break;
3624 case 0xff:
3625 gbWriteSaveMBC1(file);
3626 break;
3627 }
3628 }
3629 return true;
3630 }
3631
gbWriteBatteryFile(const char * file)3632 bool gbWriteBatteryFile(const char *file)
3633 {
3634 if (!gbBatteryError)
3635 {
3636 gbWriteBatteryFile(file, true);
3637 return true;
3638 }
3639 else return false;
3640 }
3641
gbReadBatteryFile(const char * file)3642 bool gbReadBatteryFile(const char *file)
3643 {
3644 bool res = false;
3645 if(gbBattery) {
3646 switch(gbRomType) {
3647 case 0x03:
3648 res = gbReadSaveMBC1(file);
3649 break;
3650 case 0x06:
3651 res = gbReadSaveMBC2(file);
3652 break;
3653 case 0x0d:
3654 res = gbReadSaveMMM01(file);
3655 break;
3656 case 0x0f:
3657 case 0x10:
3658 if(!gbReadSaveMBC3(file)) {
3659 time(&gbDataMBC3.mapperLastTime);
3660 struct tm *lt;
3661 lt = localtime(&gbDataMBC3.mapperLastTime);
3662 gbDataMBC3.mapperSeconds = lt->tm_sec;
3663 gbDataMBC3.mapperMinutes = lt->tm_min;
3664 gbDataMBC3.mapperHours = lt->tm_hour;
3665 gbDataMBC3.mapperDays = lt->tm_yday & 255;
3666 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
3667 (lt->tm_yday > 255 ? 1: 0);
3668 res = false;
3669 break;
3670 }
3671 res = true;
3672 break;
3673 case 0x13:
3674 case 0xfc:
3675 res = gbReadSaveMBC3(file);
3676 break;
3677 case 0x1b:
3678 case 0x1e:
3679 res = gbReadSaveMBC5(file);
3680 break;
3681 case 0x22:
3682 res = gbReadSaveMBC7(file);
3683 break;
3684 case 0xfd:
3685 if(!gbReadSaveTAMA5(file)) {
3686 u8 gbDaysinMonth [12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
3687 time(&gbDataTAMA5.mapperLastTime);
3688 struct tm *lt;
3689 lt = localtime(&gbDataTAMA5.mapperLastTime);
3690 gbDataTAMA5.mapperSeconds = lt->tm_sec;
3691 gbDataTAMA5.mapperMinutes = lt->tm_min;
3692 gbDataTAMA5.mapperHours = lt->tm_hour;
3693 gbDataTAMA5.mapperDays = 1;
3694 gbDataTAMA5.mapperMonths = 1;
3695 gbDataTAMA5.mapperYears = 1970;
3696 int days = lt->tm_yday+365*3;
3697 while (days)
3698 {
3699 gbDataTAMA5.mapperDays++;
3700 days--;
3701 if (gbDataTAMA5.mapperDays>gbDaysinMonth[gbDataTAMA5.mapperMonths-1])
3702 {
3703 gbDataTAMA5.mapperDays = 1;
3704 gbDataTAMA5.mapperMonths++;
3705 if (gbDataTAMA5.mapperMonths>12)
3706 {
3707 gbDataTAMA5.mapperMonths = 1;
3708 gbDataTAMA5.mapperYears++;
3709 if ((gbDataTAMA5.mapperYears & 3) == 0)
3710 gbDaysinMonth[1] = 29;
3711 else
3712 gbDaysinMonth[1] = 28;
3713 }
3714 }
3715 }
3716 gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) |
3717 (lt->tm_yday > 255 ? 1: 0);
3718 res = false;
3719 break;
3720 }
3721 res = true;
3722 break;
3723 case 0xff:
3724 res = gbReadSaveMBC1(file);
3725 break;
3726 }
3727 }
3728 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
3729 return res;
3730 }
3731
gbReadGSASnapshot(const char * fileName)3732 bool gbReadGSASnapshot(const char *fileName)
3733 {
3734 FILE *file = fopen(fileName, "rb");
3735
3736 if(!file) {
3737 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
3738 return false;
3739 }
3740
3741 fseek(file, 0x4, SEEK_SET);
3742 char buffer[16];
3743 char buffer2[16];
3744 fread(buffer, 1, 15, file);
3745 buffer[15] = 0;
3746 memcpy(buffer2, &gbRom[0x134], 15);
3747 buffer2[15] = 0;
3748 if(memcmp(buffer, buffer2, 15)) {
3749 systemMessage(MSG_CANNOT_IMPORT_SNAPSHOT_FOR,
3750 N_("Cannot import snapshot for %s. Current game is %s"),
3751 buffer,
3752 buffer2);
3753 fclose(file);
3754 return false;
3755 }
3756 fseek(file, 0x13, SEEK_SET);
3757 size_t read = 0;
3758 int toRead = 0;
3759 switch(gbRomType) {
3760 case 0x03:
3761 case 0x0f:
3762 case 0x10:
3763 case 0x13:
3764 case 0x1b:
3765 case 0x1e:
3766 case 0xff:
3767 read = fread(gbRam, 1, (gbRamSizeMask+1), file);
3768 toRead = (gbRamSizeMask+1);
3769 break;
3770 case 0x06:
3771 case 0x22:
3772 read = fread(&gbMemory[0xa000],1,256,file);
3773 toRead = 256;
3774 break;
3775 default:
3776 systemMessage(MSG_UNSUPPORTED_SNAPSHOT_FILE,
3777 N_("Unsupported snapshot file %s"),
3778 fileName);
3779 fclose(file);
3780 return false;
3781 }
3782 fclose(file);
3783 gbReset();
3784 return true;
3785 }
3786
3787 variable_desc gbSaveGameStruct[] = {
3788 { &PC.W, sizeof(u16) },
3789 { &SP.W, sizeof(u16) },
3790 { &AF.W, sizeof(u16) },
3791 { &BC.W, sizeof(u16) },
3792 { &DE.W, sizeof(u16) },
3793 { &HL.W, sizeof(u16) },
3794 { &IFF, sizeof(u8) },
3795 { &GBLCD_MODE_0_CLOCK_TICKS, sizeof(int) },
3796 { &GBLCD_MODE_1_CLOCK_TICKS, sizeof(int) },
3797 { &GBLCD_MODE_2_CLOCK_TICKS, sizeof(int) },
3798 { &GBLCD_MODE_3_CLOCK_TICKS, sizeof(int) },
3799 { &GBDIV_CLOCK_TICKS, sizeof(int) },
3800 { &GBLY_INCREMENT_CLOCK_TICKS, sizeof(int) },
3801 { &GBTIMER_MODE_0_CLOCK_TICKS, sizeof(int) },
3802 { &GBTIMER_MODE_1_CLOCK_TICKS, sizeof(int) },
3803 { &GBTIMER_MODE_2_CLOCK_TICKS, sizeof(int) },
3804 { &GBTIMER_MODE_3_CLOCK_TICKS, sizeof(int) },
3805 { &GBSERIAL_CLOCK_TICKS, sizeof(int) },
3806 { &GBSYNCHRONIZE_CLOCK_TICKS, sizeof(int) },
3807 { &gbDivTicks, sizeof(int) },
3808 { &gbLcdMode, sizeof(int) },
3809 { &gbLcdTicks, sizeof(int) },
3810 { &gbLcdLYIncrementTicks, sizeof(int) },
3811 { &gbTimerTicks, sizeof(int) },
3812 { &gbTimerClockTicks, sizeof(int) },
3813 { &gbSerialTicks, sizeof(int) },
3814 { &gbSerialBits, sizeof(int) },
3815 { &gbInt48Signal, sizeof(int) },
3816 { &gbInterruptWait, sizeof(int) },
3817 { &gbSynchronizeTicks, sizeof(int) },
3818 { &gbTimerOn, sizeof(int) },
3819 { &gbTimerMode, sizeof(int) },
3820 { &gbSerialOn, sizeof(int) },
3821 { &gbWindowLine, sizeof(int) },
3822 { &gbCgbMode, sizeof(int) },
3823 { &gbVramBank, sizeof(int) },
3824 { &gbWramBank, sizeof(int) },
3825 { &gbHdmaSource, sizeof(int) },
3826 { &gbHdmaDestination, sizeof(int) },
3827 { &gbHdmaBytes, sizeof(int) },
3828 { &gbHdmaOn, sizeof(int) },
3829 { &gbSpeed, sizeof(int) },
3830 { &gbSgbMode, sizeof(int) },
3831 { ®ister_DIV, sizeof(u8) },
3832 { ®ister_TIMA, sizeof(u8) },
3833 { ®ister_TMA, sizeof(u8) },
3834 { ®ister_TAC, sizeof(u8) },
3835 { ®ister_IF, sizeof(u8) },
3836 { ®ister_LCDC, sizeof(u8) },
3837 { ®ister_STAT, sizeof(u8) },
3838 { ®ister_SCY, sizeof(u8) },
3839 { ®ister_SCX, sizeof(u8) },
3840 { ®ister_LY, sizeof(u8) },
3841 { ®ister_LYC, sizeof(u8) },
3842 { ®ister_DMA, sizeof(u8) },
3843 { ®ister_WY, sizeof(u8) },
3844 { ®ister_WX, sizeof(u8) },
3845 { ®ister_VBK, sizeof(u8) },
3846 { ®ister_HDMA1, sizeof(u8) },
3847 { ®ister_HDMA2, sizeof(u8) },
3848 { ®ister_HDMA3, sizeof(u8) },
3849 { ®ister_HDMA4, sizeof(u8) },
3850 { ®ister_HDMA5, sizeof(u8) },
3851 { ®ister_SVBK, sizeof(u8) },
3852 { ®ister_IE , sizeof(u8) },
3853 { &gbBgp[0], sizeof(u8) },
3854 { &gbBgp[1], sizeof(u8) },
3855 { &gbBgp[2], sizeof(u8) },
3856 { &gbBgp[3], sizeof(u8) },
3857 { &gbObp0[0], sizeof(u8) },
3858 { &gbObp0[1], sizeof(u8) },
3859 { &gbObp0[2], sizeof(u8) },
3860 { &gbObp0[3], sizeof(u8) },
3861 { &gbObp1[0], sizeof(u8) },
3862 { &gbObp1[1], sizeof(u8) },
3863 { &gbObp1[2], sizeof(u8) },
3864 { &gbObp1[3], sizeof(u8) },
3865 { NULL, 0 }
3866 };
3867
3868
gbWriteSaveState(gzFile gzFile)3869 static bool gbWriteSaveState(gzFile gzFile)
3870 {
3871
3872 utilWriteInt(gzFile, GBSAVE_GAME_VERSION);
3873
3874 utilGzWrite(gzFile, &gbRom[0x134], 15);
3875
3876 utilWriteInt(gzFile, useBios);
3877 utilWriteInt(gzFile, inBios);
3878
3879 utilWriteData(gzFile, gbSaveGameStruct);
3880
3881 utilGzWrite(gzFile, &IFF, 2);
3882
3883 if(gbSgbMode) {
3884 gbSgbSaveGame(gzFile);
3885 }
3886
3887 utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
3888 utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
3889 utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
3890 utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
3891 utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
3892 utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
3893 utilGzWrite(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5));
3894 if (gbTAMA5ram != NULL)
3895 utilGzWrite(gzFile, gbTAMA5ram, gbTAMA5ramSize);
3896 utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
3897
3898 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
3899
3900 utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
3901
3902 if(gbRamSize && gbRam) {
3903 utilWriteInt(gzFile, gbRamSize);
3904 utilGzWrite(gzFile, gbRam, gbRamSize);
3905 }
3906
3907 if(gbCgbMode) {
3908 utilGzWrite(gzFile, gbVram, 0x4000);
3909 utilGzWrite(gzFile, gbWram, 0x8000);
3910 }
3911
3912 gbSoundSaveGame(gzFile);
3913
3914 gbCheatsSaveGame(gzFile);
3915
3916 utilWriteInt(gzFile, gbLcdModeDelayed);
3917 utilWriteInt(gzFile, gbLcdTicksDelayed);
3918 utilWriteInt(gzFile, gbLcdLYIncrementTicksDelayed);
3919 utilWriteInt(gzFile, gbSpritesTicks[299]);
3920 utilWriteInt(gzFile, gbTimerModeChange);
3921 utilWriteInt(gzFile, gbTimerOnChange);
3922 utilWriteInt(gzFile, gbHardware);
3923 utilWriteInt(gzFile, gbBlackScreen);
3924 utilWriteInt(gzFile, oldRegister_WY);
3925 utilWriteInt(gzFile, gbWindowLine);
3926 utilWriteInt(gzFile, inUseRegister_WY);
3927 utilWriteInt(gzFile, gbScreenOn);
3928 utilWriteInt(gzFile, 0x12345678); // end marker
3929 return true;
3930 }
3931
gbWriteMemSaveState(char * memory,int available,long & reserved)3932 bool gbWriteMemSaveState(char *memory, int available, long& reserved)
3933 {
3934 gzFile gzFile = utilMemGzOpen(memory, available, "w");
3935
3936 if(gzFile == NULL) {
3937 return false;
3938 }
3939
3940 bool res = gbWriteSaveState(gzFile);
3941
3942 reserved = utilGzMemTell(gzFile)+8;
3943
3944 if(reserved >= (available))
3945 res = false;
3946
3947 utilGzClose(gzFile);
3948
3949 return res;
3950 }
3951
gbWriteSaveState(const char * name)3952 bool gbWriteSaveState(const char *name)
3953 {
3954 gzFile gzFile = utilGzOpen(name,"wb");
3955
3956 if(gzFile == NULL)
3957 return false;
3958
3959 bool res = gbWriteSaveState(gzFile);
3960
3961 utilGzClose(gzFile);
3962 return res;
3963 }
3964
gbReadSaveState(gzFile gzFile)3965 static bool gbReadSaveState(gzFile gzFile)
3966 {
3967 int version = utilReadInt(gzFile);
3968
3969 if(version > GBSAVE_GAME_VERSION || version < 0) {
3970 systemMessage(MSG_UNSUPPORTED_VB_SGM,
3971 N_("Unsupported VisualBoy save game version %d"), version);
3972 return false;
3973 }
3974
3975 u8 romname[20];
3976
3977 utilGzRead(gzFile, romname, 15);
3978
3979 if(memcmp(&gbRom[0x134], romname, 15) != 0) {
3980 systemMessage(MSG_CANNOT_LOAD_SGM_FOR,
3981 N_("Cannot load save game for %s. Playing %s"),
3982 romname, &gbRom[0x134]);
3983 return false;
3984 }
3985
3986
3987 bool ub = false;
3988 bool ib = false;
3989
3990 if (version >= 11)
3991 {
3992 ub = utilReadInt(gzFile) ? true : false;
3993 ib = utilReadInt(gzFile) ? true : false;
3994
3995 if((ub != useBios) && (ib)) {
3996 if(useBios)
3997 systemMessage(MSG_SAVE_GAME_NOT_USING_BIOS,
3998 N_("Save game is not using the BIOS files"));
3999 else
4000 systemMessage(MSG_SAVE_GAME_USING_BIOS,
4001 N_("Save game is using the BIOS file"));
4002 return false;
4003 }
4004 }
4005
4006 gbReset();
4007
4008 inBios = ib;
4009
4010 utilReadData(gzFile, gbSaveGameStruct);
4011
4012
4013 // Correct crash when loading color gameboy save in regular gameboy type.
4014 if (!gbCgbMode)
4015 {
4016 if(gbVram != NULL) {
4017 free(gbVram);
4018 gbVram = NULL;
4019 }
4020 if(gbWram != NULL) {
4021 free(gbWram);
4022 gbWram = NULL;
4023 }
4024 }
4025 else
4026 {
4027 if(gbVram == NULL)
4028 gbVram = (u8 *)malloc(0x4000);
4029 if(gbWram == NULL)
4030 gbWram = (u8 *)malloc(0x8000);
4031 memset(gbVram,0,0x4000);
4032 memset(gbPalette,0, 2*128);
4033 }
4034
4035
4036
4037 if(version >= GBSAVE_GAME_VERSION_7) {
4038 utilGzRead(gzFile, &IFF, 2);
4039 }
4040
4041 if(gbSgbMode) {
4042 gbSgbReadGame(gzFile, version);
4043 } else {
4044 gbSgbMask = 0; // loading a game at the wrong time causes no display
4045 }
4046 if (version<11)
4047 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1) - sizeof(int));
4048 else
4049 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
4050 utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
4051 if(version < GBSAVE_GAME_VERSION_4)
4052 // prior to version 4, there was no adjustment for the time the game
4053 // was last played, so we have less to read. This needs update if the
4054 // structure changes again.
4055 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3)-sizeof(time_t));
4056 else
4057 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
4058 utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
4059 utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
4060 utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
4061 if(version>=11)
4062 {
4063 utilGzRead(gzFile, &gbDataTAMA5, sizeof(gbDataTAMA5));
4064 if(gbTAMA5ram != NULL) {
4065 if(skipSaveGameBattery) {
4066 utilGzSeek(gzFile, gbTAMA5ramSize, SEEK_CUR);
4067 } else {
4068 utilGzRead(gzFile, gbTAMA5ram, gbTAMA5ramSize);
4069 }
4070 }
4071 utilGzRead(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
4072 }
4073
4074 if(version < GBSAVE_GAME_VERSION_5) {
4075 utilGzRead(gzFile, pix, 256*224*sizeof(u16));
4076 }
4077 memset(pix, 0, 257*226*sizeof(u32));
4078
4079 if(version < GBSAVE_GAME_VERSION_6) {
4080 utilGzRead(gzFile, gbPalette, 64 * sizeof(u16));
4081 } else
4082 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
4083
4084 if (version < 11)
4085 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
4086
4087 if(version < GBSAVE_GAME_VERSION_10) {
4088 if(!gbCgbMode && !gbSgbMode) {
4089 for(int i = 0; i < 8; i++)
4090 gbPalette[i] = systemGbPalette[gbPaletteOption*8+i];
4091 }
4092 }
4093
4094 utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
4095
4096 if(gbRamSize && gbRam) {
4097 if(version < 11)
4098 if(skipSaveGameBattery) {
4099 utilGzSeek(gzFile, gbRamSize, SEEK_CUR); //skip
4100 } else {
4101 utilGzRead(gzFile, gbRam, gbRamSize); //read
4102 }
4103 else
4104 {
4105 int ramSize = utilReadInt(gzFile);
4106 if(skipSaveGameBattery) {
4107 utilGzSeek(gzFile, (gbRamSize>ramSize) ? ramSize : gbRamSize, SEEK_CUR); //skip
4108 } else {
4109 utilGzRead(gzFile, gbRam, (gbRamSize>ramSize) ? ramSize : gbRamSize); //read
4110 }
4111 if(ramSize>gbRamSize)
4112 utilGzSeek(gzFile,ramSize-gbRamSize,SEEK_CUR);
4113 }
4114 }
4115
4116 memset(gbSCYLine, register_SCY, sizeof(gbSCYLine));
4117 memset(gbSCXLine, register_SCX, sizeof(gbSCXLine));
4118 memset(gbBgpLine, (gbBgp[0] | (gbBgp[1]<<2) | (gbBgp[2]<<4) |
4119 (gbBgp[3]<<6)), sizeof(gbBgpLine));
4120 memset(gbObp0Line, (gbObp0[0] | (gbObp0[1]<<2) | (gbObp0[2]<<4) |
4121 (gbObp0[3]<<6)), sizeof(gbObp0Line));
4122 memset(gbObp1Line, (gbObp1[0] | (gbObp1[1]<<2) | (gbObp1[2]<<4) |
4123 (gbObp1[3]<<6)), sizeof(gbObp1Line));
4124 memset(gbSpritesTicks, 0x0, sizeof(gbSpritesTicks));
4125
4126 if (inBios)
4127 {
4128 gbMemoryMap[0x00] = &gbMemory[0x0000];
4129 if (gbHardware & 5) {
4130 memcpy ((u8 *)(gbMemory), (u8 *)(gbRom), 0x1000);
4131 memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x100);
4132 } else if (gbHardware & 2) {
4133 memcpy ((u8 *)(gbMemory), (u8 *)(bios), 0x900);
4134 memcpy ((u8 *)(gbMemory + 0x100), (u8 *)(gbRom + 0x100), 0x100);
4135 }
4136
4137 }
4138 else
4139 gbMemoryMap[0x00] = &gbRom[0x0000];
4140 gbMemoryMap[0x01] = &gbRom[0x1000];
4141 gbMemoryMap[0x02] = &gbRom[0x2000];
4142 gbMemoryMap[0x03] = &gbRom[0x3000];
4143 gbMemoryMap[0x04] = &gbRom[0x4000];
4144 gbMemoryMap[0x05] = &gbRom[0x5000];
4145 gbMemoryMap[0x06] = &gbRom[0x6000];
4146 gbMemoryMap[0x07] = &gbRom[0x7000];
4147 gbMemoryMap[0x08] = &gbMemory[0x8000];
4148 gbMemoryMap[0x09] = &gbMemory[0x9000];
4149 gbMemoryMap[0x0a] = &gbMemory[0xa000];
4150 gbMemoryMap[0x0b] = &gbMemory[0xb000];
4151 gbMemoryMap[0x0c] = &gbMemory[0xc000];
4152 gbMemoryMap[0x0d] = &gbMemory[0xd000];
4153 gbMemoryMap[0x0e] = &gbMemory[0xe000];
4154 gbMemoryMap[0x0f] = &gbMemory[0xf000];
4155
4156 switch(gbRomType) {
4157 case 0x00:
4158 case 0x01:
4159 case 0x02:
4160 case 0x03:
4161 // MBC 1
4162 memoryUpdateMapMBC1();
4163 break;
4164 case 0x05:
4165 case 0x06:
4166 // MBC2
4167 memoryUpdateMapMBC2();
4168 break;
4169 case 0x0b:
4170 case 0x0c:
4171 case 0x0d:
4172 // MMM01
4173 memoryUpdateMapMMM01();
4174 break;
4175 case 0x0f:
4176 case 0x10:
4177 case 0x11:
4178 case 0x12:
4179 case 0x13:
4180 // MBC 3
4181 memoryUpdateMapMBC3();
4182 break;
4183 case 0x19:
4184 case 0x1a:
4185 case 0x1b:
4186 // MBC5
4187 memoryUpdateMapMBC5();
4188 break;
4189 case 0x1c:
4190 case 0x1d:
4191 case 0x1e:
4192 // MBC 5 Rumble
4193 memoryUpdateMapMBC5();
4194 break;
4195 case 0x22:
4196 // MBC 7
4197 memoryUpdateMapMBC7();
4198 break;
4199 case 0x56:
4200 // GS3
4201 memoryUpdateMapGS3();
4202 break;
4203 case 0xfd:
4204 // TAMA5
4205 memoryUpdateMapTAMA5();
4206 break;
4207 case 0xfe:
4208 // HuC3
4209 memoryUpdateMapHuC3();
4210 break;
4211 case 0xff:
4212 // HuC1
4213 memoryUpdateMapHuC1();
4214 break;
4215 }
4216
4217 if(gbCgbMode) {
4218 utilGzRead(gzFile, gbVram, 0x4000);
4219 utilGzRead(gzFile, gbWram, 0x8000);
4220
4221 int value = register_SVBK;
4222 if(value == 0)
4223 value = 1;
4224
4225 gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000];
4226 gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000];
4227 gbMemoryMap[0x0d] = &gbWram[value * 0x1000];
4228 }
4229
4230 gbSoundReadGame(version, gzFile);
4231
4232 if (gbCgbMode && gbSgbMode) {
4233 gbSgbMode = 0;
4234 }
4235
4236 if(gbBorderOn && !gbSgbMask) {
4237 gbSgbRenderBorder();
4238 }
4239
4240 systemDrawScreen();
4241
4242 if(version > GBSAVE_GAME_VERSION_1)
4243 {
4244 if( skipSaveGameCheats ) {
4245 gbCheatsReadGameSkip(gzFile, version);
4246 } else {
4247 gbCheatsReadGame(gzFile, version);
4248 }
4249 }
4250
4251 if (version<11)
4252 {
4253 gbWriteMemory(0xff00, 0);
4254 gbMemory[0xff04] = register_DIV;
4255 gbMemory[0xff05] = register_TIMA;
4256 gbMemory[0xff06] = register_TMA;
4257 gbMemory[0xff07] = register_TAC;
4258 gbMemory[0xff40] = register_LCDC;
4259 gbMemory[0xff42] = register_SCY;
4260 gbMemory[0xff43] = register_SCX;
4261 gbMemory[0xff44] = register_LY;
4262 gbMemory[0xff45] = register_LYC;
4263 gbMemory[0xff46] = register_DMA;
4264 gbMemory[0xff4a] = register_WY;
4265 gbMemory[0xff4b] = register_WX;
4266 gbMemory[0xff4f] = register_VBK;
4267 gbMemory[0xff51] = register_HDMA1;
4268 gbMemory[0xff52] = register_HDMA2;
4269 gbMemory[0xff53] = register_HDMA3;
4270 gbMemory[0xff54] = register_HDMA4;
4271 gbMemory[0xff55] = register_HDMA5;
4272 gbMemory[0xff70] = register_SVBK;
4273 gbMemory[0xffff] = register_IE;
4274 GBDIV_CLOCK_TICKS = 64;
4275
4276 if (gbSpeed)
4277 gbDivTicks /=2;
4278
4279 if ((gbLcdMode == 0) && (register_STAT & 8))
4280 gbInt48Signal |= 1;
4281 if ((gbLcdMode == 1) && (register_STAT & 0x10))
4282 gbInt48Signal |= 2;
4283 if ((gbLcdMode == 2) && (register_STAT & 0x20))
4284 gbInt48Signal |= 4;
4285 if ((register_LY==register_LYC) && (register_STAT & 0x40))
4286 gbInt48Signal |= 8;
4287
4288 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS;
4289
4290 if (gbLcdMode == 2)
4291 gbLcdLYIncrementTicks-=GBLCD_MODE_2_CLOCK_TICKS-gbLcdTicks;
4292 else if (gbLcdMode == 3)
4293 gbLcdLYIncrementTicks -=GBLCD_MODE_2_CLOCK_TICKS+GBLCD_MODE_3_CLOCK_TICKS-gbLcdTicks;
4294 else if (gbLcdMode == 0)
4295 gbLcdLYIncrementTicks =gbLcdTicks;
4296 else if (gbLcdMode == 1)
4297 {
4298 gbLcdLYIncrementTicks = gbLcdTicks % GBLY_INCREMENT_CLOCK_TICKS;
4299 if (register_LY == 0x99)
4300 gbLcdLYIncrementTicks =gbLine99Ticks;
4301 else if (register_LY == 0)
4302 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
4303 }
4304
4305 gbLcdModeDelayed = gbLcdMode;
4306 gbLcdTicksDelayed = gbLcdTicks--;
4307 gbLcdLYIncrementTicksDelayed = gbLcdLYIncrementTicks--;
4308 gbInterruptWait = 0;
4309 memset(gbSpritesTicks,0,sizeof(gbSpritesTicks));
4310 }
4311 else
4312 {
4313 gbLcdModeDelayed = utilReadInt(gzFile);
4314 gbLcdTicksDelayed = utilReadInt(gzFile);
4315 gbLcdLYIncrementTicksDelayed = utilReadInt(gzFile);
4316 gbSpritesTicks[299] = utilReadInt(gzFile) & 0xff;
4317 gbTimerModeChange = (utilReadInt(gzFile) ? true : false);
4318 gbTimerOnChange = (utilReadInt(gzFile) ? true : false);
4319 gbHardware = utilReadInt(gzFile);
4320 gbBlackScreen = (utilReadInt(gzFile) ? true : false);
4321 oldRegister_WY = utilReadInt(gzFile);
4322 gbWindowLine = utilReadInt(gzFile);
4323 inUseRegister_WY = utilReadInt(gzFile);
4324 gbScreenOn = (utilReadInt(gzFile) ? true : false);
4325 }
4326
4327 if (gbSpeed)
4328 gbLine99Ticks *= 2;
4329
4330 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
4331
4332 if ( version >= 12 && utilReadInt( gzFile ) != 0x12345678 )
4333 assert( false ); // fails if something read too much/little from file
4334
4335 return true;
4336 }
4337
gbReadMemSaveState(char * memory,int available)4338 bool gbReadMemSaveState(char *memory, int available)
4339 {
4340 gzFile gzFile = utilMemGzOpen(memory, available, "r");
4341
4342 bool res = gbReadSaveState(gzFile);
4343
4344 utilGzClose(gzFile);
4345
4346 return res;
4347 }
4348
gbReadSaveState(const char * name)4349 bool gbReadSaveState(const char *name)
4350 {
4351 gzFile gzFile = utilGzOpen(name,"rb");
4352
4353 if(gzFile == NULL) {
4354 return false;
4355 }
4356
4357 bool res = gbReadSaveState(gzFile);
4358
4359 utilGzClose(gzFile);
4360
4361 return res;
4362 }
4363
gbWritePNGFile(const char * fileName)4364 bool gbWritePNGFile(const char *fileName)
4365 {
4366 if(gbBorderOn)
4367 return utilWritePNGFile(fileName, 256, 224, pix);
4368 return utilWritePNGFile(fileName, 160, 144, pix);
4369 }
4370
gbWriteBMPFile(const char * fileName)4371 bool gbWriteBMPFile(const char *fileName)
4372 {
4373 if(gbBorderOn)
4374 return utilWriteBMPFile(fileName, 256, 224, pix);
4375 return utilWriteBMPFile(fileName, 160, 144, pix);
4376 }
4377
gbCleanUp()4378 void gbCleanUp()
4379 {
4380 if(gbRam != NULL) {
4381 free(gbRam);
4382 gbRam = NULL;
4383 }
4384
4385 if(gbRom != NULL) {
4386 free(gbRom);
4387 gbRom = NULL;
4388 }
4389
4390 if(bios != NULL) {
4391 free(bios);
4392 bios = NULL;
4393 }
4394
4395 if(gbMemory != NULL) {
4396 free(gbMemory);
4397 gbMemory = NULL;
4398 }
4399
4400 if(gbLineBuffer != NULL) {
4401 free(gbLineBuffer);
4402 gbLineBuffer = NULL;
4403 }
4404
4405 if(pix != NULL) {
4406 free(pix);
4407 pix = NULL;
4408 }
4409
4410 gbSgbShutdown();
4411
4412 if(gbVram != NULL) {
4413 free(gbVram);
4414 gbVram = NULL;
4415 }
4416
4417 if(gbWram != NULL) {
4418 free(gbWram);
4419 gbWram = NULL;
4420 }
4421
4422 if(gbTAMA5ram != NULL) {
4423 free(gbTAMA5ram);
4424 gbTAMA5ram = NULL;
4425 }
4426
4427 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
4428 }
4429
gbLoadRom(const char * szFile)4430 bool gbLoadRom(const char *szFile)
4431 {
4432 int size = 0;
4433
4434 if(gbRom != NULL) {
4435 gbCleanUp();
4436 }
4437
4438 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
4439
4440 gbRom = utilLoad(szFile,
4441 utilIsGBImage,
4442 NULL,
4443 size);
4444 if(!gbRom)
4445 return false;
4446
4447 gbRomSize = size;
4448
4449 gbBatteryError = false;
4450
4451 if(bios != NULL) {
4452 free(bios);
4453 bios = NULL;
4454 }
4455 bios = (u8 *)calloc(1,0x900);
4456
4457 return gbUpdateSizes();
4458 }
4459
gbUpdateSizes()4460 bool gbUpdateSizes()
4461 {
4462 if(gbRom[0x148] > 8) {
4463 systemMessage(MSG_UNSUPPORTED_ROM_SIZE,
4464 N_("Unsupported rom size %02x"), gbRom[0x148]);
4465 return false;
4466 }
4467
4468 if(gbRomSize < gbRomSizes[gbRom[0x148]]) {
4469 u8 *gbRomNew = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
4470 if( !gbRomNew ) { assert( false ); return false; };
4471 gbRom = gbRomNew;
4472 for (int i = gbRomSize; i<gbRomSizes[gbRom[0x148]]; i++)
4473 gbRom[i] = 0x00; // Not sure if it's 0x00, 0xff or random data...
4474 }
4475 // (it's in the case a cart is 'lying' on its size.
4476 else if ((gbRomSize>gbRomSizes[gbRom[0x148]]) && (genericflashcardEnable))
4477 {
4478 gbRomSize = gbRomSize>>16;
4479 gbRom[0x148] = 0;
4480 if (gbRomSize)
4481 {
4482 while (!((gbRomSize & 1) || (gbRom[0x148] == 7)))
4483 {
4484 gbRom[0x148]++;
4485 gbRomSize>>=1;
4486 }
4487 gbRom[0x148]++;
4488 }
4489 u8 *gbRomNew = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
4490 if( !gbRomNew ) { assert( false ); return false; };
4491 gbRom = gbRomNew;
4492 }
4493 gbRomSize = gbRomSizes[gbRom[0x148]];
4494 gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]];
4495
4496
4497 // The 'genericflashcard' option allows some PD to work.
4498 // However, the setting is dangerous (if you let in enabled
4499 // and play a normal game, it might just break everything).
4500 // That's why it is not saved in the emulator options.
4501 // Also I added some checks in VBA to make sure your saves will not be
4502 // overwritten if you wrongly enable this option for a game
4503 // you already played (and vice-versa, ie. if you forgot to
4504 // enable the option for a game you played with it enabled, like Shawu Story).
4505 u8 ramsize = genericflashcardEnable ? 5 : gbRom[0x149];
4506 gbRom[0x149] = ramsize;
4507
4508 if ((gbRom[2] == 0x6D) && (gbRom[5] == 0x47) && (gbRom[6] == 0x65) && (gbRom[7] == 0x6E) &&
4509 (gbRom[8] == 0x69) && (gbRom[9] == 0x65) && (gbRom[0xA] == 0x28) && (gbRom[0xB] == 0x54))
4510 {
4511 gbCheatingDevice = 1; // GameGenie
4512 for (int i = 0; i < 0x20; i++) // Cleans GG hardware registers
4513 gbRom[0x4000+i] = 0;
4514 }
4515 else if (((gbRom[0x104] == 0x44) && (gbRom[0x156] == 0xEA) && (gbRom[0x158] == 0x7F) &&
4516 (gbRom[0x159] == 0xEA) && (gbRom[0x15B] == 0x7F)) || ((gbRom[0x165] == 0x3E) &&
4517 (gbRom[0x166] == 0xD9) && (gbRom[0x16D] == 0xE1) && (gbRom[0x16E] == 0x7F)))
4518 gbCheatingDevice = 2; // GameShark
4519 else gbCheatingDevice = 0;
4520
4521 if(ramsize > 5) {
4522 systemMessage(MSG_UNSUPPORTED_RAM_SIZE,
4523 N_("Unsupported ram size %02x"), gbRom[0x149]);
4524 return false;
4525 }
4526
4527 gbRamSize = gbRamSizes[ramsize];
4528 gbRamSizeMask = gbRamSizesMasks[ramsize];
4529
4530 gbRomType = gbRom[0x147];
4531 if (genericflashcardEnable)
4532 {
4533 /*if (gbRomType<2)
4534 gbRomType =3;
4535 else if ((gbRomType == 0xc) || (gbRomType == 0xf) || (gbRomType == 0x12) ||
4536 (gbRomType == 0x16) || (gbRomType == 0x1a) || (gbRomType == 0x1d))
4537 gbRomType++;
4538 else if ((gbRomType == 0xb) || (gbRomType == 0x11) || (gbRomType == 0x15) ||
4539 (gbRomType == 0x19) || (gbRomType == 0x1c))
4540 gbRomType+=2;
4541 else if ((gbRomType == 0x5) || (gbRomType == 0x6))
4542 gbRomType = 0x1a;*/
4543 gbRomType = 0x1b;
4544 }
4545 else if (gbCheatingDevice == 1)
4546 gbRomType = 0x55;
4547 else if (gbCheatingDevice == 2)
4548 gbRomType = 0x56;
4549
4550 gbRom[0x147] = gbRomType;
4551
4552 mapperReadRAM = NULL;
4553
4554 switch(gbRomType) {
4555 case 0x00:
4556 case 0x01:
4557 case 0x02:
4558 case 0x03:
4559 case 0x08:
4560 case 0x09:
4561 // MBC 1
4562 mapper = mapperMBC1ROM;
4563 mapperRAM = mapperMBC1RAM;
4564 mapperReadRAM = mapperMBC1ReadRAM;
4565 break;
4566 case 0x05:
4567 case 0x06:
4568 // MBC2
4569 mapper = mapperMBC2ROM;
4570 mapperRAM = mapperMBC2RAM;
4571 gbRamSize = 0x200;
4572 gbRamSizeMask = 0x1ff;
4573 break;
4574 case 0x0b:
4575 case 0x0c:
4576 case 0x0d:
4577 // MMM01
4578 mapper = mapperMMM01ROM;
4579 mapperRAM = mapperMMM01RAM;
4580 break;
4581 case 0x0f:
4582 case 0x10:
4583 case 0x11:
4584 case 0x12:
4585 case 0x13:
4586 case 0xfc:
4587 // MBC 3
4588 mapper = mapperMBC3ROM;
4589 mapperRAM = mapperMBC3RAM;
4590 mapperReadRAM = mapperMBC3ReadRAM;
4591 break;
4592 case 0x19:
4593 case 0x1a:
4594 case 0x1b:
4595 // MBC5
4596 mapper = mapperMBC5ROM;
4597 mapperRAM = mapperMBC5RAM;
4598 mapperReadRAM = mapperMBC5ReadRAM;
4599 break;
4600 case 0x1c:
4601 case 0x1d:
4602 case 0x1e:
4603 // MBC 5 Rumble
4604 mapper = mapperMBC5ROM;
4605 mapperRAM = mapperMBC5RAM;
4606 mapperReadRAM = mapperMBC5ReadRAM;
4607 break;
4608 case 0x22:
4609 // MBC 7
4610 mapper = mapperMBC7ROM;
4611 mapperRAM = mapperMBC7RAM;
4612 mapperReadRAM = mapperMBC7ReadRAM;
4613 gbRamSize = 0x200;
4614 gbRamSizeMask = 0x1ff;
4615 break;
4616 // GG (GameGenie)
4617 case 0x55:
4618 mapper = mapperGGROM;
4619 break;
4620 case 0x56:
4621 // GS (GameShark)
4622 mapper = mapperGS3ROM;
4623 break;
4624 case 0xfd:
4625 // TAMA5
4626 if (gbRam!= NULL)
4627 {
4628 free(gbRam);
4629 gbRam = NULL;
4630 }
4631
4632 ramsize = 3;
4633 gbRamSize = gbRamSizes[3];
4634 gbRamSizeMask = gbRamSizesMasks[3];
4635 gbRamFill = 0x0;
4636
4637 gbTAMA5ramSize = 0x100;
4638
4639 if (gbTAMA5ram == NULL)
4640 gbTAMA5ram = (u8 *)malloc(gbTAMA5ramSize);
4641 memset(gbTAMA5ram, 0x0, gbTAMA5ramSize);
4642
4643 mapperRAM = mapperTAMA5RAM;
4644 mapperReadRAM = mapperTAMA5ReadRAM;
4645 mapperUpdateClock = memoryUpdateTAMA5Clock;
4646 break;
4647 case 0xfe:
4648 // HuC3
4649 mapper = mapperHuC3ROM;
4650 mapperRAM = mapperHuC3RAM;
4651 mapperReadRAM = mapperHuC3ReadRAM;
4652 break;
4653 case 0xff:
4654 // HuC1
4655 mapper = mapperHuC1ROM;
4656 mapperRAM = mapperHuC1RAM;
4657 break;
4658 default:
4659 systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE,
4660 N_("Unknown cartridge type %02x"), gbRomType);
4661 return false;
4662 }
4663
4664 if(gbRamSize) {
4665 gbRam = (u8 *)malloc(gbRamSize);
4666 memset(gbRam, gbRamFill, gbRamSize);
4667 }
4668
4669 switch(gbRomType) {
4670 case 0x03:
4671 case 0x06:
4672 case 0x0f:
4673 case 0x10:
4674 case 0x13:
4675 case 0x1b:
4676 case 0x1d:
4677 case 0x1e:
4678 case 0x22:
4679 case 0xfd:
4680 case 0xff:
4681 gbBattery = 1;
4682 break;
4683 }
4684
4685 gbInit();
4686
4687 //gbReset();
4688
4689 switch(gbRomType) {
4690 case 0x1c:
4691 case 0x1d:
4692 case 0x1e:
4693 gbDataMBC5.isRumbleCartridge = 1;
4694 }
4695
4696 return true;
4697 }
4698
gbGetNextEvent(int _clockTicks)4699 int gbGetNextEvent (int _clockTicks)
4700 {
4701 if (register_LCDC & 0x80)
4702 {
4703 if(gbLcdTicks < _clockTicks)
4704 _clockTicks = gbLcdTicks;
4705
4706 if(gbLcdTicksDelayed < _clockTicks)
4707 _clockTicks = gbLcdTicksDelayed;
4708
4709 if(gbLcdLYIncrementTicksDelayed < _clockTicks)
4710 _clockTicks = gbLcdLYIncrementTicksDelayed;
4711 }
4712
4713 if(gbLcdLYIncrementTicks < _clockTicks)
4714 _clockTicks = gbLcdLYIncrementTicks;
4715
4716 if(gbSerialOn && (gbSerialTicks < _clockTicks))
4717 _clockTicks = gbSerialTicks;
4718
4719 if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < _clockTicks))
4720 _clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1;
4721
4722 //if(soundTicks && (soundTicks < _clockTicks))
4723 // _clockTicks = soundTicks;
4724
4725 if ((_clockTicks<=0) || (gbInterruptWait))
4726 _clockTicks = 1;
4727
4728 return _clockTicks;
4729 }
4730
gbDrawLine()4731 void gbDrawLine()
4732 {
4733 switch(systemColorDepth) {
4734 case 16:
4735 {
4736 u16 * dest = (u16 *)pix +
4737 (gbBorderLineSkip+2) * (register_LY + gbBorderRowSkip+1)
4738 + gbBorderColumnSkip;
4739 for(int x = 0; x < 160; ) {
4740 *dest++ = systemColorMap16[gbLineMix[x++]];
4741 *dest++ = systemColorMap16[gbLineMix[x++]];
4742 *dest++ = systemColorMap16[gbLineMix[x++]];
4743 *dest++ = systemColorMap16[gbLineMix[x++]];
4744
4745 *dest++ = systemColorMap16[gbLineMix[x++]];
4746 *dest++ = systemColorMap16[gbLineMix[x++]];
4747 *dest++ = systemColorMap16[gbLineMix[x++]];
4748 *dest++ = systemColorMap16[gbLineMix[x++]];
4749
4750 *dest++ = systemColorMap16[gbLineMix[x++]];
4751 *dest++ = systemColorMap16[gbLineMix[x++]];
4752 *dest++ = systemColorMap16[gbLineMix[x++]];
4753 *dest++ = systemColorMap16[gbLineMix[x++]];
4754
4755 *dest++ = systemColorMap16[gbLineMix[x++]];
4756 *dest++ = systemColorMap16[gbLineMix[x++]];
4757 *dest++ = systemColorMap16[gbLineMix[x++]];
4758 *dest++ = systemColorMap16[gbLineMix[x++]];
4759 }
4760 if(gbBorderOn)
4761 dest += gbBorderColumnSkip;
4762 *dest++ = 0; // for filters that read one pixel more
4763 }
4764 break;
4765
4766 case 24:
4767 {
4768 u8 *dest = (u8 *)pix +
4769 3*(gbBorderLineSkip * (register_LY + gbBorderRowSkip) +
4770 gbBorderColumnSkip);
4771 for(int x = 0; x < 160;) {
4772 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4773 dest+= 3;
4774 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4775 dest+= 3;
4776 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4777 dest+= 3;
4778 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4779 dest+= 3;
4780
4781 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4782 dest+= 3;
4783 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4784 dest+= 3;
4785 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4786 dest+= 3;
4787 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4788 dest+= 3;
4789
4790 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4791 dest+= 3;
4792 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4793 dest+= 3;
4794 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4795 dest+= 3;
4796 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4797 dest+= 3;
4798
4799 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4800 dest+= 3;
4801 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4802 dest+= 3;
4803 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4804 dest+= 3;
4805 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
4806 dest+= 3;
4807 }
4808 }
4809 break;
4810
4811 case 32:
4812 {
4813 u32 * dest = (u32 *)pix +
4814 (gbBorderLineSkip+1) * (register_LY + gbBorderRowSkip+1)
4815 + gbBorderColumnSkip;
4816 for(int x = 0; x < 160;) {
4817 *dest++ = systemColorMap32[gbLineMix[x++]];
4818 *dest++ = systemColorMap32[gbLineMix[x++]];
4819 *dest++ = systemColorMap32[gbLineMix[x++]];
4820 *dest++ = systemColorMap32[gbLineMix[x++]];
4821
4822 *dest++ = systemColorMap32[gbLineMix[x++]];
4823 *dest++ = systemColorMap32[gbLineMix[x++]];
4824 *dest++ = systemColorMap32[gbLineMix[x++]];
4825 *dest++ = systemColorMap32[gbLineMix[x++]];
4826
4827 *dest++ = systemColorMap32[gbLineMix[x++]];
4828 *dest++ = systemColorMap32[gbLineMix[x++]];
4829 *dest++ = systemColorMap32[gbLineMix[x++]];
4830 *dest++ = systemColorMap32[gbLineMix[x++]];
4831
4832 *dest++ = systemColorMap32[gbLineMix[x++]];
4833 *dest++ = systemColorMap32[gbLineMix[x++]];
4834 *dest++ = systemColorMap32[gbLineMix[x++]];
4835 *dest++ = systemColorMap32[gbLineMix[x++]];
4836 }
4837 }
4838 break;
4839 }
4840 }
4841
gbEmulate(int ticksToStop)4842 void gbEmulate(int ticksToStop)
4843 {
4844 gbRegister tempRegister;
4845 u8 tempValue;
4846 s8 offset;
4847
4848 clockTicks = 0;
4849 gbDmaTicks = 0;
4850
4851 register int opcode = 0;
4852
4853 int opcode1 = 0;
4854 int opcode2 = 0;
4855 bool execute = false;
4856
4857 while(1) {
4858 u16 oldPCW = PC.W;
4859
4860 if(IFF & 0x80) {
4861 if(register_LCDC & 0x80) {
4862 clockTicks = gbLcdTicks;
4863 } else
4864 clockTicks = 1000;
4865
4866 clockTicks = gbGetNextEvent(clockTicks);
4867
4868 /*if(gbLcdTicksDelayed < clockTicks)
4869 clockTicks = gbLcdTicksDelayed;
4870
4871 if(gbLcdLYIncrementTicksDelayed < clockTicks)
4872 clockTicks = gbLcdLYIncrementTicksDelayed;
4873
4874 if(gbLcdLYIncrementTicks < clockTicks)
4875 clockTicks = gbLcdLYIncrementTicks;
4876
4877 if(gbSerialOn && (gbSerialTicks < clockTicks))
4878 clockTicks = gbSerialTicks;
4879
4880 if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks))
4881 clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1;
4882
4883 if(soundTicks && (soundTicks < clockTicks))
4884 clockTicks = soundTicks;
4885
4886 if ((clockTicks<=0) || (gbInterruptWait))
4887 clockTicks = 1;*/
4888
4889 } else {
4890
4891 // First we apply the clockTicks, then we execute the opcodes.
4892 opcode1 = 0;
4893 opcode2 = 0;
4894 execute = true;
4895
4896 opcode2 = opcode1 = opcode = gbReadOpcode(PC.W++);
4897
4898 // If HALT state was launched while IME = 0 and (register_IF & register_IE & 0x1F),
4899 // PC.W is not incremented for the first byte of the next instruction.
4900 if (IFF & 2)
4901 {
4902 PC.W--;
4903 IFF &= ~2;
4904 }
4905
4906 clockTicks = gbCycles[opcode];
4907
4908 switch(opcode) {
4909 case 0xCB:
4910 // extended opcode
4911 opcode2 = opcode = gbReadOpcode(PC.W++);
4912 clockTicks = gbCyclesCB[opcode];
4913 break;
4914 }
4915 gbOldClockTicks = clockTicks-1;
4916 gbIntBreak = 1;
4917 }
4918
4919
4920 if(!emulating)
4921 return;
4922
4923 // For 'breakpoint' support (opcode 0xFC is considered as a breakpoint)
4924 if ((clockTicks==0) && execute)
4925 {
4926 PC.W = oldPCW;
4927 return;
4928 }
4929
4930
4931 if (!(IFF & 0x80))
4932 clockTicks = 1;
4933
4934 gbRedoLoop:
4935
4936
4937
4938 if (gbInterruptWait)
4939 gbInterruptWait = 0;
4940 else
4941 gbInterruptLaunched = 0;
4942
4943
4944 // Used for the EI/DI instruction's delay.
4945 if (IFF & 0x38)
4946 {
4947 int tempIFF = (IFF >> 4) & 3;
4948
4949 if (tempIFF <=clockTicks)
4950 {
4951 tempIFF = 0;
4952 IFF |=1;
4953 }
4954 else
4955 tempIFF -= clockTicks;
4956 IFF = (IFF & 0xCF) | (tempIFF <<4);
4957
4958 if (IFF & 0x08)
4959 IFF &= 0x82;
4960 }
4961
4962
4963 if (register_LCDCBusy)
4964 {
4965 register_LCDCBusy-=clockTicks;
4966 if (register_LCDCBusy<0)
4967 register_LCDCBusy = 0;
4968 }
4969
4970
4971 if(gbSgbMode) {
4972 if(gbSgbPacketTimeout) {
4973 gbSgbPacketTimeout -= clockTicks;
4974
4975 if(gbSgbPacketTimeout <= 0)
4976 gbSgbResetPacketState();
4977 }
4978 }
4979
4980 ticksToStop -= clockTicks;
4981
4982 // DIV register emulation
4983 gbDivTicks -= clockTicks;
4984 while(gbDivTicks <= 0) {
4985 gbMemory[0xff04] = ++register_DIV;
4986 gbDivTicks += GBDIV_CLOCK_TICKS;
4987 }
4988
4989 if(register_LCDC & 0x80) {
4990 // LCD stuff
4991
4992 gbLcdTicks -= clockTicks;
4993 gbLcdTicksDelayed -= clockTicks;
4994 gbLcdLYIncrementTicks -= clockTicks;
4995 gbLcdLYIncrementTicksDelayed -= clockTicks;
4996
4997
4998 // our counters are off, see what we need to do
4999
5000 // This looks (and kinda is) complicated, however this
5001 // is the only way I found to emulate properly the way
5002 // the real hardware operates...
5003 while(((gbLcdTicks <= 0) && (gbLCDChangeHappened == false)) ||
5004 ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened == true)) ||
5005 ((gbLcdLYIncrementTicks <= 0) && (gbLYChangeHappened == false)) ||
5006 ((gbLcdLYIncrementTicksDelayed<=0) && (gbLYChangeHappened == true)))
5007 {
5008
5009 if ((gbLcdLYIncrementTicks <= 0) && (!gbLYChangeHappened))
5010 {
5011 gbLYChangeHappened = true;
5012 gbMemory[0xff44] = register_LY = (register_LY + 1) % 154;
5013
5014 if (register_LY == 0x91)
5015 {
5016 /* if (IFF & 0x80)
5017 gbScreenOn = !gbScreenOn;
5018 else*/ if (register_LCDC & 0x80)
5019 gbScreenOn = true;
5020 }
5021
5022 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
5023
5024 if (gbLcdMode == 1)
5025 {
5026
5027 if(register_LY == 153)
5028 gbLcdLYIncrementTicks -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
5029 else if(register_LY == 0)
5030 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
5031 }
5032
5033 // GB only 'bug' : Halt state is broken one tick before LY==LYC interrupt
5034 // is reflected in the registers.
5035 if ((gbHardware & 5) && (IFF & 0x80) && (register_LY == register_LYC)
5036 && (register_STAT & 0x40) && (register_LY != 0))
5037 {
5038 if (!((gbLcdModeDelayed != 1) && (register_LY==0)))
5039 {
5040 gbInt48Signal &= ~9;
5041 gbCompareLYToLYC();
5042 gbLYChangeHappened = false;
5043 gbMemory[0xff41] = register_STAT;
5044 gbMemory[0xff0f] = register_IF;
5045 }
5046
5047 gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks+1;
5048 }
5049 }
5050
5051
5052 if ((gbLcdTicks <= 0) && (!gbLCDChangeHappened))
5053 {
5054 gbLCDChangeHappened = true;
5055
5056 switch(gbLcdMode)
5057 {
5058 case 0:
5059 {
5060 // H-Blank
5061 // check if we reached the V-Blank period
5062 if(register_LY == 144) {
5063 // Yes, V-Blank
5064 // set the LY increment counter
5065 if (gbHardware & 0x5)
5066 {
5067 register_IF |= 1; // V-Blank interrupt
5068 }
5069
5070 gbInt48Signal &= ~6;
5071 if(register_STAT & 0x10)
5072 {
5073 // send LCD interrupt only if no interrupt 48h signal...
5074 if ((!(gbInt48Signal & 1)) && ((!(gbInt48Signal & 8)) || (gbHardware & 0x0a)))
5075 {
5076 register_IF |=2;
5077 gbInterruptLaunched |= 2;
5078 if (gbHardware & 0xa)
5079 gbInterruptWait = 1;
5080 }
5081 gbInt48Signal |= 2;
5082 }
5083 gbInt48Signal &= ~1;
5084
5085 gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS;
5086 gbLcdMode = 1;
5087
5088 } else {
5089 // go the the OAM being accessed mode
5090 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
5091 gbLcdMode = 2;
5092
5093 gbInt48Signal &= ~6;
5094 if(register_STAT & 0x20)
5095 {
5096 // send LCD interrupt only if no interrupt 48h signal...
5097 if (!gbInt48Signal)
5098 {
5099 register_IF |= 2;
5100 gbInterruptLaunched |= 2;
5101 }
5102 gbInt48Signal |= 4;
5103 }
5104 gbInt48Signal &= ~1;
5105 }
5106 }
5107 break;
5108 case 1:
5109 {
5110 // V-Blank
5111 // next mode is OAM being accessed mode
5112 gbInt48Signal &= ~5;
5113 if(register_STAT & 0x20)
5114 {
5115 // send LCD interrupt only if no interrupt 48h signal...
5116 if (!gbInt48Signal)
5117 {
5118 register_IF |= 2;
5119 gbInterruptLaunched |= 2;
5120 if ((gbHardware & 0xa) && (IFF & 0x80))
5121 gbInterruptWait = 1;
5122 }
5123 gbInt48Signal |= 4;
5124 }
5125 gbInt48Signal &= ~2;
5126
5127 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
5128
5129 gbLcdMode = 2;
5130 register_LY = 0x00;
5131
5132 }
5133 break;
5134 case 2:
5135 {
5136
5137 // OAM being accessed mode
5138 // next mode is OAM and VRAM in use
5139 if ((gbScreenOn) && (register_LCDC & 0x80))
5140 {
5141 gbDrawSprites(false);
5142 // Used to add a one tick delay when a window line is drawn.
5143 //(fixes a part of Carmaggedon problem)
5144 if((register_LCDC & 0x01 || gbCgbMode) && (register_LCDC & 0x20) &&
5145 (gbWindowLine != -2)) {
5146
5147 int inUseRegister_WY = 0;
5148 int tempgbWindowLine = gbWindowLine;
5149
5150 if ((tempgbWindowLine == -1) || (tempgbWindowLine>144))
5151 {
5152 inUseRegister_WY = oldRegister_WY;
5153 if (register_LY>oldRegister_WY)
5154 tempgbWindowLine = 146;
5155 }
5156
5157 if(register_LY >= inUseRegister_WY) {
5158
5159 if (tempgbWindowLine == -1)
5160 tempgbWindowLine = 0;
5161
5162 int wx = register_WX;
5163 wx -= 7;
5164 if (wx<0)
5165 wx = 0;
5166
5167 if((wx <= 159) && (tempgbWindowLine <= 143))
5168 {
5169 for (int i = wx; i<300; i++)
5170 if (gbSpeed)
5171 gbSpritesTicks[i]+=3;
5172 else
5173 gbSpritesTicks[i]+=1;
5174 }
5175 }
5176 }
5177 }
5178
5179 gbInt48Signal &= ~7;
5180
5181 gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299];
5182 gbLcdMode = 3;
5183 }
5184 break;
5185 case 3:
5186 {
5187 // OAM and VRAM in use
5188 // next mode is H-Blank
5189
5190
5191 gbInt48Signal &= ~7;
5192 if(register_STAT & 0x08)
5193 {
5194 // send LCD interrupt only if no interrupt 48h signal...
5195 if (!(gbInt48Signal & 8))
5196 {
5197 register_IF |= 2;
5198 if ((gbHardware & 0xa) && (IFF & 0x80))
5199 gbInterruptWait = 1;
5200 }
5201 gbInt48Signal |= 1;
5202 }
5203
5204 gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299];
5205
5206 gbLcdMode = 0;
5207
5208 // No HDMA during HALT !
5209 if(gbHdmaOn && (!(IFF & 0x80) || (register_IE & register_IF & 0x1f))) {
5210 gbDoHdma();
5211 }
5212
5213 }
5214 break;
5215 }
5216 }
5217
5218
5219 if ((gbLcdTicksDelayed <= 0) && (gbLCDChangeHappened)) {
5220 int framesToSkip = systemFrameSkip;
5221 if(speedup)
5222 framesToSkip = 9; // try 6 FPS during speedup
5223 //gbLcdTicksDelayed = gbLcdTicks+1;
5224 gbLCDChangeHappened = false;
5225 switch(gbLcdModeDelayed) {
5226 case 0:
5227 {
5228 // H-Blank
5229
5230 memset(gbSCYLine,gbSCYLine[299],sizeof(gbSCYLine));
5231 memset(gbSCXLine,gbSCXLine[299],sizeof(gbSCXLine));
5232 memset(gbBgpLine,gbBgpLine[299],sizeof(gbBgpLine));
5233 memset(gbObp0Line,gbObp0Line[299],sizeof(gbObp0Line));
5234 memset(gbObp1Line,gbObp1Line[299],sizeof(gbObp1Line));
5235 memset(gbSpritesTicks,gbSpritesTicks[299],sizeof(gbSpritesTicks));
5236
5237 if (gbWindowLine <0)
5238 oldRegister_WY = register_WY;
5239 // check if we reached the V-Blank period
5240 if(register_LY == 144) {
5241 // Yes, V-Blank
5242 // set the LY increment counter
5243
5244 if(register_LCDC & 0x80) {
5245 if (gbHardware & 0xa)
5246 {
5247
5248 register_IF |= 1; // V-Blank interrupt
5249 gbInterruptLaunched |=1;
5250 }
5251
5252
5253 }
5254
5255 gbLcdTicksDelayed += GBLCD_MODE_1_CLOCK_TICKS;
5256 gbLcdModeDelayed = 1;
5257
5258 gbFrameCount++;
5259 systemFrame();
5260
5261 if((gbFrameCount % 10) == 0)
5262 system10Frames(60);
5263
5264 if(gbFrameCount >= 60) {
5265 u32 currentTime = systemGetClock();
5266 if(currentTime != gbLastTime)
5267 systemShowSpeed(100000/(currentTime - gbLastTime));
5268 else
5269 systemShowSpeed(0);
5270 gbLastTime = currentTime;
5271 gbFrameCount = 0;
5272 }
5273
5274 if(systemReadJoypads()) {
5275 // read joystick
5276 if(gbSgbMode && gbSgbMultiplayer) {
5277 if(gbSgbFourPlayers) {
5278 gbJoymask[0] = systemReadJoypad(0);
5279 gbJoymask[1] = systemReadJoypad(1);
5280 gbJoymask[2] = systemReadJoypad(2);
5281 gbJoymask[3] = systemReadJoypad(3);
5282 } else {
5283 gbJoymask[0] = systemReadJoypad(0);
5284 gbJoymask[1] = systemReadJoypad(1);
5285 }
5286 } else {
5287 gbJoymask[0] = systemReadJoypad(-1);
5288 }
5289 }
5290 int newmask = gbJoymask[0] & 255;
5291
5292 if(gbRomType == 0x22) {
5293 systemUpdateMotionSensor();
5294 }
5295
5296 if(newmask)
5297 {
5298 gbMemory[0xff0f] = register_IF |= 16;
5299 }
5300
5301
5302 newmask = (gbJoymask[0] >> 10);
5303
5304 speedup = (newmask & 1) ? true : false;
5305 gbCapture = (newmask & 2) ? true : false;
5306
5307 if(gbCapture && !gbCapturePrevious) {
5308 gbCaptureNumber++;
5309 systemScreenCapture(gbCaptureNumber);
5310 }
5311 gbCapturePrevious = gbCapture;
5312
5313 if(gbFrameSkipCount >= framesToSkip) {
5314
5315 if(!gbSgbMask)
5316 {
5317 if (gbBorderOn)
5318 gbSgbRenderBorder();
5319 //if (gbScreenOn)
5320 systemDrawScreen();
5321 if(systemPauseOnFrame())
5322 ticksToStop = 0;
5323 }
5324 gbFrameSkipCount = 0;
5325 } else
5326 gbFrameSkipCount++;
5327
5328 } else {
5329 // go the the OAM being accessed mode
5330 gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS;
5331 gbLcdModeDelayed = 2;
5332 gbInt48Signal &= ~3;
5333 }
5334 }
5335 break;
5336 case 1:
5337 {
5338 // V-Blank
5339 // next mode is OAM being accessed mode
5340
5341 // gbScreenOn = true;
5342
5343 oldRegister_WY = register_WY;
5344
5345 gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS;
5346 gbLcdModeDelayed = 2;
5347
5348 // reset the window line
5349 gbWindowLine = -1;
5350 }
5351 break;
5352 case 2:
5353 {
5354 // OAM being accessed mode
5355 // next mode is OAM and VRAM in use
5356 gbLcdTicksDelayed += GBLCD_MODE_3_CLOCK_TICKS+gbSpritesTicks[299];
5357 gbLcdModeDelayed = 3;
5358 }
5359 break;
5360 case 3:
5361 {
5362
5363 // OAM and VRAM in use
5364 // next mode is H-Blank
5365 if((register_LY < 144) && (register_LCDC & 0x80) && gbScreenOn) {
5366 if(!gbSgbMask) {
5367 if(gbFrameSkipCount >= framesToSkip) {
5368 if (!gbBlackScreen)
5369 {
5370 gbRenderLine();
5371 gbDrawSprites(true);
5372 }
5373 else if (gbBlackScreen)
5374 {
5375 u16 color = gbColorOption ? gbColorFilter[0] : 0;
5376 if (!gbCgbMode)
5377 color = gbColorOption ? gbColorFilter[gbPalette[3] & 0x7FFF] : gbPalette[3] & 0x7FFF;
5378 for(int i = 0; i < 160; i++)
5379 {
5380 gbLineMix[i] = color;
5381 gbLineBuffer[i] = 0;
5382 }
5383 }
5384 gbDrawLine();
5385 }
5386 }
5387 }
5388 gbLcdTicksDelayed += GBLCD_MODE_0_CLOCK_TICKS-gbSpritesTicks[299];
5389 gbLcdModeDelayed = 0;
5390 }
5391 break;
5392 }
5393 }
5394
5395 if ((gbLcdLYIncrementTicksDelayed <= 0) && (gbLYChangeHappened == true))
5396 {
5397
5398 gbLYChangeHappened = false;
5399
5400 if (!((gbLcdMode != 1) && (register_LY==0)))
5401 {
5402 {
5403 gbInt48Signal &= ~8;
5404 gbCompareLYToLYC();
5405 if ((gbInt48Signal == 8) && (!((register_LY == 0) && (gbHardware & 1))))
5406 gbInterruptLaunched |= 2;
5407 if ((gbHardware & (gbSpeed ? 8 : 2)) && (register_LY==0) && ((register_STAT & 0x44) == 0x44) && (gbLcdLYIncrementTicksDelayed==0))
5408 {
5409 gbInterruptWait = 1;
5410
5411 }
5412 }
5413 }
5414 gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS;
5415
5416 if (gbLcdModeDelayed == 1)
5417 {
5418
5419 if(register_LY == 153)
5420 gbLcdLYIncrementTicksDelayed -= GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
5421 else if(register_LY == 0)
5422 gbLcdLYIncrementTicksDelayed += GBLY_INCREMENT_CLOCK_TICKS - gbLine99Ticks;
5423 }
5424 gbMemory[0xff0f] = register_IF;
5425 gbMemory[0xff41] = register_STAT;
5426 }
5427 }
5428 gbMemory[0xff0f] = register_IF;
5429 gbMemory[0xff41] = register_STAT = (register_STAT & 0xfc) | gbLcdModeDelayed;
5430 }
5431 else
5432 {
5433
5434 // Used to update the screen with white lines when it's off.
5435 // (it looks strange, but it's kinda accurate :p)
5436 // You can try the Mario Demo Vx.x for exemple
5437 // (check the bottom 2 lines while moving)
5438 if (!gbWhiteScreen)
5439 {
5440 gbScreenTicks -= clockTicks;
5441 gbLcdLYIncrementTicks -= clockTicks;
5442 while (gbLcdLYIncrementTicks <=0)
5443 {
5444 register_LY = ((register_LY+1)%154);
5445 gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS;
5446 }
5447 if (gbScreenTicks <= 0)
5448 {
5449 gbWhiteScreen = 1;
5450 u8 register_LYLcdOff = ((register_LY+154)%154);
5451 for (register_LY=0;register_LY <= 0x90;register_LY++)
5452 {
5453 u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
5454 if (!gbCgbMode)
5455 color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF;
5456 for(int i = 0; i < 160; i++)
5457 {
5458 gbLineMix[i] = color;
5459 gbLineBuffer[i] = 0;
5460 }
5461 gbDrawLine();
5462 }
5463 register_LY = register_LYLcdOff;
5464 }
5465 }
5466
5467 if (gbWhiteScreen)
5468 {
5469 gbLcdLYIncrementTicks -= clockTicks;
5470
5471 while (gbLcdLYIncrementTicks <=0)
5472 {
5473 register_LY = ((register_LY+1)%154);
5474 gbLcdLYIncrementTicks+=GBLY_INCREMENT_CLOCK_TICKS;
5475 if (register_LY<144)
5476 {
5477
5478 u16 color = gbColorOption ? gbColorFilter[0x7FFF] : 0x7FFF;
5479 if (!gbCgbMode)
5480 color = gbColorOption ? gbColorFilter[gbPalette[0] & 0x7FFF] : gbPalette[0] & 0x7FFF;
5481 for(int i = 0; i < 160; i++)
5482 {
5483 gbLineMix[i] = color;
5484 gbLineBuffer[i] = 0;
5485 }
5486 gbDrawLine();
5487 }
5488 else if ((register_LY==144) && (!systemFrameSkip))
5489 {
5490 int framesToSkip = systemFrameSkip;
5491 if(speedup)
5492 framesToSkip = 9; // try 6 FPS during speedup
5493 if((gbFrameSkipCount >= framesToSkip) || (gbWhiteScreen == 1)) {
5494 gbWhiteScreen = 2;
5495
5496 if(!gbSgbMask)
5497 {
5498 if (gbBorderOn)
5499 gbSgbRenderBorder();
5500 //if (gbScreenOn)
5501 systemDrawScreen();
5502 if(systemPauseOnFrame())
5503 ticksToStop = 0;
5504 }
5505 }
5506 if(systemReadJoypads()) {
5507 // read joystick
5508 if(gbSgbMode && gbSgbMultiplayer) {
5509 if(gbSgbFourPlayers) {
5510 gbJoymask[0] = systemReadJoypad(0);
5511 gbJoymask[1] = systemReadJoypad(1);
5512 gbJoymask[2] = systemReadJoypad(2);
5513 gbJoymask[3] = systemReadJoypad(3);
5514 } else {
5515 gbJoymask[0] = systemReadJoypad(0);
5516 gbJoymask[1] = systemReadJoypad(1);
5517 }
5518 } else {
5519 gbJoymask[0] = systemReadJoypad(-1);
5520 }
5521 }
5522 gbFrameCount++;
5523
5524 systemFrame();
5525
5526 if((gbFrameCount % 10) == 0)
5527 system10Frames(60);
5528
5529 if(gbFrameCount >= 60) {
5530 u32 currentTime = systemGetClock();
5531 if(currentTime != gbLastTime)
5532 systemShowSpeed(100000/(currentTime - gbLastTime));
5533 else
5534 systemShowSpeed(0);
5535 gbLastTime = currentTime;
5536 gbFrameCount = 0;
5537 }
5538 }
5539 }
5540 }
5541 }
5542
5543 gbMemory[0xff41] = register_STAT;
5544
5545 #ifndef NO_LINK
5546 // serial emulation
5547 gbSerialOn = (gbMemory[0xff02] & 0x80);
5548 static int SIOctr = 0;
5549 SIOctr++;
5550 if (SIOctr % 5)
5551 //Transfer Started
5552 if (gbSerialOn && (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET)) {
5553 #ifdef OLD_GB_LINK
5554 if (linkConnected) {
5555 gbSerialTicks -= clockTicks;
5556
5557 while (gbSerialTicks <= 0) {
5558 // increment number of shifted bits
5559 gbSerialBits++;
5560 linkProc();
5561 if (gbSerialOn && (gbMemory[0xff02] & 1)) {
5562 if (gbSerialBits == 8) {
5563 gbSerialBits = 0;
5564 gbMemory[0xff01] = 0xff;
5565 gbMemory[0xff02] &= 0x7f;
5566 gbSerialOn = 0;
5567 gbMemory[0xff0f] = register_IF |= 8;
5568 gbSerialTicks = 0;
5569 }
5570 }
5571 gbSerialTicks += GBSERIAL_CLOCK_TICKS;
5572 }
5573 }
5574 else {
5575 #endif
5576 if (gbMemory[0xff02] & 1) { //internal clocks (master)
5577 gbSerialTicks -= clockTicks;
5578
5579 // overflow
5580 while (gbSerialTicks <= 0) {
5581 // shift serial byte to right and put a 1 bit in its place
5582 // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
5583 // increment number of shifted bits
5584 gbSerialBits++;
5585 if (gbSerialBits >= 8) {
5586 // end of transmission
5587 gbSerialTicks = 0;
5588 gbSerialBits = 0;
5589 }
5590 else
5591 gbSerialTicks += GBSERIAL_CLOCK_TICKS;
5592 }
5593 }
5594 else //external clocks (slave)
5595 {
5596 gbSerialTicks -= clockTicks;
5597
5598 // overflow
5599 while (gbSerialTicks <= 0) {
5600 // shift serial byte to right and put a 1 bit in its place
5601 // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
5602 // increment number of shifted bits
5603 gbSerialBits++;
5604 if (gbSerialBits >= 8) {
5605 // end of transmission
5606 u16 dat = 0;
5607 if (LinkIsWaiting)
5608 if (gbSerialFunction) { // external device
5609 gbSIO_SC = gbMemory[0xff02];
5610 if (!LinkFirstTime)
5611 {
5612 dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1;
5613 }
5614 else //external clock not suppose to start a transfer, but there are time where both side using external clock and couldn't communicate properly
5615 {
5616 if (gbMemory)
5617 gbSerialOn = (gbMemory[0xff02] & 0x80);
5618 dat = gbLinkUpdate(gbMemory[0xff01], gbSerialOn);
5619 }
5620 gbMemory[0xff01] = (dat >> 8);
5621 } //else
5622 gbSerialTicks = 0;
5623 if ((dat & 1) && (gbMemory[0xff02] & 0x80)) //(dat & 1)==1 when reply data received
5624 {
5625 gbMemory[0xff02] &= 0x7f;
5626 gbSerialOn = 0;
5627 gbMemory[0xff0f] = register_IF |= 8;
5628 }
5629 gbSerialBits = 0;
5630 }
5631 else
5632 gbSerialTicks += GBSERIAL_CLOCK_TICKS;
5633 }
5634 }
5635 #ifdef OLD_GB_LINK
5636 }
5637 #endif
5638 }
5639 #endif
5640
5641 soundTicks -= clockTicks;
5642 if ( !gbSpeed )
5643 soundTicks -= clockTicks;
5644
5645 while(soundTicks < 0) {
5646 soundTicks += SOUND_CLOCK_TICKS;
5647
5648 gbSoundTick();
5649 }
5650
5651
5652 // timer emulation
5653
5654 if(gbTimerOn) {
5655 gbTimerTicks= ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1-clockTicks;
5656
5657 while(gbTimerTicks <= 0) {
5658 register_TIMA++;
5659 // timer overflow!
5660 if((register_TIMA & 0xff) == 0) {
5661 // reload timer modulo
5662 register_TIMA = register_TMA;
5663 // flag interrupt
5664 gbMemory[0xff0f] = register_IF |= 4;
5665 }
5666 gbTimerTicks += gbTimerClockTicks;
5667 }
5668 gbTimerOnChange = false;
5669 gbTimerModeChange = false;
5670
5671 gbMemory[0xff05] = register_TIMA;
5672
5673 }
5674
5675 gbInternalTimer -= clockTicks;
5676 while (gbInternalTimer<0)
5677 gbInternalTimer+=0x100;
5678
5679 clockTicks = 0;
5680
5681 if (gbIntBreak == 1)
5682 {
5683 gbIntBreak = 0;
5684 if ((register_IE & register_IF & gbInterruptLaunched & 0x3) &&
5685 ((IFF & 0x81) == 1) && (!gbInterruptWait) && (execute))
5686 {
5687 gbIntBreak = 2;
5688 PC.W = oldPCW;
5689 execute = false;
5690 gbOldClockTicks = 0;
5691 }
5692 if (gbOldClockTicks)
5693 {
5694 clockTicks = gbOldClockTicks;
5695 gbOldClockTicks = 0;
5696 goto gbRedoLoop;
5697 }
5698 }
5699
5700 // Executes the opcode(s), and apply the instruction's remaining clockTicks (if any).
5701 if (execute)
5702 {
5703 switch(opcode1) {
5704 case 0xCB:
5705 // extended opcode
5706 switch(opcode2) {
5707 #include "gbCodesCB.h"
5708 }
5709 break;
5710 #include "gbCodes.h"
5711 }
5712 execute = false;
5713
5714 if (clockTicks)
5715 {
5716 gbDmaTicks += clockTicks;
5717 clockTicks = 0;
5718 }
5719 }
5720
5721 if (gbDmaTicks)
5722 {
5723 clockTicks = gbGetNextEvent(gbDmaTicks);
5724
5725 if (clockTicks<=gbDmaTicks)
5726 gbDmaTicks -= clockTicks;
5727 else
5728 {
5729 clockTicks = gbDmaTicks;
5730 gbDmaTicks = 0;
5731 }
5732
5733 goto gbRedoLoop;
5734 }
5735
5736
5737 // Remove the 'if an IE is pending' flag if IE has finished being executed.
5738 if ((IFF & 0x40) && !(IFF & 0x30))
5739 IFF &= 0x81;
5740
5741
5742
5743 if ((register_IE & register_IF & 0x1f) && (IFF & 0x81) && (!gbInterruptWait))
5744 {
5745
5746 if (IFF & 1)
5747 {
5748 // Add 5 ticks for the interrupt execution time
5749 gbDmaTicks += 5;
5750
5751 if (gbIntBreak == 2)
5752 {
5753 gbDmaTicks--;
5754 gbIntBreak = 0;
5755 }
5756
5757
5758 if(register_IF & register_IE & 1)
5759 gbVblank_interrupt();
5760 else if(register_IF & register_IE & 2)
5761 gbLcd_interrupt();
5762 else if(register_IF & register_IE & 4)
5763 gbTimer_interrupt();
5764 else if(register_IF & register_IE & 8)
5765 gbSerial_interrupt();
5766 else if(register_IF & register_IE & 16)
5767 gbJoypad_interrupt();
5768 }
5769
5770 IFF &= ~0x81;
5771 }
5772
5773 if (IFF & 0x08)
5774 IFF &=~0x79;
5775
5776 // Used to apply the interrupt's execution time.
5777 if (gbDmaTicks)
5778 {
5779 clockTicks = gbGetNextEvent(gbDmaTicks);
5780
5781 if (clockTicks<=gbDmaTicks)
5782 gbDmaTicks -= clockTicks;
5783 else
5784 {
5785 clockTicks = gbDmaTicks;
5786 gbDmaTicks = 0;
5787 }
5788 goto gbRedoLoop;
5789 }
5790
5791
5792 gbBlackScreen = false;
5793
5794 if((ticksToStop <= 0)) {
5795 if(!(register_LCDC & 0x80)) {
5796 if(systemReadJoypads()) {
5797 // read joystick
5798 if(gbSgbMode && gbSgbMultiplayer) {
5799 if(gbSgbFourPlayers) {
5800 gbJoymask[0] = systemReadJoypad(0);
5801 gbJoymask[1] = systemReadJoypad(1);
5802 gbJoymask[2] = systemReadJoypad(2);
5803 gbJoymask[3] = systemReadJoypad(3);
5804 } else {
5805 gbJoymask[0] = systemReadJoypad(0);
5806 gbJoymask[1] = systemReadJoypad(1);
5807 }
5808 } else {
5809 gbJoymask[0] = systemReadJoypad(-1);
5810 }
5811 }
5812 }
5813 return;
5814 }
5815 }
5816 }
5817
5818 struct EmulatedSystem GBSystem = {
5819 // emuMain
5820 gbEmulate,
5821 // emuReset
5822 gbReset,
5823 // emuCleanUp
5824 gbCleanUp,
5825 // emuReadBattery
5826 gbReadBatteryFile,
5827 // emuWriteBattery
5828 gbWriteBatteryFile,
5829 // emuReadState
5830 gbReadSaveState,
5831 // emuWriteState
5832 gbWriteSaveState,
5833 // emuReadMemState
5834 gbReadMemSaveState,
5835 // emuWriteMemState
5836 gbWriteMemSaveState,
5837 // emuWritePNG
5838 gbWritePNGFile,
5839 // emuWriteBMP
5840 gbWriteBMPFile,
5841 // emuUpdateCPSR
5842 NULL,
5843 // emuHasDebugger
5844 false,
5845 // emuCount
5846 #ifdef FINAL_VERSION
5847 70000/4,
5848 #else
5849 1000,
5850 #endif
5851 };
5852