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   { &register_DIV, sizeof(u8) },
3832   { &register_TIMA, sizeof(u8) },
3833   { &register_TMA, sizeof(u8) },
3834   { &register_TAC, sizeof(u8) },
3835   { &register_IF, sizeof(u8) },
3836   { &register_LCDC, sizeof(u8) },
3837   { &register_STAT, sizeof(u8) },
3838   { &register_SCY, sizeof(u8) },
3839   { &register_SCX, sizeof(u8) },
3840   { &register_LY, sizeof(u8) },
3841   { &register_LYC, sizeof(u8) },
3842   { &register_DMA, sizeof(u8) },
3843   { &register_WY, sizeof(u8) },
3844   { &register_WX, sizeof(u8) },
3845   { &register_VBK, sizeof(u8) },
3846   { &register_HDMA1, sizeof(u8) },
3847   { &register_HDMA2, sizeof(u8) },
3848   { &register_HDMA3, sizeof(u8) },
3849   { &register_HDMA4, sizeof(u8) },
3850   { &register_HDMA5, sizeof(u8) },
3851   { &register_SVBK, sizeof(u8) },
3852   { &register_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