Mercurial > vba-clojure
comparison src/sdl/SDL.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children | 48369c6aeaa0 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. | |
2 // Copyright (C) 1999-2003 Forgotten | |
3 // Copyright (C) 2004 Forgotten and the VBA development team | |
4 | |
5 // This program is free software; you can redistribute it and/or modify | |
6 // it under the terms of the GNU General Public License as published by | |
7 // the Free Software Foundation; either version 2, or(at your option) | |
8 // any later version. | |
9 // | |
10 // This program is distributed in the hope that it will be useful, | |
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 // GNU General Public License for more details. | |
14 // | |
15 // You should have received a copy of the GNU General Public License | |
16 // along with this program; if not, write to the Free Software Foundation, | |
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | |
19 #include <stdarg.h> | |
20 #include <stdlib.h> | |
21 #include <stdio.h> | |
22 #include <string.h> | |
23 #include <sys/types.h> | |
24 #include <sys/stat.h> | |
25 | |
26 #include "AutoBuild.h" | |
27 | |
28 #include "Port.h" | |
29 #include "SDL.h" | |
30 #include "debugger.h" | |
31 #include "gba/GBA.h" | |
32 #include "gba/GBAGlobals.h" | |
33 #include "gba/agbprint.h" | |
34 #include "gba/Flash.h" | |
35 #include "gba/RTC.h" | |
36 #include "gba/GBASound.h" | |
37 #include "gb/GB.h" | |
38 #include "gb/gbGlobals.h" | |
39 #include "common/Text.h" | |
40 #include "common/unzip.h" | |
41 #include "common/Util.h" | |
42 #include "common/movie.h" | |
43 #include "common/System.h" | |
44 #include "common/inputGlobal.h" | |
45 #include "../common/vbalua.h" | |
46 #include "SoundSDL.h" | |
47 | |
48 | |
49 #define GBC_CAPABLE ((gbRom[0x143] & 0x80) != 0) | |
50 #define SGB_CAPABLE (gbRom[0x146] == 0x03) | |
51 | |
52 #ifndef WIN32 | |
53 # include <unistd.h> | |
54 # define GETCWD getcwd | |
55 #else // WIN32 | |
56 # include <direct.h> | |
57 # define GETCWD _getcwd | |
58 #endif // WIN32 | |
59 | |
60 #ifndef __GNUC__ | |
61 # define HAVE_DECL_GETOPT 0 | |
62 # define __STDC__ 1 | |
63 # include "getopt.h" | |
64 #else // ! __GNUC__ | |
65 # define HAVE_DECL_GETOPT 1 | |
66 # include "getopt.h" | |
67 #endif // ! __GNUC__ | |
68 | |
69 #ifdef MMX | |
70 extern "C" bool cpu_mmx; | |
71 #endif | |
72 extern bool8 soundEcho; | |
73 extern bool8 soundLowPass; | |
74 extern bool8 soundReverse; | |
75 extern int Init_2xSaI(u32); | |
76 extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int); | |
77 extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int); | |
78 extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int); | |
79 extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int); | |
80 extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int); | |
81 extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int); | |
82 extern void Pixelate2x16(u8*,u32,u8*,u8*,u32,int,int); | |
83 extern void Pixelate2x32(u8*,u32,u8*,u8*,u32,int,int); | |
84 extern void MotionBlur(u8*,u32,u8*,u8*,u32,int,int); | |
85 extern void MotionBlur32(u8*,u32,u8*,u8*,u32,int,int); | |
86 extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int); | |
87 extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int); | |
88 extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int); | |
89 extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int); | |
90 extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int); | |
91 extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int); | |
92 extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int); | |
93 extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int); | |
94 extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int); | |
95 extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int); | |
96 extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int); | |
97 extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int); | |
98 extern void hq2x(u8*,u32,u8*,u8*,u32,int,int); | |
99 extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int); | |
100 extern void lq2x(u8*,u32,u8*,u8*,u32,int,int); | |
101 extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int); | |
102 | |
103 extern void SmartIB(u8*,u32,int,int); | |
104 extern void SmartIB32(u8*,u32,int,int); | |
105 extern void MotionBlurIB(u8*,u32,int,int); | |
106 extern void MotionBlurIB32(u8*,u32,int,int); | |
107 | |
108 void Init_Overlay(SDL_Surface *surface, int overlaytype); | |
109 void Quit_Overlay(void); | |
110 void Draw_Overlay(SDL_Surface *surface, int size); | |
111 | |
112 extern void remoteInit(); | |
113 extern void remoteCleanUp(); | |
114 extern void remoteStubMain(); | |
115 extern void remoteStubSignal(int,int); | |
116 extern void remoteOutput(char *, u32); | |
117 extern void remoteSetProtocol(int); | |
118 extern void remoteSetPort(int); | |
119 extern void debuggerOutput(char *, u32); | |
120 | |
121 extern void CPUUpdateRenderBuffers(bool); | |
122 | |
123 struct EmulatedSystem theEmulator = { | |
124 NULL, | |
125 NULL, | |
126 NULL, | |
127 NULL, | |
128 NULL, | |
129 NULL, | |
130 NULL, | |
131 NULL, | |
132 NULL, | |
133 NULL, | |
134 NULL, | |
135 NULL, | |
136 false, | |
137 0 | |
138 }; | |
139 | |
140 SDL_Surface *surface = NULL; | |
141 SDL_Overlay *overlay = NULL; | |
142 SDL_Rect overlay_rect; | |
143 | |
144 int systemSpeed = 0; | |
145 int systemRedShift = 0; | |
146 int systemBlueShift = 0; | |
147 int systemGreenShift = 0; | |
148 int systemColorDepth = 0; | |
149 int systemDebug = 0; | |
150 int systemVerbose = 0; | |
151 int systemFrameSkip = 0; | |
152 int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
153 | |
154 int srcPitch = 0; | |
155 int srcWidth = 0; | |
156 int srcHeight = 0; | |
157 int destWidth = 0; | |
158 int destHeight = 0; | |
159 | |
160 int sensorX = 2047; | |
161 int sensorY = 2047; | |
162 bool sensorOn = false; | |
163 | |
164 int filter = 0; | |
165 u8 *delta = NULL; | |
166 | |
167 int sdlPrintUsage = 0; | |
168 int disableMMX = 0; | |
169 | |
170 int systemCartridgeType = 3; | |
171 int sizeOption = 0; | |
172 int captureFormat = 0; | |
173 int useMovie = 0; | |
174 | |
175 int pauseWhenInactive = 0; | |
176 int active = 1; | |
177 int emulating = 0; | |
178 int RGB_LOW_BITS_MASK=0x821; | |
179 u32 systemColorMap32[0x10000]; | |
180 u16 systemColorMap16[0x10000]; | |
181 u16 systemGbPalette[24]; | |
182 void (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int) = NULL; | |
183 void (*ifbFunction)(u8*,u32,int,int) = NULL; | |
184 int ifbType = 0; | |
185 char filename[2048]; | |
186 char ipsname[2048]; | |
187 char biosFileName[2048]; | |
188 char movieFileName[2048]; | |
189 char captureDir[2048]; | |
190 char saveDir[2048]; | |
191 char batteryDir[2048]; | |
192 | |
193 static char *rewindMemory = NULL; | |
194 static int rewindPos = 0; | |
195 static int rewindTopPos = 0; | |
196 static int rewindCounter = 0; | |
197 static int rewindCount = 0; | |
198 static bool rewindSaveNeeded = false; | |
199 static int rewindTimer = 0; | |
200 | |
201 #define REWIND_SIZE 400000 | |
202 | |
203 #define _stricmp strcasecmp | |
204 | |
205 /*bool sdlButtons[4][12] = { | |
206 { false, false, false, false, false, false, | |
207 false, false, false, false, false, false }, | |
208 { false, false, false, false, false, false, | |
209 false, false, false, false, false, false }, | |
210 { false, false, false, false, false, false, | |
211 false, false, false, false, false, false }, | |
212 { false, false, false, false, false, false, | |
213 false, false, false, false, false, false } | |
214 };*/ | |
215 /* | |
216 I'm changing the way the SDL GUI handles the button | |
217 input to match the one in win32, this is needed in | |
218 order to be compatible with the format required by | |
219 common/movie.cpp | |
220 --Felipe | |
221 */ | |
222 | |
223 u16 currentButtons[4] = {0, 0, 0, 0}; | |
224 | |
225 bool sdlMotionButtons[4] = { false, false, false, false }; | |
226 const int32 INITIAL_SENSOR_VALUE = 2047; | |
227 | |
228 int sdlNumDevices = 0; | |
229 SDL_Joystick **sdlDevices = NULL; | |
230 | |
231 bool wasPaused = false; | |
232 int autoFrameSkip = 0; | |
233 int frameskipadjust = 0; | |
234 int showRenderedFrames = 0; | |
235 int renderedFrames = 0; | |
236 | |
237 int throttle = 0; | |
238 u32 throttleLastTime = 0; | |
239 u32 autoFrameSkipLastTime = 0; | |
240 | |
241 int showSpeed = 1; | |
242 int showSpeedTransparent = 1; | |
243 bool disableStatusMessages = false; | |
244 bool paused = false; | |
245 bool pauseNextFrame = false; | |
246 bool debugger = false; | |
247 bool debuggerStub = false; | |
248 int fullscreen = 0; | |
249 bool systemSoundOn = false; | |
250 bool yuv = false; | |
251 int yuvType = 0; | |
252 bool removeIntros = false; | |
253 int sdlFlashSize = 0; | |
254 int sdlAutoIPS = 1; | |
255 int sdlRtcEnable = 0; | |
256 int sdlAgbPrint = 0; | |
257 | |
258 int sdlDefaultJoypad = 0; | |
259 | |
260 extern void debuggerSignal(int,int); | |
261 | |
262 void (*dbgMain)() = debuggerMain; | |
263 void (*dbgSignal)(int,int) = debuggerSignal; | |
264 void (*dbgOutput)(char *, u32) = debuggerOutput; | |
265 | |
266 int mouseCounter = 0; | |
267 int autoFire = 0; | |
268 bool autoFireToggle = false; | |
269 | |
270 bool screenMessage[8] = {false,false,false,false,false,false,false,false}; | |
271 char screenMessageBuffer[8][21]; | |
272 u32 screenMessageTime[8] = {0,0,0,0,0,0,0,0}; | |
273 u32 screenMessageDuration[8] = {0,0,0,0,0,0,0,0}; | |
274 | |
275 SDL_cond *cond = NULL; | |
276 SDL_mutex *mutex = NULL; | |
277 u8* sdlBuffer; | |
278 int sdlSoundLen = 0; | |
279 SoundSDL* soundDriver = NULL; | |
280 | |
281 char *arg0; | |
282 | |
283 #ifndef C_CORE | |
284 u8 sdlStretcher[16384]; | |
285 int sdlStretcherPos; | |
286 #else | |
287 void (*sdlStretcher)(u8 *, u8*) = NULL; | |
288 #endif | |
289 | |
290 u16 joypad[4][12] = { | |
291 { SDLK_LEFT, SDLK_RIGHT, | |
292 SDLK_UP, SDLK_DOWN, | |
293 SDLK_z, SDLK_x, | |
294 SDLK_RETURN,SDLK_BACKSPACE, | |
295 SDLK_a, SDLK_s, | |
296 SDLK_SPACE, SDLK_F12 | |
297 }, | |
298 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
299 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
300 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } | |
301 }; | |
302 | |
303 u16 defaultJoypad[12] = { | |
304 SDLK_LEFT, SDLK_RIGHT, | |
305 SDLK_UP, SDLK_DOWN, | |
306 SDLK_z, SDLK_x, | |
307 SDLK_RETURN,SDLK_BACKSPACE, | |
308 SDLK_a, SDLK_s, | |
309 SDLK_SPACE, SDLK_F12 | |
310 }; | |
311 | |
312 u16 motion[4] = { | |
313 SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 | |
314 }; | |
315 | |
316 u16 defaultMotion[4] = { | |
317 SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 | |
318 }; | |
319 | |
320 struct option sdlOptions[] = { | |
321 { "agb-print", no_argument, &sdlAgbPrint, 1 }, | |
322 { "auto-frameskip", no_argument, &autoFrameSkip, 1 }, | |
323 { "bios", required_argument, 0, 'b' }, | |
324 { "config", required_argument, 0, 'c' }, | |
325 { "debug", no_argument, 0, 'd' }, | |
326 { "filter", required_argument, 0, 'f' }, | |
327 { "filter-normal", no_argument, &filter, 0 }, | |
328 { "filter-tv-mode", no_argument, &filter, 1 }, | |
329 { "filter-2xsai", no_argument, &filter, 2 }, | |
330 { "filter-super-2xsai", no_argument, &filter, 3 }, | |
331 { "filter-super-eagle", no_argument, &filter, 4 }, | |
332 { "filter-pixelate", no_argument, &filter, 5 }, | |
333 { "filter-motion-blur", no_argument, &filter, 6 }, | |
334 { "filter-advmame", no_argument, &filter, 7 }, | |
335 { "filter-simple2x", no_argument, &filter, 8 }, | |
336 { "filter-bilinear", no_argument, &filter, 9 }, | |
337 { "filter-bilinear+", no_argument, &filter, 10 }, | |
338 { "filter-scanlines", no_argument, &filter, 11 }, | |
339 { "filter-hq2x", no_argument, &filter, 12 }, | |
340 { "filter-lq2x", no_argument, &filter, 13 }, | |
341 { "flash-size", required_argument, 0, 'S' }, | |
342 { "flash-64k", no_argument, &sdlFlashSize, 0 }, | |
343 { "flash-128k", no_argument, &sdlFlashSize, 1 }, | |
344 { "frameskip", required_argument, 0, 's' }, | |
345 { "fullscreen", no_argument, &fullscreen, 1 }, | |
346 { "gdb", required_argument, 0, 'G' }, | |
347 { "help", no_argument, &sdlPrintUsage, 1 }, | |
348 { "ifb-none", no_argument, &ifbType, 0 }, | |
349 { "ifb-motion-blur", no_argument, &ifbType, 1 }, | |
350 { "ifb-smart", no_argument, &ifbType, 2 }, | |
351 { "ips", required_argument, 0, 'i' }, | |
352 { "no-agb-print", no_argument, &sdlAgbPrint, 0 }, | |
353 { "no-auto-frameskip", no_argument, &autoFrameSkip, 0 }, | |
354 { "no-debug", no_argument, 0, 'N' }, | |
355 { "no-ips", no_argument, &sdlAutoIPS, 0 }, | |
356 { "no-mmx", no_argument, &disableMMX, 1 }, | |
357 { "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 }, | |
358 { "no-rtc", no_argument, &sdlRtcEnable, 0 }, | |
359 { "no-show-speed", no_argument, &showSpeed, 0 }, | |
360 { "no-throttle", no_argument, &throttle, 0 }, | |
361 { "pause-when-inactive", no_argument, &pauseWhenInactive, 1 }, | |
362 { "profile", optional_argument, 0, 'P' }, | |
363 { "rtc", no_argument, &sdlRtcEnable, 1 }, | |
364 { "save-type", required_argument, 0, 't' }, | |
365 { "save-auto", no_argument, &cpuSaveType, 0 }, | |
366 { "save-eeprom", no_argument, &cpuSaveType, 1 }, | |
367 { "save-sram", no_argument, &cpuSaveType, 2 }, | |
368 { "save-flash", no_argument, &cpuSaveType, 3 }, | |
369 { "save-sensor", no_argument, &cpuSaveType, 4 }, | |
370 { "save-none", no_argument, &cpuSaveType, 5 }, | |
371 { "show-speed-normal", no_argument, &showSpeed, 1 }, | |
372 { "show-speed-detailed", no_argument, &showSpeed, 2 }, | |
373 { "throttle", required_argument, 0, 'T' }, | |
374 { "verbose", required_argument, 0, 'v' }, | |
375 { "video-1x", no_argument, &sizeOption, 0 }, | |
376 { "video-2x", no_argument, &sizeOption, 1 }, | |
377 { "video-3x", no_argument, &sizeOption, 2 }, | |
378 { "video-4x", no_argument, &sizeOption, 3 }, | |
379 { "yuv", required_argument, 0, 'Y' }, | |
380 { "recordmovie", required_argument, 0, 'r' }, | |
381 { "playmovie", required_argument, 0, 'p' }, | |
382 { "watchmovie", required_argument, 0, 'w' }, | |
383 { NULL, no_argument, NULL, 0 } | |
384 }; | |
385 | |
386 #ifndef C_CORE | |
387 #define SDL_LONG(val) \ | |
388 *((u32 *)&sdlStretcher[sdlStretcherPos]) = val;\ | |
389 sdlStretcherPos+=4; | |
390 | |
391 #define SDL_AND_EAX(val) \ | |
392 sdlStretcher[sdlStretcherPos++] = 0x25;\ | |
393 SDL_LONG(val); | |
394 | |
395 #define SDL_AND_EBX(val) \ | |
396 sdlStretcher[sdlStretcherPos++] = 0x81;\ | |
397 sdlStretcher[sdlStretcherPos++] = 0xe3;\ | |
398 SDL_LONG(val); | |
399 | |
400 #define SDL_OR_EAX_EBX \ | |
401 sdlStretcher[sdlStretcherPos++] = 0x09;\ | |
402 sdlStretcher[sdlStretcherPos++] = 0xd8; | |
403 | |
404 #define SDL_LOADL_EBX \ | |
405 sdlStretcher[sdlStretcherPos++] = 0x8b;\ | |
406 sdlStretcher[sdlStretcherPos++] = 0x1f; | |
407 | |
408 #define SDL_LOADW \ | |
409 sdlStretcher[sdlStretcherPos++] = 0x66;\ | |
410 sdlStretcher[sdlStretcherPos++] = 0x8b;\ | |
411 sdlStretcher[sdlStretcherPos++] = 0x06;\ | |
412 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
413 sdlStretcher[sdlStretcherPos++] = 0xc6;\ | |
414 sdlStretcher[sdlStretcherPos++] = 0x02; | |
415 | |
416 #define SDL_LOADL \ | |
417 sdlStretcher[sdlStretcherPos++] = 0x8b;\ | |
418 sdlStretcher[sdlStretcherPos++] = 0x06;\ | |
419 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
420 sdlStretcher[sdlStretcherPos++] = 0xc6;\ | |
421 sdlStretcher[sdlStretcherPos++] = 0x04; | |
422 | |
423 #define SDL_LOADL2 \ | |
424 sdlStretcher[sdlStretcherPos++] = 0x8b;\ | |
425 sdlStretcher[sdlStretcherPos++] = 0x06;\ | |
426 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
427 sdlStretcher[sdlStretcherPos++] = 0xc6;\ | |
428 sdlStretcher[sdlStretcherPos++] = 0x03; | |
429 | |
430 #define SDL_STOREW \ | |
431 sdlStretcher[sdlStretcherPos++] = 0x66;\ | |
432 sdlStretcher[sdlStretcherPos++] = 0x89;\ | |
433 sdlStretcher[sdlStretcherPos++] = 0x07;\ | |
434 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
435 sdlStretcher[sdlStretcherPos++] = 0xc7;\ | |
436 sdlStretcher[sdlStretcherPos++] = 0x02; | |
437 | |
438 #define SDL_STOREL \ | |
439 sdlStretcher[sdlStretcherPos++] = 0x89;\ | |
440 sdlStretcher[sdlStretcherPos++] = 0x07;\ | |
441 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
442 sdlStretcher[sdlStretcherPos++] = 0xc7;\ | |
443 sdlStretcher[sdlStretcherPos++] = 0x04; | |
444 | |
445 #define SDL_STOREL2 \ | |
446 sdlStretcher[sdlStretcherPos++] = 0x89;\ | |
447 sdlStretcher[sdlStretcherPos++] = 0x07;\ | |
448 sdlStretcher[sdlStretcherPos++] = 0x83;\ | |
449 sdlStretcher[sdlStretcherPos++] = 0xc7;\ | |
450 sdlStretcher[sdlStretcherPos++] = 0x03; | |
451 | |
452 #define SDL_RET \ | |
453 sdlStretcher[sdlStretcherPos++] = 0xc3; | |
454 | |
455 #define SDL_PUSH_EAX \ | |
456 sdlStretcher[sdlStretcherPos++] = 0x50; | |
457 | |
458 #define SDL_PUSH_ECX \ | |
459 sdlStretcher[sdlStretcherPos++] = 0x51; | |
460 | |
461 #define SDL_PUSH_EBX \ | |
462 sdlStretcher[sdlStretcherPos++] = 0x53; | |
463 | |
464 #define SDL_PUSH_ESI \ | |
465 sdlStretcher[sdlStretcherPos++] = 0x56; | |
466 | |
467 #define SDL_PUSH_EDI \ | |
468 sdlStretcher[sdlStretcherPos++] = 0x57; | |
469 | |
470 #define SDL_POP_EAX \ | |
471 sdlStretcher[sdlStretcherPos++] = 0x58; | |
472 | |
473 #define SDL_POP_ECX \ | |
474 sdlStretcher[sdlStretcherPos++] = 0x59; | |
475 | |
476 #define SDL_POP_EBX \ | |
477 sdlStretcher[sdlStretcherPos++] = 0x5b; | |
478 | |
479 #define SDL_POP_ESI \ | |
480 sdlStretcher[sdlStretcherPos++] = 0x5e; | |
481 | |
482 #define SDL_POP_EDI \ | |
483 sdlStretcher[sdlStretcherPos++] = 0x5f; | |
484 | |
485 #define SDL_MOV_ECX(val) \ | |
486 sdlStretcher[sdlStretcherPos++] = 0xb9;\ | |
487 SDL_LONG(val); | |
488 | |
489 #define SDL_REP_MOVSB \ | |
490 sdlStretcher[sdlStretcherPos++] = 0xf3;\ | |
491 sdlStretcher[sdlStretcherPos++] = 0xa4; | |
492 | |
493 #define SDL_REP_MOVSW \ | |
494 sdlStretcher[sdlStretcherPos++] = 0xf3;\ | |
495 sdlStretcher[sdlStretcherPos++] = 0x66;\ | |
496 sdlStretcher[sdlStretcherPos++] = 0xa5; | |
497 | |
498 #define SDL_REP_MOVSL \ | |
499 sdlStretcher[sdlStretcherPos++] = 0xf3;\ | |
500 sdlStretcher[sdlStretcherPos++] = 0xa5; | |
501 | |
502 void sdlMakeStretcher(int width) | |
503 { | |
504 sdlStretcherPos = 0; | |
505 switch(systemColorDepth) { | |
506 case 16: | |
507 if(sizeOption) { | |
508 SDL_PUSH_EAX; | |
509 SDL_PUSH_ESI; | |
510 SDL_PUSH_EDI; | |
511 for(int i = 0; i < width; i++) { | |
512 SDL_LOADW; | |
513 SDL_STOREW; | |
514 SDL_STOREW; | |
515 if(sizeOption > 1) { | |
516 SDL_STOREW; | |
517 } | |
518 if(sizeOption > 2) { | |
519 SDL_STOREW; | |
520 } | |
521 } | |
522 SDL_POP_EDI; | |
523 SDL_POP_ESI; | |
524 SDL_POP_EAX; | |
525 SDL_RET; | |
526 } else { | |
527 SDL_PUSH_ESI; | |
528 SDL_PUSH_EDI; | |
529 SDL_PUSH_ECX; | |
530 SDL_MOV_ECX(width); | |
531 SDL_REP_MOVSW; | |
532 SDL_POP_ECX; | |
533 SDL_POP_EDI; | |
534 SDL_POP_ESI; | |
535 SDL_RET; | |
536 } | |
537 break; | |
538 case 24: | |
539 if(sizeOption) { | |
540 SDL_PUSH_EAX; | |
541 SDL_PUSH_ESI; | |
542 SDL_PUSH_EDI; | |
543 int w = width - 1; | |
544 for(int i = 0; i < w; i++) { | |
545 SDL_LOADL2; | |
546 SDL_STOREL2; | |
547 SDL_STOREL2; | |
548 if(sizeOption > 1) { | |
549 SDL_STOREL2; | |
550 } | |
551 if(sizeOption > 2) { | |
552 SDL_STOREL2; | |
553 } | |
554 } | |
555 // need to write the last one | |
556 SDL_LOADL2; | |
557 SDL_STOREL2; | |
558 if(sizeOption > 1) { | |
559 SDL_STOREL2; | |
560 } | |
561 if(sizeOption > 2) { | |
562 SDL_STOREL2; | |
563 } | |
564 SDL_AND_EAX(0x00ffffff); | |
565 SDL_PUSH_EBX; | |
566 SDL_LOADL_EBX; | |
567 SDL_AND_EBX(0xff000000); | |
568 SDL_OR_EAX_EBX; | |
569 SDL_POP_EBX; | |
570 SDL_STOREL2; | |
571 SDL_POP_EDI; | |
572 SDL_POP_ESI; | |
573 SDL_POP_EAX; | |
574 SDL_RET; | |
575 } else { | |
576 SDL_PUSH_ESI; | |
577 SDL_PUSH_EDI; | |
578 SDL_PUSH_ECX; | |
579 SDL_MOV_ECX(3*width); | |
580 SDL_REP_MOVSB; | |
581 SDL_POP_ECX; | |
582 SDL_POP_EDI; | |
583 SDL_POP_ESI; | |
584 SDL_RET; | |
585 } | |
586 break; | |
587 case 32: | |
588 if(sizeOption) { | |
589 SDL_PUSH_EAX; | |
590 SDL_PUSH_ESI; | |
591 SDL_PUSH_EDI; | |
592 for(int i = 0; i < width; i++) { | |
593 SDL_LOADL; | |
594 SDL_STOREL; | |
595 SDL_STOREL; | |
596 if(sizeOption > 1) { | |
597 SDL_STOREL; | |
598 } | |
599 if(sizeOption > 2) { | |
600 SDL_STOREL; | |
601 } | |
602 } | |
603 SDL_POP_EDI; | |
604 SDL_POP_ESI; | |
605 SDL_POP_EAX; | |
606 SDL_RET; | |
607 } else { | |
608 SDL_PUSH_ESI; | |
609 SDL_PUSH_EDI; | |
610 SDL_PUSH_ECX; | |
611 SDL_MOV_ECX(width); | |
612 SDL_REP_MOVSL; | |
613 SDL_POP_ECX; | |
614 SDL_POP_EDI; | |
615 SDL_POP_ESI; | |
616 SDL_RET; | |
617 } | |
618 break; | |
619 } | |
620 } | |
621 | |
622 #ifdef _MSC_VER | |
623 #define SDL_CALL_STRETCHER \ | |
624 {\ | |
625 __asm mov eax, stretcher\ | |
626 __asm mov edi, dest\ | |
627 __asm mov esi, src\ | |
628 __asm call eax\ | |
629 } | |
630 #else | |
631 #define SDL_CALL_STRETCHER \ | |
632 asm volatile("call *%%eax"::"a" (stretcher),"S" (src),"D" (dest)) | |
633 #endif | |
634 #else | |
635 #define SDL_CALL_STRETCHER \ | |
636 sdlStretcher(src, dest) | |
637 | |
638 void sdlStretch16x1(u8 *src, u8 *dest) | |
639 { | |
640 u16 *s = (u16 *)src; | |
641 u16 *d = (u16 *)dest; | |
642 for(int i = 0; i < srcWidth; i++) | |
643 *d++ = *s++; | |
644 } | |
645 | |
646 void sdlStretch16x2(u8 *src, u8 *dest) | |
647 { | |
648 u16 *s = (u16 *)src; | |
649 u16 *d = (u16 *)dest; | |
650 for(int i = 0; i < srcWidth; i++) { | |
651 *d++ = *s; | |
652 *d++ = *s++; | |
653 } | |
654 } | |
655 | |
656 void sdlStretch16x3(u8 *src, u8 *dest) | |
657 { | |
658 u16 *s = (u16 *)src; | |
659 u16 *d = (u16 *)dest; | |
660 for(int i = 0; i < srcWidth; i++) { | |
661 *d++ = *s; | |
662 *d++ = *s; | |
663 *d++ = *s++; | |
664 } | |
665 } | |
666 | |
667 void sdlStretch16x4(u8 *src, u8 *dest) | |
668 { | |
669 u16 *s = (u16 *)src; | |
670 u16 *d = (u16 *)dest; | |
671 for(int i = 0; i < srcWidth; i++) { | |
672 *d++ = *s; | |
673 *d++ = *s; | |
674 *d++ = *s; | |
675 *d++ = *s++; | |
676 } | |
677 } | |
678 | |
679 void (*sdlStretcher16[4])(u8 *, u8 *) = { | |
680 sdlStretch16x1, | |
681 sdlStretch16x2, | |
682 sdlStretch16x3, | |
683 sdlStretch16x4 | |
684 }; | |
685 | |
686 void sdlStretch32x1(u8 *src, u8 *dest) | |
687 { | |
688 u32 *s = (u32 *)src; | |
689 u32 *d = (u32 *)dest; | |
690 for(int i = 0; i < srcWidth; i++) | |
691 *d++ = *s++; | |
692 } | |
693 | |
694 void sdlStretch32x2(u8 *src, u8 *dest) | |
695 { | |
696 u32 *s = (u32 *)src; | |
697 u32 *d = (u32 *)dest; | |
698 for(int i = 0; i < srcWidth; i++) { | |
699 *d++ = *s; | |
700 *d++ = *s++; | |
701 } | |
702 } | |
703 | |
704 void sdlStretch32x3(u8 *src, u8 *dest) | |
705 { | |
706 u32 *s = (u32 *)src; | |
707 u32 *d = (u32 *)dest; | |
708 for(int i = 0; i < srcWidth; i++) { | |
709 *d++ = *s; | |
710 *d++ = *s; | |
711 *d++ = *s++; | |
712 } | |
713 } | |
714 | |
715 void sdlStretch32x4(u8 *src, u8 *dest) | |
716 { | |
717 u32 *s = (u32 *)src; | |
718 u32 *d = (u32 *)dest; | |
719 for(int i = 0; i < srcWidth; i++) { | |
720 *d++ = *s; | |
721 *d++ = *s; | |
722 *d++ = *s; | |
723 *d++ = *s++; | |
724 } | |
725 } | |
726 | |
727 void (*sdlStretcher32[4])(u8 *, u8 *) = { | |
728 sdlStretch32x1, | |
729 sdlStretch32x2, | |
730 sdlStretch32x3, | |
731 sdlStretch32x4 | |
732 }; | |
733 | |
734 void sdlStretch24x1(u8 *src, u8 *dest) | |
735 { | |
736 u8 *s = src; | |
737 u8 *d = dest; | |
738 for(int i = 0; i < srcWidth; i++) { | |
739 *d++ = *s++; | |
740 *d++ = *s++; | |
741 *d++ = *s++; | |
742 } | |
743 } | |
744 | |
745 void sdlStretch24x2(u8 *src, u8 *dest) | |
746 { | |
747 u8 *s = (u8 *)src; | |
748 u8 *d = (u8 *)dest; | |
749 for(int i = 0; i < srcWidth; i++) { | |
750 *d++ = *s; | |
751 *d++ = *(s+1); | |
752 *d++ = *(s+2); | |
753 s += 3; | |
754 *d++ = *s; | |
755 *d++ = *(s+1); | |
756 *d++ = *(s+2); | |
757 s += 3; | |
758 } | |
759 } | |
760 | |
761 void sdlStretch24x3(u8 *src, u8 *dest) | |
762 { | |
763 u8 *s = (u8 *)src; | |
764 u8 *d = (u8 *)dest; | |
765 for(int i = 0; i < srcWidth; i++) { | |
766 *d++ = *s; | |
767 *d++ = *(s+1); | |
768 *d++ = *(s+2); | |
769 s += 3; | |
770 *d++ = *s; | |
771 *d++ = *(s+1); | |
772 *d++ = *(s+2); | |
773 s += 3; | |
774 *d++ = *s; | |
775 *d++ = *(s+1); | |
776 *d++ = *(s+2); | |
777 s += 3; | |
778 } | |
779 } | |
780 | |
781 void sdlStretch24x4(u8 *src, u8 *dest) | |
782 { | |
783 u8 *s = (u8 *)src; | |
784 u8 *d = (u8 *)dest; | |
785 for(int i = 0; i < srcWidth; i++) { | |
786 *d++ = *s; | |
787 *d++ = *(s+1); | |
788 *d++ = *(s+2); | |
789 s += 3; | |
790 *d++ = *s; | |
791 *d++ = *(s+1); | |
792 *d++ = *(s+2); | |
793 s += 3; | |
794 *d++ = *s; | |
795 *d++ = *(s+1); | |
796 *d++ = *(s+2); | |
797 s += 3; | |
798 *d++ = *s; | |
799 *d++ = *(s+1); | |
800 *d++ = *(s+2); | |
801 s += 3; | |
802 } | |
803 } | |
804 | |
805 void (*sdlStretcher24[4])(u8 *, u8 *) = { | |
806 sdlStretch24x1, | |
807 sdlStretch24x2, | |
808 sdlStretch24x3, | |
809 sdlStretch24x4 | |
810 }; | |
811 | |
812 #endif | |
813 | |
814 u32 sdlFromHex(char *s) | |
815 { | |
816 u32 value; | |
817 sscanf(s, "%x", &value); | |
818 return value; | |
819 } | |
820 | |
821 #ifdef __MSC__ | |
822 #define stat _stat | |
823 #define S_IFDIR _S_IFDIR | |
824 #endif | |
825 | |
826 void sdlCheckDirectory(char *dir) | |
827 { | |
828 struct stat buf; | |
829 | |
830 int len = strlen(dir); | |
831 | |
832 char *p = dir + len - 1; | |
833 | |
834 if(*p == '/' || | |
835 *p == '\\') | |
836 *p = 0; | |
837 | |
838 if(stat(dir, &buf) == 0) { | |
839 if(!(buf.st_mode & S_IFDIR)) { | |
840 fprintf(stderr, "Error: %s is not a directory\n", dir); | |
841 dir[0] = 0; | |
842 } | |
843 } else { | |
844 fprintf(stderr, "Error: %s does not exist\n", dir); | |
845 dir[0] = 0; | |
846 } | |
847 } | |
848 | |
849 char *sdlGetFilename(char *name) | |
850 { | |
851 static char filebuffer[2048]; | |
852 | |
853 int len = strlen(name); | |
854 | |
855 char *p = name + len - 1; | |
856 | |
857 while(true) { | |
858 if(*p == '/' || | |
859 *p == '\\') { | |
860 p++; | |
861 break; | |
862 } | |
863 len--; | |
864 p--; | |
865 if(len == 0) | |
866 break; | |
867 } | |
868 | |
869 if(len == 0) | |
870 strcpy(filebuffer, name); | |
871 else | |
872 strcpy(filebuffer, p); | |
873 return filebuffer; | |
874 } | |
875 | |
876 FILE *sdlFindFile(const char *name) | |
877 { | |
878 char buffer[4096]; | |
879 char path[2048]; | |
880 | |
881 #ifdef WIN32 | |
882 #define PATH_SEP ";" | |
883 #define FILE_SEP '\\' | |
884 #define EXE_NAME "VisualBoyAdvance-SDL.exe" | |
885 #else // ! WIN32 | |
886 #define PATH_SEP ":" | |
887 #define FILE_SEP '/' | |
888 #define EXE_NAME "VisualBoyAdvance" | |
889 #endif // ! WIN32 | |
890 | |
891 fprintf(stderr, "Searching for file %s\n", name); | |
892 | |
893 if(GETCWD(buffer, 2048)) { | |
894 fprintf(stderr, "Searching current directory: %s\n", buffer); | |
895 } | |
896 | |
897 FILE *f = fopen(name, "r"); | |
898 if(f != NULL) { | |
899 return f; | |
900 } | |
901 | |
902 char *home = getenv("HOME"); | |
903 | |
904 if(home != NULL) { | |
905 fprintf(stderr, "Searching home directory: %s\n", home); | |
906 sprintf(path, "%s%c%s", home, FILE_SEP, name); | |
907 f = fopen(path, "r"); | |
908 if(f != NULL) | |
909 return f; | |
910 } | |
911 | |
912 #ifdef WIN32 | |
913 home = getenv("USERPROFILE"); | |
914 if(home != NULL) { | |
915 fprintf(stderr, "Searching user profile directory: %s\n", home); | |
916 sprintf(path, "%s%c%s", home, FILE_SEP, name); | |
917 f = fopen(path, "r"); | |
918 if(f != NULL) | |
919 return f; | |
920 } | |
921 #else // ! WIN32 | |
922 fprintf(stderr, "Searching system config directory: %s\n", SYSCONFDIR); | |
923 sprintf(path, "%s%c%s", SYSCONFDIR, FILE_SEP, name); | |
924 f = fopen(path, "r"); | |
925 if(f != NULL) | |
926 return f; | |
927 #endif // ! WIN32 | |
928 | |
929 if(!strchr(arg0, '/') && | |
930 !strchr(arg0, '\\')) { | |
931 char *path = getenv("PATH"); | |
932 | |
933 if(path != NULL) { | |
934 fprintf(stderr, "Searching PATH\n"); | |
935 strncpy(buffer, path, 4096); | |
936 buffer[4095] = 0; | |
937 char *tok = strtok(buffer, PATH_SEP); | |
938 | |
939 while(tok) { | |
940 sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME); | |
941 f = fopen(path, "r"); | |
942 if(f != NULL) { | |
943 char path2[2048]; | |
944 fclose(f); | |
945 sprintf(path2, "%s%c%s", tok, FILE_SEP, name); | |
946 f = fopen(path2, "r"); | |
947 if(f != NULL) { | |
948 fprintf(stderr, "Found at %s\n", path2); | |
949 return f; | |
950 } | |
951 } | |
952 tok = strtok(NULL, PATH_SEP); | |
953 } | |
954 } | |
955 } else { | |
956 // executable is relative to some directory | |
957 fprintf(stderr, "Searching executable directory\n"); | |
958 strcpy(buffer, arg0); | |
959 char *p = strrchr(buffer, FILE_SEP); | |
960 if(p) { | |
961 *p = 0; | |
962 sprintf(path, "%s%c%s", buffer, FILE_SEP, name); | |
963 f = fopen(path, "r"); | |
964 if(f != NULL) | |
965 return f; | |
966 } | |
967 } | |
968 return NULL; | |
969 } | |
970 | |
971 void sdlReadPreferences(FILE *f) | |
972 { | |
973 char buffer[2048]; | |
974 | |
975 while(1) { | |
976 char *s = fgets(buffer, 2048, f); | |
977 | |
978 if(s == NULL) | |
979 break; | |
980 | |
981 char *p = strchr(s, '#'); | |
982 | |
983 if(p) | |
984 *p = 0; | |
985 | |
986 char *token = strtok(s, " \t\n\r="); | |
987 | |
988 if(!token) | |
989 continue; | |
990 | |
991 if(strlen(token) == 0) | |
992 continue; | |
993 | |
994 char *key = token; | |
995 char *value = strtok(NULL, "\t\n\r"); | |
996 | |
997 if(value == NULL) { | |
998 fprintf(stderr, "Empty value for key %s\n", key); | |
999 continue; | |
1000 } | |
1001 | |
1002 if(!strcmp(key,"Joy0_Left")) { | |
1003 joypad[0][KEY_LEFT] = sdlFromHex(value); | |
1004 } else if(!strcmp(key, "Joy0_Right")) { | |
1005 joypad[0][KEY_RIGHT] = sdlFromHex(value); | |
1006 } else if(!strcmp(key, "Joy0_Up")) { | |
1007 joypad[0][KEY_UP] = sdlFromHex(value); | |
1008 } else if(!strcmp(key, "Joy0_Down")) { | |
1009 joypad[0][KEY_DOWN] = sdlFromHex(value); | |
1010 } else if(!strcmp(key, "Joy0_A")) { | |
1011 joypad[0][KEY_BUTTON_A] = sdlFromHex(value); | |
1012 } else if(!strcmp(key, "Joy0_B")) { | |
1013 joypad[0][KEY_BUTTON_B] = sdlFromHex(value); | |
1014 } else if(!strcmp(key, "Joy0_L")) { | |
1015 joypad[0][KEY_BUTTON_L] = sdlFromHex(value); | |
1016 } else if(!strcmp(key, "Joy0_R")) { | |
1017 joypad[0][KEY_BUTTON_R] = sdlFromHex(value); | |
1018 } else if(!strcmp(key, "Joy0_Start")) { | |
1019 joypad[0][KEY_BUTTON_START] = sdlFromHex(value); | |
1020 } else if(!strcmp(key, "Joy0_Select")) { | |
1021 joypad[0][KEY_BUTTON_SELECT] = sdlFromHex(value); | |
1022 } else if(!strcmp(key, "Joy0_Speed")) { | |
1023 joypad[0][KEY_BUTTON_SPEED] = sdlFromHex(value); | |
1024 } else if(!strcmp(key, "Joy0_Capture")) { | |
1025 joypad[0][KEY_BUTTON_CAPTURE] = sdlFromHex(value); | |
1026 } else if(!strcmp(key,"Joy1_Left")) { | |
1027 joypad[1][KEY_LEFT] = sdlFromHex(value); | |
1028 } else if(!strcmp(key, "Joy1_Right")) { | |
1029 joypad[1][KEY_RIGHT] = sdlFromHex(value); | |
1030 } else if(!strcmp(key, "Joy1_Up")) { | |
1031 joypad[1][KEY_UP] = sdlFromHex(value); | |
1032 } else if(!strcmp(key, "Joy1_Down")) { | |
1033 joypad[1][KEY_DOWN] = sdlFromHex(value); | |
1034 } else if(!strcmp(key, "Joy1_A")) { | |
1035 joypad[1][KEY_BUTTON_A] = sdlFromHex(value); | |
1036 } else if(!strcmp(key, "Joy1_B")) { | |
1037 joypad[1][KEY_BUTTON_B] = sdlFromHex(value); | |
1038 } else if(!strcmp(key, "Joy1_L")) { | |
1039 joypad[1][KEY_BUTTON_L] = sdlFromHex(value); | |
1040 } else if(!strcmp(key, "Joy1_R")) { | |
1041 joypad[1][KEY_BUTTON_R] = sdlFromHex(value); | |
1042 } else if(!strcmp(key, "Joy1_Start")) { | |
1043 joypad[1][KEY_BUTTON_START] = sdlFromHex(value); | |
1044 } else if(!strcmp(key, "Joy1_Select")) { | |
1045 joypad[1][KEY_BUTTON_SELECT] = sdlFromHex(value); | |
1046 } else if(!strcmp(key, "Joy1_Speed")) { | |
1047 joypad[1][KEY_BUTTON_SPEED] = sdlFromHex(value); | |
1048 } else if(!strcmp(key, "Joy1_Capture")) { | |
1049 joypad[1][KEY_BUTTON_CAPTURE] = sdlFromHex(value); | |
1050 } else if(!strcmp(key,"Joy2_Left")) { | |
1051 joypad[2][KEY_LEFT] = sdlFromHex(value); | |
1052 } else if(!strcmp(key, "Joy2_Right")) { | |
1053 joypad[2][KEY_RIGHT] = sdlFromHex(value); | |
1054 } else if(!strcmp(key, "Joy2_Up")) { | |
1055 joypad[2][KEY_UP] = sdlFromHex(value); | |
1056 } else if(!strcmp(key, "Joy2_Down")) { | |
1057 joypad[2][KEY_DOWN] = sdlFromHex(value); | |
1058 } else if(!strcmp(key, "Joy2_A")) { | |
1059 joypad[2][KEY_BUTTON_A] = sdlFromHex(value); | |
1060 } else if(!strcmp(key, "Joy2_B")) { | |
1061 joypad[2][KEY_BUTTON_B] = sdlFromHex(value); | |
1062 } else if(!strcmp(key, "Joy2_L")) { | |
1063 joypad[2][KEY_BUTTON_L] = sdlFromHex(value); | |
1064 } else if(!strcmp(key, "Joy2_R")) { | |
1065 joypad[2][KEY_BUTTON_R] = sdlFromHex(value); | |
1066 } else if(!strcmp(key, "Joy2_Start")) { | |
1067 joypad[2][KEY_BUTTON_START] = sdlFromHex(value); | |
1068 } else if(!strcmp(key, "Joy2_Select")) { | |
1069 joypad[2][KEY_BUTTON_SELECT] = sdlFromHex(value); | |
1070 } else if(!strcmp(key, "Joy2_Speed")) { | |
1071 joypad[2][KEY_BUTTON_SPEED] = sdlFromHex(value); | |
1072 } else if(!strcmp(key, "Joy2_Capture")) { | |
1073 joypad[2][KEY_BUTTON_CAPTURE] = sdlFromHex(value); | |
1074 } else if(!strcmp(key,"Joy4_Left")) { | |
1075 joypad[4][KEY_LEFT] = sdlFromHex(value); | |
1076 } else if(!strcmp(key, "Joy4_Right")) { | |
1077 joypad[4][KEY_RIGHT] = sdlFromHex(value); | |
1078 } else if(!strcmp(key, "Joy4_Up")) { | |
1079 joypad[4][KEY_UP] = sdlFromHex(value); | |
1080 } else if(!strcmp(key, "Joy4_Down")) { | |
1081 joypad[4][KEY_DOWN] = sdlFromHex(value); | |
1082 } else if(!strcmp(key, "Joy4_A")) { | |
1083 joypad[4][KEY_BUTTON_A] = sdlFromHex(value); | |
1084 } else if(!strcmp(key, "Joy4_B")) { | |
1085 joypad[4][KEY_BUTTON_B] = sdlFromHex(value); | |
1086 } else if(!strcmp(key, "Joy4_L")) { | |
1087 joypad[4][KEY_BUTTON_L] = sdlFromHex(value); | |
1088 } else if(!strcmp(key, "Joy4_R")) { | |
1089 joypad[4][KEY_BUTTON_R] = sdlFromHex(value); | |
1090 } else if(!strcmp(key, "Joy4_Start")) { | |
1091 joypad[4][KEY_BUTTON_START] = sdlFromHex(value); | |
1092 } else if(!strcmp(key, "Joy4_Select")) { | |
1093 joypad[4][KEY_BUTTON_SELECT] = sdlFromHex(value); | |
1094 } else if(!strcmp(key, "Joy4_Speed")) { | |
1095 joypad[4][KEY_BUTTON_SPEED] = sdlFromHex(value); | |
1096 } else if(!strcmp(key, "Joy4_Capture")) { | |
1097 joypad[4][KEY_BUTTON_CAPTURE] = sdlFromHex(value); | |
1098 } else if(!strcmp(key, "Motion_Left")) { | |
1099 motion[KEY_LEFT] = sdlFromHex(value); | |
1100 } else if(!strcmp(key, "Motion_Right")) { | |
1101 motion[KEY_RIGHT] = sdlFromHex(value); | |
1102 } else if(!strcmp(key, "Motion_Up")) { | |
1103 motion[KEY_UP] = sdlFromHex(value); | |
1104 } else if(!strcmp(key, "Motion_Down")) { | |
1105 motion[KEY_DOWN] = sdlFromHex(value); | |
1106 } else if(!strcmp(key, "frameSkip")) { | |
1107 frameSkip = sdlFromHex(value); | |
1108 if(frameSkip < 0 || frameSkip > 9) | |
1109 frameSkip = 2; | |
1110 } else if(!strcmp(key, "gbFrameSkip")) { | |
1111 gbFrameSkip = sdlFromHex(value); | |
1112 if(gbFrameSkip < 0 || gbFrameSkip > 9) | |
1113 gbFrameSkip = 0; | |
1114 } else if(!strcmp(key, "video")) { | |
1115 sizeOption = sdlFromHex(value); | |
1116 if(sizeOption < 0 || sizeOption > 3) | |
1117 sizeOption = 1; | |
1118 } else if(!strcmp(key, "fullScreen")) { | |
1119 fullscreen = sdlFromHex(value) ? 1 : 0; | |
1120 } else if(!strcmp(key, "useBios")) { | |
1121 useBios = sdlFromHex(value) ? true : false; | |
1122 } else if(!strcmp(key, "skipBios")) { | |
1123 skipBios = sdlFromHex(value) ? true : false; | |
1124 } else if(!strcmp(key, "biosFile")) { | |
1125 strcpy(biosFileName, value); | |
1126 } else if(!strcmp(key, "filter")) { | |
1127 filter = sdlFromHex(value); | |
1128 if(filter < 0 || filter > 13) | |
1129 filter = 0; | |
1130 } else if(!strcmp(key, "disableStatus")) { | |
1131 disableStatusMessages = sdlFromHex(value) ? true : false; | |
1132 } else if(!strcmp(key, "borderOn")) { | |
1133 gbBorderOn = sdlFromHex(value) ? true : false; | |
1134 } else if(!strcmp(key, "borderAutomatic")) { | |
1135 gbBorderAutomatic = sdlFromHex(value) ? true : false; | |
1136 } else if(!strcmp(key, "emulatorType")) { | |
1137 gbEmulatorType = sdlFromHex(value); | |
1138 if(gbEmulatorType < 0 || gbEmulatorType > 5) | |
1139 gbEmulatorType = 1; | |
1140 } else if(!strcmp(key, "colorOption")) { | |
1141 gbColorOption = sdlFromHex(value) ? true : false; | |
1142 } else if(!strcmp(key, "captureDir")) { | |
1143 sdlCheckDirectory(value); | |
1144 strcpy(captureDir, value); | |
1145 } else if(!strcmp(key, "saveDir")) { | |
1146 sdlCheckDirectory(value); | |
1147 strcpy(saveDir, value); | |
1148 } else if(!strcmp(key, "batteryDir")) { | |
1149 sdlCheckDirectory(value); | |
1150 strcpy(batteryDir, value); | |
1151 } else if(!strcmp(key, "captureFormat")) { | |
1152 captureFormat = sdlFromHex(value); | |
1153 } else if(!strcmp(key, "soundQuality")) { | |
1154 soundQuality = sdlFromHex(value); | |
1155 switch(soundQuality) { | |
1156 case 1: break; | |
1157 default: | |
1158 fprintf(stderr, "The rerecording version will run only sound at highest quality. Defaulting to 44.1 KHz\n"); | |
1159 soundQuality = 1; | |
1160 break; | |
1161 } | |
1162 } else if(!strcmp(key, "soundOff")) { | |
1163 soundOffFlag = sdlFromHex(value) ? true : false; | |
1164 } else if(!strcmp(key, "soundEnable")) { | |
1165 int res = sdlFromHex(value) & 0x30f; | |
1166 soundEnableChannels(res); | |
1167 soundDisableChannels(~res); | |
1168 } else if(!strcmp(key, "soundEcho")) { | |
1169 soundEcho = sdlFromHex(value) ? true : false; | |
1170 } else if(!strcmp(key, "soundLowPass")) { | |
1171 soundLowPass = sdlFromHex(value) ? true : false; | |
1172 } else if(!strcmp(key, "soundReverse")) { | |
1173 soundReverse = sdlFromHex(value) ? true : false; | |
1174 } else if(!strcmp(key, "soundVolume")) { | |
1175 soundVolume = sdlFromHex(value); | |
1176 if(soundVolume < 0 || soundVolume > 3) | |
1177 soundVolume = 0; | |
1178 } else if(!strcmp(key, "removeIntros")) { | |
1179 removeIntros = sdlFromHex(value) ? true : false; | |
1180 } else if(!strcmp(key, "saveType")) { | |
1181 cpuSaveType = sdlFromHex(value); | |
1182 if(cpuSaveType < 0 || cpuSaveType > 5) | |
1183 cpuSaveType = 0; | |
1184 } else if(!strcmp(key, "flashSize")) { | |
1185 sdlFlashSize = sdlFromHex(value); | |
1186 if(sdlFlashSize != 0 && sdlFlashSize != 1) | |
1187 sdlFlashSize = 0; | |
1188 } else if(!strcmp(key, "ifbType")) { | |
1189 ifbType = sdlFromHex(value); | |
1190 if(ifbType < 0 || ifbType > 2) | |
1191 ifbType = 0; | |
1192 } else if(!strcmp(key, "showSpeed")) { | |
1193 showSpeed = sdlFromHex(value); | |
1194 if(showSpeed < 0 || showSpeed > 2) | |
1195 showSpeed = 1; | |
1196 } else if(!strcmp(key, "showSpeedTransparent")) { | |
1197 showSpeedTransparent = sdlFromHex(value); | |
1198 } else if(!strcmp(key, "autoFrameSkip")) { | |
1199 autoFrameSkip = sdlFromHex(value); | |
1200 } else if(!strcmp(key, "throttle")) { | |
1201 throttle = sdlFromHex(value); | |
1202 if(throttle != 0 && (throttle < 5 || throttle > 1000)) | |
1203 throttle = 0; | |
1204 } else if(!strcmp(key, "disableMMX")) { | |
1205 #ifdef MMX | |
1206 cpu_mmx = sdlFromHex(value) ? false : true; | |
1207 #endif | |
1208 } else if(!strcmp(key, "pauseWhenInactive")) { | |
1209 pauseWhenInactive = sdlFromHex(value) ? true : false; | |
1210 } else if(!strcmp(key, "agbPrint")) { | |
1211 sdlAgbPrint = sdlFromHex(value); | |
1212 } else if(!strcmp(key, "rtcEnabled")) { | |
1213 sdlRtcEnable = sdlFromHex(value); | |
1214 } else if(!strcmp(key, "rewindTimer")) { | |
1215 rewindTimer = sdlFromHex(value); | |
1216 if(rewindTimer < 0 || rewindTimer > 600) | |
1217 rewindTimer = 0; | |
1218 rewindTimer *= 6; // convert value to 10 frames multiple | |
1219 } else if(!strcmp(key, "enhancedDetection")) { | |
1220 cpuEnhancedDetection = sdlFromHex(value) ? true : false; | |
1221 } else { | |
1222 fprintf(stderr, "Unknown configuration key %s\n", key); | |
1223 } | |
1224 } | |
1225 } | |
1226 | |
1227 void sdlReadPreferences() | |
1228 { | |
1229 FILE *f = sdlFindFile("VisualBoyAdvance.cfg"); | |
1230 | |
1231 if(f == NULL) { | |
1232 fprintf(stderr, "Configuration file NOT FOUND (using defaults)\n"); | |
1233 return; | |
1234 } else | |
1235 fprintf(stderr, "Reading configuration file.\n"); | |
1236 | |
1237 sdlReadPreferences(f); | |
1238 | |
1239 fclose(f); | |
1240 } | |
1241 | |
1242 static void sdlApplyPerImagePreferences() | |
1243 { | |
1244 FILE *f = sdlFindFile("vba-over.ini"); | |
1245 if(!f) { | |
1246 fprintf(stderr, "vba-over.ini NOT FOUND (using emulator settings)\n"); | |
1247 return; | |
1248 } else | |
1249 fprintf(stderr, "Reading vba-over.ini\n"); | |
1250 | |
1251 char buffer[7]; | |
1252 buffer[0] = '['; | |
1253 buffer[1] = rom[0xac]; | |
1254 buffer[2] = rom[0xad]; | |
1255 buffer[3] = rom[0xae]; | |
1256 buffer[4] = rom[0xaf]; | |
1257 buffer[5] = ']'; | |
1258 buffer[6] = 0; | |
1259 | |
1260 char readBuffer[2048]; | |
1261 | |
1262 bool found = false; | |
1263 | |
1264 while(1) { | |
1265 char *s = fgets(readBuffer, 2048, f); | |
1266 | |
1267 if(s == NULL) | |
1268 break; | |
1269 | |
1270 char *p = strchr(s, ';'); | |
1271 | |
1272 if(p) | |
1273 *p = 0; | |
1274 | |
1275 char *token = strtok(s, " \t\n\r="); | |
1276 | |
1277 if(!token) | |
1278 continue; | |
1279 if(strlen(token) == 0) | |
1280 continue; | |
1281 | |
1282 if(!strcmp(token, buffer)) { | |
1283 found = true; | |
1284 break; | |
1285 } | |
1286 } | |
1287 | |
1288 if(found) { | |
1289 while(1) { | |
1290 char *s = fgets(readBuffer, 2048, f); | |
1291 | |
1292 if(s == NULL) | |
1293 break; | |
1294 | |
1295 char *p = strchr(s, ';'); | |
1296 if(p) | |
1297 *p = 0; | |
1298 | |
1299 char *token = strtok(s, " \t\n\r="); | |
1300 if(!token) | |
1301 continue; | |
1302 if(strlen(token) == 0) | |
1303 continue; | |
1304 | |
1305 if(token[0] == '[') // starting another image settings | |
1306 break; | |
1307 char *value = strtok(NULL, "\t\n\r="); | |
1308 if(value == NULL) | |
1309 continue; | |
1310 | |
1311 if(!strcmp(token, "rtcEnabled")) | |
1312 rtcEnable(atoi(value) == 0 ? false : true); | |
1313 else if(!strcmp(token, "flashSize")) { | |
1314 int size = atoi(value); | |
1315 if(size == 0x10000 || size == 0x20000) | |
1316 flashSetSize(size); | |
1317 } else if(!strcmp(token, "saveType")) { | |
1318 int save = atoi(value); | |
1319 if(save >= 0 && save <= 5) | |
1320 cpuSaveType = save; | |
1321 } | |
1322 } | |
1323 } | |
1324 fclose(f); | |
1325 } | |
1326 | |
1327 static int sdlCalculateShift(u32 mask) | |
1328 { | |
1329 int m = 0; | |
1330 | |
1331 while(mask) { | |
1332 m++; | |
1333 mask >>= 1; | |
1334 } | |
1335 | |
1336 return m-5; | |
1337 } | |
1338 | |
1339 static int sdlCalculateMaskWidth(u32 mask) | |
1340 { | |
1341 int m = 0; | |
1342 int mask2 = mask; | |
1343 | |
1344 while(mask2) { | |
1345 m++; | |
1346 mask2 >>= 1; | |
1347 } | |
1348 | |
1349 int m2 = 0; | |
1350 mask2 = mask; | |
1351 while(!(mask2 & 1)) { | |
1352 m2++; | |
1353 mask2 >>= 1; | |
1354 } | |
1355 | |
1356 return m - m2; | |
1357 } | |
1358 | |
1359 void sdlWriteState(int num) | |
1360 { | |
1361 char stateName[2048]; | |
1362 | |
1363 if(saveDir[0]) | |
1364 sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), | |
1365 num+1); | |
1366 else | |
1367 sprintf(stateName,"%s%d.sgm", filename, num+1); | |
1368 if(theEmulator.emuWriteState) | |
1369 theEmulator.emuWriteState(stateName); | |
1370 sprintf(stateName, "Wrote state %d", num+1); | |
1371 systemScreenMessage(stateName); | |
1372 } | |
1373 | |
1374 void sdlReadState(int num) | |
1375 { | |
1376 char stateName[2048]; | |
1377 | |
1378 if(saveDir[0]) | |
1379 sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename), | |
1380 num+1); | |
1381 else | |
1382 sprintf(stateName,"%s%d.sgm", filename, num+1); | |
1383 | |
1384 if(theEmulator.emuReadState) | |
1385 theEmulator.emuReadState(stateName); | |
1386 | |
1387 sprintf(stateName, "Loaded state %d", num+1); | |
1388 systemScreenMessage(stateName); | |
1389 } | |
1390 | |
1391 void sdlWriteBattery() | |
1392 { | |
1393 char buffer[1048]; | |
1394 | |
1395 if(batteryDir[0]) | |
1396 sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); | |
1397 else | |
1398 sprintf(buffer, "%s.sav", filename); | |
1399 | |
1400 theEmulator.emuWriteBattery(buffer); | |
1401 | |
1402 systemScreenMessage("Wrote battery"); | |
1403 } | |
1404 | |
1405 void sdlReadBattery() | |
1406 { | |
1407 char buffer[1048]; | |
1408 | |
1409 if(batteryDir[0]) | |
1410 sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename)); | |
1411 else | |
1412 sprintf(buffer, "%s.sav", filename); | |
1413 | |
1414 bool res = false; | |
1415 | |
1416 res = theEmulator.emuReadBattery(buffer); | |
1417 | |
1418 if(res) | |
1419 systemScreenMessage("Loaded battery"); | |
1420 } | |
1421 | |
1422 #define MOD_KEYS (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_META) | |
1423 #define MOD_NOCTRL (KMOD_SHIFT|KMOD_ALT|KMOD_META) | |
1424 #define MOD_NOALT (KMOD_CTRL|KMOD_SHIFT|KMOD_META) | |
1425 #define MOD_NOSHIFT (KMOD_CTRL|KMOD_ALT|KMOD_META) | |
1426 | |
1427 void sdlUpdateKey(int key, bool down) | |
1428 { | |
1429 int i; | |
1430 for(int j = 0; j < 4; j++) { | |
1431 for(i = 0 ; i < 12; i++) { | |
1432 if((joypad[j][i] & 0xf000) == 0) { | |
1433 if(key == joypad[j][i]) | |
1434 if (down) currentButtons[j] |= 1<<i; | |
1435 else currentButtons[j] ^= 1<<i; | |
1436 } | |
1437 } | |
1438 } | |
1439 for(i = 0 ; i < 4; i++) { | |
1440 if((motion[i] & 0xf000) == 0) { | |
1441 if(key == motion[i]) | |
1442 sdlMotionButtons[i] = down; | |
1443 } | |
1444 } | |
1445 } | |
1446 | |
1447 void sdlUpdateJoyButton(int which, | |
1448 int button, | |
1449 bool pressed) | |
1450 { | |
1451 int i; | |
1452 for(int j = 0; j < 4; j++) { | |
1453 for(i = 0; i < 12; i++) { | |
1454 int dev = (joypad[j][i] >> 12); | |
1455 int b = joypad[j][i] & 0xfff; | |
1456 if(dev) { | |
1457 dev--; | |
1458 | |
1459 if((dev == which) && (b >= 128) && (b == (button+128))) { | |
1460 if (pressed) currentButtons[j] |= 1<<i; | |
1461 else currentButtons[j] ^= 1<<i; | |
1462 } | |
1463 } | |
1464 } | |
1465 } | |
1466 for(i = 0; i < 4; i++) { | |
1467 int dev = (motion[i] >> 12); | |
1468 int b = motion[i] & 0xfff; | |
1469 if(dev) { | |
1470 dev--; | |
1471 | |
1472 if((dev == which) && (b >= 128) && (b == (button+128))) { | |
1473 sdlMotionButtons[i] = pressed; | |
1474 } | |
1475 } | |
1476 } | |
1477 } | |
1478 | |
1479 void sdlUpdateJoyHat(int which, | |
1480 int hat, | |
1481 int value) | |
1482 { | |
1483 int i; | |
1484 for(int j = 0; j < 4; j++) { | |
1485 for(i = 0; i < 12; i++) { | |
1486 int dev = (joypad[j][i] >> 12); | |
1487 int a = joypad[j][i] & 0xfff; | |
1488 if(dev) { | |
1489 dev--; | |
1490 | |
1491 if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) { | |
1492 int dir = a & 3; | |
1493 int v = 0; | |
1494 switch(dir) { | |
1495 case 0: | |
1496 v = value & SDL_HAT_UP; | |
1497 break; | |
1498 case 1: | |
1499 v = value & SDL_HAT_DOWN; | |
1500 break; | |
1501 case 2: | |
1502 v = value & SDL_HAT_RIGHT; | |
1503 break; | |
1504 case 3: | |
1505 v = value & SDL_HAT_LEFT; | |
1506 break; | |
1507 } | |
1508 if (v) currentButtons[j] |= 1<<i; | |
1509 else currentButtons[j] ^= 1<<i; | |
1510 } | |
1511 } | |
1512 } | |
1513 } | |
1514 for(i = 0; i < 4; i++) { | |
1515 int dev = (motion[i] >> 12); | |
1516 int a = motion[i] & 0xfff; | |
1517 if(dev) { | |
1518 dev--; | |
1519 | |
1520 if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) { | |
1521 int dir = a & 3; | |
1522 int v = 0; | |
1523 switch(dir) { | |
1524 case 0: | |
1525 v = value & SDL_HAT_UP; | |
1526 break; | |
1527 case 1: | |
1528 v = value & SDL_HAT_DOWN; | |
1529 break; | |
1530 case 2: | |
1531 v = value & SDL_HAT_RIGHT; | |
1532 break; | |
1533 case 3: | |
1534 v = value & SDL_HAT_LEFT; | |
1535 break; | |
1536 } | |
1537 sdlMotionButtons[i] = (v ? true : false); | |
1538 } | |
1539 } | |
1540 } | |
1541 } | |
1542 | |
1543 void sdlUpdateJoyAxis(int which, | |
1544 int axis, | |
1545 int value) | |
1546 { | |
1547 int i; | |
1548 for(int j = 0; j < 4; j++) { | |
1549 for(i = 0; i < 12; i++) { | |
1550 int dev = (joypad[j][i] >> 12); | |
1551 int a = joypad[j][i] & 0xfff; | |
1552 if(dev) { | |
1553 dev--; | |
1554 | |
1555 if((dev == which) && (a < 32) && ((a>>1) == axis)) { | |
1556 //I have no idea what this does, is this reimplementation correct? --Felipe | |
1557 if (value>16384) { | |
1558 if (a&1) currentButtons[j] |= 1<<i; | |
1559 else currentButtons[j] ^= 1<<i; | |
1560 } | |
1561 else if (value<16384){ | |
1562 if (a&1) currentButtons[j] ^= 1<<i; | |
1563 else currentButtons[j] |= 1<<i; | |
1564 } | |
1565 } | |
1566 } | |
1567 } | |
1568 } | |
1569 for(i = 0; i < 4; i++) { | |
1570 int dev = (motion[i] >> 12); | |
1571 int a = motion[i] & 0xfff; | |
1572 if(dev) { | |
1573 dev--; | |
1574 | |
1575 if((dev == which) && (a < 32) && ((a>>1) == axis)) { | |
1576 sdlMotionButtons[i] = (a & 1) ? (value > 16384) : (value < -16384); | |
1577 } | |
1578 } | |
1579 } | |
1580 } | |
1581 | |
1582 bool sdlCheckJoyKey(int key) | |
1583 { | |
1584 int dev = (key >> 12) - 1; | |
1585 int what = key & 0xfff; | |
1586 | |
1587 if(what >= 128) { | |
1588 // joystick button | |
1589 int button = what - 128; | |
1590 | |
1591 if(button >= SDL_JoystickNumButtons(sdlDevices[dev])) | |
1592 return false; | |
1593 } else if (what < 0x20) { | |
1594 // joystick axis | |
1595 what >>= 1; | |
1596 if(what >= SDL_JoystickNumAxes(sdlDevices[dev])) | |
1597 return false; | |
1598 } else if (what < 0x30) { | |
1599 // joystick hat | |
1600 what = (what & 15); | |
1601 what >>= 2; | |
1602 if(what >= SDL_JoystickNumHats(sdlDevices[dev])) | |
1603 return false; | |
1604 } | |
1605 | |
1606 // no problem found | |
1607 return true; | |
1608 } | |
1609 | |
1610 void sdlCheckKeys() | |
1611 { | |
1612 sdlNumDevices = SDL_NumJoysticks(); | |
1613 | |
1614 if(sdlNumDevices) | |
1615 sdlDevices = (SDL_Joystick **)calloc(1,sdlNumDevices * | |
1616 sizeof(SDL_Joystick **)); | |
1617 int i; | |
1618 | |
1619 bool usesJoy = false; | |
1620 | |
1621 for(int j = 0; j < 4; j++) { | |
1622 for(i = 0; i < 12; i++) { | |
1623 int dev = joypad[j][i] >> 12; | |
1624 if(dev) { | |
1625 dev--; | |
1626 bool ok = false; | |
1627 | |
1628 if(sdlDevices) { | |
1629 if(dev < sdlNumDevices) { | |
1630 if(sdlDevices[dev] == NULL) { | |
1631 sdlDevices[dev] = SDL_JoystickOpen(dev); | |
1632 } | |
1633 | |
1634 ok = sdlCheckJoyKey(joypad[j][i]); | |
1635 } else | |
1636 ok = false; | |
1637 } | |
1638 | |
1639 if(!ok) | |
1640 joypad[j][i] = defaultJoypad[i]; | |
1641 else | |
1642 usesJoy = true; | |
1643 } | |
1644 } | |
1645 } | |
1646 | |
1647 for(i = 0; i < 4; i++) { | |
1648 int dev = motion[i] >> 12; | |
1649 if(dev) { | |
1650 dev--; | |
1651 bool ok = false; | |
1652 | |
1653 if(sdlDevices) { | |
1654 if(dev < sdlNumDevices) { | |
1655 if(sdlDevices[dev] == NULL) { | |
1656 sdlDevices[dev] = SDL_JoystickOpen(dev); | |
1657 } | |
1658 | |
1659 ok = sdlCheckJoyKey(motion[i]); | |
1660 } else | |
1661 ok = false; | |
1662 } | |
1663 | |
1664 if(!ok) | |
1665 motion[i] = defaultMotion[i]; | |
1666 else | |
1667 usesJoy = true; | |
1668 } | |
1669 } | |
1670 | |
1671 if(usesJoy) | |
1672 SDL_JoystickEventState(SDL_ENABLE); | |
1673 } | |
1674 | |
1675 void sdlPollEvents() | |
1676 { | |
1677 SDL_Event event; | |
1678 while(SDL_PollEvent(&event)) { | |
1679 switch(event.type) { | |
1680 case SDL_QUIT: | |
1681 emulating = 0; | |
1682 break; | |
1683 case SDL_ACTIVEEVENT: | |
1684 if(pauseWhenInactive && (event.active.state & SDL_APPINPUTFOCUS)) { | |
1685 active = event.active.gain; | |
1686 if(active) { | |
1687 if(!paused) { | |
1688 if(emulating) | |
1689 soundResume(); | |
1690 } | |
1691 } else { | |
1692 wasPaused = true; | |
1693 if(pauseWhenInactive) { | |
1694 if(emulating) | |
1695 soundPause(); | |
1696 } | |
1697 | |
1698 memset(delta,255,sizeof(delta)); | |
1699 } | |
1700 } | |
1701 break; | |
1702 case SDL_MOUSEMOTION: | |
1703 case SDL_MOUSEBUTTONUP: | |
1704 case SDL_MOUSEBUTTONDOWN: | |
1705 if(fullscreen) { | |
1706 SDL_ShowCursor(SDL_ENABLE); | |
1707 mouseCounter = 120; | |
1708 } | |
1709 break; | |
1710 case SDL_JOYHATMOTION: | |
1711 sdlUpdateJoyHat(event.jhat.which, | |
1712 event.jhat.hat, | |
1713 event.jhat.value); | |
1714 break; | |
1715 case SDL_JOYBUTTONDOWN: | |
1716 case SDL_JOYBUTTONUP: | |
1717 sdlUpdateJoyButton(event.jbutton.which, | |
1718 event.jbutton.button, | |
1719 event.jbutton.state == SDL_PRESSED); | |
1720 break; | |
1721 case SDL_JOYAXISMOTION: | |
1722 sdlUpdateJoyAxis(event.jaxis.which, | |
1723 event.jaxis.axis, | |
1724 event.jaxis.value); | |
1725 break; | |
1726 case SDL_KEYDOWN: | |
1727 sdlUpdateKey(event.key.keysym.sym, true); | |
1728 break; | |
1729 case SDL_KEYUP: | |
1730 switch(event.key.keysym.sym) { | |
1731 case SDLK_r: | |
1732 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1733 (event.key.keysym.mod & KMOD_CTRL)) { | |
1734 if(emulating) { | |
1735 theEmulator.emuReset(true); | |
1736 | |
1737 systemScreenMessage("Reset"); | |
1738 } | |
1739 } | |
1740 break; | |
1741 case SDLK_b: | |
1742 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1743 (event.key.keysym.mod & KMOD_CTRL)) { | |
1744 if(emulating && theEmulator.emuReadMemState && rewindMemory | |
1745 && rewindCount) { | |
1746 rewindPos = --rewindPos & 7; | |
1747 theEmulator.emuReadMemState(&rewindMemory[REWIND_SIZE*rewindPos], | |
1748 REWIND_SIZE); | |
1749 rewindCount--; | |
1750 rewindCounter = 0; | |
1751 systemScreenMessage("Rewind"); | |
1752 } | |
1753 } | |
1754 break; | |
1755 case SDLK_p: | |
1756 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1757 (event.key.keysym.mod & KMOD_CTRL)) { | |
1758 paused = !paused; | |
1759 SDL_PauseAudio(paused); | |
1760 if(paused) | |
1761 wasPaused = true; | |
1762 } | |
1763 break; | |
1764 case SDLK_ESCAPE: | |
1765 emulating = 0; | |
1766 break; | |
1767 case SDLK_f: | |
1768 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1769 (event.key.keysym.mod & KMOD_CTRL)) { | |
1770 int flags = 0; | |
1771 fullscreen = !fullscreen; | |
1772 if(fullscreen) | |
1773 flags |= SDL_FULLSCREEN; | |
1774 SDL_SetVideoMode(destWidth, destHeight, systemColorDepth, flags); | |
1775 // if(SDL_WM_ToggleFullScreen(surface)) | |
1776 // fullscreen = !fullscreen; | |
1777 } | |
1778 break; | |
1779 case SDLK_F11: | |
1780 if(dbgMain != debuggerMain) { | |
1781 if(armState) { | |
1782 armNextPC -= 4; | |
1783 reg[15].I -= 4; | |
1784 } else { | |
1785 armNextPC -= 2; | |
1786 reg[15].I -= 2; | |
1787 } | |
1788 } | |
1789 debugger = true; | |
1790 break; | |
1791 case SDLK_F1: | |
1792 case SDLK_F2: | |
1793 case SDLK_F3: | |
1794 case SDLK_F4: | |
1795 case SDLK_F5: | |
1796 case SDLK_F6: | |
1797 case SDLK_F7: | |
1798 case SDLK_F8: | |
1799 case SDLK_F9: | |
1800 case SDLK_F10: | |
1801 if(!(event.key.keysym.mod & MOD_NOSHIFT) && | |
1802 (event.key.keysym.mod & KMOD_SHIFT)) { | |
1803 sdlWriteState(event.key.keysym.sym-SDLK_F1); | |
1804 } else if(!(event.key.keysym.mod & MOD_KEYS)) { | |
1805 sdlReadState(event.key.keysym.sym-SDLK_F1); | |
1806 } | |
1807 break; | |
1808 case SDLK_1: | |
1809 case SDLK_2: | |
1810 case SDLK_3: | |
1811 case SDLK_4: | |
1812 if(!(event.key.keysym.mod & MOD_NOALT) && | |
1813 (event.key.keysym.mod & KMOD_ALT)) { | |
1814 char *disableMessages[4] = | |
1815 { "autofire A disabled", | |
1816 "autofire B disabled", | |
1817 "autofire R disabled", | |
1818 "autofire L disabled"}; | |
1819 char *enableMessages[4] = | |
1820 { "autofire A", | |
1821 "autofire B", | |
1822 "autofire R", | |
1823 "autofire L"}; | |
1824 int mask = 1 << (event.key.keysym.sym - SDLK_1); | |
1825 if(event.key.keysym.sym > SDLK_2) | |
1826 mask <<= 6; | |
1827 if(autoFire & mask) { | |
1828 autoFire &= ~mask; | |
1829 systemScreenMessage(disableMessages[event.key.keysym.sym - SDLK_1]); | |
1830 } else { | |
1831 autoFire |= mask; | |
1832 systemScreenMessage(enableMessages[event.key.keysym.sym - SDLK_1]); | |
1833 } | |
1834 } if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1835 (event.key.keysym.mod & KMOD_CTRL)) { | |
1836 int mask = 0x0100 << (event.key.keysym.sym - SDLK_1); | |
1837 layerSettings ^= mask; | |
1838 layerEnable = DISPCNT & layerSettings; | |
1839 CPUUpdateRenderBuffers(false); | |
1840 } | |
1841 break; | |
1842 case SDLK_5: | |
1843 case SDLK_6: | |
1844 case SDLK_7: | |
1845 case SDLK_8: | |
1846 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1847 (event.key.keysym.mod & KMOD_CTRL)) { | |
1848 int mask = 0x0100 << (event.key.keysym.sym - SDLK_1); | |
1849 layerSettings ^= mask; | |
1850 layerEnable = DISPCNT & layerSettings; | |
1851 } | |
1852 break; | |
1853 case SDLK_n: | |
1854 if(!(event.key.keysym.mod & MOD_NOCTRL) && | |
1855 (event.key.keysym.mod & KMOD_CTRL)) { | |
1856 if(paused) | |
1857 paused = false; | |
1858 pauseNextFrame = true; | |
1859 } | |
1860 break; | |
1861 default: | |
1862 break; | |
1863 } | |
1864 sdlUpdateKey(event.key.keysym.sym, false); | |
1865 break; | |
1866 } | |
1867 } | |
1868 } | |
1869 | |
1870 void usage(char *cmd) | |
1871 { | |
1872 printf("%s [option ...] file\n", cmd); | |
1873 printf("\ | |
1874 \n\ | |
1875 Options:\n\ | |
1876 -1, --video-1x 1x\n\ | |
1877 -2, --video-2x 2x\n\ | |
1878 -3, --video-3x 3x\n\ | |
1879 -4, --video-4x 4x\n\ | |
1880 -F, --fullscreen Full screen\n\ | |
1881 -G, --gdb=PROTOCOL GNU Remote Stub mode:\n\ | |
1882 tcp - use TCP at port 55555\n\ | |
1883 tcp:PORT - use TCP at port PORT\n\ | |
1884 pipe - use pipe transport\n\ | |
1885 -N, --no-debug Don't parse debug information\n\ | |
1886 -S, --flash-size=SIZE Set the Flash size\n\ | |
1887 --flash-64k 0 - 64K Flash\n\ | |
1888 --flash-128k 1 - 128K Flash\n\ | |
1889 -T, --throttle=THROTTLE Set the desired throttle (5...1000)\n\ | |
1890 -Y, --yuv=TYPE Use YUV overlay for drawing:\n\ | |
1891 0 - YV12\n\ | |
1892 1 - UYVY\n\ | |
1893 2 - YVYU\n\ | |
1894 3 - YUY2\n\ | |
1895 4 - IYUV\n\ | |
1896 -b, --bios=BIOS Use given bios file\n\ | |
1897 -c, --config=FILE Read the given configuration file\n\ | |
1898 -d, --debug Enter debugger\n\ | |
1899 -f, --filter=FILTER Select filter:\n\ | |
1900 --filter-normal 0 - normal mode\n\ | |
1901 --filter-tv-mode 1 - TV Mode\n\ | |
1902 --filter-2xsai 2 - 2xSaI\n\ | |
1903 --filter-super-2xsai 3 - Super 2xSaI\n\ | |
1904 --filter-super-eagle 4 - Super Eagle\n\ | |
1905 --filter-pixelate 5 - Pixelate\n\ | |
1906 --filter-motion-blur 6 - Motion Blur\n\ | |
1907 --filter-advmame 7 - AdvanceMAME Scale2x\n\ | |
1908 --filter-simple2x 8 - Simple2x\n\ | |
1909 --filter-bilinear 9 - Bilinear\n\ | |
1910 --filter-bilinear+ 10 - Bilinear Plus\n\ | |
1911 --filter-scanlines 11 - Scanlines\n\ | |
1912 --filter-hq2x 12 - hq2x\n\ | |
1913 --filter-lq2x 13 - lq2x\n\ | |
1914 -h, --help Print this help\n\ | |
1915 -i, --ips=PATCH Apply given IPS patch\n\ | |
1916 -P, --profile=[HERTZ] Enable profiling\n\ | |
1917 -s, --frameskip=FRAMESKIP Set frame skip (0...9)\n\ | |
1918 "); | |
1919 printf("\ | |
1920 -t, --save-type=TYPE Set the available save type\n\ | |
1921 --save-auto 0 - Automatic (EEPROM, SRAM, FLASH)\n\ | |
1922 --save-eeprom 1 - EEPROM\n\ | |
1923 --save-sram 2 - SRAM\n\ | |
1924 --save-flash 3 - FLASH\n\ | |
1925 --save-sensor 4 - EEPROM+Sensor\n\ | |
1926 --save-none 5 - NONE\n\ | |
1927 -v, --verbose=VERBOSE Set verbose logging (trace.log)\n\ | |
1928 1 - SWI\n\ | |
1929 2 - Unaligned memory access\n\ | |
1930 4 - Illegal memory write\n\ | |
1931 8 - Illegal memory read\n\ | |
1932 16 - DMA 0\n\ | |
1933 32 - DMA 1\n\ | |
1934 64 - DMA 2\n\ | |
1935 128 - DMA 3\n\ | |
1936 256 - Undefined instruction\n\ | |
1937 512 - AGBPrint messages\n\ | |
1938 \n\ | |
1939 Long options only:\n\ | |
1940 --agb-print Enable AGBPrint support\n\ | |
1941 --auto-frameskip Enable auto frameskipping\n\ | |
1942 --ifb-none No interframe blending\n\ | |
1943 --ifb-motion-blur Interframe motion blur\n\ | |
1944 --ifb-smart Smart interframe blending\n\ | |
1945 --no-agb-print Disable AGBPrint support\n\ | |
1946 --no-auto-frameskip Disable auto frameskipping\n\ | |
1947 --no-ips Do not apply IPS patch\n\ | |
1948 --no-mmx Disable MMX support\n\ | |
1949 --no-pause-when-inactive Don't pause when inactive\n\ | |
1950 --no-rtc Disable RTC support\n\ | |
1951 --no-show-speed Don't show emulation speed\n\ | |
1952 --no-throttle Disable thrrotle\n\ | |
1953 --pause-when-inactive Pause when inactive\n\ | |
1954 --rtc Enable RTC support\n\ | |
1955 --show-speed-normal Show emulation speed\n\ | |
1956 --show-speed-detailed Show detailed speed data\n\ | |
1957 "); | |
1958 printf("\ | |
1959 -r, --recordmovie=filename Start recording input movie\n\ | |
1960 -p, --playmovie=filename Play input movie non-read-only\n\ | |
1961 -w, --watchmovie=filename Play input movie in read-only mode\n\ | |
1962 "); | |
1963 } | |
1964 | |
1965 static char *szFile; | |
1966 | |
1967 void file_run() | |
1968 { | |
1969 utilGetBaseName(szFile, filename); | |
1970 char *p = strrchr(filename, '.'); | |
1971 | |
1972 if(p) | |
1973 *p = 0; | |
1974 | |
1975 if(ipsname[0] == 0) | |
1976 sprintf(ipsname, "%s.ips", filename); | |
1977 | |
1978 bool failed = false; | |
1979 | |
1980 IMAGE_TYPE type = utilFindType(szFile); | |
1981 | |
1982 if(type == IMAGE_UNKNOWN) { | |
1983 systemMessage(0, "Unknown file type %s", szFile); | |
1984 exit(-1); | |
1985 } | |
1986 systemCartridgeType = (int)type; | |
1987 | |
1988 if(type == IMAGE_GB) { | |
1989 failed = !gbLoadRom(szFile); | |
1990 if(!failed) { | |
1991 systemCartridgeType = 1; | |
1992 theEmulator = GBSystem; | |
1993 if(sdlAutoIPS) { | |
1994 int size = gbRomSize; | |
1995 utilApplyIPS(ipsname, &gbRom, &size); | |
1996 if(size != gbRomSize) { | |
1997 extern bool gbUpdateSizes(); | |
1998 gbUpdateSizes(); | |
1999 gbReset(); | |
2000 } | |
2001 } | |
2002 } | |
2003 } else if(type == IMAGE_GBA) { | |
2004 int size = CPULoadRom(szFile); | |
2005 failed = (size == 0); | |
2006 if(!failed) { | |
2007 // if(cpuEnhancedDetection && cpuSaveType == 0) { | |
2008 // utilGBAFindSave(rom, size); | |
2009 // } | |
2010 | |
2011 sdlApplyPerImagePreferences(); | |
2012 | |
2013 systemCartridgeType = 0; | |
2014 theEmulator = GBASystem; | |
2015 | |
2016 /* disabled due to problems | |
2017 if(removeIntros && rom != NULL) { | |
2018 WRITE32LE(&rom[0], 0xea00002e); | |
2019 } | |
2020 */ | |
2021 | |
2022 //CPUInit(biosFileName, useBios); | |
2023 CPUInit(); | |
2024 CPUReset(); | |
2025 if(sdlAutoIPS) { | |
2026 int size = 0x2000000; | |
2027 utilApplyIPS(ipsname, &rom, &size); | |
2028 if(size != 0x2000000) { | |
2029 CPUReset(); | |
2030 } | |
2031 } | |
2032 } | |
2033 } | |
2034 | |
2035 if(failed) { | |
2036 systemMessage(0, "Failed to load file %s", szFile); | |
2037 exit(-1); | |
2038 } | |
2039 | |
2040 emulating = 1; | |
2041 renderedFrames = 0; | |
2042 } | |
2043 | |
2044 int main(int argc, char **argv) | |
2045 { | |
2046 fprintf(stderr, "VisualBoyAdvance version %s [SDL]\n", VERSION); | |
2047 | |
2048 arg0 = argv[0]; | |
2049 | |
2050 captureDir[0] = 0; | |
2051 saveDir[0] = 0; | |
2052 batteryDir[0] = 0; | |
2053 ipsname[0] = 0; | |
2054 | |
2055 int op = -1; | |
2056 | |
2057 frameSkip = 2; | |
2058 gbBorderOn = 0; | |
2059 | |
2060 parseDebug = true; | |
2061 | |
2062 sdlReadPreferences(); | |
2063 | |
2064 sdlPrintUsage = 0; | |
2065 | |
2066 while((op = getopt_long(argc, | |
2067 argv, | |
2068 "FNT:Y:G:D:b:c:df:hi:p::s:t:v:1234", | |
2069 sdlOptions, | |
2070 NULL)) != -1) { | |
2071 switch(op) { | |
2072 case 0: | |
2073 // long option already processed by getopt_long | |
2074 break; | |
2075 case 'b': | |
2076 useBios = true; | |
2077 if(optarg == NULL) { | |
2078 fprintf(stderr, "Missing BIOS file name\n"); | |
2079 exit(-1); | |
2080 } | |
2081 strcpy(biosFileName, optarg); | |
2082 break; | |
2083 case 'c': | |
2084 { | |
2085 if(optarg == NULL) { | |
2086 fprintf(stderr, "Missing config file name\n"); | |
2087 exit(-1); | |
2088 } | |
2089 FILE *f = fopen(optarg, "r"); | |
2090 if(f == NULL) { | |
2091 fprintf(stderr, "File not found %s\n", optarg); | |
2092 exit(-1); | |
2093 } | |
2094 sdlReadPreferences(f); | |
2095 fclose(f); | |
2096 } | |
2097 break; | |
2098 case 'd': | |
2099 debugger = true; | |
2100 break; | |
2101 case 'h': | |
2102 sdlPrintUsage = 1; | |
2103 break; | |
2104 case 'i': | |
2105 if(optarg == NULL) { | |
2106 fprintf(stderr, "Missing IPS name\n"); | |
2107 exit(-1); | |
2108 strcpy(ipsname, optarg); | |
2109 } | |
2110 break; | |
2111 case 'Y': | |
2112 yuv = true; | |
2113 if(optarg) { | |
2114 yuvType = atoi(optarg); | |
2115 switch(yuvType) { | |
2116 case 0: | |
2117 yuvType = SDL_YV12_OVERLAY; | |
2118 break; | |
2119 case 1: | |
2120 yuvType = SDL_UYVY_OVERLAY; | |
2121 break; | |
2122 case 2: | |
2123 yuvType = SDL_YVYU_OVERLAY; | |
2124 break; | |
2125 case 3: | |
2126 yuvType = SDL_YUY2_OVERLAY; | |
2127 break; | |
2128 case 4: | |
2129 yuvType = SDL_IYUV_OVERLAY; | |
2130 break; | |
2131 default: | |
2132 yuvType = SDL_YV12_OVERLAY; | |
2133 } | |
2134 } else | |
2135 yuvType = SDL_YV12_OVERLAY; | |
2136 break; | |
2137 case 'G': | |
2138 dbgMain = remoteStubMain; | |
2139 dbgSignal = remoteStubSignal; | |
2140 dbgOutput = remoteOutput; | |
2141 debugger = true; | |
2142 debuggerStub = true; | |
2143 if(optarg) { | |
2144 char *s = optarg; | |
2145 if(strncmp(s,"tcp:", 4) == 0) { | |
2146 s+=4; | |
2147 int port = atoi(s); | |
2148 remoteSetProtocol(0); | |
2149 remoteSetPort(port); | |
2150 } else if(strcmp(s,"tcp") == 0) { | |
2151 remoteSetProtocol(0); | |
2152 } else if(strcmp(s, "pipe") == 0) { | |
2153 remoteSetProtocol(1); | |
2154 } else { | |
2155 fprintf(stderr, "Unknown protocol %s\n", s); | |
2156 exit(-1); | |
2157 } | |
2158 } else { | |
2159 remoteSetProtocol(0); | |
2160 } | |
2161 break; | |
2162 case 'N': | |
2163 parseDebug = false; | |
2164 break; | |
2165 case 'D': | |
2166 if(optarg) { | |
2167 systemDebug = atoi(optarg); | |
2168 } else { | |
2169 systemDebug = 1; | |
2170 } | |
2171 break; | |
2172 case 'F': | |
2173 fullscreen = 1; | |
2174 mouseCounter = 120; | |
2175 break; | |
2176 case 'f': | |
2177 if(optarg) { | |
2178 filter = atoi(optarg); | |
2179 } else { | |
2180 filter = 0; | |
2181 } | |
2182 break; | |
2183 | |
2184 case 'r': | |
2185 if(optarg == NULL) { | |
2186 fprintf(stderr, "ERROR: --recordMovie ('r') needs movie filename as option\n"); | |
2187 exit(-1); | |
2188 } | |
2189 strcpy(movieFileName, optarg); | |
2190 useMovie = 1; | |
2191 break; | |
2192 case 'p': // play without read-only (editable) | |
2193 fprintf (stderr, "-p got called!\n"); | |
2194 if(optarg == NULL) { | |
2195 fprintf(stderr, "ERROR: --playMovie ('p') needs movie filename as option\n"); | |
2196 exit(-1); | |
2197 } | |
2198 strcpy(movieFileName, optarg); | |
2199 useMovie = 2; | |
2200 break; | |
2201 case 'w': // play with read-only | |
2202 fprintf (stderr, "-w got called!\n"); | |
2203 if(optarg == NULL) { | |
2204 fprintf(stderr, "ERROR: --watchMovie ('w') needs movie filename as option\n"); | |
2205 exit(-1); | |
2206 } | |
2207 strcpy(movieFileName, optarg); | |
2208 useMovie = 3; | |
2209 break; | |
2210 | |
2211 case 'P': | |
2212 #ifdef PROFILING | |
2213 if(optarg) { | |
2214 cpuEnableProfiling(atoi(optarg)); | |
2215 } else | |
2216 cpuEnableProfiling(100); | |
2217 #endif | |
2218 break; | |
2219 case 'S': | |
2220 sdlFlashSize = atoi(optarg); | |
2221 if(sdlFlashSize < 0 || sdlFlashSize > 1) | |
2222 sdlFlashSize = 0; | |
2223 break; | |
2224 case 's': | |
2225 if(optarg) { | |
2226 int a = atoi(optarg); | |
2227 if(a >= 0 && a <= 9) { | |
2228 gbFrameSkip = a; | |
2229 frameSkip = a; | |
2230 } | |
2231 } else { | |
2232 frameSkip = 2; | |
2233 gbFrameSkip = 0; | |
2234 } | |
2235 break; | |
2236 case 't': | |
2237 if(optarg) { | |
2238 int a = atoi(optarg); | |
2239 if(a < 0 || a > 5) | |
2240 a = 0; | |
2241 cpuSaveType = a; | |
2242 } | |
2243 break; | |
2244 case 'T': | |
2245 if(optarg) { | |
2246 int t = atoi(optarg); | |
2247 throttle = t; | |
2248 } | |
2249 break; | |
2250 case 'v': | |
2251 if(optarg) { | |
2252 systemVerbose = atoi(optarg); | |
2253 } else | |
2254 systemVerbose = 0; | |
2255 break; | |
2256 case '1': | |
2257 sizeOption = 0; | |
2258 break; | |
2259 case '2': | |
2260 sizeOption = 1; | |
2261 break; | |
2262 case '3': | |
2263 sizeOption = 2; | |
2264 break; | |
2265 case '4': | |
2266 sizeOption = 3; | |
2267 break; | |
2268 case '?': | |
2269 sdlPrintUsage = 1; | |
2270 break; | |
2271 } | |
2272 } | |
2273 | |
2274 if(sdlPrintUsage) { | |
2275 usage(argv[0]); | |
2276 exit(-1); | |
2277 } | |
2278 | |
2279 #ifdef MMX | |
2280 if(disableMMX) | |
2281 cpu_mmx = 0; | |
2282 #endif | |
2283 | |
2284 if(rewindTimer) | |
2285 rewindMemory = (char *)malloc(8*REWIND_SIZE); | |
2286 | |
2287 if(sdlFlashSize == 0) | |
2288 flashSetSize(0x10000); | |
2289 else | |
2290 flashSetSize(0x20000); | |
2291 | |
2292 rtcEnable(sdlRtcEnable ? true : false); | |
2293 agbPrintEnable(sdlAgbPrint ? true : false); | |
2294 | |
2295 if(!debuggerStub) { | |
2296 if(optind >= argc) { | |
2297 systemMessage(0,"Missing image name"); | |
2298 usage(argv[0]); | |
2299 exit(-1); | |
2300 } | |
2301 } | |
2302 | |
2303 if(filter) { | |
2304 sizeOption = 1; | |
2305 } | |
2306 | |
2307 for(int i = 0; i < 24;) { | |
2308 systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); | |
2309 systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); | |
2310 systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); | |
2311 systemGbPalette[i++] = 0; | |
2312 } | |
2313 | |
2314 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
2315 | |
2316 if(optind < argc) | |
2317 { | |
2318 szFile = argv[optind]; | |
2319 file_run(); | |
2320 } | |
2321 else | |
2322 { | |
2323 systemCartridgeType = 0; | |
2324 strcpy(filename, "gnu_stub"); | |
2325 rom = (u8 *)malloc(0x2000000); | |
2326 workRAM = (u8 *)calloc(1, 0x40000); | |
2327 bios = (u8 *)calloc(1,0x4000); | |
2328 internalRAM = (u8 *)calloc(1,0x8000); | |
2329 paletteRAM = (u8 *)calloc(1,0x400); | |
2330 vram = (u8 *)calloc(1, 0x20000); | |
2331 oam = (u8 *)calloc(1, 0x400); | |
2332 pix = (u8 *)calloc(1, 4 * 240 * 160); | |
2333 ioMem = (u8 *)calloc(1, 0x400); | |
2334 | |
2335 theEmulator = GBASystem; | |
2336 | |
2337 //CPUInit(biosFileName, useBios); | |
2338 CPUInit(); | |
2339 CPUReset(); | |
2340 } | |
2341 | |
2342 if(debuggerStub) | |
2343 remoteInit(); | |
2344 | |
2345 int flags = SDL_INIT_VIDEO|SDL_INIT_AUDIO| | |
2346 SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE; | |
2347 | |
2348 if(soundOffFlag) | |
2349 flags ^= SDL_INIT_AUDIO; | |
2350 | |
2351 if(SDL_Init(flags)) { | |
2352 systemMessage(0, "Failed to init SDL: %s", SDL_GetError()); | |
2353 exit(-1); | |
2354 } | |
2355 | |
2356 if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) { | |
2357 systemMessage(0, "Failed to init joystick support: %s", SDL_GetError()); | |
2358 } | |
2359 | |
2360 sdlCheckKeys(); | |
2361 | |
2362 if(systemCartridgeType == 0) { | |
2363 srcWidth = 240; | |
2364 srcHeight = 160; | |
2365 systemFrameSkip = frameSkip; | |
2366 } else if (systemCartridgeType == 1) { | |
2367 if(gbBorderOn) { | |
2368 srcWidth = 256; | |
2369 srcHeight = 224; | |
2370 gbBorderLineSkip = 256; | |
2371 gbBorderColumnSkip = 48; | |
2372 gbBorderRowSkip = 40; | |
2373 } else { | |
2374 srcWidth = 160; | |
2375 srcHeight = 144; | |
2376 gbBorderLineSkip = 160; | |
2377 gbBorderColumnSkip = 0; | |
2378 gbBorderRowSkip = 0; | |
2379 } | |
2380 systemFrameSkip = gbFrameSkip; | |
2381 } else { | |
2382 srcWidth = 320; | |
2383 srcHeight = 240; | |
2384 } | |
2385 | |
2386 destWidth = (sizeOption+1)*srcWidth; | |
2387 destHeight = (sizeOption+1)*srcHeight; | |
2388 | |
2389 surface = SDL_SetVideoMode(destWidth, destHeight, 16, | |
2390 SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF| | |
2391 (fullscreen ? SDL_FULLSCREEN : 0)); | |
2392 | |
2393 if(surface == NULL) { | |
2394 systemMessage(0, "Failed to set video mode"); | |
2395 SDL_Quit(); | |
2396 exit(-1); | |
2397 } | |
2398 | |
2399 systemRedShift = sdlCalculateShift(surface->format->Rmask); | |
2400 systemGreenShift = sdlCalculateShift(surface->format->Gmask); | |
2401 systemBlueShift = sdlCalculateShift(surface->format->Bmask); | |
2402 | |
2403 systemColorDepth = surface->format->BitsPerPixel; | |
2404 if(systemColorDepth == 15) | |
2405 systemColorDepth = 16; | |
2406 | |
2407 if(yuv) { | |
2408 Init_Overlay(surface, yuvType); | |
2409 systemColorDepth = 32; | |
2410 systemRedShift = 3; | |
2411 systemGreenShift = 11; | |
2412 systemBlueShift = 19; | |
2413 } | |
2414 | |
2415 if(systemColorDepth != 16 && systemColorDepth != 24 && | |
2416 systemColorDepth != 32) { | |
2417 fprintf(stderr,"Unsupported color depth '%d'.\nOnly 16, 24 and 32 bit color depths are supported\n", systemColorDepth); | |
2418 exit(-1); | |
2419 } | |
2420 | |
2421 #ifndef C_CORE | |
2422 sdlMakeStretcher(srcWidth); | |
2423 #else | |
2424 switch(systemColorDepth) { | |
2425 case 16: | |
2426 sdlStretcher = sdlStretcher16[sizeOption]; | |
2427 break; | |
2428 case 24: | |
2429 sdlStretcher = sdlStretcher24[sizeOption]; | |
2430 break; | |
2431 case 32: | |
2432 sdlStretcher = sdlStretcher32[sizeOption]; | |
2433 break; | |
2434 default: | |
2435 fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth); | |
2436 exit(-1); | |
2437 } | |
2438 #endif | |
2439 | |
2440 fprintf(stderr,"Color depth: %d\n", systemColorDepth); | |
2441 | |
2442 if(systemColorDepth == 16) { | |
2443 if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) { | |
2444 Init_2xSaI(565); | |
2445 RGB_LOW_BITS_MASK = 0x821; | |
2446 } else { | |
2447 Init_2xSaI(555); | |
2448 RGB_LOW_BITS_MASK = 0x421; | |
2449 } | |
2450 if(systemCartridgeType == 2) { | |
2451 for(int i = 0; i < 0x10000; i++) { | |
2452 systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) | | |
2453 (((i & 0x7c0) >> 6) << systemGreenShift) | | |
2454 (((i & 0xf800) >> 11) << systemRedShift); | |
2455 } | |
2456 } else { | |
2457 for(int i = 0; i < 0x10000; i++) { | |
2458 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | | |
2459 (((i & 0x3e0) >> 5) << systemGreenShift) | | |
2460 (((i & 0x7c00) >> 10) << systemBlueShift); | |
2461 } | |
2462 } | |
2463 srcPitch = srcWidth * 2+4; | |
2464 } else { | |
2465 if(systemColorDepth != 32) | |
2466 filterFunction = NULL; | |
2467 RGB_LOW_BITS_MASK = 0x010101; | |
2468 if(systemColorDepth == 32) { | |
2469 Init_2xSaI(32); | |
2470 } | |
2471 for(int i = 0; i < 0x10000; i++) { | |
2472 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | | |
2473 (((i & 0x3e0) >> 5) << systemGreenShift) | | |
2474 (((i & 0x7c00) >> 10) << systemBlueShift); | |
2475 } | |
2476 if(systemColorDepth == 32) | |
2477 srcPitch = srcWidth*4 + 4; | |
2478 else | |
2479 srcPitch = srcWidth*3; | |
2480 } | |
2481 | |
2482 if(systemColorDepth != 32) { | |
2483 switch(filter) { | |
2484 case 0: | |
2485 filterFunction = NULL; | |
2486 break; | |
2487 case 1: | |
2488 filterFunction = ScanlinesTV; | |
2489 break; | |
2490 case 2: | |
2491 filterFunction = _2xSaI; | |
2492 break; | |
2493 case 3: | |
2494 filterFunction = Super2xSaI; | |
2495 break; | |
2496 case 4: | |
2497 filterFunction = SuperEagle; | |
2498 break; | |
2499 case 5: | |
2500 filterFunction = Pixelate2x16; | |
2501 break; | |
2502 case 6: | |
2503 filterFunction = MotionBlur; | |
2504 break; | |
2505 case 7: | |
2506 filterFunction = AdMame2x; | |
2507 break; | |
2508 case 8: | |
2509 filterFunction = Simple2x16; | |
2510 break; | |
2511 case 9: | |
2512 filterFunction = Bilinear; | |
2513 break; | |
2514 case 10: | |
2515 filterFunction = BilinearPlus; | |
2516 break; | |
2517 case 11: | |
2518 filterFunction = Scanlines; | |
2519 break; | |
2520 case 12: | |
2521 filterFunction = hq2x; | |
2522 break; | |
2523 case 13: | |
2524 filterFunction = lq2x; | |
2525 break; | |
2526 default: | |
2527 filterFunction = NULL; | |
2528 break; | |
2529 } | |
2530 } else { | |
2531 switch(filter) { | |
2532 case 0: | |
2533 filterFunction = NULL; | |
2534 break; | |
2535 case 1: | |
2536 filterFunction = ScanlinesTV32; | |
2537 break; | |
2538 case 2: | |
2539 filterFunction = _2xSaI32; | |
2540 break; | |
2541 case 3: | |
2542 filterFunction = Super2xSaI32; | |
2543 break; | |
2544 case 4: | |
2545 filterFunction = SuperEagle32; | |
2546 break; | |
2547 case 5: | |
2548 filterFunction = Pixelate2x32; | |
2549 break; | |
2550 case 6: | |
2551 filterFunction = MotionBlur32; | |
2552 break; | |
2553 case 7: | |
2554 filterFunction = AdMame2x32; | |
2555 break; | |
2556 case 8: | |
2557 filterFunction = Simple2x32; | |
2558 break; | |
2559 case 9: | |
2560 filterFunction = Bilinear32; | |
2561 break; | |
2562 case 10: | |
2563 filterFunction = BilinearPlus32; | |
2564 break; | |
2565 case 11: | |
2566 filterFunction = Scanlines32; | |
2567 break; | |
2568 case 12: | |
2569 filterFunction = hq2x32; | |
2570 break; | |
2571 case 13: | |
2572 filterFunction = lq2x32; | |
2573 break; | |
2574 default: | |
2575 filterFunction = NULL; | |
2576 break; | |
2577 } | |
2578 } | |
2579 | |
2580 if(systemColorDepth == 16) { | |
2581 switch(ifbType) { | |
2582 case 0: | |
2583 default: | |
2584 ifbFunction = NULL; | |
2585 break; | |
2586 case 1: | |
2587 ifbFunction = MotionBlurIB; | |
2588 break; | |
2589 case 2: | |
2590 ifbFunction = SmartIB; | |
2591 break; | |
2592 } | |
2593 } else if(systemColorDepth == 32) { | |
2594 switch(ifbType) { | |
2595 case 0: | |
2596 default: | |
2597 ifbFunction = NULL; | |
2598 break; | |
2599 case 1: | |
2600 ifbFunction = MotionBlurIB32; | |
2601 break; | |
2602 case 2: | |
2603 ifbFunction = SmartIB32; | |
2604 break; | |
2605 } | |
2606 } else | |
2607 ifbFunction = NULL; | |
2608 | |
2609 if(delta == NULL) { | |
2610 delta = (u8*)malloc(322*242*4); | |
2611 memset(delta, 255, 322*242*4); | |
2612 } | |
2613 | |
2614 if(!soundOffFlag) | |
2615 soundInit(); | |
2616 | |
2617 autoFrameSkipLastTime = throttleLastTime = systemGetClock(); | |
2618 | |
2619 switch(useMovie) | |
2620 { | |
2621 case 1: // --recordMovie | |
2622 VBAMovieCreate(movieFileName, | |
2623 /*authorInfo*/"", | |
2624 /*startFlags*/0, | |
2625 /*controllerFlags*/MOVIE_CONTROLLER(0), | |
2626 /*typeFlags*/(systemCartridgeType==IMAGE_GBA)?(MOVIE_TYPE_GBA):(GBC_CAPABLE?MOVIE_TYPE_GBC:MOVIE_TYPE_SGB)); | |
2627 break; | |
2628 case 2: // --playMovie | |
2629 VBAMovieOpen(movieFileName, false); | |
2630 break; | |
2631 case 3: // --watchMovie | |
2632 VBAMovieOpen(movieFileName, true); | |
2633 break; | |
2634 default: | |
2635 sdlReadBattery(); | |
2636 break; | |
2637 } | |
2638 SDL_WM_SetCaption("VisualBoyAdvance", NULL); | |
2639 | |
2640 char *moviefile = getenv("AUTODEMO"); | |
2641 // fprintf (stderr, "Checking for AUTODEMO...\n"); | |
2642 if (moviefile) | |
2643 { | |
2644 // fprintf (stderr, "I got a filename OMG!\nCalling VBAMovieOpen...\n"); | |
2645 VBAMovieOpen(moviefile, true); | |
2646 } | |
2647 | |
2648 while(emulating) { | |
2649 if(!paused && active) { | |
2650 if(debugger && theEmulator.emuHasDebugger) | |
2651 dbgMain(); | |
2652 else { | |
2653 theEmulator.emuMain(theEmulator.emuCount); | |
2654 if(rewindSaveNeeded && rewindMemory && theEmulator.emuWriteMemState) { | |
2655 rewindCount++; | |
2656 if(rewindCount > 8) | |
2657 rewindCount = 8; | |
2658 if(theEmulator.emuWriteMemState && | |
2659 theEmulator.emuWriteMemState(&rewindMemory[rewindPos*REWIND_SIZE], | |
2660 REWIND_SIZE)) { | |
2661 rewindPos = ++rewindPos & 7; | |
2662 if(rewindCount == 8) | |
2663 rewindTopPos = ++rewindTopPos & 7; | |
2664 } | |
2665 } | |
2666 | |
2667 rewindSaveNeeded = false; | |
2668 } | |
2669 } else { | |
2670 SDL_Delay(500); | |
2671 } | |
2672 sdlPollEvents(); | |
2673 if(mouseCounter) { | |
2674 mouseCounter--; | |
2675 if(mouseCounter == 0) | |
2676 SDL_ShowCursor(SDL_DISABLE); | |
2677 } | |
2678 } | |
2679 | |
2680 emulating = 0; | |
2681 fprintf(stderr,"Shutting down\n"); | |
2682 remoteCleanUp(); | |
2683 soundShutdown(); | |
2684 | |
2685 if(gbRom != NULL || rom != NULL) { | |
2686 sdlWriteBattery(); | |
2687 theEmulator.emuCleanUp(); | |
2688 } | |
2689 | |
2690 if(delta) { | |
2691 free(delta); | |
2692 delta = NULL; | |
2693 } | |
2694 | |
2695 SDL_Quit(); | |
2696 return 0; | |
2697 } | |
2698 | |
2699 void systemMessage(int num, const char *msg, ...) | |
2700 { | |
2701 char buffer[2048]; | |
2702 va_list valist; | |
2703 | |
2704 va_start(valist, msg); | |
2705 vsprintf(buffer, msg, valist); | |
2706 | |
2707 fprintf(stderr, "%s\n", buffer); | |
2708 va_end(valist); | |
2709 } | |
2710 | |
2711 //On WIN32, this function messages requesting | |
2712 //the window to be redrawn. Can this be ignored here? | |
2713 void systemRefreshScreen(){} | |
2714 | |
2715 void systemRenderFrame() | |
2716 { | |
2717 renderedFrames++; | |
2718 VBAUpdateFrameCountDisplay(); | |
2719 VBAUpdateButtonPressDisplay(); | |
2720 | |
2721 if(yuv) { | |
2722 Draw_Overlay(surface, sizeOption+1); | |
2723 return; | |
2724 } | |
2725 | |
2726 SDL_LockSurface(surface); | |
2727 | |
2728 for(int slot = 0 ; slot < 8 ; slot++) | |
2729 { | |
2730 if(screenMessage[slot]) { | |
2731 if(systemCartridgeType == 1 && gbBorderOn) { | |
2732 gbSgbRenderBorder(); | |
2733 } | |
2734 if(((systemGetClock() - screenMessageTime[slot]) < screenMessageDuration[slot]) && | |
2735 !disableStatusMessages) { | |
2736 drawText(pix, srcPitch, 10, srcHeight - 20*(slot+1), | |
2737 screenMessageBuffer[slot]); | |
2738 } else { | |
2739 screenMessage[slot] = false; | |
2740 } | |
2741 } | |
2742 } | |
2743 | |
2744 if(ifbFunction) { | |
2745 if(systemColorDepth == 16) | |
2746 ifbFunction(pix+destWidth+4, destWidth+4, srcWidth, srcHeight); | |
2747 else | |
2748 ifbFunction(pix+destWidth*2+4, destWidth*2+4, srcWidth, srcHeight); | |
2749 } | |
2750 | |
2751 if(filterFunction) { | |
2752 if(systemColorDepth == 16) | |
2753 filterFunction(pix+destWidth+4,destWidth+4, delta, | |
2754 (u8*)surface->pixels,surface->pitch, | |
2755 srcWidth, | |
2756 srcHeight); | |
2757 else | |
2758 filterFunction(pix+destWidth*2+4, | |
2759 destWidth*2+4, | |
2760 delta, | |
2761 (u8*)surface->pixels, | |
2762 surface->pitch, | |
2763 srcWidth, | |
2764 srcHeight); | |
2765 } else { | |
2766 int destPitch = surface->pitch; | |
2767 u8 *src = pix; | |
2768 u8 *dest = (u8*)surface->pixels; | |
2769 int i; | |
2770 u32 *stretcher = (u32 *)sdlStretcher; | |
2771 if(systemColorDepth == 16) | |
2772 src += srcPitch; | |
2773 int option = sizeOption; | |
2774 if(yuv) | |
2775 option = 0; | |
2776 switch(sizeOption) { | |
2777 case 0: | |
2778 for(i = 0; i < srcHeight; i++) { | |
2779 SDL_CALL_STRETCHER; | |
2780 src += srcPitch; | |
2781 dest += destPitch; | |
2782 } | |
2783 break; | |
2784 case 1: | |
2785 for(i = 0; i < srcHeight; i++) { | |
2786 SDL_CALL_STRETCHER; | |
2787 dest += destPitch; | |
2788 SDL_CALL_STRETCHER; | |
2789 src += srcPitch; | |
2790 dest += destPitch; | |
2791 } | |
2792 break; | |
2793 case 2: | |
2794 for(i = 0; i < srcHeight; i++) { | |
2795 SDL_CALL_STRETCHER; | |
2796 dest += destPitch; | |
2797 SDL_CALL_STRETCHER; | |
2798 dest += destPitch; | |
2799 SDL_CALL_STRETCHER; | |
2800 src += srcPitch; | |
2801 dest += destPitch; | |
2802 } | |
2803 break; | |
2804 case 3: | |
2805 for(i = 0; i < srcHeight; i++) { | |
2806 SDL_CALL_STRETCHER; | |
2807 dest += destPitch; | |
2808 SDL_CALL_STRETCHER; | |
2809 dest += destPitch; | |
2810 SDL_CALL_STRETCHER; | |
2811 dest += destPitch; | |
2812 SDL_CALL_STRETCHER; | |
2813 src += srcPitch; | |
2814 dest += destPitch; | |
2815 } | |
2816 break; | |
2817 } | |
2818 } | |
2819 | |
2820 if(showSpeed && fullscreen) { | |
2821 char buffer[50]; | |
2822 if(showSpeed == 1) | |
2823 sprintf(buffer, "%d%%", systemSpeed); | |
2824 else | |
2825 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, | |
2826 systemFrameSkip, | |
2827 showRenderedFrames); | |
2828 if(showSpeedTransparent) | |
2829 drawTextTransp((u8*)surface->pixels, | |
2830 surface->pitch, | |
2831 10, | |
2832 surface->h-20, | |
2833 buffer); | |
2834 else | |
2835 drawText((u8*)surface->pixels, | |
2836 surface->pitch, | |
2837 10, | |
2838 surface->h-20, | |
2839 buffer); | |
2840 } | |
2841 | |
2842 SDL_UnlockSurface(surface); | |
2843 // SDL_UpdateRect(surface, 0, 0, destWidth, destHeight); | |
2844 SDL_Flip(surface); | |
2845 } | |
2846 | |
2847 bool systemReadJoypads() | |
2848 { | |
2849 return true; | |
2850 } | |
2851 | |
2852 // Kludge to make Lua call the right function. | |
2853 u32 systemGetOriginalJoypad(int which, bool sensor){ | |
2854 return systemGetJoypad(which,sensor); | |
2855 } | |
2856 | |
2857 u32 systemGetJoypad(int which, bool sensor) | |
2858 { | |
2859 sensorOn = sensor; | |
2860 if(which < 0 || which > 3) | |
2861 which = sdlDefaultJoypad; | |
2862 | |
2863 //VBAMovieUpdate(which); | |
2864 //VBAMovieUpdateState(); | |
2865 u32 res = 0; | |
2866 | |
2867 //----------------------------// | |
2868 if (VBAMoviePlaying()){ | |
2869 // VBAMovieRead() overwrites currentButtons[i] | |
2870 VBAMovieRead(which, sensor); | |
2871 res = currentButtons[which]; | |
2872 return res; | |
2873 } | |
2874 //---------------------------// | |
2875 //Temporary implementation, not sure if it's correct --Felipe | |
2876 | |
2877 /* | |
2878 if(sdlButtons[which][KEY_BUTTON_A]) | |
2879 res |= BUTTON_MASK_A; | |
2880 if(sdlButtons[which][KEY_BUTTON_B]) | |
2881 res |= BUTTON_MASK_B; | |
2882 if(sdlButtons[which][KEY_BUTTON_SELECT]) | |
2883 res |= BUTTON_MASK_SELECT; | |
2884 if(sdlButtons[which][KEY_BUTTON_START]) | |
2885 res |= BUTTON_MASK_START; | |
2886 if(sdlButtons[which][KEY_RIGHT]) | |
2887 res |= BUTTON_MASK_RIGHT; | |
2888 if(sdlButtons[which][KEY_LEFT]) | |
2889 res |= BUTTON_MASK_LEFT; | |
2890 if(sdlButtons[which][KEY_UP]) | |
2891 res |= BUTTON_MASK_UP; | |
2892 if(sdlButtons[which][KEY_DOWN]) | |
2893 res |= BUTTON_MASK_DOWN; | |
2894 if(sdlButtons[which][KEY_BUTTON_R]) | |
2895 res |= BUTTON_MASK_R; | |
2896 if(sdlButtons[which][KEY_BUTTON_L]) | |
2897 res |= BUTTON_MASK_L; | |
2898 */ | |
2899 /* | |
2900 // disallow L+R or U+D of being pressed at the same time | |
2901 if((res & 48) == 48) | |
2902 res &= ~16; | |
2903 if((res & 192) == 192) | |
2904 res &= ~128; | |
2905 */ | |
2906 /* | |
2907 if(sdlbuttons[which][KEY_BUTTON_SPEED]) | |
2908 res |= 1024; | |
2909 if(sdlButtons[which][KEY_BUTTON_CAPTURE]) | |
2910 res |= 2048; | |
2911 */ | |
2912 res = currentButtons[which]; | |
2913 | |
2914 if(autoFire) { | |
2915 res &= (~autoFire); | |
2916 if(autoFireToggle) | |
2917 res |= autoFire; | |
2918 autoFireToggle = !autoFireToggle; | |
2919 } | |
2920 | |
2921 //if (res) fprintf(stdout,"%x\n",res); | |
2922 | |
2923 return res; | |
2924 } | |
2925 | |
2926 void systemSetJoypad(int which, u32 buttons) | |
2927 { | |
2928 if(which < 0 || which > 3) | |
2929 which = sdlDefaultJoypad; | |
2930 /* | |
2931 sdlButtons[which][KEY_BUTTON_A] = (buttons & 1) != 0; | |
2932 sdlButtons[which][KEY_BUTTON_B] = (buttons & 2) != 0; | |
2933 sdlButtons[which][KEY_BUTTON_SELECT] = (buttons & 4) != 0; | |
2934 sdlButtons[which][KEY_BUTTON_START] = (buttons & 8) != 0; | |
2935 sdlButtons[which][KEY_RIGHT] = (buttons & 16) != 0; | |
2936 sdlButtons[which][KEY_LEFT] = (buttons & 32) != 0; | |
2937 sdlButtons[which][KEY_UP] = (buttons & 64) != 0; | |
2938 sdlButtons[which][KEY_DOWN] = (buttons & 128) != 0; | |
2939 sdlButtons[which][KEY_BUTTON_R] = (buttons & 256) != 0; | |
2940 sdlButtons[which][KEY_BUTTON_L] = (buttons & 512) != 0; | |
2941 */ | |
2942 currentButtons[which]= buttons & 0x3ff; | |
2943 } | |
2944 | |
2945 void systemClearJoypads() | |
2946 { | |
2947 for (int i = 0; i < 4; ++i) | |
2948 currentButtons[i] = 0; | |
2949 | |
2950 //lastKeys = 0; | |
2951 } | |
2952 | |
2953 void systemSetTitle(const char *title) | |
2954 { | |
2955 SDL_WM_SetCaption(title, NULL); | |
2956 } | |
2957 | |
2958 void systemShowSpeed(int speed) | |
2959 { | |
2960 systemSpeed = speed; | |
2961 | |
2962 showRenderedFrames = renderedFrames; | |
2963 renderedFrames = 0; | |
2964 | |
2965 if(!fullscreen && showSpeed) { | |
2966 char buffer[80]; | |
2967 if(showSpeed == 1) | |
2968 sprintf(buffer, "VisualBoyAdvance-%3d%%", systemSpeed); | |
2969 else | |
2970 sprintf(buffer, "VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed, | |
2971 systemFrameSkip, | |
2972 showRenderedFrames); | |
2973 | |
2974 systemSetTitle(buffer); | |
2975 } | |
2976 } | |
2977 | |
2978 // FIXME: the timing | |
2979 void systemFrame(/*int rate*/) //Looking at System.cpp, it looks like rate should be 600 | |
2980 { | |
2981 u32 time = systemGetClock(); | |
2982 if(!wasPaused && autoFrameSkip && !throttle) { | |
2983 u32 diff = time - autoFrameSkipLastTime; | |
2984 int speed = 100; | |
2985 | |
2986 if(diff) | |
2987 speed = (1000000/600)/diff; | |
2988 | |
2989 if(speed >= 98) { | |
2990 frameskipadjust++; | |
2991 | |
2992 if(frameskipadjust >= 3) { | |
2993 frameskipadjust=0; | |
2994 if(systemFrameSkip > 0) | |
2995 systemFrameSkip--; | |
2996 } | |
2997 } else { | |
2998 if(speed < 80) | |
2999 frameskipadjust -= (90 - speed)/5; | |
3000 else if(systemFrameSkip < 9) | |
3001 frameskipadjust--; | |
3002 | |
3003 if(frameskipadjust <= -2) { | |
3004 frameskipadjust += 2; | |
3005 if(systemFrameSkip < 9) | |
3006 systemFrameSkip++; | |
3007 } | |
3008 } | |
3009 } | |
3010 if(!wasPaused && throttle) { | |
3011 /*if(!speedup) { | |
3012 u32 diff = time - throttleLastTime; | |
3013 | |
3014 int target = (1000000.0/(600*throttle)); | |
3015 int d = (target - diff); | |
3016 | |
3017 if(d > 0) { | |
3018 SDL_Delay(d); | |
3019 } | |
3020 } | |
3021 throttleLastTime = systemGetClock(); | |
3022 */ | |
3023 } | |
3024 if(rewindMemory) { | |
3025 if(++rewindCounter >= rewindTimer) { | |
3026 rewindSaveNeeded = true; | |
3027 rewindCounter = 0; | |
3028 } | |
3029 } | |
3030 | |
3031 if(systemSaveUpdateCounter) { | |
3032 if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) { | |
3033 sdlWriteBattery(); | |
3034 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; | |
3035 } | |
3036 } | |
3037 | |
3038 wasPaused = false; | |
3039 autoFrameSkipLastTime = time; | |
3040 } | |
3041 | |
3042 int systemFramesToSkip(){ | |
3043 return systemFrameSkip; | |
3044 } | |
3045 | |
3046 int systemScreenCapture(int a) | |
3047 { | |
3048 char buffer[2048]; | |
3049 | |
3050 if(captureFormat) { | |
3051 if(captureDir[0]) | |
3052 sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a); | |
3053 else | |
3054 sprintf(buffer, "%s%02d.bmp", filename, a); | |
3055 | |
3056 theEmulator.emuWriteBMP(buffer); | |
3057 } else { | |
3058 if(captureDir[0]) | |
3059 sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a); | |
3060 else | |
3061 sprintf(buffer, "%s%02d.png", filename, a); | |
3062 theEmulator.emuWritePNG(buffer); | |
3063 } | |
3064 | |
3065 systemScreenMessage("Screen capture"); | |
3066 return a; | |
3067 } | |
3068 | |
3069 void soundCallback(void *,u8 *stream,int len){} | |
3070 | |
3071 void systemSoundWriteToBuffer(){ | |
3072 soundDriver->write(soundFinalWave, soundBufferLen); | |
3073 } | |
3074 | |
3075 void systemSoundClearBuffer() | |
3076 { | |
3077 SDL_mutexP(mutex); | |
3078 memset(sdlBuffer,0,soundBufferTotalLen); | |
3079 sdlSoundLen=0; | |
3080 printf("Hi\n"); | |
3081 SDL_mutexV(mutex); | |
3082 } | |
3083 | |
3084 bool systemSoundInit(){ | |
3085 systemSoundShutdown(); | |
3086 soundDriver = new SoundSDL(); | |
3087 if ( !soundDriver ) | |
3088 return false; | |
3089 | |
3090 if (!soundDriver->init()) //<-- sound sample rate | |
3091 return false; | |
3092 | |
3093 if (!(soundDriver->setThrottle(throttle))){ | |
3094 fprintf(stderr,"Failed to set desired throttle, defaulting to 100 %%.\n"); | |
3095 if (!soundDriver->setThrottle(100)) return false; | |
3096 } | |
3097 soundPaused = true; | |
3098 systemSoundOn = true; | |
3099 return true; | |
3100 } | |
3101 | |
3102 void systemSoundShutdown(){ | |
3103 if (soundDriver) | |
3104 { | |
3105 delete soundDriver; | |
3106 soundDriver = 0; | |
3107 } | |
3108 } | |
3109 | |
3110 void systemSoundPause() | |
3111 { | |
3112 SDL_PauseAudio(1); | |
3113 } | |
3114 | |
3115 void systemSoundResume() | |
3116 { | |
3117 SDL_PauseAudio(0); | |
3118 } | |
3119 | |
3120 void systemSoundReset() | |
3121 { | |
3122 } | |
3123 | |
3124 u32 systemGetClock() | |
3125 { | |
3126 return SDL_GetTicks(); | |
3127 } | |
3128 | |
3129 void systemUpdateMotionSensor() | |
3130 { | |
3131 if(sdlMotionButtons[KEY_LEFT]) { | |
3132 sensorX += 3; | |
3133 if(sensorX > 2197) | |
3134 sensorX = 2197; | |
3135 if(sensorX < 2047) | |
3136 sensorX = 2057; | |
3137 } else if(sdlMotionButtons[KEY_RIGHT]) { | |
3138 sensorX -= 3; | |
3139 if(sensorX < 1897) | |
3140 sensorX = 1897; | |
3141 if(sensorX > 2047) | |
3142 sensorX = 2037; | |
3143 } else if(sensorX > 2047) { | |
3144 sensorX -= 2; | |
3145 if(sensorX < 2047) | |
3146 sensorX = 2047; | |
3147 } else { | |
3148 sensorX += 2; | |
3149 if(sensorX > 2047) | |
3150 sensorX = 2047; | |
3151 } | |
3152 | |
3153 if(sdlMotionButtons[KEY_UP]) { | |
3154 sensorY += 3; | |
3155 if(sensorY > 2197) | |
3156 sensorY = 2197; | |
3157 if(sensorY < 2047) | |
3158 sensorY = 2057; | |
3159 } else if(sdlMotionButtons[KEY_DOWN]) { | |
3160 sensorY -= 3; | |
3161 if(sensorY < 1897) | |
3162 sensorY = 1897; | |
3163 if(sensorY > 2047) | |
3164 sensorY = 2037; | |
3165 } else if(sensorY > 2047) { | |
3166 sensorY -= 2; | |
3167 if(sensorY < 2047) | |
3168 sensorY = 2047; | |
3169 } else { | |
3170 sensorY += 2; | |
3171 if(sensorY > 2047) | |
3172 sensorY = 2047; | |
3173 } | |
3174 } | |
3175 | |
3176 void systemResetSensor() | |
3177 { | |
3178 sensorX = sensorY = INITIAL_SENSOR_VALUE; | |
3179 } | |
3180 | |
3181 int systemGetSensorX() | |
3182 { | |
3183 return sensorX; | |
3184 } | |
3185 | |
3186 int systemGetSensorY() | |
3187 { | |
3188 return sensorY; | |
3189 } | |
3190 | |
3191 void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast) | |
3192 { | |
3193 } | |
3194 | |
3195 void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList) | |
3196 { | |
3197 screenMessage[slot] = true; | |
3198 screenMessageTime[slot] = systemGetClock(); | |
3199 screenMessageDuration[slot] = duration; | |
3200 if(strlen(msg) > 20) { | |
3201 strncpy(screenMessageBuffer[slot], msg, 20); | |
3202 screenMessageBuffer[slot][20] = 0; | |
3203 } else | |
3204 strcpy(screenMessageBuffer[slot], msg); | |
3205 } | |
3206 | |
3207 bool systemSoundCanChangeQuality() | |
3208 { | |
3209 return false; | |
3210 } | |
3211 | |
3212 bool systemSoundSetQuality(int quality) | |
3213 { | |
3214 if (systemCartridgeType == 0) | |
3215 soundSetQuality(quality); | |
3216 else | |
3217 gbSoundSetQuality(quality); | |
3218 | |
3219 return true; | |
3220 } | |
3221 | |
3222 bool systemPauseOnFrame() | |
3223 { | |
3224 if(pauseNextFrame) { | |
3225 paused = true; | |
3226 pauseNextFrame = false; | |
3227 return true; | |
3228 } | |
3229 return false; | |
3230 } | |
3231 | |
3232 // Code donated by Niels Wagenaar (BoycottAdvance) | |
3233 | |
3234 // GBA screensize. | |
3235 #define GBA_WIDTH 240 | |
3236 #define GBA_HEIGHT 160 | |
3237 | |
3238 void Init_Overlay(SDL_Surface *gbascreen, int overlaytype) | |
3239 { | |
3240 | |
3241 overlay = SDL_CreateYUVOverlay( GBA_WIDTH, | |
3242 GBA_HEIGHT, | |
3243 overlaytype, gbascreen); | |
3244 fprintf(stderr, "Created %dx%dx%d %s %s overlay\n", | |
3245 overlay->w,overlay->h,overlay->planes, | |
3246 overlay->hw_overlay?"hardware":"software", | |
3247 overlay->format==SDL_YV12_OVERLAY?"YV12": | |
3248 overlay->format==SDL_IYUV_OVERLAY?"IYUV": | |
3249 overlay->format==SDL_YUY2_OVERLAY?"YUY2": | |
3250 overlay->format==SDL_UYVY_OVERLAY?"UYVY": | |
3251 overlay->format==SDL_YVYU_OVERLAY?"YVYU": | |
3252 "Unknown"); | |
3253 } | |
3254 | |
3255 void Quit_Overlay(void) | |
3256 { | |
3257 | |
3258 SDL_FreeYUVOverlay(overlay); | |
3259 } | |
3260 | |
3261 /* NOTE: These RGB conversion functions are not intended for speed, | |
3262 only as examples. | |
3263 */ | |
3264 inline void RGBtoYUV(Uint8 *rgb, int *yuv) | |
3265 { | |
3266 yuv[0] = (int)((0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16); | |
3267 yuv[1] = (int)(128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2])); | |
3268 yuv[2] = (int)(128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2])); | |
3269 } | |
3270 | |
3271 inline void ConvertRGBtoYV12(SDL_Overlay *o) | |
3272 { | |
3273 int x,y; | |
3274 int yuv[3]; | |
3275 Uint8 *p,*op[3]; | |
3276 | |
3277 SDL_LockYUVOverlay(o); | |
3278 | |
3279 /* Black initialization */ | |
3280 /* | |
3281 memset(o->pixels[0],0,o->pitches[0]*o->h); | |
3282 memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2)); | |
3283 memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2)); | |
3284 */ | |
3285 | |
3286 /* Convert */ | |
3287 for(y=0; y<160 && y<o->h; y++) { | |
3288 p=(Uint8 *)pix+srcPitch*y; | |
3289 op[0]=o->pixels[0]+o->pitches[0]*y; | |
3290 op[1]=o->pixels[1]+o->pitches[1]*(y/2); | |
3291 op[2]=o->pixels[2]+o->pitches[2]*(y/2); | |
3292 for(x=0; x<240 && x<o->w; x++) { | |
3293 RGBtoYUV(p,yuv); | |
3294 *(op[0]++)=yuv[0]; | |
3295 if(x%2==0 && y%2==0) { | |
3296 *(op[1]++)=yuv[2]; | |
3297 *(op[2]++)=yuv[1]; | |
3298 } | |
3299 p+=4;//s->format->BytesPerPixel; | |
3300 } | |
3301 } | |
3302 | |
3303 SDL_UnlockYUVOverlay(o); | |
3304 } | |
3305 | |
3306 inline void ConvertRGBtoIYUV(SDL_Overlay *o) | |
3307 { | |
3308 int x,y; | |
3309 int yuv[3]; | |
3310 Uint8 *p,*op[3]; | |
3311 | |
3312 SDL_LockYUVOverlay(o); | |
3313 | |
3314 /* Black initialization */ | |
3315 /* | |
3316 memset(o->pixels[0],0,o->pitches[0]*o->h); | |
3317 memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2)); | |
3318 memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2)); | |
3319 */ | |
3320 | |
3321 /* Convert */ | |
3322 for(y=0; y<160 && y<o->h; y++) { | |
3323 p=(Uint8 *)pix+srcPitch*y; | |
3324 op[0]=o->pixels[0]+o->pitches[0]*y; | |
3325 op[1]=o->pixels[1]+o->pitches[1]*(y/2); | |
3326 op[2]=o->pixels[2]+o->pitches[2]*(y/2); | |
3327 for(x=0; x<240 && x<o->w; x++) { | |
3328 RGBtoYUV(p,yuv); | |
3329 *(op[0]++)=yuv[0]; | |
3330 if(x%2==0 && y%2==0) { | |
3331 *(op[1]++)=yuv[1]; | |
3332 *(op[2]++)=yuv[2]; | |
3333 } | |
3334 p+=4; //s->format->BytesPerPixel; | |
3335 } | |
3336 } | |
3337 | |
3338 SDL_UnlockYUVOverlay(o); | |
3339 } | |
3340 | |
3341 inline void ConvertRGBtoUYVY(SDL_Overlay *o) | |
3342 { | |
3343 int x,y; | |
3344 int yuv[3]; | |
3345 Uint8 *p,*op; | |
3346 | |
3347 SDL_LockYUVOverlay(o); | |
3348 | |
3349 for(y=0; y<160 && y<o->h; y++) { | |
3350 p=(Uint8 *)pix+srcPitch*y; | |
3351 op=o->pixels[0]+o->pitches[0]*y; | |
3352 for(x=0; x<240 && x<o->w; x++) { | |
3353 RGBtoYUV(p,yuv); | |
3354 if(x%2==0) { | |
3355 *(op++)=yuv[1]; | |
3356 *(op++)=yuv[0]; | |
3357 *(op++)=yuv[2]; | |
3358 } else | |
3359 *(op++)=yuv[0]; | |
3360 | |
3361 p+=4; //s->format->BytesPerPixel; | |
3362 } | |
3363 } | |
3364 | |
3365 SDL_UnlockYUVOverlay(o); | |
3366 } | |
3367 | |
3368 inline void ConvertRGBtoYVYU(SDL_Overlay *o) | |
3369 { | |
3370 int x,y; | |
3371 int yuv[3]; | |
3372 Uint8 *p,*op; | |
3373 | |
3374 SDL_LockYUVOverlay(o); | |
3375 | |
3376 for(y=0; y<160 && y<o->h; y++) { | |
3377 p=(Uint8 *)pix+srcPitch*y; | |
3378 op=o->pixels[0]+o->pitches[0]*y; | |
3379 for(x=0; x<240 && x<o->w; x++) { | |
3380 RGBtoYUV(p,yuv); | |
3381 if(x%2==0) { | |
3382 *(op++)=yuv[0]; | |
3383 *(op++)=yuv[2]; | |
3384 op[1]=yuv[1]; | |
3385 } else { | |
3386 *op=yuv[0]; | |
3387 op+=2; | |
3388 } | |
3389 | |
3390 p+=4; //s->format->BytesPerPixel; | |
3391 } | |
3392 } | |
3393 | |
3394 SDL_UnlockYUVOverlay(o); | |
3395 } | |
3396 | |
3397 inline void ConvertRGBtoYUY2(SDL_Overlay *o) | |
3398 { | |
3399 int x,y; | |
3400 int yuv[3]; | |
3401 Uint8 *p,*op; | |
3402 | |
3403 SDL_LockYUVOverlay(o); | |
3404 | |
3405 for(y=0; y<160 && y<o->h; y++) { | |
3406 p=(Uint8 *)pix+srcPitch*y; | |
3407 op=o->pixels[0]+o->pitches[0]*y; | |
3408 for(x=0; x<240 && x<o->w; x++) { | |
3409 RGBtoYUV(p,yuv); | |
3410 if(x%2==0) { | |
3411 *(op++)=yuv[0]; | |
3412 *(op++)=yuv[1]; | |
3413 op[1]=yuv[2]; | |
3414 } else { | |
3415 *op=yuv[0]; | |
3416 op+=2; | |
3417 } | |
3418 | |
3419 p+=4; //s->format->BytesPerPixel; | |
3420 } | |
3421 } | |
3422 | |
3423 SDL_UnlockYUVOverlay(o); | |
3424 } | |
3425 | |
3426 inline void Convert32bit(SDL_Surface *display) | |
3427 { | |
3428 switch(overlay->format) { | |
3429 case SDL_YV12_OVERLAY: | |
3430 ConvertRGBtoYV12(overlay); | |
3431 break; | |
3432 case SDL_UYVY_OVERLAY: | |
3433 ConvertRGBtoUYVY(overlay); | |
3434 break; | |
3435 case SDL_YVYU_OVERLAY: | |
3436 ConvertRGBtoYVYU(overlay); | |
3437 break; | |
3438 case SDL_YUY2_OVERLAY: | |
3439 ConvertRGBtoYUY2(overlay); | |
3440 break; | |
3441 case SDL_IYUV_OVERLAY: | |
3442 ConvertRGBtoIYUV(overlay); | |
3443 break; | |
3444 default: | |
3445 fprintf(stderr, "cannot convert RGB picture to obtained YUV format!\n"); | |
3446 exit(1); | |
3447 break; | |
3448 } | |
3449 | |
3450 } | |
3451 | |
3452 | |
3453 inline void Draw_Overlay(SDL_Surface *display, int size) | |
3454 { | |
3455 SDL_LockYUVOverlay(overlay); | |
3456 | |
3457 Convert32bit(display); | |
3458 | |
3459 overlay_rect.x = 0; | |
3460 overlay_rect.y = 0; | |
3461 overlay_rect.w = GBA_WIDTH * size; | |
3462 overlay_rect.h = GBA_HEIGHT * size; | |
3463 | |
3464 SDL_DisplayYUVOverlay(overlay, &overlay_rect); | |
3465 SDL_UnlockYUVOverlay(overlay); | |
3466 } | |
3467 | |
3468 bool systemIsEmulating() | |
3469 { | |
3470 return emulating != 0; | |
3471 } | |
3472 | |
3473 void systemGbBorderOn() | |
3474 { | |
3475 srcWidth = 256; | |
3476 srcHeight = 224; | |
3477 gbBorderLineSkip = 256; | |
3478 gbBorderColumnSkip = 48; | |
3479 gbBorderRowSkip = 40; | |
3480 | |
3481 destWidth = (sizeOption+1)*srcWidth; | |
3482 destHeight = (sizeOption+1)*srcHeight; | |
3483 | |
3484 surface = SDL_SetVideoMode(destWidth, destHeight, 16, | |
3485 SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF| | |
3486 (fullscreen ? SDL_FULLSCREEN : 0)); | |
3487 #ifndef C_CORE | |
3488 sdlMakeStretcher(srcWidth); | |
3489 #else | |
3490 switch(systemColorDepth) { | |
3491 case 16: | |
3492 sdlStretcher = sdlStretcher16[sizeOption]; | |
3493 break; | |
3494 case 24: | |
3495 sdlStretcher = sdlStretcher24[sizeOption]; | |
3496 break; | |
3497 case 32: | |
3498 sdlStretcher = sdlStretcher32[sizeOption]; | |
3499 break; | |
3500 default: | |
3501 fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth); | |
3502 exit(-1); | |
3503 } | |
3504 #endif | |
3505 | |
3506 if(systemColorDepth == 16) { | |
3507 if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) { | |
3508 Init_2xSaI(565); | |
3509 RGB_LOW_BITS_MASK = 0x821; | |
3510 } else { | |
3511 Init_2xSaI(555); | |
3512 RGB_LOW_BITS_MASK = 0x421; | |
3513 } | |
3514 if(systemCartridgeType == 2) { | |
3515 for(int i = 0; i < 0x10000; i++) { | |
3516 systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) | | |
3517 (((i & 0x7c0) >> 6) << systemGreenShift) | | |
3518 (((i & 0xf800) >> 11) << systemRedShift); | |
3519 } | |
3520 } else { | |
3521 for(int i = 0; i < 0x10000; i++) { | |
3522 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | | |
3523 (((i & 0x3e0) >> 5) << systemGreenShift) | | |
3524 (((i & 0x7c00) >> 10) << systemBlueShift); | |
3525 } | |
3526 } | |
3527 srcPitch = srcWidth * 2+4; | |
3528 } else { | |
3529 if(systemColorDepth != 32) | |
3530 filterFunction = NULL; | |
3531 RGB_LOW_BITS_MASK = 0x010101; | |
3532 if(systemColorDepth == 32) { | |
3533 Init_2xSaI(32); | |
3534 } | |
3535 for(int i = 0; i < 0x10000; i++) { | |
3536 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | | |
3537 (((i & 0x3e0) >> 5) << systemGreenShift) | | |
3538 (((i & 0x7c00) >> 10) << systemBlueShift); | |
3539 } | |
3540 if(systemColorDepth == 32) | |
3541 srcPitch = srcWidth*4 + 4; | |
3542 else | |
3543 srcPitch = srcWidth*3; | |
3544 } | |
3545 } | |
3546 | |
3547 bool systemIsRunningGBA() | |
3548 { | |
3549 return (rom != NULL); | |
3550 } | |
3551 | |
3552 int systemGetDefaultJoypad() | |
3553 { | |
3554 return sdlDefaultJoypad; | |
3555 } | |
3556 | |
3557 bool systemIsPaused() | |
3558 { | |
3559 return paused; | |
3560 } | |
3561 | |
3562 void systemSetPause(bool pause) | |
3563 { | |
3564 paused = pause; | |
3565 if (pause) | |
3566 systemSoundPause(); | |
3567 else | |
3568 systemSoundResume(); | |
3569 } | |
3570 | |
3571 u16 checksumBIOS() | |
3572 { | |
3573 bool hasBIOS = false; | |
3574 u8 * tempBIOS; | |
3575 if(useBios) | |
3576 { | |
3577 tempBIOS = (u8 *)malloc(0x4000); | |
3578 int size = 0x4000; | |
3579 if(utilLoad(biosFileName, | |
3580 utilIsGBABios, | |
3581 tempBIOS, | |
3582 size)) { | |
3583 if(size == 0x4000) | |
3584 hasBIOS = true; | |
3585 } | |
3586 } | |
3587 | |
3588 u16 biosCheck = 0; | |
3589 if(hasBIOS) { | |
3590 for(int i = 0; i < 0x4000; i += 4) | |
3591 biosCheck += *((u32 *)&tempBIOS[i]); | |
3592 free(tempBIOS); | |
3593 } | |
3594 | |
3595 return biosCheck; | |
3596 } | |
3597 | |
3598 EmulatedSystemCounters systemCounters = { | |
3599 0, //framecount | |
3600 0, //lagcount | |
3601 0, //extracount | |
3602 true, //lagged | |
3603 true //laggedLast | |
3604 }; | |
3605 | |
3606 void VBAOnEnteringFrameBoundary() | |
3607 { | |
3608 CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION); | |
3609 | |
3610 if (VBALuaRunning()) | |
3611 { | |
3612 VBALuaFrameBoundary(); | |
3613 } | |
3614 | |
3615 VBAMovieUpdateState(); | |
3616 } | |
3617 | |
3618 void VBAOnExitingFrameBoundary() | |
3619 { | |
3620 ; | |
3621 } | |
3622 | |
3623 |