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@92
|
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@93
|
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@93
|
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@92
|
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@76
|
2466
|
rlm@33
|
2467 utilWriteInt(gzFile, GBSAVE_GAME_VERSION);
|
rlm@33
|
2468
|
rlm@76
|
2469
|
rlm@33
|
2470 utilGzWrite(gzFile, &gbRom[0x134], 15);
|
rlm@33
|
2471
|
rlm@33
|
2472 utilWriteData(gzFile, gbSaveGameStruct);
|
rlm@76
|
2473
|
rlm@33
|
2474 utilGzWrite(gzFile, &IFF, 2);
|
rlm@76
|
2475
|
rlm@33
|
2476 if (gbSgbMode)
|
rlm@33
|
2477 {
|
rlm@33
|
2478 gbSgbSaveGame(gzFile);
|
rlm@33
|
2479 }
|
rlm@33
|
2480
|
rlm@33
|
2481 utilGzWrite(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
|
rlm@33
|
2482 utilGzWrite(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
|
rlm@33
|
2483 //assert(sizeof(time_t) == 4);
|
rlm@33
|
2484 utilGzWrite(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
|
rlm@33
|
2485 utilGzWrite(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
|
rlm@33
|
2486 utilGzWrite(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
|
rlm@33
|
2487 utilGzWrite(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
|
rlm@33
|
2488
|
rlm@33
|
2489 // yes, this definitely needs to be saved, or loading paused games will show a black screen
|
rlm@33
|
2490 // this is also necessary to be consistent with what the GBA saving does
|
rlm@33
|
2491 utilGzWrite(gzFile, pix, 4 * 257 * 226);
|
rlm@33
|
2492
|
rlm@33
|
2493 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
|
rlm@33
|
2494 // todo: remove
|
rlm@33
|
2495 utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
|
rlm@33
|
2496
|
rlm@33
|
2497 utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
|
rlm@33
|
2498
|
rlm@59
|
2499
|
rlm@33
|
2500 if (gbRamSize && gbRam)
|
rlm@33
|
2501 {
|
rlm@33
|
2502 utilGzWrite(gzFile, gbRam, gbRamSize);
|
rlm@33
|
2503 }
|
rlm@33
|
2504
|
rlm@33
|
2505 if (gbCgbMode)
|
rlm@33
|
2506 {
|
rlm@33
|
2507 utilGzWrite(gzFile, gbVram, 0x4000);
|
rlm@33
|
2508 utilGzWrite(gzFile, gbWram, 0x8000);
|
rlm@33
|
2509 }
|
rlm@33
|
2510
|
rlm@33
|
2511 gbSoundSaveGame(gzFile);
|
rlm@33
|
2512
|
rlm@33
|
2513 gbCheatsSaveGame(gzFile);
|
rlm@33
|
2514
|
rlm@33
|
2515 // new to re-recording version:
|
rlm@33
|
2516 {
|
rlm@33
|
2517 extern int32 sensorX, sensorY;
|
rlm@33
|
2518 utilGzWrite(gzFile, &sensorX, sizeof(sensorX));
|
rlm@33
|
2519 utilGzWrite(gzFile, &sensorY, sizeof(sensorY));
|
rlm@33
|
2520 utilGzWrite(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get
|
rlm@33
|
2521 // carried
|
rlm@33
|
2522 // back on loading a snapshot!
|
rlm@33
|
2523
|
rlm@33
|
2524 bool8 movieActive = VBAMovieActive();
|
rlm@33
|
2525 utilGzWrite(gzFile, &movieActive, sizeof(movieActive));
|
rlm@33
|
2526 if (movieActive)
|
rlm@33
|
2527 {
|
rlm@33
|
2528 uint8 *movie_freeze_buf = NULL;
|
rlm@33
|
2529 uint32 movie_freeze_size = 0;
|
rlm@33
|
2530
|
rlm@33
|
2531 VBAMovieFreeze(&movie_freeze_buf, &movie_freeze_size);
|
rlm@33
|
2532 if (movie_freeze_buf)
|
rlm@33
|
2533 {
|
rlm@33
|
2534 utilGzWrite(gzFile, &movie_freeze_size, sizeof(movie_freeze_size));
|
rlm@33
|
2535 utilGzWrite(gzFile, movie_freeze_buf, movie_freeze_size);
|
rlm@33
|
2536 delete [] movie_freeze_buf;
|
rlm@33
|
2537 }
|
rlm@33
|
2538 else
|
rlm@33
|
2539 {
|
rlm@33
|
2540 systemMessage(0, N_("Failed to save movie snapshot."));
|
rlm@33
|
2541 return false;
|
rlm@33
|
2542 }
|
rlm@33
|
2543 }
|
rlm@33
|
2544 utilGzWrite(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount));
|
rlm@33
|
2545 }
|
rlm@33
|
2546
|
rlm@33
|
2547 // new to rerecording 19.4 wip (svn r22+):
|
rlm@33
|
2548 {
|
rlm@33
|
2549 utilGzWrite(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount));
|
rlm@33
|
2550 utilGzWrite(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged));
|
rlm@33
|
2551 utilGzWrite(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast));
|
rlm@33
|
2552 }
|
rlm@33
|
2553
|
rlm@76
|
2554 utilWriteInt(gzFile, 0x07); // RLM this is the end of file marker.
|
rlm@33
|
2555 return true;
|
rlm@1
|
2556 }
|
rlm@1
|
2557
|
rlm@76
|
2558
|
rlm@76
|
2559 long gbWriteMemSaveStatePos(char *memory, int available){
|
rlm@33
|
2560 gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
rlm@33
|
2561
|
rlm@33
|
2562 if (gzFile == NULL)
|
rlm@33
|
2563 {
|
rlm@33
|
2564 return false;
|
rlm@33
|
2565 }
|
rlm@33
|
2566
|
rlm@33
|
2567 bool res = gbWriteSaveStateToStream(gzFile);
|
rlm@33
|
2568
|
rlm@33
|
2569 long pos = utilGzTell(gzFile) + 8;
|
rlm@33
|
2570
|
rlm@76
|
2571 if (pos >= available){
|
rlm@76
|
2572 pos = 0;
|
rlm@76
|
2573 }
|
rlm@33
|
2574
|
rlm@33
|
2575 utilGzClose(gzFile);
|
rlm@33
|
2576
|
rlm@76
|
2577 return pos;
|
rlm@76
|
2578
|
rlm@76
|
2579 }
|
rlm@76
|
2580
|
rlm@76
|
2581 bool gbWriteMemSaveState(char *memory, int available)
|
rlm@76
|
2582 {
|
rlm@76
|
2583 long pos = gbWriteMemSaveStatePos(memory, available);
|
rlm@76
|
2584 if (pos > 0) { return true; }
|
rlm@76
|
2585 else{ return false; }
|
rlm@1
|
2586 }
|
rlm@1
|
2587
|
rlm@1
|
2588 bool gbWriteSaveState(const char *name)
|
rlm@1
|
2589 {
|
rlm@33
|
2590 gzFile gzFile = utilGzOpen(name, "wb");
|
rlm@33
|
2591
|
rlm@33
|
2592 if (gzFile == NULL)
|
rlm@33
|
2593 return false;
|
rlm@33
|
2594
|
rlm@33
|
2595 bool res = gbWriteSaveStateToStream(gzFile);
|
rlm@33
|
2596
|
rlm@33
|
2597 utilGzClose(gzFile);
|
rlm@33
|
2598 return res;
|
rlm@1
|
2599 }
|
rlm@1
|
2600
|
rlm@1
|
2601 static int tempStateID = 0;
|
rlm@1
|
2602 static int tempFailCount = 0;
|
rlm@1
|
2603 static bool backupSafe = true;
|
rlm@1
|
2604
|
rlm@1
|
2605 bool gbReadSaveStateFromStream(gzFile gzFile)
|
rlm@1
|
2606 {
|
rlm@33
|
2607 int type;
|
rlm@33
|
2608 char tempBackupName [128];
|
rlm@33
|
2609 if (backupSafe)
|
rlm@33
|
2610 {
|
rlm@33
|
2611 sprintf(tempBackupName, "gbatempsave%d.sav", tempStateID++);
|
rlm@33
|
2612 gbWriteSaveState(tempBackupName);
|
rlm@33
|
2613 }
|
rlm@33
|
2614
|
rlm@33
|
2615 int version = utilReadInt(gzFile);
|
rlm@33
|
2616
|
rlm@33
|
2617 if (version > GBSAVE_GAME_VERSION || version < 0)
|
rlm@33
|
2618 {
|
rlm@33
|
2619 systemMessage(MSG_UNSUPPORTED_VB_SGM,
|
rlm@33
|
2620 N_("Unsupported VisualBoy save game version %d"), version);
|
rlm@33
|
2621 goto failedLoadGB;
|
rlm@33
|
2622 }
|
rlm@33
|
2623
|
rlm@33
|
2624 u8 romname[20];
|
rlm@33
|
2625
|
rlm@33
|
2626 utilGzRead(gzFile, romname, 15);
|
rlm@33
|
2627
|
rlm@33
|
2628 if (memcmp(&gbRom[0x134], romname, 15) != 0)
|
rlm@33
|
2629 {
|
rlm@33
|
2630 systemMessage(MSG_CANNOT_LOAD_SGM_FOR,
|
rlm@33
|
2631 N_("Cannot load save game for %s. Playing %s"),
|
rlm@33
|
2632 romname, &gbRom[0x134]);
|
rlm@33
|
2633 goto failedLoadGB;
|
rlm@33
|
2634 }
|
rlm@33
|
2635
|
rlm@33
|
2636 utilReadData(gzFile, gbSaveGameStruct);
|
rlm@33
|
2637
|
rlm@33
|
2638 if (version >= GBSAVE_GAME_VERSION_7)
|
rlm@33
|
2639 {
|
rlm@33
|
2640 utilGzRead(gzFile, &IFF, 2);
|
rlm@33
|
2641 }
|
rlm@33
|
2642
|
rlm@33
|
2643 if (gbSgbMode)
|
rlm@33
|
2644 {
|
rlm@33
|
2645 gbSgbReadGame(gzFile, version);
|
rlm@33
|
2646 }
|
rlm@33
|
2647 else
|
rlm@33
|
2648 {
|
rlm@33
|
2649 gbSgbMask = 0; // loading a game at the wrong time causes no display
|
rlm@33
|
2650 }
|
rlm@33
|
2651
|
rlm@33
|
2652 utilGzRead(gzFile, &gbDataMBC1, sizeof(gbDataMBC1));
|
rlm@33
|
2653 utilGzRead(gzFile, &gbDataMBC2, sizeof(gbDataMBC2));
|
rlm@33
|
2654 if (version < GBSAVE_GAME_VERSION_4)
|
rlm@33
|
2655 // prior to version 4, there was no adjustment for the time the game
|
rlm@33
|
2656 // was last played, so we have less to read. This needs update if the
|
rlm@33
|
2657 // structure changes again.
|
rlm@33
|
2658 utilGzRead(gzFile, &gbDataMBC3, sizeof(int32) * 10);
|
rlm@33
|
2659 else
|
rlm@33
|
2660 {
|
rlm@33
|
2661 //assert(sizeof(time_t) == 4);
|
rlm@33
|
2662 utilGzRead(gzFile, &gbDataMBC3, sizeof(gbDataMBC3));
|
rlm@33
|
2663 }
|
rlm@33
|
2664 utilGzRead(gzFile, &gbDataMBC5, sizeof(gbDataMBC5));
|
rlm@33
|
2665 utilGzRead(gzFile, &gbDataHuC1, sizeof(gbDataHuC1));
|
rlm@33
|
2666 utilGzRead(gzFile, &gbDataHuC3, sizeof(gbDataHuC3));
|
rlm@33
|
2667
|
rlm@33
|
2668 if (version >= GBSAVE_GAME_VERSION_12)
|
rlm@33
|
2669 {
|
rlm@33
|
2670 utilGzRead(gzFile, pix, 4 * 257 * 226);
|
rlm@33
|
2671 }
|
rlm@33
|
2672 else
|
rlm@33
|
2673 {
|
rlm@33
|
2674 memset(pix, 0, 257 * 226 * sizeof(u32));
|
rlm@33
|
2675 // if(version < GBSAVE_GAME_VERSION_5)
|
rlm@33
|
2676 // utilGzRead(gzFile, pix, 256*224*sizeof(u16));
|
rlm@33
|
2677 }
|
rlm@33
|
2678
|
rlm@33
|
2679 if (version < GBSAVE_GAME_VERSION_6)
|
rlm@33
|
2680 {
|
rlm@33
|
2681 utilGzRead(gzFile, gbPalette, 64 * sizeof(u16));
|
rlm@33
|
2682 }
|
rlm@33
|
2683 else
|
rlm@33
|
2684 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
|
rlm@33
|
2685
|
rlm@33
|
2686 // todo: remove
|
rlm@33
|
2687 utilGzRead(gzFile, gbPalette, 128 * sizeof(u16));
|
rlm@33
|
2688
|
rlm@33
|
2689 if (version < GBSAVE_GAME_VERSION_10)
|
rlm@33
|
2690 {
|
rlm@33
|
2691 if (!gbCgbMode && !gbSgbMode)
|
rlm@1
|
2692 {
|
rlm@33
|
2693 for (int i = 0; i < 8; i++)
|
rlm@33
|
2694 gbPalette[i] = systemGbPalette[gbPaletteOption * 8 + i];
|
rlm@1
|
2695 }
|
rlm@33
|
2696 }
|
rlm@33
|
2697
|
rlm@33
|
2698 utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
|
rlm@33
|
2699
|
rlm@33
|
2700 if (gbRamSize && gbRam)
|
rlm@33
|
2701 {
|
rlm@33
|
2702 utilGzRead(gzFile, gbRam, gbRamSize);
|
rlm@33
|
2703 }
|
rlm@33
|
2704
|
rlm@33
|
2705 gbMemoryMap[0x00] = &gbRom[0x0000];
|
rlm@33
|
2706 gbMemoryMap[0x01] = &gbRom[0x1000];
|
rlm@33
|
2707 gbMemoryMap[0x02] = &gbRom[0x2000];
|
rlm@33
|
2708 gbMemoryMap[0x03] = &gbRom[0x3000];
|
rlm@33
|
2709 gbMemoryMap[0x04] = &gbRom[0x4000];
|
rlm@33
|
2710 gbMemoryMap[0x05] = &gbRom[0x5000];
|
rlm@33
|
2711 gbMemoryMap[0x06] = &gbRom[0x6000];
|
rlm@33
|
2712 gbMemoryMap[0x07] = &gbRom[0x7000];
|
rlm@33
|
2713 gbMemoryMap[0x08] = &gbMemory[0x8000];
|
rlm@33
|
2714 gbMemoryMap[0x09] = &gbMemory[0x9000];
|
rlm@33
|
2715 gbMemoryMap[0x0a] = &gbMemory[0xa000];
|
rlm@33
|
2716 gbMemoryMap[0x0b] = &gbMemory[0xb000];
|
rlm@33
|
2717 gbMemoryMap[0x0c] = &gbMemory[0xc000];
|
rlm@33
|
2718 gbMemoryMap[0x0d] = &gbMemory[0xd000];
|
rlm@33
|
2719 gbMemoryMap[0x0e] = &gbMemory[0xe000];
|
rlm@33
|
2720 gbMemoryMap[0x0f] = &gbMemory[0xf000];
|
rlm@33
|
2721
|
rlm@33
|
2722 type = gbRom[0x147];
|
rlm@33
|
2723
|
rlm@33
|
2724 switch (type)
|
rlm@33
|
2725 {
|
rlm@33
|
2726 case 0x00:
|
rlm@33
|
2727 case 0x01:
|
rlm@33
|
2728 case 0x02:
|
rlm@33
|
2729 case 0x03:
|
rlm@33
|
2730 // MBC 1
|
rlm@33
|
2731 memoryUpdateMapMBC1();
|
rlm@33
|
2732 break;
|
rlm@33
|
2733 case 0x05:
|
rlm@33
|
2734 case 0x06:
|
rlm@33
|
2735 // MBC2
|
rlm@33
|
2736 memoryUpdateMapMBC2();
|
rlm@33
|
2737 break;
|
rlm@33
|
2738 case 0x0f:
|
rlm@33
|
2739 case 0x10:
|
rlm@33
|
2740 case 0x11:
|
rlm@33
|
2741 case 0x12:
|
rlm@33
|
2742 case 0x13:
|
rlm@33
|
2743 // MBC 3
|
rlm@33
|
2744 memoryUpdateMapMBC3();
|
rlm@33
|
2745 break;
|
rlm@33
|
2746 case 0x19:
|
rlm@33
|
2747 case 0x1a:
|
rlm@33
|
2748 case 0x1b:
|
rlm@33
|
2749 // MBC5
|
rlm@33
|
2750 memoryUpdateMapMBC5();
|
rlm@33
|
2751 break;
|
rlm@33
|
2752 case 0x1c:
|
rlm@33
|
2753 case 0x1d:
|
rlm@33
|
2754 case 0x1e:
|
rlm@33
|
2755 // MBC 5 Rumble
|
rlm@33
|
2756 memoryUpdateMapMBC5();
|
rlm@33
|
2757 break;
|
rlm@33
|
2758 case 0x22:
|
rlm@33
|
2759 // MBC 7
|
rlm@33
|
2760 memoryUpdateMapMBC7();
|
rlm@33
|
2761 break;
|
rlm@33
|
2762 case 0xfe:
|
rlm@33
|
2763 // HuC3
|
rlm@33
|
2764 memoryUpdateMapHuC3();
|
rlm@33
|
2765 break;
|
rlm@33
|
2766 case 0xff:
|
rlm@33
|
2767 // HuC1
|
rlm@33
|
2768 memoryUpdateMapHuC1();
|
rlm@33
|
2769 break;
|
rlm@33
|
2770 }
|
rlm@33
|
2771
|
rlm@33
|
2772 if (gbCgbMode)
|
rlm@33
|
2773 {
|
rlm@33
|
2774 if (!gbVram)
|
rlm@33
|
2775 gbVram = (u8 *)malloc(0x4000 + 4);
|
rlm@33
|
2776 if (!gbWram)
|
rlm@33
|
2777 gbWram = (u8 *)malloc(0x8000 + 4);
|
rlm@33
|
2778 utilGzRead(gzFile, gbVram, 0x4000);
|
rlm@33
|
2779 utilGzRead(gzFile, gbWram, 0x8000);
|
rlm@33
|
2780
|
rlm@33
|
2781 int value = register_SVBK;
|
rlm@33
|
2782 if (value == 0)
|
rlm@33
|
2783 value = 1;
|
rlm@33
|
2784
|
rlm@33
|
2785 gbMemoryMap[0x08] = &gbVram[register_VBK * 0x2000];
|
rlm@33
|
2786 gbMemoryMap[0x09] = &gbVram[register_VBK * 0x2000 + 0x1000];
|
rlm@33
|
2787 gbMemoryMap[0x0d] = &gbWram[value * 0x1000];
|
rlm@33
|
2788 }
|
rlm@33
|
2789 else
|
rlm@33
|
2790 {
|
rlm@33
|
2791 if (gbVram)
|
rlm@1
|
2792 {
|
rlm@33
|
2793 free(gbVram);
|
rlm@33
|
2794 gbVram = NULL;
|
rlm@1
|
2795 }
|
rlm@33
|
2796 if (gbWram)
|
rlm@1
|
2797 {
|
rlm@33
|
2798 free(gbWram);
|
rlm@33
|
2799 gbWram = NULL;
|
rlm@1
|
2800 }
|
rlm@33
|
2801 }
|
rlm@33
|
2802
|
rlm@33
|
2803 gbSoundReadGame(version, gzFile);
|
rlm@33
|
2804
|
rlm@33
|
2805 #if 0
|
rlm@33
|
2806 if (gbBorderOn)
|
rlm@33
|
2807 {
|
rlm@33
|
2808 gbSgbRenderBorder();
|
rlm@33
|
2809 }
|
rlm@33
|
2810
|
rlm@33
|
2811 systemRefreshScreen();
|
rlm@33
|
2812 #endif
|
rlm@33
|
2813
|
rlm@33
|
2814 if (version > GBSAVE_GAME_VERSION_1)
|
rlm@33
|
2815 gbCheatsReadGame(gzFile, version);
|
rlm@33
|
2816
|
rlm@33
|
2817 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
rlm@33
|
2818
|
rlm@33
|
2819 if (version >= GBSAVE_GAME_VERSION_11) // new to re-recording version:
|
rlm@33
|
2820 {
|
rlm@33
|
2821 extern int32 sensorX, sensorY; // from SDL.cpp
|
rlm@33
|
2822 utilGzRead(gzFile, &sensorX, sizeof(sensorX));
|
rlm@33
|
2823 utilGzRead(gzFile, &sensorY, sizeof(sensorY));
|
rlm@33
|
2824 utilGzRead(gzFile, gbJoymask, 4 * sizeof(*gbJoymask)); // this has to be saved or old input will incorrectly get carried
|
rlm@33
|
2825 // back on loading a snapshot!
|
rlm@33
|
2826
|
rlm@33
|
2827 bool8 movieSnapshot;
|
rlm@33
|
2828 utilGzRead(gzFile, &movieSnapshot, sizeof(movieSnapshot));
|
rlm@33
|
2829 if (VBAMovieActive() && !movieSnapshot)
|
rlm@1
|
2830 {
|
rlm@33
|
2831 systemMessage(0, N_("Can't load a non-movie snapshot while a movie is active."));
|
rlm@33
|
2832 goto failedLoadGB;
|
rlm@1
|
2833 }
|
rlm@1
|
2834
|
rlm@33
|
2835 if (movieSnapshot) // even if a movie isn't active we still want to parse through this in case other stuff is added
|
rlm@33
|
2836 // later on in the save format
|
rlm@1
|
2837 {
|
rlm@33
|
2838 uint32 movieInputDataSize = 0;
|
rlm@33
|
2839 utilGzRead(gzFile, &movieInputDataSize, sizeof(movieInputDataSize));
|
rlm@33
|
2840 uint8 *local_movie_data = new uint8 [movieInputDataSize];
|
rlm@33
|
2841 int readBytes = utilGzRead(gzFile, local_movie_data, movieInputDataSize);
|
rlm@33
|
2842 if (readBytes != movieInputDataSize)
|
rlm@33
|
2843 {
|
rlm@33
|
2844 systemMessage(0, N_("Corrupt movie snapshot."));
|
rlm@33
|
2845 if (local_movie_data)
|
rlm@33
|
2846 delete [] local_movie_data;
|
rlm@33
|
2847 goto failedLoadGB;
|
rlm@33
|
2848 }
|
rlm@33
|
2849 int code = VBAMovieUnfreeze(local_movie_data, movieInputDataSize);
|
rlm@33
|
2850 if (local_movie_data)
|
rlm@33
|
2851 delete [] local_movie_data;
|
rlm@33
|
2852 if (code != MOVIE_SUCCESS && VBAMovieActive())
|
rlm@33
|
2853 {
|
rlm@33
|
2854 char errStr [1024];
|
rlm@33
|
2855 strcpy(errStr, "Failed to load movie snapshot");
|
rlm@33
|
2856 switch (code)
|
rlm@33
|
2857 {
|
rlm@33
|
2858 case MOVIE_NOT_FROM_THIS_MOVIE:
|
rlm@33
|
2859 strcat(errStr, ";\nSnapshot not from this movie"); break;
|
rlm@33
|
2860 case MOVIE_NOT_FROM_A_MOVIE:
|
rlm@33
|
2861 strcat(errStr, ";\nNot a movie snapshot"); break; // shouldn't get here...
|
rlm@33
|
2862 case MOVIE_SNAPSHOT_INCONSISTENT:
|
rlm@33
|
2863 strcat(errStr, ";\nSnapshot inconsistent with movie"); break;
|
rlm@33
|
2864 case MOVIE_WRONG_FORMAT:
|
rlm@33
|
2865 strcat(errStr, ";\nWrong format"); break;
|
rlm@33
|
2866 }
|
rlm@33
|
2867 strcat(errStr, ".");
|
rlm@33
|
2868 systemMessage(0, N_(errStr));
|
rlm@33
|
2869 goto failedLoadGB;
|
rlm@33
|
2870 }
|
rlm@1
|
2871 }
|
rlm@33
|
2872 utilGzRead(gzFile, &GBSystemCounters.frameCount, sizeof(GBSystemCounters.frameCount));
|
rlm@33
|
2873 }
|
rlm@33
|
2874
|
rlm@33
|
2875 if (version >= GBSAVE_GAME_VERSION_13) // new to rerecording 19.4 wip (svn r22+):
|
rlm@33
|
2876 {
|
rlm@33
|
2877 utilGzRead(gzFile, &GBSystemCounters.lagCount, sizeof(GBSystemCounters.lagCount));
|
rlm@33
|
2878 utilGzRead(gzFile, &GBSystemCounters.lagged, sizeof(GBSystemCounters.lagged));
|
rlm@33
|
2879 utilGzRead(gzFile, &GBSystemCounters.laggedLast, sizeof(GBSystemCounters.laggedLast));
|
rlm@33
|
2880 }
|
rlm@33
|
2881
|
rlm@33
|
2882 if (backupSafe)
|
rlm@33
|
2883 {
|
rlm@33
|
2884 remove(tempBackupName);
|
rlm@33
|
2885 tempFailCount = 0;
|
rlm@33
|
2886 }
|
rlm@33
|
2887
|
rlm@33
|
2888 for (int i = 0; i < 4; ++i)
|
rlm@33
|
2889 systemSetJoypad(i, gbJoymask[i] & 0xFFFF);
|
rlm@33
|
2890
|
rlm@33
|
2891 // FIXME: horrible kludge
|
rlm@33
|
2892 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask));
|
rlm@33
|
2893
|
rlm@33
|
2894 VBAUpdateButtonPressDisplay();
|
rlm@33
|
2895 VBAUpdateFrameCountDisplay();
|
rlm@33
|
2896 systemRefreshScreen();
|
rlm@33
|
2897 return true;
|
rlm@33
|
2898
|
rlm@33
|
2899 failedLoadGB:
|
rlm@33
|
2900 if (backupSafe)
|
rlm@33
|
2901 {
|
rlm@33
|
2902 tempFailCount++;
|
rlm@33
|
2903 if (tempFailCount < 3) // fail no more than 2 times in a row
|
rlm@33
|
2904 gbReadSaveState(tempBackupName);
|
rlm@33
|
2905 remove(tempBackupName);
|
rlm@33
|
2906 }
|
rlm@33
|
2907 return false;
|
rlm@1
|
2908 }
|
rlm@1
|
2909
|
rlm@1
|
2910 bool gbReadMemSaveState(char *memory, int available)
|
rlm@1
|
2911 {
|
rlm@33
|
2912 gzFile gzFile = utilMemGzOpen(memory, available, "r");
|
rlm@33
|
2913
|
rlm@33
|
2914 backupSafe = false;
|
rlm@33
|
2915 bool res = gbReadSaveStateFromStream(gzFile);
|
rlm@33
|
2916 backupSafe = true;
|
rlm@33
|
2917
|
rlm@33
|
2918 utilGzClose(gzFile);
|
rlm@33
|
2919
|
rlm@33
|
2920 return res;
|
rlm@1
|
2921 }
|
rlm@1
|
2922
|
rlm@1
|
2923 bool gbReadSaveState(const char *name)
|
rlm@1
|
2924 {
|
rlm@33
|
2925 gzFile gzFile = utilGzOpen(name, "rb");
|
rlm@33
|
2926
|
rlm@33
|
2927 if (gzFile == NULL)
|
rlm@33
|
2928 {
|
rlm@33
|
2929 return false;
|
rlm@33
|
2930 }
|
rlm@33
|
2931
|
rlm@33
|
2932 bool res = gbReadSaveStateFromStream(gzFile);
|
rlm@33
|
2933
|
rlm@33
|
2934 utilGzClose(gzFile);
|
rlm@33
|
2935
|
rlm@33
|
2936 return res;
|
rlm@1
|
2937 }
|
rlm@1
|
2938
|
rlm@1
|
2939 bool gbWritePNGFile(const char *fileName)
|
rlm@1
|
2940 {
|
rlm@33
|
2941 if (gbBorderOn)
|
rlm@33
|
2942 return utilWritePNGFile(fileName, 256, 224, pix);
|
rlm@33
|
2943 return utilWritePNGFile(fileName, 160, 144, pix);
|
rlm@1
|
2944 }
|
rlm@1
|
2945
|
rlm@1
|
2946 bool gbWriteBMPFile(const char *fileName)
|
rlm@1
|
2947 {
|
rlm@33
|
2948 if (gbBorderOn)
|
rlm@33
|
2949 return utilWriteBMPFile(fileName, 256, 224, pix);
|
rlm@33
|
2950 return utilWriteBMPFile(fileName, 160, 144, pix);
|
rlm@1
|
2951 }
|
rlm@1
|
2952
|
rlm@1
|
2953 void gbCleanUp()
|
rlm@1
|
2954 {
|
rlm@33
|
2955 newFrame = true;
|
rlm@33
|
2956
|
rlm@33
|
2957 GBSystemCounters.frameCount = 0;
|
rlm@33
|
2958 GBSystemCounters.lagCount = 0;
|
rlm@33
|
2959 GBSystemCounters.extraCount = 0;
|
rlm@33
|
2960 GBSystemCounters.lagged = true;
|
rlm@33
|
2961 GBSystemCounters.laggedLast = true;
|
rlm@33
|
2962
|
rlm@33
|
2963 if (gbRam != NULL)
|
rlm@33
|
2964 {
|
rlm@33
|
2965 free(gbRam);
|
rlm@33
|
2966 gbRam = NULL;
|
rlm@33
|
2967 }
|
rlm@33
|
2968
|
rlm@33
|
2969 if (gbRom != NULL)
|
rlm@33
|
2970 {
|
rlm@33
|
2971 free(gbRom);
|
rlm@33
|
2972 gbRom = NULL;
|
rlm@33
|
2973 }
|
rlm@33
|
2974
|
rlm@33
|
2975 if (gbMemory != NULL)
|
rlm@33
|
2976 {
|
rlm@33
|
2977 free(gbMemory);
|
rlm@33
|
2978 gbMemory = NULL;
|
rlm@33
|
2979 }
|
rlm@33
|
2980
|
rlm@33
|
2981 if (gbLineBuffer != NULL)
|
rlm@33
|
2982 {
|
rlm@33
|
2983 free(gbLineBuffer);
|
rlm@33
|
2984 gbLineBuffer = NULL;
|
rlm@33
|
2985 }
|
rlm@33
|
2986
|
rlm@33
|
2987 if (origPix != NULL)
|
rlm@33
|
2988 {
|
rlm@33
|
2989 free(origPix);
|
rlm@33
|
2990 origPix = NULL;
|
rlm@33
|
2991 }
|
rlm@33
|
2992 pix = NULL;
|
rlm@33
|
2993
|
rlm@33
|
2994 gbSgbShutdown();
|
rlm@33
|
2995
|
rlm@33
|
2996 if (gbVram != NULL)
|
rlm@33
|
2997 {
|
rlm@33
|
2998 free(gbVram);
|
rlm@33
|
2999 gbVram = NULL;
|
rlm@33
|
3000 }
|
rlm@33
|
3001
|
rlm@33
|
3002 if (gbWram != NULL)
|
rlm@33
|
3003 {
|
rlm@33
|
3004 free(gbWram);
|
rlm@33
|
3005 gbWram = NULL;
|
rlm@33
|
3006 }
|
rlm@33
|
3007
|
rlm@33
|
3008 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
rlm@33
|
3009
|
rlm@33
|
3010 memset(gbJoymask, 0, sizeof(gbJoymask));
|
rlm@33
|
3011 // FIXME: horrible kludge
|
rlm@33
|
3012 memset(s_gbJoymask, 0, sizeof(s_gbJoymask));
|
rlm@33
|
3013
|
rlm@33
|
3014 systemClearJoypads();
|
rlm@33
|
3015 systemResetSensor();
|
rlm@33
|
3016
|
rlm@33
|
3017 // gbLastTime = gbFrameCount = 0;
|
rlm@33
|
3018 systemRefreshScreen();
|
rlm@1
|
3019 }
|
rlm@1
|
3020
|
rlm@1
|
3021 bool gbLoadRom(const char *szFile)
|
rlm@1
|
3022 {
|
rlm@33
|
3023 int size = 0;
|
rlm@33
|
3024
|
rlm@33
|
3025 if (gbRom != NULL)
|
rlm@33
|
3026 {
|
rlm@33
|
3027 gbCleanUp();
|
rlm@33
|
3028 }
|
rlm@33
|
3029
|
rlm@33
|
3030 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
rlm@33
|
3031
|
rlm@33
|
3032 gbRom = utilLoad(szFile,
|
rlm@33
|
3033 utilIsGBImage,
|
rlm@33
|
3034 NULL,
|
rlm@33
|
3035 size);
|
rlm@33
|
3036 if (!gbRom)
|
rlm@33
|
3037 return false;
|
rlm@33
|
3038
|
rlm@33
|
3039 gbRomSize = size;
|
rlm@33
|
3040
|
rlm@33
|
3041 return gbUpdateSizes();
|
rlm@1
|
3042 }
|
rlm@1
|
3043
|
rlm@1
|
3044 bool gbUpdateSizes()
|
rlm@1
|
3045 {
|
rlm@33
|
3046 if (gbRom[0x148] > 8)
|
rlm@33
|
3047 {
|
rlm@33
|
3048 systemMessage(MSG_UNSUPPORTED_ROM_SIZE,
|
rlm@33
|
3049 N_("Unsupported rom size %02x"), gbRom[0x148]);
|
rlm@33
|
3050 return false;
|
rlm@33
|
3051 }
|
rlm@33
|
3052
|
rlm@33
|
3053 if (gbRomSize < gbRomSizes[gbRom[0x148]])
|
rlm@33
|
3054 {
|
rlm@33
|
3055 gbRom = (u8 *)realloc(gbRom, gbRomSizes[gbRom[0x148]]);
|
rlm@33
|
3056 }
|
rlm@33
|
3057 gbRomSize = gbRomSizes[gbRom[0x148]];
|
rlm@33
|
3058 gbRomSizeMask = gbRomSizesMasks[gbRom[0x148]];
|
rlm@33
|
3059
|
rlm@33
|
3060 if (gbRom[0x149] > 5)
|
rlm@33
|
3061 {
|
rlm@33
|
3062 systemMessage(MSG_UNSUPPORTED_RAM_SIZE,
|
rlm@33
|
3063 N_("Unsupported ram size %02x"), gbRom[0x149]);
|
rlm@33
|
3064 return false;
|
rlm@33
|
3065 }
|
rlm@33
|
3066
|
rlm@33
|
3067 gbRamSize = gbRamSizes[gbRom[0x149]];
|
rlm@33
|
3068 gbRamSizeMask = gbRamSizesMasks[gbRom[0x149]];
|
rlm@33
|
3069
|
rlm@33
|
3070 if (gbRamSize)
|
rlm@33
|
3071 {
|
rlm@33
|
3072 gbRam = (u8 *)malloc(gbRamSize + 4);
|
rlm@33
|
3073 memset(gbRam, 0xFF, gbRamSize + 4);
|
rlm@33
|
3074 }
|
rlm@33
|
3075
|
rlm@33
|
3076 int type = gbRom[0x147];
|
rlm@33
|
3077
|
rlm@33
|
3078 mapperReadRAM = NULL;
|
rlm@33
|
3079
|
rlm@33
|
3080 switch (type)
|
rlm@33
|
3081 {
|
rlm@33
|
3082 case 0x00:
|
rlm@33
|
3083 case 0x01:
|
rlm@33
|
3084 case 0x02:
|
rlm@33
|
3085 case 0x03:
|
rlm@33
|
3086 // MBC 1
|
rlm@33
|
3087 mapper = mapperMBC1ROM;
|
rlm@33
|
3088 mapperRAM = mapperMBC1RAM;
|
rlm@33
|
3089 break;
|
rlm@33
|
3090 case 0x05:
|
rlm@33
|
3091 case 0x06:
|
rlm@33
|
3092 // MBC2
|
rlm@33
|
3093 mapper = mapperMBC2ROM;
|
rlm@33
|
3094 mapperRAM = mapperMBC2RAM;
|
rlm@33
|
3095 gbRamSize = 0x200;
|
rlm@33
|
3096 gbRamSizeMask = 0x1ff;
|
rlm@33
|
3097 break;
|
rlm@33
|
3098 case 0x0f:
|
rlm@33
|
3099 case 0x10:
|
rlm@33
|
3100 case 0x11:
|
rlm@33
|
3101 case 0x12:
|
rlm@33
|
3102 case 0x13:
|
rlm@33
|
3103 // MBC 3
|
rlm@33
|
3104 mapper = mapperMBC3ROM;
|
rlm@33
|
3105 mapperRAM = mapperMBC3RAM;
|
rlm@33
|
3106 mapperReadRAM = mapperMBC3ReadRAM;
|
rlm@33
|
3107 break;
|
rlm@33
|
3108 case 0x19:
|
rlm@33
|
3109 case 0x1a:
|
rlm@33
|
3110 case 0x1b:
|
rlm@33
|
3111 // MBC5
|
rlm@33
|
3112 mapper = mapperMBC5ROM;
|
rlm@33
|
3113 mapperRAM = mapperMBC5RAM;
|
rlm@33
|
3114 break;
|
rlm@33
|
3115 case 0x1c:
|
rlm@33
|
3116 case 0x1d:
|
rlm@33
|
3117 case 0x1e:
|
rlm@33
|
3118 // MBC 5 Rumble
|
rlm@33
|
3119 mapper = mapperMBC5ROM;
|
rlm@33
|
3120 mapperRAM = mapperMBC5RAM;
|
rlm@33
|
3121 break;
|
rlm@33
|
3122 case 0x22:
|
rlm@33
|
3123 // MBC 7
|
rlm@33
|
3124 mapper = mapperMBC7ROM;
|
rlm@33
|
3125 mapperRAM = mapperMBC7RAM;
|
rlm@33
|
3126 mapperReadRAM = mapperMBC7ReadRAM;
|
rlm@33
|
3127 break;
|
rlm@33
|
3128 case 0xfe:
|
rlm@33
|
3129 // HuC3
|
rlm@33
|
3130 mapper = mapperHuC3ROM;
|
rlm@33
|
3131 mapperRAM = mapperHuC3RAM;
|
rlm@33
|
3132 mapperReadRAM = mapperHuC3ReadRAM;
|
rlm@33
|
3133 break;
|
rlm@33
|
3134 case 0xff:
|
rlm@33
|
3135 // HuC1
|
rlm@33
|
3136 mapper = mapperHuC1ROM;
|
rlm@33
|
3137 mapperRAM = mapperHuC1RAM;
|
rlm@33
|
3138 break;
|
rlm@33
|
3139 default:
|
rlm@33
|
3140 systemMessage(MSG_UNKNOWN_CARTRIDGE_TYPE,
|
rlm@33
|
3141 N_("Unknown cartridge type %02x"), type);
|
rlm@33
|
3142 return false;
|
rlm@33
|
3143 }
|
rlm@33
|
3144
|
rlm@33
|
3145 switch (type)
|
rlm@33
|
3146 {
|
rlm@33
|
3147 case 0x03:
|
rlm@33
|
3148 case 0x06:
|
rlm@33
|
3149 case 0x0f:
|
rlm@33
|
3150 case 0x10:
|
rlm@33
|
3151 case 0x13:
|
rlm@33
|
3152 case 0x1b:
|
rlm@33
|
3153 case 0x1d:
|
rlm@33
|
3154 case 0x1e:
|
rlm@33
|
3155 case 0x22:
|
rlm@33
|
3156 case 0xff:
|
rlm@33
|
3157 gbBattery = 1;
|
rlm@33
|
3158 break;
|
rlm@33
|
3159 }
|
rlm@33
|
3160
|
rlm@33
|
3161 gbInit();
|
rlm@33
|
3162 gbReset();
|
rlm@33
|
3163
|
rlm@33
|
3164 return true;
|
rlm@1
|
3165 }
|
rlm@1
|
3166
|
rlm@92
|
3167 int gbEmulate(int ticksToStop)
|
rlm@1
|
3168 {
|
rlm@92
|
3169 int rlm_count = 0;
|
rlm@39
|
3170 //printf("RLM: Inside the GB!\n");
|
rlm@33
|
3171 gbRegister tempRegister;
|
rlm@33
|
3172 u8 tempValue;
|
rlm@33
|
3173 s8 offset;
|
rlm@33
|
3174
|
rlm@33
|
3175 int clockTicks = 0;
|
rlm@33
|
3176 gbDmaTicks = 0;
|
rlm@33
|
3177
|
rlm@33
|
3178 register int opcode = 0;
|
rlm@33
|
3179
|
rlm@33
|
3180 u32 newmask = 0;
|
rlm@39
|
3181 //printf("RLM: newframe = %d\n", newFrame);
|
rlm@33
|
3182 if (newFrame)
|
rlm@33
|
3183 {
|
rlm@33
|
3184 extern void VBAOnExitingFrameBoundary();
|
rlm@33
|
3185 VBAOnExitingFrameBoundary();
|
rlm@39
|
3186 //printf("RLM: exiting frame boundary?\n");
|
rlm@33
|
3187 // update joystick information
|
rlm@33
|
3188 systemReadJoypads();
|
rlm@33
|
3189
|
rlm@33
|
3190 bool sensor = (gbRom[0x147] == 0x22);
|
rlm@33
|
3191
|
rlm@33
|
3192 // read joystick
|
rlm@33
|
3193 if (gbSgbMode && gbSgbMultiplayer)
|
rlm@1
|
3194 {
|
rlm@33
|
3195 if (gbSgbFourPlayers)
|
rlm@33
|
3196 {
|
rlm@33
|
3197 gbJoymask[0] = systemGetJoypad(0, sensor);
|
rlm@33
|
3198 gbJoymask[1] = systemGetJoypad(1, false);
|
rlm@33
|
3199 gbJoymask[2] = systemGetJoypad(2, false);
|
rlm@33
|
3200 gbJoymask[3] = systemGetJoypad(3, false);
|
rlm@33
|
3201 }
|
rlm@33
|
3202 else
|
rlm@33
|
3203 {
|
rlm@33
|
3204 gbJoymask[0] = systemGetJoypad(0, sensor);
|
rlm@33
|
3205 gbJoymask[1] = systemGetJoypad(1, false);
|
rlm@33
|
3206 }
|
rlm@33
|
3207 }
|
rlm@33
|
3208 else
|
rlm@33
|
3209 {
|
rlm@33
|
3210 gbJoymask[0] = systemGetJoypad(0, sensor);
|
rlm@33
|
3211 }
|
rlm@33
|
3212
|
rlm@33
|
3213 // FIXME: horrible kludge
|
rlm@33
|
3214 memcpy(s_gbJoymask, gbJoymask, sizeof(gbJoymask));
|
rlm@33
|
3215
|
rlm@33
|
3216 // if (sensor)
|
rlm@33
|
3217 // systemUpdateMotionSensor(0);
|
rlm@33
|
3218
|
rlm@33
|
3219 newmask = gbJoymask[0];
|
rlm@33
|
3220 if (newmask & 0xFF)
|
rlm@33
|
3221 {
|
rlm@33
|
3222 gbInterrupt |= 16;
|
rlm@33
|
3223 }
|
rlm@33
|
3224
|
rlm@33
|
3225 extButtons = (newmask >> 18);
|
rlm@525
|
3226 speedup = (extButtons & 1) != 0;
|
rlm@33
|
3227
|
rlm@33
|
3228 VBAMovieResetIfRequested();
|
rlm@39
|
3229 //printf("RLM: before Lua functions\n");
|
rlm@33
|
3230 //CallRegisteredLuaFunctions(LUACALL_BEFOREEMULATION);
|
rlm@39
|
3231 //printf("RLM: after Lua functions\n");
|
rlm@33
|
3232 newFrame = false;
|
rlm@33
|
3233 }
|
rlm@33
|
3234
|
rlm@33
|
3235
|
rlm@92
|
3236 //for (;; )
|
rlm@92
|
3237 // {
|
rlm@33
|
3238 #ifndef FINAL_VERSION
|
rlm@33
|
3239 if (systemDebug)
|
rlm@33
|
3240 {
|
rlm@33
|
3241 if (!(IFF & 0x80))
|
rlm@33
|
3242 {
|
rlm@33
|
3243 if (systemDebug > 1)
|
rlm@1
|
3244 {
|
rlm@33
|
3245 sprintf(gbBuffer, "PC=%04x AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x I=%04x\n",
|
rlm@33
|
3246 PC.W, AF.W, BC.W, DE.W, HL.W, SP.W, IFF);
|
rlm@33
|
3247 }
|
rlm@33
|
3248 else
|
rlm@33
|
3249 {
|
rlm@33
|
3250 sprintf(gbBuffer, "PC=%04x I=%02x\n", PC.W, IFF);
|
rlm@33
|
3251 }
|
rlm@33
|
3252 log(gbBuffer);
|
rlm@33
|
3253 }
|
rlm@33
|
3254 }
|
rlm@33
|
3255 #endif
|
rlm@33
|
3256 if (IFF & 0x80)
|
rlm@33
|
3257 {
|
rlm@33
|
3258 if (register_LCDC & 0x80)
|
rlm@33
|
3259 {
|
rlm@33
|
3260 clockTicks = gbLcdTicks;
|
rlm@33
|
3261 }
|
rlm@33
|
3262 else
|
rlm@33
|
3263 clockTicks = 100;
|
rlm@33
|
3264
|
rlm@33
|
3265 if (gbLcdMode == 1 && (gbLcdLYIncrementTicks < clockTicks))
|
rlm@33
|
3266 clockTicks = gbLcdLYIncrementTicks;
|
rlm@33
|
3267
|
rlm@33
|
3268 if (gbSerialOn && (gbSerialTicks < clockTicks))
|
rlm@33
|
3269 clockTicks = gbSerialTicks;
|
rlm@33
|
3270
|
rlm@33
|
3271 if (gbTimerOn && (gbTimerTicks < clockTicks))
|
rlm@33
|
3272 clockTicks = gbTimerTicks;
|
rlm@33
|
3273
|
rlm@33
|
3274 if (soundTicks && (soundTicks < clockTicks))
|
rlm@33
|
3275 clockTicks = soundTicks;
|
rlm@33
|
3276 }
|
rlm@33
|
3277 else
|
rlm@33
|
3278 {
|
rlm@33
|
3279 opcode = gbReadOpcode(PC.W);
|
rlm@92
|
3280 //printf("RLM: calling mem Hook ; %07d\n", rlm_count++);
|
rlm@92
|
3281 //CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC);
|
rlm@33
|
3282 PC.W++;
|
rlm@33
|
3283
|
rlm@33
|
3284 if (IFF & 0x100)
|
rlm@33
|
3285 {
|
rlm@33
|
3286 IFF &= 0xff;
|
rlm@33
|
3287 PC.W--;
|
rlm@33
|
3288 }
|
rlm@33
|
3289
|
rlm@33
|
3290 clockTicks = gbCycles[opcode];
|
rlm@33
|
3291
|
rlm@33
|
3292 switch (opcode)
|
rlm@33
|
3293 {
|
rlm@33
|
3294 case 0xCB:
|
rlm@33
|
3295 // extended opcode
|
rlm@33
|
3296 //CallRegisteredLuaMemHook(PC.W, 1, opcode, LUAMEMHOOK_EXEC); // is this desired?
|
rlm@33
|
3297 opcode = gbReadOpcode(PC.W++);
|
rlm@33
|
3298 clockTicks = gbCyclesCB[opcode];
|
rlm@33
|
3299 switch (opcode)
|
rlm@33
|
3300 {
|
rlm@33
|
3301 #include "gbCodesCB.h"
|
rlm@33
|
3302 }
|
rlm@33
|
3303 break;
|
rlm@33
|
3304 #include "gbCodes.h"
|
rlm@33
|
3305 }
|
rlm@33
|
3306 }
|
rlm@33
|
3307
|
rlm@33
|
3308 if (!emulating)
|
rlm@92
|
3309 return 1;
|
rlm@33
|
3310
|
rlm@33
|
3311 if (gbDmaTicks)
|
rlm@33
|
3312 {
|
rlm@33
|
3313 clockTicks += gbDmaTicks;
|
rlm@33
|
3314 gbDmaTicks = 0;
|
rlm@33
|
3315 }
|
rlm@33
|
3316
|
rlm@33
|
3317 if (gbSgbMode)
|
rlm@33
|
3318 {
|
rlm@33
|
3319 if (gbSgbPacketTimeout)
|
rlm@33
|
3320 {
|
rlm@33
|
3321 gbSgbPacketTimeout -= clockTicks;
|
rlm@33
|
3322
|
rlm@33
|
3323 if (gbSgbPacketTimeout <= 0)
|
rlm@33
|
3324 gbSgbResetPacketState();
|
rlm@33
|
3325 }
|
rlm@33
|
3326 }
|
rlm@33
|
3327
|
rlm@33
|
3328 ticksToStop -= clockTicks;
|
rlm@33
|
3329
|
rlm@33
|
3330 // DIV register emulation
|
rlm@33
|
3331 gbDivTicks -= clockTicks;
|
rlm@33
|
3332 while (gbDivTicks <= 0)
|
rlm@33
|
3333 {
|
rlm@33
|
3334 register_DIV++;
|
rlm@33
|
3335 gbDivTicks += GBDIV_CLOCK_TICKS;
|
rlm@33
|
3336 }
|
rlm@33
|
3337
|
rlm@33
|
3338 if (register_LCDC & 0x80)
|
rlm@33
|
3339 {
|
rlm@33
|
3340 // LCD stuff
|
rlm@33
|
3341 gbLcdTicks -= clockTicks;
|
rlm@33
|
3342 if (gbLcdMode == 1)
|
rlm@33
|
3343 {
|
rlm@33
|
3344 // during V-BLANK,we need to increment LY at the same rate!
|
rlm@33
|
3345 gbLcdLYIncrementTicks -= clockTicks;
|
rlm@33
|
3346 while (gbLcdLYIncrementTicks <= 0)
|
rlm@33
|
3347 {
|
rlm@33
|
3348 gbLcdLYIncrementTicks += GBLY_INCREMENT_CLOCK_TICKS;
|
rlm@33
|
3349
|
rlm@33
|
3350 if (register_LY < 153)
|
rlm@33
|
3351 {
|
rlm@33
|
3352 register_LY++;
|
rlm@33
|
3353
|
rlm@33
|
3354 gbCompareLYToLYC();
|
rlm@33
|
3355
|
rlm@33
|
3356 if (register_LY >= 153)
|
rlm@33
|
3357 gbLcdLYIncrementTicks = 6;
|
rlm@33
|
3358 }
|
rlm@33
|
3359 else
|
rlm@33
|
3360 {
|
rlm@33
|
3361 register_LY = 0x00;
|
rlm@33
|
3362 // reset the window line
|
rlm@33
|
3363 gbWindowLine = -1;
|
rlm@33
|
3364 gbLcdLYIncrementTicks = GBLY_INCREMENT_CLOCK_TICKS * 2;
|
rlm@33
|
3365 gbCompareLYToLYC();
|
rlm@33
|
3366 }
|
rlm@33
|
3367 }
|
rlm@33
|
3368 }
|
rlm@33
|
3369
|
rlm@33
|
3370 // our counter is off, see what we need to do
|
rlm@33
|
3371 while (gbLcdTicks <= 0)
|
rlm@33
|
3372 {
|
rlm@33
|
3373 int framesToSkip = systemFramesToSkip();
|
rlm@33
|
3374
|
rlm@33
|
3375 switch (gbLcdMode)
|
rlm@33
|
3376 {
|
rlm@33
|
3377 case 0:
|
rlm@33
|
3378 // H-Blank
|
rlm@33
|
3379 register_LY++;
|
rlm@33
|
3380
|
rlm@33
|
3381 gbCompareLYToLYC();
|
rlm@33
|
3382
|
rlm@33
|
3383 // check if we reached the V-Blank period
|
rlm@33
|
3384 if (register_LY == 144)
|
rlm@33
|
3385 {
|
rlm@33
|
3386 // Yes, V-Blank
|
rlm@33
|
3387 // set the LY increment counter
|
rlm@33
|
3388 gbLcdLYIncrementTicks = gbLcdTicks + GBLY_INCREMENT_CLOCK_TICKS;
|
rlm@33
|
3389 gbLcdTicks += GBLCD_MODE_1_CLOCK_TICKS;
|
rlm@33
|
3390 gbLcdMode = 1;
|
rlm@33
|
3391 if (register_LCDC & 0x80)
|
rlm@1
|
3392 {
|
rlm@33
|
3393 gbInterrupt |= 1; // V-Blank interrupt
|
rlm@33
|
3394 gbInterruptWait = 6;
|
rlm@33
|
3395 if (register_STAT & 0x10)
|
rlm@33
|
3396 gbInterrupt |= 2;
|
rlm@1
|
3397 }
|
rlm@33
|
3398
|
rlm@33
|
3399 systemFrame();
|
rlm@33
|
3400
|
rlm@33
|
3401 ++gbFrameCount;
|
rlm@33
|
3402 u32 currentTime = systemGetClock();
|
rlm@33
|
3403 if (currentTime - gbLastTime >= 1000)
|
rlm@1
|
3404 {
|
rlm@33
|
3405 systemShowSpeed(int(float(gbFrameCount) * 100000 / (float(currentTime - gbLastTime) * 60) + .5f));
|
rlm@33
|
3406 gbLastTime = currentTime;
|
rlm@33
|
3407 gbFrameCount = 0;
|
rlm@1
|
3408 }
|
rlm@33
|
3409
|
rlm@33
|
3410 ++GBSystemCounters.frameCount;
|
rlm@33
|
3411 if (GBSystemCounters.lagged)
|
rlm@33
|
3412 {
|
rlm@33
|
3413 ++GBSystemCounters.lagCount;
|
rlm@33
|
3414 }
|
rlm@33
|
3415 GBSystemCounters.laggedLast = GBSystemCounters.lagged;
|
rlm@33
|
3416 GBSystemCounters.lagged = true;
|
rlm@33
|
3417
|
rlm@33
|
3418 extern void VBAOnEnteringFrameBoundary();
|
rlm@33
|
3419 VBAOnEnteringFrameBoundary();
|
rlm@33
|
3420
|
rlm@33
|
3421 newFrame = true;
|
rlm@33
|
3422
|
rlm@33
|
3423 pauseAfterFrameAdvance = systemPauseOnFrame();
|
rlm@33
|
3424
|
rlm@33
|
3425 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance)
|
rlm@33
|
3426 {
|
rlm@33
|
3427 if (gbBorderOn)
|
rlm@33
|
3428 gbSgbRenderBorder(); // clear unnecessary things on border (e.g. in-game text message)
|
rlm@33
|
3429
|
rlm@33
|
3430 systemRenderFrame();
|
rlm@33
|
3431 gbFrameSkipCount = 0;
|
rlm@33
|
3432
|
rlm@33
|
3433 bool capturePressed = (extButtons & 2) != 0;
|
rlm@33
|
3434 if (capturePressed && !capturePrevious)
|
rlm@33
|
3435 {
|
rlm@33
|
3436 captureNumber = systemScreenCapture(captureNumber);
|
rlm@33
|
3437 }
|
rlm@33
|
3438 capturePrevious = capturePressed && !pauseAfterFrameAdvance;
|
rlm@33
|
3439 }
|
rlm@33
|
3440 else
|
rlm@33
|
3441 {
|
rlm@33
|
3442 ++gbFrameSkipCount;
|
rlm@33
|
3443 }
|
rlm@33
|
3444
|
rlm@33
|
3445 if (pauseAfterFrameAdvance)
|
rlm@33
|
3446 {
|
rlm@33
|
3447 systemSetPause(true);
|
rlm@33
|
3448 }
|
rlm@33
|
3449 }
|
rlm@33
|
3450 else
|
rlm@33
|
3451 {
|
rlm@33
|
3452 // go the the OAM being accessed mode
|
rlm@33
|
3453 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
|
rlm@33
|
3454 gbLcdMode = 2;
|
rlm@33
|
3455
|
rlm@33
|
3456 // only one LCD interrupt per line. may need to generalize...
|
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 }
|
rlm@33
|
3464
|
rlm@33
|
3465 break;
|
rlm@33
|
3466 case 1:
|
rlm@33
|
3467 // V-Blank
|
rlm@33
|
3468 // next mode is OAM being accessed mode
|
rlm@33
|
3469 gbLcdTicks += GBLCD_MODE_2_CLOCK_TICKS;
|
rlm@33
|
3470 gbLcdMode = 2;
|
rlm@33
|
3471 if (!(register_STAT & 0x40) ||
|
rlm@33
|
3472 (register_LY != register_LYC))
|
rlm@33
|
3473 {
|
rlm@33
|
3474 if ((register_STAT & 0x28) == 0x20)
|
rlm@33
|
3475 gbInterrupt |= 2;
|
rlm@33
|
3476 }
|
rlm@33
|
3477 break;
|
rlm@33
|
3478 case 2:
|
rlm@33
|
3479 // OAM being accessed mode
|
rlm@33
|
3480
|
rlm@33
|
3481 // next mode is OAM and VRAM in use
|
rlm@33
|
3482 gbLcdTicks += GBLCD_MODE_3_CLOCK_TICKS;
|
rlm@33
|
3483 gbLcdMode = 3;
|
rlm@33
|
3484 break;
|
rlm@33
|
3485 case 3:
|
rlm@33
|
3486 // OAM and VRAM in use
|
rlm@33
|
3487 // next mode is H-Blank
|
rlm@33
|
3488 if (register_LY < 144)
|
rlm@33
|
3489 {
|
rlm@33
|
3490 if (!gbSgbMask)
|
rlm@33
|
3491 {
|
rlm@33
|
3492 if (gbFrameSkipCount >= framesToSkip || pauseAfterFrameAdvance)
|
rlm@33
|
3493 {
|
rlm@33
|
3494 gbRenderLine();
|
rlm@33
|
3495 gbDrawSprites();
|
rlm@33
|
3496
|
rlm@33
|
3497 switch (systemColorDepth)
|
rlm@33
|
3498 {
|
rlm@33
|
3499 case 16:
|
rlm@33
|
3500
|
rlm@33
|
3501 {
|
rlm@33
|
3502 u16 *dest = (u16 *)pix +
|
rlm@33
|
3503 (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1)
|
rlm@33
|
3504 + gbBorderColumnSkip;
|
rlm@33
|
3505 for (int x = 0; x < 160; )
|
rlm@33
|
3506 {
|
rlm@33
|
3507 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3508 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3509 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3510 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3511
|
rlm@33
|
3512 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3513 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3514 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3515 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3516
|
rlm@33
|
3517 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3518 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3519 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3520 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3521
|
rlm@33
|
3522 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3523 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3524 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3525 *dest++ = systemColorMap16[gbLineMix[x++]];
|
rlm@33
|
3526 }
|
rlm@33
|
3527 if (gbBorderOn)
|
rlm@33
|
3528 dest += gbBorderColumnSkip;
|
rlm@33
|
3529 *dest++ = 0; // for filters that read one pixel more
|
rlm@33
|
3530 break;
|
rlm@33
|
3531 }
|
rlm@33
|
3532 case 24:
|
rlm@33
|
3533
|
rlm@33
|
3534 {
|
rlm@33
|
3535 u8 *dest = (u8 *)pix +
|
rlm@33
|
3536 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) +
|
rlm@33
|
3537 gbBorderColumnSkip);
|
rlm@33
|
3538 for (int x = 0; x < 160; )
|
rlm@33
|
3539 {
|
rlm@33
|
3540 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3541 dest += 3;
|
rlm@33
|
3542 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3543 dest += 3;
|
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
|
rlm@33
|
3549 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3550 dest += 3;
|
rlm@33
|
3551 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3552 dest += 3;
|
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
|
rlm@33
|
3558 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3559 dest += 3;
|
rlm@33
|
3560 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3561 dest += 3;
|
rlm@33
|
3562 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3563 dest += 3;
|
rlm@33
|
3564 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3565 dest += 3;
|
rlm@33
|
3566
|
rlm@33
|
3567 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3568 dest += 3;
|
rlm@33
|
3569 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3570 dest += 3;
|
rlm@33
|
3571 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3572 dest += 3;
|
rlm@33
|
3573 *((u32 *)dest) = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3574 dest += 3;
|
rlm@33
|
3575 }
|
rlm@33
|
3576 break;
|
rlm@33
|
3577 }
|
rlm@33
|
3578 case 32:
|
rlm@33
|
3579
|
rlm@33
|
3580 {
|
rlm@33
|
3581 u32 *dest = (u32 *)pix +
|
rlm@33
|
3582 (gbBorderLineSkip + 1) * (register_LY + gbBorderRowSkip + 1)
|
rlm@33
|
3583 + gbBorderColumnSkip;
|
rlm@33
|
3584 for (int x = 0; x < 160; )
|
rlm@33
|
3585 {
|
rlm@33
|
3586 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3587 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3588 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3589 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3590
|
rlm@33
|
3591 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3592 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3593 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3594 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3595
|
rlm@33
|
3596 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3597 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3598 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3599 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3600
|
rlm@33
|
3601 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3602 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3603 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3604 *dest++ = systemColorMap32[gbLineMix[x++]];
|
rlm@33
|
3605 }
|
rlm@33
|
3606 break;
|
rlm@33
|
3607 }
|
rlm@33
|
3608 }
|
rlm@33
|
3609 }
|
rlm@33
|
3610 }
|
rlm@33
|
3611 }
|
rlm@33
|
3612 gbLcdTicks += GBLCD_MODE_0_CLOCK_TICKS;
|
rlm@33
|
3613 gbLcdMode = 0;
|
rlm@33
|
3614 // only one LCD interrupt per line. may need to generalize...
|
rlm@33
|
3615 if (!(register_STAT & 0x40) ||
|
rlm@33
|
3616 (register_LY != register_LYC))
|
rlm@33
|
3617 {
|
rlm@33
|
3618 if (register_STAT & 0x08)
|
rlm@33
|
3619 gbInterrupt |= 2;
|
rlm@33
|
3620 }
|
rlm@33
|
3621 if (gbHdmaOn)
|
rlm@33
|
3622 {
|
rlm@33
|
3623 gbDoHdma();
|
rlm@33
|
3624 }
|
rlm@33
|
3625 break;
|
rlm@1
|
3626 }
|
rlm@33
|
3627 // mark the correct lcd mode on STAT register
|
rlm@33
|
3628 register_STAT = (register_STAT & 0xfc) | gbLcdMode;
|
rlm@33
|
3629 }
|
rlm@33
|
3630 }
|
rlm@33
|
3631
|
rlm@33
|
3632 // serial emulation
|
rlm@33
|
3633 if (gbSerialOn)
|
rlm@33
|
3634 {
|
rlm@33
|
3635 #ifdef LINK_EMULATION
|
rlm@33
|
3636 if (linkConnected)
|
rlm@33
|
3637 {
|
rlm@33
|
3638 gbSerialTicks -= clockTicks;
|
rlm@33
|
3639
|
rlm@33
|
3640 while (gbSerialTicks <= 0)
|
rlm@1
|
3641 {
|
rlm@33
|
3642 // increment number of shifted bits
|
rlm@33
|
3643 gbSerialBits++;
|
rlm@33
|
3644 linkProc();
|
rlm@33
|
3645 if (gbSerialOn && (gbMemory[0xff02] & 1))
|
rlm@33
|
3646 {
|
rlm@33
|
3647 if (gbSerialBits == 8)
|
rlm@33
|
3648 {
|
rlm@33
|
3649 gbSerialBits = 0;
|
rlm@33
|
3650 gbMemory[0xff01] = 0xff;
|
rlm@33
|
3651 gbMemory[0xff02] &= 0x7f;
|
rlm@33
|
3652 gbSerialOn = 0;
|
rlm@33
|
3653 gbInterrupt |= 8;
|
rlm@33
|
3654 gbSerialTicks = 0;
|
rlm@33
|
3655 }
|
rlm@33
|
3656 }
|
rlm@33
|
3657 gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
rlm@1
|
3658 }
|
rlm@33
|
3659 }
|
rlm@33
|
3660 else
|
rlm@33
|
3661 {
|
rlm@33
|
3662 #endif
|
rlm@33
|
3663 if (gbMemory[0xff02] & 1)
|
rlm@1
|
3664 {
|
rlm@33
|
3665 gbSerialTicks -= clockTicks;
|
rlm@33
|
3666
|
rlm@33
|
3667 // overflow
|
rlm@33
|
3668 while (gbSerialTicks <= 0)
|
rlm@33
|
3669 {
|
rlm@33
|
3670 // shift serial byte to right and put a 1 bit in its place
|
rlm@33
|
3671 // gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
rlm@33
|
3672 // increment number of shifted bits
|
rlm@33
|
3673 gbSerialBits++;
|
rlm@33
|
3674 if (gbSerialBits == 8)
|
rlm@33
|
3675 {
|
rlm@33
|
3676 // end of transmission
|
rlm@33
|
3677 if (gbSerialFunction) // external device
|
rlm@33
|
3678 gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
|
rlm@33
|
3679 else
|
rlm@33
|
3680 gbMemory[0xff01] = 0xff;
|
rlm@33
|
3681 gbSerialTicks = 0;
|
rlm@33
|
3682 gbMemory[0xff02] &= 0x7f;
|
rlm@33
|
3683 gbSerialOn = 0;
|
rlm@33
|
3684 gbInterrupt |= 8;
|
rlm@33
|
3685 gbSerialBits = 0;
|
rlm@33
|
3686 }
|
rlm@33
|
3687 else
|
rlm@33
|
3688 gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
rlm@33
|
3689 }
|
rlm@1
|
3690 }
|
rlm@33
|
3691 #ifdef LINK_EMULATION
|
rlm@33
|
3692 }
|
rlm@33
|
3693 #endif
|
rlm@1
|
3694 }
|
rlm@1
|
3695
|
rlm@33
|
3696 // timer emulation
|
rlm@33
|
3697 if (gbTimerOn)
|
rlm@1
|
3698 {
|
rlm@33
|
3699 gbTimerTicks -= clockTicks;
|
rlm@33
|
3700
|
rlm@33
|
3701 while (gbTimerTicks <= 0)
|
rlm@33
|
3702 {
|
rlm@33
|
3703 register_TIMA++;
|
rlm@33
|
3704
|
rlm@33
|
3705 if (register_TIMA == 0)
|
rlm@1
|
3706 {
|
rlm@33
|
3707 // timer overflow!
|
rlm@33
|
3708
|
rlm@33
|
3709 // reload timer modulo
|
rlm@33
|
3710 register_TIMA = register_TMA;
|
rlm@33
|
3711
|
rlm@33
|
3712 // flag interrupt
|
rlm@33
|
3713 gbInterrupt |= 4;
|
rlm@33
|
3714 }
|
rlm@33
|
3715
|
rlm@33
|
3716 gbTimerTicks += gbTimerClockTicks;
|
rlm@33
|
3717 }
|
rlm@33
|
3718 }
|
rlm@33
|
3719
|
rlm@33
|
3720 /*
|
rlm@33
|
3721 if(soundOffFlag)
|
rlm@33
|
3722 {
|
rlm@33
|
3723 if(synchronize && !speedup)
|
rlm@33
|
3724 {
|
rlm@33
|
3725 synchronizeTicks -= clockTicks;
|
rlm@33
|
3726
|
rlm@33
|
3727 while(synchronizeTicks < 0)
|
rlm@33
|
3728 {
|
rlm@33
|
3729 synchronizeTicks += SYNCHRONIZE_CLOCK_TICKS;
|
rlm@33
|
3730
|
rlm@33
|
3731 DWORD now = timeGetTime();
|
rlm@33
|
3732 gbElapsedTime += (now - timeNow);
|
rlm@33
|
3733
|
rlm@33
|
3734 if(gbElapsedTime < 50)
|
rlm@33
|
3735 {
|
rlm@33
|
3736 DWORD diff = 50 - gbElapsedTime;
|
rlm@33
|
3737 Sleep(diff);
|
rlm@33
|
3738 timeNow = timeGetTime();
|
rlm@33
|
3739 elapsedTime = timeNow - now - diff;
|
rlm@33
|
3740 if((int)elapsedTime < 0)
|
rlm@33
|
3741 elapsedTime = 0;
|
rlm@33
|
3742 } else
|
rlm@33
|
3743 {
|
rlm@33
|
3744 timeNow = timeGetTime();
|
rlm@33
|
3745 elapsedTime = 0;
|
rlm@33
|
3746 }
|
rlm@33
|
3747 }
|
rlm@33
|
3748 }
|
rlm@33
|
3749 }
|
rlm@33
|
3750 */
|
rlm@33
|
3751
|
rlm@33
|
3752 soundTicks -= clockTicks;
|
rlm@33
|
3753 while (soundTicks < 0) // must be < 1 when soundtick_t is real data type
|
rlm@33
|
3754 {
|
rlm@33
|
3755 soundTicks += SOUND_CLOCK_TICKS;
|
rlm@527
|
3756 //printf("RLM: gbSoundTick()\n");
|
rlm@33
|
3757 gbSoundTick();
|
rlm@33
|
3758 }
|
rlm@33
|
3759
|
rlm@33
|
3760 register_IF = gbInterrupt;
|
rlm@33
|
3761
|
rlm@33
|
3762 if (IFF & 0x20)
|
rlm@33
|
3763 {
|
rlm@33
|
3764 IFF &= 0xdf;
|
rlm@33
|
3765 IFF |= 0x01;
|
rlm@33
|
3766 gbInterruptWait = 0;
|
rlm@33
|
3767 }
|
rlm@33
|
3768 else if (gbInterrupt)
|
rlm@33
|
3769 {
|
rlm@33
|
3770 if (gbInterruptWait == 0)
|
rlm@33
|
3771 {
|
rlm@33
|
3772 // gbInterruptWait = 0;
|
rlm@33
|
3773
|
rlm@33
|
3774 if (IFF & 0x01)
|
rlm@33
|
3775 {
|
rlm@33
|
3776 if ((gbInterrupt & 1) && (register_IE & 1))
|
rlm@33
|
3777 {
|
rlm@33
|
3778 gbVblank_interrupt();
|
rlm@92
|
3779 return newFrame;
|
rlm@33
|
3780 }
|
rlm@33
|
3781
|
rlm@33
|
3782 if ((gbInterrupt & 2) && (register_IE & 2))
|
rlm@33
|
3783 {
|
rlm@33
|
3784 gbLcd_interrupt();
|
rlm@92
|
3785 return newFrame;
|
rlm@33
|
3786 }
|
rlm@33
|
3787
|
rlm@33
|
3788 if ((gbInterrupt & 4) && (register_IE & 4))
|
rlm@33
|
3789 {
|
rlm@33
|
3790 gbTimer_interrupt();
|
rlm@92
|
3791 return newFrame;
|
rlm@33
|
3792 }
|
rlm@33
|
3793
|
rlm@33
|
3794 if ((gbInterrupt & 8) && (register_IE & 8))
|
rlm@33
|
3795 {
|
rlm@33
|
3796 gbSerial_interrupt();
|
rlm@92
|
3797 return newFrame;
|
rlm@33
|
3798 }
|
rlm@33
|
3799
|
rlm@33
|
3800 if ((gbInterrupt & 16) && (register_IE & 16))
|
rlm@33
|
3801 {
|
rlm@33
|
3802 gbJoypad_interrupt();
|
rlm@92
|
3803 return newFrame;
|
rlm@33
|
3804 }
|
rlm@33
|
3805 }
|
rlm@33
|
3806 }
|
rlm@33
|
3807 else
|
rlm@33
|
3808 {
|
rlm@33
|
3809 gbInterruptWait -= clockTicks;
|
rlm@33
|
3810 if (gbInterruptWait < 0)
|
rlm@33
|
3811 gbInterruptWait = 0;
|
rlm@33
|
3812 }
|
rlm@33
|
3813 }
|
rlm@33
|
3814
|
rlm@33
|
3815 if (useOldFrameTiming)
|
rlm@33
|
3816 {
|
rlm@33
|
3817 // old timing code
|
rlm@33
|
3818 if (ticksToStop > 0)
|
rlm@92
|
3819 return newFrame;
|
rlm@33
|
3820 }
|
rlm@33
|
3821 else
|
rlm@33
|
3822 {
|
rlm@33
|
3823 if (!newFrame && (register_LCDC & 0x80) != 0)
|
rlm@92
|
3824 return newFrame;
|
rlm@33
|
3825 }
|
rlm@33
|
3826
|
rlm@33
|
3827 if (!(register_LCDC & 0x80))
|
rlm@33
|
3828 {
|
rlm@33
|
3829 if (!useOldFrameTiming)
|
rlm@33
|
3830 {
|
rlm@33
|
3831 // FIXME: since register_LY can be reset to 0 by some games, frame length is variable
|
rlm@33
|
3832 // and infinite loops can occurr
|
rlm@33
|
3833 // for now, it IS necessary to do something on this condition or games like
|
rlm@33
|
3834 // Megaman would freeze upon low-level restart interrupt sequence (Start+Select+A+B).
|
rlm@33
|
3835 // the only sensible way to fix this issue is to implement the RIGHT frame timing
|
rlm@33
|
3836 #ifdef WANTS_INCOMPLETE_WORKAROUND
|
rlm@33
|
3837 if (systemReadJoypads())
|
rlm@33
|
3838 {
|
rlm@33
|
3839 if (gbSgbMode && gbSgbMultiplayer)
|
rlm@33
|
3840 {
|
rlm@33
|
3841 if (gbSgbFourPlayers)
|
rlm@1
|
3842 {
|
rlm@33
|
3843 gbJoymask[0] = systemGetJoypad(0, false);
|
rlm@33
|
3844 gbJoymask[1] = systemGetJoypad(1, false);
|
rlm@33
|
3845 gbJoymask[2] = systemGetJoypad(2, false);
|
rlm@33
|
3846 gbJoymask[3] = systemGetJoypad(3, false);
|
rlm@1
|
3847 }
|
rlm@33
|
3848 else
|
rlm@33
|
3849 {
|
rlm@33
|
3850 gbJoymask[0] = systemGetJoypad(0, false);
|
rlm@33
|
3851 gbJoymask[1] = systemGetJoypad(1, false);
|
rlm@33
|
3852 }
|
rlm@33
|
3853 }
|
rlm@33
|
3854 else
|
rlm@33
|
3855 {
|
rlm@33
|
3856 gbJoymask[0] = systemGetJoypad(0, false);
|
rlm@33
|
3857 }
|
rlm@1
|
3858 }
|
rlm@33
|
3859 else
|
rlm@33
|
3860 gbJoymask[0] = gbJoymask[1] = gbJoymask[2] = gbJoymask[3] = 0;
|
rlm@1
|
3861 #else
|
rlm@1
|
3862 #endif
|
rlm@33
|
3863 }
|
rlm@1
|
3864 }
|
rlm@33
|
3865
|
rlm@33
|
3866 // makes sure frames are really divided across input sampling boundaries which occur at a constant rate
|
rlm@92
|
3867 //if (newFrame || useOldFrameTiming)
|
rlm@92
|
3868 // {
|
rlm@33
|
3869 /// extern void VBAOnEnteringFrameBoundary();
|
rlm@33
|
3870 /// VBAOnEnteringFrameBoundary();
|
rlm@33
|
3871
|
rlm@92
|
3872 // break;
|
rlm@92
|
3873 // }
|
rlm@92
|
3874 // RLM removing for loop }
|
rlm@92
|
3875 return newFrame;
|
rlm@1
|
3876 }
|
rlm@1
|
3877
|
rlm@59
|
3878
|
rlm@59
|
3879
|
rlm@59
|
3880 //RLM:
|
rlm@496
|
3881 /**
|
rlm@496
|
3882 void getPixels32(int32* store){
|
rlm@496
|
3883 utilWriteBMP((u8*)store, 144, 160, 32, pix);
|
rlm@496
|
3884 }
|
rlm@496
|
3885 **/
|
rlm@496
|
3886
|
rlm@496
|
3887 void getPixels32(int32* store){
|
rlm@496
|
3888 int w = 160;
|
rlm@496
|
3889 int h = 144;
|
rlm@496
|
3890
|
rlm@496
|
3891 int sizeX = w;
|
rlm@496
|
3892 int sizeY = h;
|
rlm@497
|
3893
|
rlm@497
|
3894 store += w * (h - 1);
|
rlm@496
|
3895
|
rlm@496
|
3896 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
|
rlm@496
|
3897 for (int y = 0; y < sizeY; y++)
|
rlm@496
|
3898 {
|
rlm@496
|
3899 for (int x = 0; x < sizeX; x++)
|
rlm@496
|
3900 {
|
rlm@496
|
3901 u32 v = *pixU32++;
|
rlm@496
|
3902
|
rlm@496
|
3903 u8 b = ((v >> systemBlueShift) & 0x001f) << 3; // B
|
rlm@496
|
3904 u8 g = ((v >> systemGreenShift) & 0x001f) << 3; // G
|
rlm@496
|
3905 u8 r = ((v >> systemRedShift) & 0x001f) << 3; // R
|
rlm@496
|
3906
|
rlm@496
|
3907 int32 rgb = (r << 16 ) + (g << 8) + b;
|
rlm@496
|
3908 *store++ = rgb;
|
rlm@496
|
3909 }
|
rlm@497
|
3910 store -= (2 * w);
|
rlm@496
|
3911 pixU32++;
|
rlm@496
|
3912 pixU32 -= 2 * (w + 1);
|
rlm@496
|
3913 }
|
rlm@496
|
3914 }
|
rlm@496
|
3915
|
rlm@496
|
3916
|
rlm@59
|
3917 int getRamSize(){
|
rlm@59
|
3918 return gbRamSize;
|
rlm@59
|
3919 }
|
rlm@59
|
3920
|
rlm@59
|
3921 int getRomSize(){
|
rlm@59
|
3922 return gbRomSize;
|
rlm@59
|
3923 }
|
rlm@59
|
3924
|
rlm@93
|
3925 void storeMemory(int32* store){
|
rlm@93
|
3926 int i;
|
rlm@94
|
3927 int j;
|
rlm@94
|
3928 for (i = 0; i < 0x10; i++){
|
rlm@94
|
3929 for (j = 0; j < 0x1000; j++){
|
rlm@94
|
3930 store[i*0x1000 + j] = (int32) gbMemoryMap[i][j];
|
rlm@94
|
3931 }
|
rlm@93
|
3932 }
|
rlm@93
|
3933 }
|
rlm@93
|
3934
|
rlm@96
|
3935 void writeMemory(int32* newMemory){
|
rlm@96
|
3936 int i;
|
rlm@96
|
3937 int j;
|
rlm@96
|
3938 for (i = 0; i < 0x10; i++){
|
rlm@96
|
3939 for (j = 0; j< 0x1000; j++){
|
rlm@96
|
3940 gbMemoryMap[i][j] = (u8)(0xFF & newMemory[i*0x1000 + j]);
|
rlm@96
|
3941 }
|
rlm@96
|
3942 }
|
rlm@96
|
3943 }
|
rlm@96
|
3944
|
rlm@60
|
3945 void storeRam(int32* store){
|
rlm@60
|
3946 int i;
|
rlm@60
|
3947 for (i = 0; i < gbRamSize; i++){
|
rlm@60
|
3948 store[i] = (int32) gbRam[i];
|
rlm@60
|
3949 }
|
rlm@60
|
3950 }
|
rlm@60
|
3951
|
rlm@61
|
3952 void storeRom(int32* store){
|
rlm@61
|
3953 int i;
|
rlm@61
|
3954 for (i = 0; i < gbRomSize; i++){
|
rlm@61
|
3955 store[i] = (int32) gbRom[i];
|
rlm@61
|
3956 }
|
rlm@61
|
3957 }
|
rlm@61
|
3958
|
rlm@191
|
3959 void writeRom(int32* new_rom){
|
rlm@191
|
3960 int i;
|
rlm@191
|
3961 for (i = 0; i < gbRomSize; i++){
|
rlm@191
|
3962 gbRom[i] = (u8)(0xFF & new_rom[i]);
|
rlm@191
|
3963 }
|
rlm@191
|
3964 }
|
rlm@191
|
3965
|
rlm@61
|
3966 void storeWRam(int32* store){
|
rlm@61
|
3967 int i;
|
rlm@61
|
3968 for (i = 0; i < 0x8000; i++){
|
rlm@61
|
3969 store[i] = (int32) gbWram[i];
|
rlm@61
|
3970 }
|
rlm@61
|
3971 }
|
rlm@61
|
3972
|
rlm@61
|
3973 void storeVRam(int32* store){
|
rlm@61
|
3974 int i;
|
rlm@61
|
3975 for (i = 0; i < 0x4000; i++){
|
rlm@61
|
3976 store[i] = (int32) gbVram[i];
|
rlm@61
|
3977 }
|
rlm@61
|
3978 }
|
rlm@61
|
3979
|
rlm@100
|
3980
|
rlm@62
|
3981 void storeRegisters(int32* store){
|
rlm@62
|
3982 store[0] = (int32) PC.W;
|
rlm@62
|
3983 store[1] = (int32) SP.W;
|
rlm@62
|
3984 store[2] = (int32) AF.W;
|
rlm@62
|
3985 store[3] = (int32) BC.W;
|
rlm@62
|
3986 store[4] = (int32) DE.W;
|
rlm@62
|
3987 store[5] = (int32) HL.W;
|
rlm@100
|
3988
|
rlm@100
|
3989 store[6] = (int32) IFF;
|
rlm@100
|
3990
|
rlm@100
|
3991 store[7] = (int32) register_DIV;
|
rlm@100
|
3992 store[8] = (int32) register_TIMA;
|
rlm@100
|
3993 store[9] = (int32) register_TMA;
|
rlm@100
|
3994 store[10] = (int32) register_TAC;
|
rlm@100
|
3995 store[11] = (int32) register_IF;
|
rlm@100
|
3996 store[12] = (int32) register_LCDC;
|
rlm@100
|
3997 store[13] = (int32) register_STAT;
|
rlm@100
|
3998 store[14] = (int32) register_SCY;
|
rlm@100
|
3999 store[15] = (int32) register_SCX;
|
rlm@100
|
4000 store[16] = (int32) register_LY;
|
rlm@100
|
4001 store[17] = (int32) register_LYC;
|
rlm@100
|
4002 store[18] = (int32) register_DMA;
|
rlm@100
|
4003 store[19] = (int32) register_WY;
|
rlm@100
|
4004 store[20] = (int32) register_WX;
|
rlm@100
|
4005 store[21] = (int32) register_VBK;
|
rlm@100
|
4006 store[22] = (int32) register_HDMA1;
|
rlm@100
|
4007 store[23] = (int32) register_HDMA2;
|
rlm@100
|
4008 store[24] = (int32) register_HDMA3;
|
rlm@100
|
4009 store[25] = (int32) register_HDMA4;
|
rlm@100
|
4010 store[26] = (int32) register_HDMA5;
|
rlm@100
|
4011 store[27] = (int32) register_SVBK;
|
rlm@100
|
4012 store[28] = (int32) register_IE;
|
rlm@100
|
4013 }
|
rlm@100
|
4014
|
rlm@100
|
4015 void setRegisters(int32* registers){
|
rlm@100
|
4016 PC.W = (u16) (0xFFFF & registers[0]);
|
rlm@100
|
4017 SP.W = (u16) (0xFFFF & registers[1]);
|
rlm@100
|
4018 AF.W = (u16) (0xFFFF & registers[2]);
|
rlm@100
|
4019 BC.W = (u16) (0xFFFF & registers[3]);
|
rlm@100
|
4020 DE.W = (u16) (0xFFFF & registers[4]);
|
rlm@100
|
4021 HL.W = (u16) (0xFFFF & registers[5]);
|
rlm@100
|
4022 IFF = (u16) (0xFFFF & registers[6]);
|
rlm@100
|
4023
|
rlm@100
|
4024 register_DIV = (u8) (0xFF & registers[7]);
|
rlm@100
|
4025 register_TIMA = (u8) (0xFF & registers[8]);
|
rlm@100
|
4026 register_TMA = (u8) (0xFF & registers[9]);
|
rlm@100
|
4027 register_TAC = (u8) (0xFF & registers[10]);
|
rlm@100
|
4028 register_IF = (u8) (0xFF & registers[11]);
|
rlm@100
|
4029 register_LCDC = (u8) (0xFF & registers[12]);
|
rlm@100
|
4030 register_STAT = (u8) (0xFF & registers[13]);
|
rlm@100
|
4031 register_SCY = (u8) (0xFF & registers[14]);
|
rlm@100
|
4032 register_SCX = (u8) (0xFF & registers[15]);
|
rlm@100
|
4033 register_LY = (u8) (0xFF & registers[16]);
|
rlm@100
|
4034 register_LYC = (u8) (0xFF & registers[17]);
|
rlm@100
|
4035 register_DMA = (u8) (0xFF & registers[18]);
|
rlm@100
|
4036 register_WY = (u8) (0xFF & registers[19]);
|
rlm@100
|
4037 register_WX = (u8) (0xFF & registers[20]);
|
rlm@100
|
4038 register_VBK = (u8) (0xFF & registers[21]);
|
rlm@100
|
4039 register_HDMA1 = (u8) (0xFF & registers[22]);
|
rlm@100
|
4040 register_HDMA2 = (u8) (0xFF & registers[23]);
|
rlm@100
|
4041 register_HDMA3 = (u8) (0xFF & registers[24]);
|
rlm@100
|
4042 register_HDMA4 = (u8) (0xFF & registers[25]);
|
rlm@100
|
4043 register_HDMA5 = (u8) (0xFF & registers[26]);
|
rlm@100
|
4044 register_SVBK = (u8) (0xFF & registers[27]);
|
rlm@100
|
4045 register_IE = (u8) (0xFF & registers[28]);
|
rlm@62
|
4046 }
|
rlm@59
|
4047
|
rlm@1
|
4048 struct EmulatedSystem GBSystem =
|
rlm@33
|
4049 {
|
rlm@33
|
4050 // emuMain
|
rlm@33
|
4051 gbEmulate,
|
rlm@33
|
4052 // emuReset
|
rlm@33
|
4053 gbReset,
|
rlm@33
|
4054 // emuCleanUp
|
rlm@33
|
4055 gbCleanUp,
|
rlm@33
|
4056 // emuReadBattery
|
rlm@33
|
4057 gbReadBatteryFile,
|
rlm@33
|
4058 // emuWriteBattery
|
rlm@33
|
4059 gbWriteBatteryFile,
|
rlm@33
|
4060 // emuReadBatteryFromStream
|
rlm@33
|
4061 gbReadBatteryFromStream,
|
rlm@33
|
4062 // emuWriteBatteryToStream
|
rlm@33
|
4063 gbWriteBatteryToStream,
|
rlm@33
|
4064 // emuReadState
|
rlm@33
|
4065 gbReadSaveState,
|
rlm@33
|
4066 // emuWriteState
|
rlm@33
|
4067 gbWriteSaveState,
|
rlm@33
|
4068 // emuReadStateFromStream
|
rlm@33
|
4069 gbReadSaveStateFromStream,
|
rlm@92
|
4070 // emuwritestatetostream
|
rlm@33
|
4071 gbWriteSaveStateToStream,
|
rlm@33
|
4072 // emuReadMemState
|
rlm@33
|
4073 gbReadMemSaveState,
|
rlm@33
|
4074 // emuWriteMemState
|
rlm@33
|
4075 gbWriteMemSaveState,
|
rlm@33
|
4076 // emuWritePNG
|
rlm@33
|
4077 gbWritePNGFile,
|
rlm@33
|
4078 // emuWriteBMP
|
rlm@33
|
4079 gbWriteBMPFile,
|
rlm@33
|
4080 // emuUpdateCPSR
|
rlm@33
|
4081 NULL,
|
rlm@33
|
4082 // emuHasDebugger
|
rlm@33
|
4083 false,
|
rlm@33
|
4084 // emuCount
|
rlm@1
|
4085 #ifdef FINAL_VERSION
|
rlm@33
|
4086 70000 / 4,
|
rlm@1
|
4087 #else
|
rlm@33
|
4088 1000,
|
rlm@1
|
4089 #endif
|
rlm@33
|
4090 };
|
rlm@1
|
4091
|
rlm@1
|
4092 // is there a reason to use more than one set of counters?
|
rlm@1
|
4093 EmulatedSystemCounters &GBSystemCounters = systemCounters;
|
rlm@1
|
4094
|
rlm@1
|
4095 /*
|
rlm@33
|
4096 EmulatedSystemCounters GBSystemCounters =
|
rlm@33
|
4097 {
|
rlm@33
|
4098 // frameCount
|
rlm@33
|
4099 0,
|
rlm@33
|
4100 // lagCount
|
rlm@33
|
4101 0,
|
rlm@33
|
4102 // lagged
|
rlm@33
|
4103 true,
|
rlm@33
|
4104 // laggedLast
|
rlm@33
|
4105 true,
|
rlm@33
|
4106 };
|
rlm@33
|
4107 */
|