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