PageRenderTime 73ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sdl/SDL.cpp

https://bitbucket.org/kanzure/vba-clojure
C++ | 3688 lines | 3106 code | 401 blank | 181 comment | 752 complexity | 5972383e5966ce44ecfbbe5c3d51fc38 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2, or(at your option)
  7. // any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software Foundation,
  16. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. #include <stdarg.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <config.h>
  24. #include "AutoBuild.h"
  25. #include "Port.h"
  26. #include "SDL.h"
  27. #include "debugger.h"
  28. #include "gba/GBA.h"
  29. #include "gba/GBAGlobals.h"
  30. #include "gba/agbprint.h"
  31. #include "gba/Flash.h"
  32. #include "gba/RTC.h"
  33. #include "gba/GBASound.h"
  34. #include "gb/GB.h"
  35. #include "gb/gbGlobals.h"
  36. #include "common/Text.h"
  37. #include "common/unzip.h"
  38. #include "common/Util.h"
  39. #include "common/movie.h"
  40. #include "common/System.h"
  41. #include "common/inputGlobal.h"
  42. #include "../common/vbalua.h"
  43. #include "SoundSDL.h"
  44. #include "Drive.h"
  45. #define GBC_CAPABLE ((gbRom[0x143] & 0x80) != 0)
  46. #define SGB_CAPABLE (gbRom[0x146] == 0x03)
  47. #ifndef WIN32
  48. # include <unistd.h>
  49. # define GETCWD getcwd
  50. #else // WIN32
  51. # include <direct.h>
  52. # define GETCWD _getcwd
  53. #endif // WIN32
  54. #ifndef __GNUC__
  55. # define HAVE_DECL_GETOPT 0
  56. # define __STDC__ 1
  57. # include "getopt.h"
  58. #else // ! __GNUC__
  59. # define HAVE_DECL_GETOPT 1
  60. # include "getopt.h"
  61. #endif // ! __GNUC__
  62. #ifdef MMX
  63. extern "C" bool cpu_mmx;
  64. #endif
  65. extern bool8 soundEcho;
  66. extern bool8 soundLowPass;
  67. extern bool8 soundReverse;
  68. extern int Init_2xSaI(u32);
  69. extern void _2xSaI(u8*,u32,u8*,u8*,u32,int,int);
  70. extern void _2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
  71. extern void Super2xSaI(u8*,u32,u8*,u8*,u32,int,int);
  72. extern void Super2xSaI32(u8*,u32,u8*,u8*,u32,int,int);
  73. extern void SuperEagle(u8*,u32,u8*,u8*,u32,int,int);
  74. extern void SuperEagle32(u8*,u32,u8*,u8*,u32,int,int);
  75. extern void Pixelate2x16(u8*,u32,u8*,u8*,u32,int,int);
  76. extern void Pixelate2x32(u8*,u32,u8*,u8*,u32,int,int);
  77. extern void MotionBlur(u8*,u32,u8*,u8*,u32,int,int);
  78. extern void MotionBlur32(u8*,u32,u8*,u8*,u32,int,int);
  79. extern void AdMame2x(u8*,u32,u8*,u8*,u32,int,int);
  80. extern void AdMame2x32(u8*,u32,u8*,u8*,u32,int,int);
  81. extern void Simple2x16(u8*,u32,u8*,u8*,u32,int,int);
  82. extern void Simple2x32(u8*,u32,u8*,u8*,u32,int,int);
  83. extern void Bilinear(u8*,u32,u8*,u8*,u32,int,int);
  84. extern void Bilinear32(u8*,u32,u8*,u8*,u32,int,int);
  85. extern void BilinearPlus(u8*,u32,u8*,u8*,u32,int,int);
  86. extern void BilinearPlus32(u8*,u32,u8*,u8*,u32,int,int);
  87. extern void Scanlines(u8*,u32,u8*,u8*,u32,int,int);
  88. extern void Scanlines32(u8*,u32,u8*,u8*,u32,int,int);
  89. extern void ScanlinesTV(u8*,u32,u8*,u8*,u32,int,int);
  90. extern void ScanlinesTV32(u8*,u32,u8*,u8*,u32,int,int);
  91. extern void hq2x(u8*,u32,u8*,u8*,u32,int,int);
  92. extern void hq2x32(u8*,u32,u8*,u8*,u32,int,int);
  93. extern void lq2x(u8*,u32,u8*,u8*,u32,int,int);
  94. extern void lq2x32(u8*,u32,u8*,u8*,u32,int,int);
  95. extern void SmartIB(u8*,u32,int,int);
  96. extern void SmartIB32(u8*,u32,int,int);
  97. extern void MotionBlurIB(u8*,u32,int,int);
  98. extern void MotionBlurIB32(u8*,u32,int,int);
  99. void Init_Overlay(SDL_Surface *surface, int overlaytype);
  100. void Quit_Overlay(void);
  101. void Draw_Overlay(SDL_Surface *surface, int size);
  102. extern void remoteInit();
  103. extern void remoteCleanUp();
  104. extern void remoteStubMain();
  105. extern void remoteStubSignal(int,int);
  106. extern void remoteOutput(char *, u32);
  107. extern void remoteSetProtocol(int);
  108. extern void remoteSetPort(int);
  109. extern void debuggerOutput(char *, u32);
  110. extern void CPUUpdateRenderBuffers(bool);
  111. struct EmulatedSystem theEmulator = {
  112. NULL,
  113. NULL,
  114. NULL,
  115. NULL,
  116. NULL,
  117. NULL,
  118. NULL,
  119. NULL,
  120. NULL,
  121. NULL,
  122. NULL,
  123. NULL,
  124. false,
  125. 0
  126. };
  127. SDL_Surface *surface = NULL;
  128. SDL_Overlay *overlay = NULL;
  129. SDL_Rect overlay_rect;
  130. int systemSpeed = 0;
  131. int systemRedShift = 0;
  132. int systemBlueShift = 0;
  133. int systemGreenShift = 0;
  134. int systemColorDepth = 0;
  135. int systemDebug = 0;
  136. int systemVerbose = 0;
  137. int systemFrameSkip = 0;
  138. int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
  139. int srcPitch = 0;
  140. int srcWidth = 0;
  141. int srcHeight = 0;
  142. int destWidth = 0;
  143. int destHeight = 0;
  144. int sensorX = 2047;
  145. int sensorY = 2047;
  146. bool sensorOn = false;
  147. int filter = 0;
  148. u8 *delta = NULL;
  149. int sdlPrintUsage = 0;
  150. int disableMMX = 0;
  151. int systemCartridgeType = 3;
  152. int sizeOption = 0;
  153. int captureFormat = 0;
  154. int useMovie = 0;
  155. int pauseWhenInactive = 0;
  156. int active = 1;
  157. int emulating = 0;
  158. int RGB_LOW_BITS_MASK=0x821;
  159. u32 systemColorMap32[0x10000];
  160. u16 systemColorMap16[0x10000];
  161. u16 systemGbPalette[24];
  162. void (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int) = NULL;
  163. void (*ifbFunction)(u8*,u32,int,int) = NULL;
  164. int ifbType = 0;
  165. char filename[2048];
  166. char ipsname[2048];
  167. char biosFileName[2048];
  168. char movieFileName[2048];
  169. char captureDir[2048];
  170. char saveDir[2048];
  171. char batteryDir[2048];
  172. static char *rewindMemory = NULL;
  173. static int rewindPos = 0;
  174. static int rewindTopPos = 0;
  175. static int rewindCounter = 0;
  176. static int rewindCount = 0;
  177. static bool rewindSaveNeeded = false;
  178. static int rewindTimer = 0;
  179. #define REWIND_SIZE 400000
  180. #define _stricmp strcasecmp
  181. /*bool sdlButtons[4][12] = {
  182. { false, false, false, false, false, false,
  183. false, false, false, false, false, false },
  184. { false, false, false, false, false, false,
  185. false, false, false, false, false, false },
  186. { false, false, false, false, false, false,
  187. false, false, false, false, false, false },
  188. { false, false, false, false, false, false,
  189. false, false, false, false, false, false }
  190. };*/
  191. /*
  192. I'm changing the way the SDL GUI handles the button
  193. input to match the one in win32, this is needed in
  194. order to be compatible with the format required by
  195. common/movie.cpp
  196. --Felipe
  197. */
  198. u16 currentButtons[4] = {0, 0, 0, 0};
  199. bool sdlMotionButtons[4] = { false, false, false, false };
  200. const int32 INITIAL_SENSOR_VALUE = 2047;
  201. int sdlNumDevices = 0;
  202. SDL_Joystick **sdlDevices = NULL;
  203. bool wasPaused = false;
  204. int autoFrameSkip = 0;
  205. int frameskipadjust = 0;
  206. int showRenderedFrames = 0;
  207. int renderedFrames = 0;
  208. int throttle = 0;
  209. u32 throttleLastTime = 0;
  210. u32 autoFrameSkipLastTime = 0;
  211. int showSpeed = 1;
  212. int showSpeedTransparent = 1;
  213. bool disableStatusMessages = false;
  214. bool paused = false;
  215. bool untilCapture = false;
  216. bool pauseNextFrame = false;
  217. bool debugger = false;
  218. bool debuggerStub = false;
  219. int fullscreen = 0;
  220. bool systemSoundOn = false;
  221. bool yuv = false;
  222. int yuvType = 0;
  223. bool removeIntros = false;
  224. int sdlFlashSize = 0;
  225. int sdlAutoIPS = 1;
  226. int sdlRtcEnable = 0;
  227. int sdlAgbPrint = 0;
  228. int sdlDefaultJoypad = 0;
  229. extern void debuggerSignal(int,int);
  230. void (*dbgMain)() = debuggerMain;
  231. void (*dbgSignal)(int,int) = debuggerSignal;
  232. void (*dbgOutput)(char *, u32) = debuggerOutput;
  233. int mouseCounter = 0;
  234. int autoFire = 0;
  235. bool autoFireToggle = false;
  236. bool screenMessage[8] = {false,false,false,false,false,false,false,false};
  237. char screenMessageBuffer[8][21];
  238. u32 screenMessageTime[8] = {0,0,0,0,0,0,0,0};
  239. u32 screenMessageDuration[8] = {0,0,0,0,0,0,0,0};
  240. SDL_cond *cond = NULL;
  241. SDL_mutex *mutex = NULL;
  242. u8* sdlBuffer;
  243. int sdlSoundLen = 0;
  244. SoundSDL* soundDriver = NULL;
  245. char *arg0;
  246. #ifndef C_CORE
  247. u8 sdlStretcher[16384];
  248. int sdlStretcherPos;
  249. #else
  250. void (*sdlStretcher)(u8 *, u8*) = NULL;
  251. #endif
  252. u16 joypad[4][12] = {
  253. { SDLK_LEFT, SDLK_RIGHT,
  254. SDLK_UP, SDLK_DOWN,
  255. SDLK_z, SDLK_x,
  256. SDLK_RETURN,SDLK_BACKSPACE,
  257. SDLK_a, SDLK_s,
  258. SDLK_SPACE, SDLK_F12
  259. },
  260. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  261. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  262. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  263. };
  264. u16 defaultJoypad[12] = {
  265. SDLK_LEFT, SDLK_RIGHT,
  266. SDLK_UP, SDLK_DOWN,
  267. SDLK_z, SDLK_x,
  268. SDLK_RETURN,SDLK_BACKSPACE,
  269. SDLK_a, SDLK_s,
  270. SDLK_SPACE, SDLK_F12
  271. };
  272. u16 motion[4] = {
  273. SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2
  274. };
  275. u16 defaultMotion[4] = {
  276. SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2
  277. };
  278. struct option sdlOptions[] = {
  279. { "agb-print", no_argument, &sdlAgbPrint, 1 },
  280. { "auto-frameskip", no_argument, &autoFrameSkip, 1 },
  281. { "bios", required_argument, 0, 'b' },
  282. { "config", required_argument, 0, 'c' },
  283. { "debug", no_argument, 0, 'd' },
  284. { "filter", required_argument, 0, 'f' },
  285. { "filter-normal", no_argument, &filter, 0 },
  286. { "filter-tv-mode", no_argument, &filter, 1 },
  287. { "filter-2xsai", no_argument, &filter, 2 },
  288. { "filter-super-2xsai", no_argument, &filter, 3 },
  289. { "filter-super-eagle", no_argument, &filter, 4 },
  290. { "filter-pixelate", no_argument, &filter, 5 },
  291. { "filter-motion-blur", no_argument, &filter, 6 },
  292. { "filter-advmame", no_argument, &filter, 7 },
  293. { "filter-simple2x", no_argument, &filter, 8 },
  294. { "filter-bilinear", no_argument, &filter, 9 },
  295. { "filter-bilinear+", no_argument, &filter, 10 },
  296. { "filter-scanlines", no_argument, &filter, 11 },
  297. { "filter-hq2x", no_argument, &filter, 12 },
  298. { "filter-lq2x", no_argument, &filter, 13 },
  299. { "flash-size", required_argument, 0, 'S' },
  300. { "flash-64k", no_argument, &sdlFlashSize, 0 },
  301. { "flash-128k", no_argument, &sdlFlashSize, 1 },
  302. { "frameskip", required_argument, 0, 's' },
  303. { "fullscreen", no_argument, &fullscreen, 1 },
  304. { "gdb", required_argument, 0, 'G' },
  305. { "help", no_argument, &sdlPrintUsage, 1 },
  306. { "ifb-none", no_argument, &ifbType, 0 },
  307. { "ifb-motion-blur", no_argument, &ifbType, 1 },
  308. { "ifb-smart", no_argument, &ifbType, 2 },
  309. { "ips", required_argument, 0, 'i' },
  310. { "no-agb-print", no_argument, &sdlAgbPrint, 0 },
  311. { "no-auto-frameskip", no_argument, &autoFrameSkip, 0 },
  312. { "no-debug", no_argument, 0, 'N' },
  313. { "no-ips", no_argument, &sdlAutoIPS, 0 },
  314. { "no-mmx", no_argument, &disableMMX, 1 },
  315. { "no-pause-when-inactive", no_argument, &pauseWhenInactive, 0 },
  316. { "no-rtc", no_argument, &sdlRtcEnable, 0 },
  317. { "no-show-speed", no_argument, &showSpeed, 0 },
  318. { "no-throttle", no_argument, &throttle, 0 },
  319. { "pause-when-inactive", no_argument, &pauseWhenInactive, 1 },
  320. { "profile", optional_argument, 0, 'P' },
  321. { "rtc", no_argument, &sdlRtcEnable, 1 },
  322. { "save-type", required_argument, 0, 't' },
  323. { "save-auto", no_argument, &cpuSaveType, 0 },
  324. { "save-eeprom", no_argument, &cpuSaveType, 1 },
  325. { "save-sram", no_argument, &cpuSaveType, 2 },
  326. { "save-flash", no_argument, &cpuSaveType, 3 },
  327. { "save-sensor", no_argument, &cpuSaveType, 4 },
  328. { "save-none", no_argument, &cpuSaveType, 5 },
  329. { "show-speed-normal", no_argument, &showSpeed, 1 },
  330. { "show-speed-detailed", no_argument, &showSpeed, 2 },
  331. { "throttle", required_argument, 0, 'T' },
  332. { "verbose", required_argument, 0, 'v' },
  333. { "video-1x", no_argument, &sizeOption, 0 },
  334. { "video-2x", no_argument, &sizeOption, 1 },
  335. { "video-3x", no_argument, &sizeOption, 2 },
  336. { "video-4x", no_argument, &sizeOption, 3 },
  337. { "yuv", required_argument, 0, 'Y' },
  338. { "recordmovie", required_argument, 0, 'r' },
  339. { "playmovie", required_argument, 0, 'p' },
  340. { "watchmovie", required_argument, 0, 'w' },
  341. { NULL, no_argument, NULL, 0 }
  342. };
  343. #ifndef C_CORE
  344. #define SDL_LONG(val) \
  345. *((u32 *)&sdlStretcher[sdlStretcherPos]) = val;\
  346. sdlStretcherPos+=4;
  347. #define SDL_AND_EAX(val) \
  348. sdlStretcher[sdlStretcherPos++] = 0x25;\
  349. SDL_LONG(val);
  350. #define SDL_AND_EBX(val) \
  351. sdlStretcher[sdlStretcherPos++] = 0x81;\
  352. sdlStretcher[sdlStretcherPos++] = 0xe3;\
  353. SDL_LONG(val);
  354. #define SDL_OR_EAX_EBX \
  355. sdlStretcher[sdlStretcherPos++] = 0x09;\
  356. sdlStretcher[sdlStretcherPos++] = 0xd8;
  357. #define SDL_LOADL_EBX \
  358. sdlStretcher[sdlStretcherPos++] = 0x8b;\
  359. sdlStretcher[sdlStretcherPos++] = 0x1f;
  360. #define SDL_LOADW \
  361. sdlStretcher[sdlStretcherPos++] = 0x66;\
  362. sdlStretcher[sdlStretcherPos++] = 0x8b;\
  363. sdlStretcher[sdlStretcherPos++] = 0x06;\
  364. sdlStretcher[sdlStretcherPos++] = 0x83;\
  365. sdlStretcher[sdlStretcherPos++] = 0xc6;\
  366. sdlStretcher[sdlStretcherPos++] = 0x02;
  367. #define SDL_LOADL \
  368. sdlStretcher[sdlStretcherPos++] = 0x8b;\
  369. sdlStretcher[sdlStretcherPos++] = 0x06;\
  370. sdlStretcher[sdlStretcherPos++] = 0x83;\
  371. sdlStretcher[sdlStretcherPos++] = 0xc6;\
  372. sdlStretcher[sdlStretcherPos++] = 0x04;
  373. #define SDL_LOADL2 \
  374. sdlStretcher[sdlStretcherPos++] = 0x8b;\
  375. sdlStretcher[sdlStretcherPos++] = 0x06;\
  376. sdlStretcher[sdlStretcherPos++] = 0x83;\
  377. sdlStretcher[sdlStretcherPos++] = 0xc6;\
  378. sdlStretcher[sdlStretcherPos++] = 0x03;
  379. #define SDL_STOREW \
  380. sdlStretcher[sdlStretcherPos++] = 0x66;\
  381. sdlStretcher[sdlStretcherPos++] = 0x89;\
  382. sdlStretcher[sdlStretcherPos++] = 0x07;\
  383. sdlStretcher[sdlStretcherPos++] = 0x83;\
  384. sdlStretcher[sdlStretcherPos++] = 0xc7;\
  385. sdlStretcher[sdlStretcherPos++] = 0x02;
  386. #define SDL_STOREL \
  387. sdlStretcher[sdlStretcherPos++] = 0x89;\
  388. sdlStretcher[sdlStretcherPos++] = 0x07;\
  389. sdlStretcher[sdlStretcherPos++] = 0x83;\
  390. sdlStretcher[sdlStretcherPos++] = 0xc7;\
  391. sdlStretcher[sdlStretcherPos++] = 0x04;
  392. #define SDL_STOREL2 \
  393. sdlStretcher[sdlStretcherPos++] = 0x89;\
  394. sdlStretcher[sdlStretcherPos++] = 0x07;\
  395. sdlStretcher[sdlStretcherPos++] = 0x83;\
  396. sdlStretcher[sdlStretcherPos++] = 0xc7;\
  397. sdlStretcher[sdlStretcherPos++] = 0x03;
  398. #define SDL_RET \
  399. sdlStretcher[sdlStretcherPos++] = 0xc3;
  400. #define SDL_PUSH_EAX \
  401. sdlStretcher[sdlStretcherPos++] = 0x50;
  402. #define SDL_PUSH_ECX \
  403. sdlStretcher[sdlStretcherPos++] = 0x51;
  404. #define SDL_PUSH_EBX \
  405. sdlStretcher[sdlStretcherPos++] = 0x53;
  406. #define SDL_PUSH_ESI \
  407. sdlStretcher[sdlStretcherPos++] = 0x56;
  408. #define SDL_PUSH_EDI \
  409. sdlStretcher[sdlStretcherPos++] = 0x57;
  410. #define SDL_POP_EAX \
  411. sdlStretcher[sdlStretcherPos++] = 0x58;
  412. #define SDL_POP_ECX \
  413. sdlStretcher[sdlStretcherPos++] = 0x59;
  414. #define SDL_POP_EBX \
  415. sdlStretcher[sdlStretcherPos++] = 0x5b;
  416. #define SDL_POP_ESI \
  417. sdlStretcher[sdlStretcherPos++] = 0x5e;
  418. #define SDL_POP_EDI \
  419. sdlStretcher[sdlStretcherPos++] = 0x5f;
  420. #define SDL_MOV_ECX(val) \
  421. sdlStretcher[sdlStretcherPos++] = 0xb9;\
  422. SDL_LONG(val);
  423. #define SDL_REP_MOVSB \
  424. sdlStretcher[sdlStretcherPos++] = 0xf3;\
  425. sdlStretcher[sdlStretcherPos++] = 0xa4;
  426. #define SDL_REP_MOVSW \
  427. sdlStretcher[sdlStretcherPos++] = 0xf3;\
  428. sdlStretcher[sdlStretcherPos++] = 0x66;\
  429. sdlStretcher[sdlStretcherPos++] = 0xa5;
  430. #define SDL_REP_MOVSL \
  431. sdlStretcher[sdlStretcherPos++] = 0xf3;\
  432. sdlStretcher[sdlStretcherPos++] = 0xa5;
  433. void sdlMakeStretcher(int width)
  434. {
  435. sdlStretcherPos = 0;
  436. switch(systemColorDepth) {
  437. case 16:
  438. if(sizeOption) {
  439. SDL_PUSH_EAX;
  440. SDL_PUSH_ESI;
  441. SDL_PUSH_EDI;
  442. for(int i = 0; i < width; i++) {
  443. SDL_LOADW;
  444. SDL_STOREW;
  445. SDL_STOREW;
  446. if(sizeOption > 1) {
  447. SDL_STOREW;
  448. }
  449. if(sizeOption > 2) {
  450. SDL_STOREW;
  451. }
  452. }
  453. SDL_POP_EDI;
  454. SDL_POP_ESI;
  455. SDL_POP_EAX;
  456. SDL_RET;
  457. } else {
  458. SDL_PUSH_ESI;
  459. SDL_PUSH_EDI;
  460. SDL_PUSH_ECX;
  461. SDL_MOV_ECX(width);
  462. SDL_REP_MOVSW;
  463. SDL_POP_ECX;
  464. SDL_POP_EDI;
  465. SDL_POP_ESI;
  466. SDL_RET;
  467. }
  468. break;
  469. case 24:
  470. if(sizeOption) {
  471. SDL_PUSH_EAX;
  472. SDL_PUSH_ESI;
  473. SDL_PUSH_EDI;
  474. int w = width - 1;
  475. for(int i = 0; i < w; i++) {
  476. SDL_LOADL2;
  477. SDL_STOREL2;
  478. SDL_STOREL2;
  479. if(sizeOption > 1) {
  480. SDL_STOREL2;
  481. }
  482. if(sizeOption > 2) {
  483. SDL_STOREL2;
  484. }
  485. }
  486. // need to write the last one
  487. SDL_LOADL2;
  488. SDL_STOREL2;
  489. if(sizeOption > 1) {
  490. SDL_STOREL2;
  491. }
  492. if(sizeOption > 2) {
  493. SDL_STOREL2;
  494. }
  495. SDL_AND_EAX(0x00ffffff);
  496. SDL_PUSH_EBX;
  497. SDL_LOADL_EBX;
  498. SDL_AND_EBX(0xff000000);
  499. SDL_OR_EAX_EBX;
  500. SDL_POP_EBX;
  501. SDL_STOREL2;
  502. SDL_POP_EDI;
  503. SDL_POP_ESI;
  504. SDL_POP_EAX;
  505. SDL_RET;
  506. } else {
  507. SDL_PUSH_ESI;
  508. SDL_PUSH_EDI;
  509. SDL_PUSH_ECX;
  510. SDL_MOV_ECX(3*width);
  511. SDL_REP_MOVSB;
  512. SDL_POP_ECX;
  513. SDL_POP_EDI;
  514. SDL_POP_ESI;
  515. SDL_RET;
  516. }
  517. break;
  518. case 32:
  519. if(sizeOption) {
  520. SDL_PUSH_EAX;
  521. SDL_PUSH_ESI;
  522. SDL_PUSH_EDI;
  523. for(int i = 0; i < width; i++) {
  524. SDL_LOADL;
  525. SDL_STOREL;
  526. SDL_STOREL;
  527. if(sizeOption > 1) {
  528. SDL_STOREL;
  529. }
  530. if(sizeOption > 2) {
  531. SDL_STOREL;
  532. }
  533. }
  534. SDL_POP_EDI;
  535. SDL_POP_ESI;
  536. SDL_POP_EAX;
  537. SDL_RET;
  538. } else {
  539. SDL_PUSH_ESI;
  540. SDL_PUSH_EDI;
  541. SDL_PUSH_ECX;
  542. SDL_MOV_ECX(width);
  543. SDL_REP_MOVSL;
  544. SDL_POP_ECX;
  545. SDL_POP_EDI;
  546. SDL_POP_ESI;
  547. SDL_RET;
  548. }
  549. break;
  550. }
  551. }
  552. #ifdef _MSC_VER
  553. #define SDL_CALL_STRETCHER \
  554. {\
  555. __asm mov eax, stretcher\
  556. __asm mov edi, dest\
  557. __asm mov esi, src\
  558. __asm call eax\
  559. }
  560. #else
  561. #define SDL_CALL_STRETCHER \
  562. asm volatile("call *%%eax"::"a" (stretcher),"S" (src),"D" (dest))
  563. #endif
  564. #else
  565. #define SDL_CALL_STRETCHER \
  566. sdlStretcher(src, dest)
  567. void sdlStretch16x1(u8 *src, u8 *dest)
  568. {
  569. u16 *s = (u16 *)src;
  570. u16 *d = (u16 *)dest;
  571. for(int i = 0; i < srcWidth; i++)
  572. *d++ = *s++;
  573. }
  574. void sdlStretch16x2(u8 *src, u8 *dest)
  575. {
  576. u16 *s = (u16 *)src;
  577. u16 *d = (u16 *)dest;
  578. for(int i = 0; i < srcWidth; i++) {
  579. *d++ = *s;
  580. *d++ = *s++;
  581. }
  582. }
  583. void sdlStretch16x3(u8 *src, u8 *dest)
  584. {
  585. u16 *s = (u16 *)src;
  586. u16 *d = (u16 *)dest;
  587. for(int i = 0; i < srcWidth; i++) {
  588. *d++ = *s;
  589. *d++ = *s;
  590. *d++ = *s++;
  591. }
  592. }
  593. void sdlStretch16x4(u8 *src, u8 *dest)
  594. {
  595. u16 *s = (u16 *)src;
  596. u16 *d = (u16 *)dest;
  597. for(int i = 0; i < srcWidth; i++) {
  598. *d++ = *s;
  599. *d++ = *s;
  600. *d++ = *s;
  601. *d++ = *s++;
  602. }
  603. }
  604. void (*sdlStretcher16[4])(u8 *, u8 *) = {
  605. sdlStretch16x1,
  606. sdlStretch16x2,
  607. sdlStretch16x3,
  608. sdlStretch16x4
  609. };
  610. void sdlStretch32x1(u8 *src, u8 *dest)
  611. {
  612. u32 *s = (u32 *)src;
  613. u32 *d = (u32 *)dest;
  614. for(int i = 0; i < srcWidth; i++)
  615. *d++ = *s++;
  616. }
  617. void sdlStretch32x2(u8 *src, u8 *dest)
  618. {
  619. u32 *s = (u32 *)src;
  620. u32 *d = (u32 *)dest;
  621. for(int i = 0; i < srcWidth; i++) {
  622. *d++ = *s;
  623. *d++ = *s++;
  624. }
  625. }
  626. void sdlStretch32x3(u8 *src, u8 *dest)
  627. {
  628. u32 *s = (u32 *)src;
  629. u32 *d = (u32 *)dest;
  630. for(int i = 0; i < srcWidth; i++) {
  631. *d++ = *s;
  632. *d++ = *s;
  633. *d++ = *s++;
  634. }
  635. }
  636. void sdlStretch32x4(u8 *src, u8 *dest)
  637. {
  638. u32 *s = (u32 *)src;
  639. u32 *d = (u32 *)dest;
  640. for(int i = 0; i < srcWidth; i++) {
  641. *d++ = *s;
  642. *d++ = *s;
  643. *d++ = *s;
  644. *d++ = *s++;
  645. }
  646. }
  647. void (*sdlStretcher32[4])(u8 *, u8 *) = {
  648. sdlStretch32x1,
  649. sdlStretch32x2,
  650. sdlStretch32x3,
  651. sdlStretch32x4
  652. };
  653. void sdlStretch24x1(u8 *src, u8 *dest)
  654. {
  655. u8 *s = src;
  656. u8 *d = dest;
  657. for(int i = 0; i < srcWidth; i++) {
  658. *d++ = *s++;
  659. *d++ = *s++;
  660. *d++ = *s++;
  661. }
  662. }
  663. void sdlStretch24x2(u8 *src, u8 *dest)
  664. {
  665. u8 *s = (u8 *)src;
  666. u8 *d = (u8 *)dest;
  667. for(int i = 0; i < srcWidth; i++) {
  668. *d++ = *s;
  669. *d++ = *(s+1);
  670. *d++ = *(s+2);
  671. s += 3;
  672. *d++ = *s;
  673. *d++ = *(s+1);
  674. *d++ = *(s+2);
  675. s += 3;
  676. }
  677. }
  678. void sdlStretch24x3(u8 *src, u8 *dest)
  679. {
  680. u8 *s = (u8 *)src;
  681. u8 *d = (u8 *)dest;
  682. for(int i = 0; i < srcWidth; i++) {
  683. *d++ = *s;
  684. *d++ = *(s+1);
  685. *d++ = *(s+2);
  686. s += 3;
  687. *d++ = *s;
  688. *d++ = *(s+1);
  689. *d++ = *(s+2);
  690. s += 3;
  691. *d++ = *s;
  692. *d++ = *(s+1);
  693. *d++ = *(s+2);
  694. s += 3;
  695. }
  696. }
  697. void sdlStretch24x4(u8 *src, u8 *dest)
  698. {
  699. u8 *s = (u8 *)src;
  700. u8 *d = (u8 *)dest;
  701. for(int i = 0; i < srcWidth; i++) {
  702. *d++ = *s;
  703. *d++ = *(s+1);
  704. *d++ = *(s+2);
  705. s += 3;
  706. *d++ = *s;
  707. *d++ = *(s+1);
  708. *d++ = *(s+2);
  709. s += 3;
  710. *d++ = *s;
  711. *d++ = *(s+1);
  712. *d++ = *(s+2);
  713. s += 3;
  714. *d++ = *s;
  715. *d++ = *(s+1);
  716. *d++ = *(s+2);
  717. s += 3;
  718. }
  719. }
  720. void (*sdlStretcher24[4])(u8 *, u8 *) = {
  721. sdlStretch24x1,
  722. sdlStretch24x2,
  723. sdlStretch24x3,
  724. sdlStretch24x4
  725. };
  726. #endif
  727. u32 sdlFromHex(char *s)
  728. {
  729. u32 value;
  730. sscanf(s, "%x", &value);
  731. return value;
  732. }
  733. #ifdef __MSC__
  734. #define stat _stat
  735. #define S_IFDIR _S_IFDIR
  736. #endif
  737. void sdlCheckDirectory(char *dir)
  738. {
  739. struct stat buf;
  740. int len = strlen(dir);
  741. char *p = dir + len - 1;
  742. if(*p == '/' ||
  743. *p == '\\')
  744. *p = 0;
  745. if(stat(dir, &buf) == 0) {
  746. if(!(buf.st_mode & S_IFDIR)) {
  747. fprintf(stderr, "Error: %s is not a directory\n", dir);
  748. dir[0] = 0;
  749. }
  750. } else {
  751. fprintf(stderr, "Error: %s does not exist\n", dir);
  752. dir[0] = 0;
  753. }
  754. }
  755. char *sdlGetFilename(char *name)
  756. {
  757. static char filebuffer[2048];
  758. int len = strlen(name);
  759. char *p = name + len - 1;
  760. while(true) {
  761. if(*p == '/' ||
  762. *p == '\\') {
  763. p++;
  764. break;
  765. }
  766. len--;
  767. p--;
  768. if(len == 0)
  769. break;
  770. }
  771. if(len == 0)
  772. strcpy(filebuffer, name);
  773. else
  774. strcpy(filebuffer, p);
  775. return filebuffer;
  776. }
  777. FILE *sdlFindFile(const char *name)
  778. {
  779. char buffer[4096];
  780. char path[2048];
  781. #ifdef WIN32
  782. #define PATH_SEP ";"
  783. #define FILE_SEP '\\'
  784. #define EXE_NAME "VisualBoyAdvance-SDL.exe"
  785. #else // ! WIN32
  786. #define PATH_SEP ":"
  787. #define FILE_SEP '/'
  788. #define EXE_NAME "VisualBoyAdvance"
  789. #endif // ! WIN32
  790. fprintf(stderr, "Searching for file %s\n", name);
  791. if(GETCWD(buffer, 2048)) {
  792. fprintf(stderr, "Searching current directory: %s\n", buffer);
  793. }
  794. FILE *f = fopen(name, "r");
  795. if(f != NULL) {
  796. return f;
  797. }
  798. char *home = getenv("HOME");
  799. if(home != NULL) {
  800. fprintf(stderr, "Searching home directory: %s\n", home);
  801. sprintf(path, "%s%c%s", home, FILE_SEP, name);
  802. f = fopen(path, "r");
  803. if(f != NULL)
  804. return f;
  805. }
  806. #ifdef WIN32
  807. home = getenv("USERPROFILE");
  808. if(home != NULL) {
  809. fprintf(stderr, "Searching user profile directory: %s\n", home);
  810. sprintf(path, "%s%c%s", home, FILE_SEP, name);
  811. f = fopen(path, "r");
  812. if(f != NULL)
  813. return f;
  814. }
  815. #else // ! WIN32
  816. fprintf(stderr, "Searching system config directory: %s\n", SYSCONFDIR);
  817. sprintf(path, "%s%c%s", SYSCONFDIR, FILE_SEP, name);
  818. f = fopen(path, "r");
  819. if(f != NULL)
  820. return f;
  821. #endif // ! WIN32
  822. if(!strchr(arg0, '/') &&
  823. !strchr(arg0, '\\')) {
  824. char *path = getenv("PATH");
  825. if(path != NULL) {
  826. fprintf(stderr, "Searching PATH\n");
  827. strncpy(buffer, path, 4096);
  828. buffer[4095] = 0;
  829. char *tok = strtok(buffer, PATH_SEP);
  830. while(tok) {
  831. sprintf(path, "%s%c%s", tok, FILE_SEP, EXE_NAME);
  832. f = fopen(path, "r");
  833. if(f != NULL) {
  834. char path2[2048];
  835. fclose(f);
  836. sprintf(path2, "%s%c%s", tok, FILE_SEP, name);
  837. f = fopen(path2, "r");
  838. if(f != NULL) {
  839. fprintf(stderr, "Found at %s\n", path2);
  840. return f;
  841. }
  842. }
  843. tok = strtok(NULL, PATH_SEP);
  844. }
  845. }
  846. } else {
  847. // executable is relative to some directory
  848. fprintf(stderr, "Searching executable directory\n");
  849. strcpy(buffer, arg0);
  850. char *p = strrchr(buffer, FILE_SEP);
  851. if(p) {
  852. *p = 0;
  853. sprintf(path, "%s%c%s", buffer, FILE_SEP, name);
  854. f = fopen(path, "r");
  855. if(f != NULL)
  856. return f;
  857. }
  858. }
  859. return NULL;
  860. }
  861. void sdlReadPreferences(FILE *f)
  862. {
  863. char buffer[2048];
  864. while(1) {
  865. char *s = fgets(buffer, 2048, f);
  866. if(s == NULL)
  867. break;
  868. char *p = strchr(s, '#');
  869. if(p)
  870. *p = 0;
  871. char *token = strtok(s, " \t\n\r=");
  872. if(!token)
  873. continue;
  874. if(strlen(token) == 0)
  875. continue;
  876. char *key = token;
  877. char *value = strtok(NULL, "\t\n\r");
  878. if(value == NULL) {
  879. fprintf(stderr, "Empty value for key %s\n", key);
  880. continue;
  881. }
  882. if(!strcmp(key,"Joy0_Left")) {
  883. joypad[0][KEY_LEFT] = sdlFromHex(value);
  884. } else if(!strcmp(key, "Joy0_Right")) {
  885. joypad[0][KEY_RIGHT] = sdlFromHex(value);
  886. } else if(!strcmp(key, "Joy0_Up")) {
  887. joypad[0][KEY_UP] = sdlFromHex(value);
  888. } else if(!strcmp(key, "Joy0_Down")) {
  889. joypad[0][KEY_DOWN] = sdlFromHex(value);
  890. } else if(!strcmp(key, "Joy0_A")) {
  891. joypad[0][KEY_BUTTON_A] = sdlFromHex(value);
  892. } else if(!strcmp(key, "Joy0_B")) {
  893. joypad[0][KEY_BUTTON_B] = sdlFromHex(value);
  894. } else if(!strcmp(key, "Joy0_L")) {
  895. joypad[0][KEY_BUTTON_L] = sdlFromHex(value);
  896. } else if(!strcmp(key, "Joy0_R")) {
  897. joypad[0][KEY_BUTTON_R] = sdlFromHex(value);
  898. } else if(!strcmp(key, "Joy0_Start")) {
  899. joypad[0][KEY_BUTTON_START] = sdlFromHex(value);
  900. } else if(!strcmp(key, "Joy0_Select")) {
  901. joypad[0][KEY_BUTTON_SELECT] = sdlFromHex(value);
  902. } else if(!strcmp(key, "Joy0_Speed")) {
  903. joypad[0][KEY_BUTTON_SPEED] = sdlFromHex(value);
  904. } else if(!strcmp(key, "Joy0_Capture")) {
  905. joypad[0][KEY_BUTTON_CAPTURE] = sdlFromHex(value);
  906. } else if(!strcmp(key,"Joy1_Left")) {
  907. joypad[1][KEY_LEFT] = sdlFromHex(value);
  908. } else if(!strcmp(key, "Joy1_Right")) {
  909. joypad[1][KEY_RIGHT] = sdlFromHex(value);
  910. } else if(!strcmp(key, "Joy1_Up")) {
  911. joypad[1][KEY_UP] = sdlFromHex(value);
  912. } else if(!strcmp(key, "Joy1_Down")) {
  913. joypad[1][KEY_DOWN] = sdlFromHex(value);
  914. } else if(!strcmp(key, "Joy1_A")) {
  915. joypad[1][KEY_BUTTON_A] = sdlFromHex(value);
  916. } else if(!strcmp(key, "Joy1_B")) {
  917. joypad[1][KEY_BUTTON_B] = sdlFromHex(value);
  918. } else if(!strcmp(key, "Joy1_L")) {
  919. joypad[1][KEY_BUTTON_L] = sdlFromHex(value);
  920. } else if(!strcmp(key, "Joy1_R")) {
  921. joypad[1][KEY_BUTTON_R] = sdlFromHex(value);
  922. } else if(!strcmp(key, "Joy1_Start")) {
  923. joypad[1][KEY_BUTTON_START] = sdlFromHex(value);
  924. } else if(!strcmp(key, "Joy1_Select")) {
  925. joypad[1][KEY_BUTTON_SELECT] = sdlFromHex(value);
  926. } else if(!strcmp(key, "Joy1_Speed")) {
  927. joypad[1][KEY_BUTTON_SPEED] = sdlFromHex(value);
  928. } else if(!strcmp(key, "Joy1_Capture")) {
  929. joypad[1][KEY_BUTTON_CAPTURE] = sdlFromHex(value);
  930. } else if(!strcmp(key,"Joy2_Left")) {
  931. joypad[2][KEY_LEFT] = sdlFromHex(value);
  932. } else if(!strcmp(key, "Joy2_Right")) {
  933. joypad[2][KEY_RIGHT] = sdlFromHex(value);
  934. } else if(!strcmp(key, "Joy2_Up")) {
  935. joypad[2][KEY_UP] = sdlFromHex(value);
  936. } else if(!strcmp(key, "Joy2_Down")) {
  937. joypad[2][KEY_DOWN] = sdlFromHex(value);
  938. } else if(!strcmp(key, "Joy2_A")) {
  939. joypad[2][KEY_BUTTON_A] = sdlFromHex(value);
  940. } else if(!strcmp(key, "Joy2_B")) {
  941. joypad[2][KEY_BUTTON_B] = sdlFromHex(value);
  942. } else if(!strcmp(key, "Joy2_L")) {
  943. joypad[2][KEY_BUTTON_L] = sdlFromHex(value);
  944. } else if(!strcmp(key, "Joy2_R")) {
  945. joypad[2][KEY_BUTTON_R] = sdlFromHex(value);
  946. } else if(!strcmp(key, "Joy2_Start")) {
  947. joypad[2][KEY_BUTTON_START] = sdlFromHex(value);
  948. } else if(!strcmp(key, "Joy2_Select")) {
  949. joypad[2][KEY_BUTTON_SELECT] = sdlFromHex(value);
  950. } else if(!strcmp(key, "Joy2_Speed")) {
  951. joypad[2][KEY_BUTTON_SPEED] = sdlFromHex(value);
  952. } else if(!strcmp(key, "Joy2_Capture")) {
  953. joypad[2][KEY_BUTTON_CAPTURE] = sdlFromHex(value);
  954. } else if(!strcmp(key,"Joy4_Left")) {
  955. joypad[4][KEY_LEFT] = sdlFromHex(value);
  956. } else if(!strcmp(key, "Joy4_Right")) {
  957. joypad[4][KEY_RIGHT] = sdlFromHex(value);
  958. } else if(!strcmp(key, "Joy4_Up")) {
  959. joypad[4][KEY_UP] = sdlFromHex(value);
  960. } else if(!strcmp(key, "Joy4_Down")) {
  961. joypad[4][KEY_DOWN] = sdlFromHex(value);
  962. } else if(!strcmp(key, "Joy4_A")) {
  963. joypad[4][KEY_BUTTON_A] = sdlFromHex(value);
  964. } else if(!strcmp(key, "Joy4_B")) {
  965. joypad[4][KEY_BUTTON_B] = sdlFromHex(value);
  966. } else if(!strcmp(key, "Joy4_L")) {
  967. joypad[4][KEY_BUTTON_L] = sdlFromHex(value);
  968. } else if(!strcmp(key, "Joy4_R")) {
  969. joypad[4][KEY_BUTTON_R] = sdlFromHex(value);
  970. } else if(!strcmp(key, "Joy4_Start")) {
  971. joypad[4][KEY_BUTTON_START] = sdlFromHex(value);
  972. } else if(!strcmp(key, "Joy4_Select")) {
  973. joypad[4][KEY_BUTTON_SELECT] = sdlFromHex(value);
  974. } else if(!strcmp(key, "Joy4_Speed")) {
  975. joypad[4][KEY_BUTTON_SPEED] = sdlFromHex(value);
  976. } else if(!strcmp(key, "Joy4_Capture")) {
  977. joypad[4][KEY_BUTTON_CAPTURE] = sdlFromHex(value);
  978. } else if(!strcmp(key, "Motion_Left")) {
  979. motion[KEY_LEFT] = sdlFromHex(value);
  980. } else if(!strcmp(key, "Motion_Right")) {
  981. motion[KEY_RIGHT] = sdlFromHex(value);
  982. } else if(!strcmp(key, "Motion_Up")) {
  983. motion[KEY_UP] = sdlFromHex(value);
  984. } else if(!strcmp(key, "Motion_Down")) {
  985. motion[KEY_DOWN] = sdlFromHex(value);
  986. } else if(!strcmp(key, "frameSkip")) {
  987. frameSkip = sdlFromHex(value);
  988. if(frameSkip < 0 || frameSkip > 9)
  989. frameSkip = 2;
  990. } else if(!strcmp(key, "gbFrameSkip")) {
  991. gbFrameSkip = sdlFromHex(value);
  992. if(gbFrameSkip < 0 || gbFrameSkip > 9)
  993. gbFrameSkip = 0;
  994. } else if(!strcmp(key, "video")) {
  995. sizeOption = sdlFromHex(value);
  996. if(sizeOption < 0 || sizeOption > 3)
  997. sizeOption = 1;
  998. } else if(!strcmp(key, "fullScreen")) {
  999. fullscreen = sdlFromHex(value) ? 1 : 0;
  1000. } else if(!strcmp(key, "useBios")) {
  1001. useBios = sdlFromHex(value) ? true : false;
  1002. } else if(!strcmp(key, "skipBios")) {
  1003. skipBios = sdlFromHex(value) ? true : false;
  1004. } else if(!strcmp(key, "biosFile")) {
  1005. strcpy(biosFileName, value);
  1006. } else if(!strcmp(key, "filter")) {
  1007. filter = sdlFromHex(value);
  1008. if(filter < 0 || filter > 13)
  1009. filter = 0;
  1010. } else if(!strcmp(key, "disableStatus")) {
  1011. disableStatusMessages = sdlFromHex(value) ? true : false;
  1012. } else if(!strcmp(key, "borderOn")) {
  1013. gbBorderOn = sdlFromHex(value) ? true : false;
  1014. } else if(!strcmp(key, "borderAutomatic")) {
  1015. gbBorderAutomatic = sdlFromHex(value) ? true : false;
  1016. } else if(!strcmp(key, "emulatorType")) {
  1017. gbEmulatorType = sdlFromHex(value);
  1018. if(gbEmulatorType < 0 || gbEmulatorType > 5)
  1019. gbEmulatorType = 1;
  1020. } else if(!strcmp(key, "colorOption")) {
  1021. gbColorOption = sdlFromHex(value) ? true : false;
  1022. } else if(!strcmp(key, "captureDir")) {
  1023. sdlCheckDirectory(value);
  1024. strcpy(captureDir, value);
  1025. } else if(!strcmp(key, "saveDir")) {
  1026. sdlCheckDirectory(value);
  1027. strcpy(saveDir, value);
  1028. } else if(!strcmp(key, "batteryDir")) {
  1029. sdlCheckDirectory(value);
  1030. strcpy(batteryDir, value);
  1031. } else if(!strcmp(key, "captureFormat")) {
  1032. captureFormat = sdlFromHex(value);
  1033. } else if(!strcmp(key, "soundQuality")) {
  1034. soundQuality = sdlFromHex(value);
  1035. switch(soundQuality) {
  1036. case 1: break;
  1037. default:
  1038. fprintf(stderr, "The rerecording version will run only sound at highest quality. Defaulting to 44.1 KHz\n");
  1039. soundQuality = 1;
  1040. break;
  1041. }
  1042. } else if(!strcmp(key, "soundOff")) {
  1043. soundOffFlag = sdlFromHex(value) ? true : false;
  1044. } else if(!strcmp(key, "soundEnable")) {
  1045. int res = sdlFromHex(value) & 0x30f;
  1046. soundEnableChannels(res);
  1047. soundDisableChannels(~res);
  1048. } else if(!strcmp(key, "soundEcho")) {
  1049. soundEcho = sdlFromHex(value) ? true : false;
  1050. } else if(!strcmp(key, "soundLowPass")) {
  1051. soundLowPass = sdlFromHex(value) ? true : false;
  1052. } else if(!strcmp(key, "soundReverse")) {
  1053. soundReverse = sdlFromHex(value) ? true : false;
  1054. } else if(!strcmp(key, "soundVolume")) {
  1055. soundVolume = sdlFromHex(value);
  1056. if(soundVolume < 0 || soundVolume > 3)
  1057. soundVolume = 0;
  1058. } else if(!strcmp(key, "removeIntros")) {
  1059. removeIntros = sdlFromHex(value) ? true : false;
  1060. } else if(!strcmp(key, "saveType")) {
  1061. cpuSaveType = sdlFromHex(value);
  1062. if(cpuSaveType < 0 || cpuSaveType > 5)
  1063. cpuSaveType = 0;
  1064. } else if(!strcmp(key, "flashSize")) {
  1065. sdlFlashSize = sdlFromHex(value);
  1066. if(sdlFlashSize != 0 && sdlFlashSize != 1)
  1067. sdlFlashSize = 0;
  1068. } else if(!strcmp(key, "ifbType")) {
  1069. ifbType = sdlFromHex(value);
  1070. if(ifbType < 0 || ifbType > 2)
  1071. ifbType = 0;
  1072. } else if(!strcmp(key, "showSpeed")) {
  1073. showSpeed = sdlFromHex(value);
  1074. if(showSpeed < 0 || showSpeed > 2)
  1075. showSpeed = 1;
  1076. } else if(!strcmp(key, "showSpeedTransparent")) {
  1077. showSpeedTransparent = sdlFromHex(value);
  1078. } else if(!strcmp(key, "autoFrameSkip")) {
  1079. autoFrameSkip = sdlFromHex(value);
  1080. } else if(!strcmp(key, "throttle")) {
  1081. throttle = sdlFromHex(value);
  1082. if(throttle != 0 && (throttle < 5 || throttle > 1000))
  1083. throttle = 0;
  1084. } else if(!strcmp(key, "disableMMX")) {
  1085. #ifdef MMX
  1086. cpu_mmx = sdlFromHex(value) ? false : true;
  1087. #endif
  1088. } else if(!strcmp(key, "pauseWhenInactive")) {
  1089. pauseWhenInactive = sdlFromHex(value) ? true : false;
  1090. } else if(!strcmp(key, "agbPrint")) {
  1091. sdlAgbPrint = sdlFromHex(value);
  1092. } else if(!strcmp(key, "rtcEnabled")) {
  1093. sdlRtcEnable = sdlFromHex(value);
  1094. } else if(!strcmp(key, "rewindTimer")) {
  1095. rewindTimer = sdlFromHex(value);
  1096. if(rewindTimer < 0 || rewindTimer > 600)
  1097. rewindTimer = 0;
  1098. rewindTimer *= 6; // convert value to 10 frames multiple
  1099. } else if(!strcmp(key, "enhancedDetection")) {
  1100. cpuEnhancedDetection = sdlFromHex(value) ? true : false;
  1101. } else {
  1102. fprintf(stderr, "Unknown configuration key %s\n", key);
  1103. }
  1104. }
  1105. }
  1106. void sdlReadPreferences()
  1107. {
  1108. FILE *f = sdlFindFile("VisualBoyAdvance.cfg");
  1109. if(f == NULL) {
  1110. fprintf(stderr, "Configuration file NOT FOUND (using defaults)\n");
  1111. return;
  1112. } else
  1113. fprintf(stderr, "Reading configuration file.\n");
  1114. sdlReadPreferences(f);
  1115. fclose(f);
  1116. }
  1117. static void sdlApplyPerImagePreferences()
  1118. {
  1119. FILE *f = sdlFindFile("vba-over.ini");
  1120. if(!f) {
  1121. fprintf(stderr, "vba-over.ini NOT FOUND (using emulator settings)\n");
  1122. return;
  1123. } else
  1124. fprintf(stderr, "Reading vba-over.ini\n");
  1125. char buffer[7];
  1126. buffer[0] = '[';
  1127. buffer[1] = rom[0xac];
  1128. buffer[2] = rom[0xad];
  1129. buffer[3] = rom[0xae];
  1130. buffer[4] = rom[0xaf];
  1131. buffer[5] = ']';
  1132. buffer[6] = 0;
  1133. char readBuffer[2048];
  1134. bool found = false;
  1135. while(1) {
  1136. char *s = fgets(readBuffer, 2048, f);
  1137. if(s == NULL)
  1138. break;
  1139. char *p = strchr(s, ';');
  1140. if(p)
  1141. *p = 0;
  1142. char *token = strtok(s, " \t\n\r=");
  1143. if(!token)
  1144. continue;
  1145. if(strlen(token) == 0)
  1146. continue;
  1147. if(!strcmp(token, buffer)) {
  1148. found = true;
  1149. break;
  1150. }
  1151. }
  1152. if(found) {
  1153. while(1) {
  1154. char *s = fgets(readBuffer, 2048, f);
  1155. if(s == NULL)
  1156. break;
  1157. char *p = strchr(s, ';');
  1158. if(p)
  1159. *p = 0;
  1160. char *token = strtok(s, " \t\n\r=");
  1161. if(!token)
  1162. continue;
  1163. if(strlen(token) == 0)
  1164. continue;
  1165. if(token[0] == '[') // starting another image settings
  1166. break;
  1167. char *value = strtok(NULL, "\t\n\r=");
  1168. if(value == NULL)
  1169. continue;
  1170. if(!strcmp(token, "rtcEnabled"))
  1171. rtcEnable(atoi(value) == 0 ? false : true);
  1172. else if(!strcmp(token, "flashSize")) {
  1173. int size = atoi(value);
  1174. if(size == 0x10000 || size == 0x20000)
  1175. flashSetSize(size);
  1176. } else if(!strcmp(token, "saveType")) {
  1177. int save = atoi(value);
  1178. if(save >= 0 && save <= 5)
  1179. cpuSaveType = save;
  1180. }
  1181. }
  1182. }
  1183. fclose(f);
  1184. }
  1185. static int sdlCalculateShift(u32 mask)
  1186. {
  1187. int m = 0;
  1188. while(mask) {
  1189. m++;
  1190. mask >>= 1;
  1191. }
  1192. return m-5;
  1193. }
  1194. static int sdlCalculateMaskWidth(u32 mask)
  1195. {
  1196. int m = 0;
  1197. int mask2 = mask;
  1198. while(mask2) {
  1199. m++;
  1200. mask2 >>= 1;
  1201. }
  1202. int m2 = 0;
  1203. mask2 = mask;
  1204. while(!(mask2 & 1)) {
  1205. m2++;
  1206. mask2 >>= 1;
  1207. }
  1208. return m - m2;
  1209. }
  1210. void sdlWriteState(int num)
  1211. {
  1212. char stateName[2048];
  1213. if(saveDir[0])
  1214. sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename),
  1215. num+1);
  1216. else
  1217. sprintf(stateName,"%s%d.sgm", filename, num+1);
  1218. if(theEmulator.emuWriteState)
  1219. theEmulator.emuWriteState(stateName);
  1220. sprintf(stateName, "Wrote state %d", num+1);
  1221. systemScreenMessage(stateName);
  1222. }
  1223. void sdlReadState(int num)
  1224. {
  1225. char stateName[2048];
  1226. if(saveDir[0])
  1227. sprintf(stateName, "%s/%s%d.sgm", saveDir, sdlGetFilename(filename),
  1228. num+1);
  1229. else
  1230. sprintf(stateName,"%s%d.sgm", filename, num+1);
  1231. if(theEmulator.emuReadState)
  1232. theEmulator.emuReadState(stateName);
  1233. sprintf(stateName, "Loaded state %d", num+1);
  1234. systemScreenMessage(stateName);
  1235. }
  1236. void sdlWriteBattery()
  1237. {
  1238. char buffer[1048];
  1239. if(batteryDir[0])
  1240. sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename));
  1241. else
  1242. sprintf(buffer, "%s.sav", filename);
  1243. theEmulator.emuWriteBattery(buffer);
  1244. systemScreenMessage("Wrote battery");
  1245. }
  1246. void sdlReadBattery()
  1247. {
  1248. char buffer[1048];
  1249. if(batteryDir[0])
  1250. sprintf(buffer, "%s/%s.sav", batteryDir, sdlGetFilename(filename));
  1251. else
  1252. sprintf(buffer, "%s.sav", filename);
  1253. bool res = false;
  1254. res = theEmulator.emuReadBattery(buffer);
  1255. if(res)
  1256. systemScreenMessage("Loaded battery");
  1257. }
  1258. #define MOD_KEYS (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_META)
  1259. #define MOD_NOCTRL (KMOD_SHIFT|KMOD_ALT|KMOD_META)
  1260. #define MOD_NOALT (KMOD_CTRL|KMOD_SHIFT|KMOD_META)
  1261. #define MOD_NOSHIFT (KMOD_CTRL|KMOD_ALT|KMOD_META)
  1262. void sdlUpdateKey(int key, bool down)
  1263. {
  1264. int i;
  1265. for(int j = 0; j < 4; j++) {
  1266. for(i = 0 ; i < 12; i++) {
  1267. if((joypad[j][i] & 0xf000) == 0) {
  1268. if(key == joypad[j][i])
  1269. if (down) currentButtons[j] |= 1<<i;
  1270. else currentButtons[j] ^= 1<<i;
  1271. }
  1272. }
  1273. }
  1274. for(i = 0 ; i < 4; i++) {
  1275. if((motion[i] & 0xf000) == 0) {
  1276. if(key == motion[i])
  1277. sdlMotionButtons[i] = down;
  1278. }
  1279. }
  1280. }
  1281. void sdlUpdateJoyButton(int which,
  1282. int button,
  1283. bool pressed)
  1284. {
  1285. int i;
  1286. for(int j = 0; j < 4; j++) {
  1287. for(i = 0; i < 12; i++) {
  1288. int dev = (joypad[j][i] >> 12);
  1289. int b = joypad[j][i] & 0xfff;
  1290. if(dev) {
  1291. dev--;
  1292. if((dev == which) && (b >= 128) && (b == (button+128))) {
  1293. if (pressed) currentButtons[j] |= 1<<i;
  1294. else currentButtons[j] ^= 1<<i;
  1295. }
  1296. }
  1297. }
  1298. }
  1299. for(i = 0; i < 4; i++) {
  1300. int dev = (motion[i] >> 12);
  1301. int b = motion[i] & 0xfff;
  1302. if(dev) {
  1303. dev--;
  1304. if((dev == which) && (b >= 128) && (b == (button+128))) {
  1305. sdlMotionButtons[i] = pressed;
  1306. }
  1307. }
  1308. }
  1309. }
  1310. void sdlUpdateJoyHat(int which,
  1311. int hat,
  1312. int value)
  1313. {
  1314. int i;
  1315. for(int j = 0; j < 4; j++) {
  1316. for(i = 0; i < 12; i++) {
  1317. int dev = (joypad[j][i] >> 12);
  1318. int a = joypad[j][i] & 0xfff;
  1319. if(dev) {
  1320. dev--;
  1321. if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) {
  1322. int dir = a & 3;
  1323. int v = 0;
  1324. switch(dir) {
  1325. case 0:
  1326. v = value & SDL_HAT_UP;
  1327. break;
  1328. case 1:
  1329. v = value & SDL_HAT_DOWN;
  1330. break;
  1331. case 2:
  1332. v = value & SDL_HAT_RIGHT;
  1333. break;
  1334. case 3:
  1335. v = value & SDL_HAT_LEFT;
  1336. break;
  1337. }
  1338. if (v) currentButtons[j] |= 1<<i;
  1339. else currentButtons[j] ^= 1<<i;
  1340. }
  1341. }
  1342. }
  1343. }
  1344. for(i = 0; i < 4; i++) {
  1345. int dev = (motion[i] >> 12);
  1346. int a = motion[i] & 0xfff;
  1347. if(dev) {
  1348. dev--;
  1349. if((dev == which) && (a>=32) && (a < 48) && (((a&15)>>2) == hat)) {
  1350. int dir = a & 3;
  1351. int v = 0;
  1352. switch(dir) {
  1353. case 0:
  1354. v = value & SDL_HAT_UP;
  1355. break;
  1356. case 1:
  1357. v = value & SDL_HAT_DOWN;
  1358. break;
  1359. case 2:
  1360. v = value & SDL_HAT_RIGHT;
  1361. break;
  1362. case 3:
  1363. v = value & SDL_HAT_LEFT;
  1364. break;
  1365. }
  1366. sdlMotionButtons[i] = (v ? true : false);
  1367. }
  1368. }
  1369. }
  1370. }
  1371. void sdlUpdateJoyAxis(int which,
  1372. int axis,
  1373. int value)
  1374. {
  1375. int i;
  1376. for(int j = 0; j < 4; j++) {
  1377. for(i = 0; i < 12; i++) {
  1378. int dev = (joypad[j][i] >> 12);
  1379. int a = joypad[j][i] & 0xfff;
  1380. if(dev) {
  1381. dev--;
  1382. if((dev == which) && (a < 32) && ((a>>1) == axis)) {
  1383. //I have no idea what this does, is this reimplementation correct? --Felipe
  1384. if (value>16384) {
  1385. if (a&1) currentButtons[j] |= 1<<i;
  1386. else currentButtons[j] ^= 1<<i;
  1387. }
  1388. else if (value<16384){
  1389. if (a&1) currentButtons[j] ^= 1<<i;
  1390. else currentButtons[j] |= 1<<i;
  1391. }
  1392. }
  1393. }
  1394. }
  1395. }
  1396. for(i = 0; i < 4; i++) {
  1397. int dev = (motion[i] >> 12);
  1398. int a = motion[i] & 0xfff;
  1399. if(dev) {
  1400. dev--;
  1401. if((dev == which) && (a < 32) && ((a>>1) == axis)) {
  1402. sdlMotionButtons[i] = (a & 1) ? (value > 16384) : (value < -16384);
  1403. }
  1404. }
  1405. }
  1406. }
  1407. bool sdlCheckJoyKey(int key)
  1408. {
  1409. int dev = (key >> 12) - 1;
  1410. int what = key & 0xfff;
  1411. if(what >= 128) {
  1412. // joystick button
  1413. int button = what - 128;
  1414. if(button >= SDL_JoystickNumButtons(sdlDevices[dev]))
  1415. return false;
  1416. } else if (what < 0x20) {
  1417. // joystick axis
  1418. what >>= 1;
  1419. if(what >= SDL_JoystickNumAxes(sdlDevices[dev]))
  1420. return false;
  1421. } else if (what < 0x30) {
  1422. // joystick hat
  1423. what = (what & 15);
  1424. what >>= 2;
  1425. if(what >= SDL_JoystickNumHats(sdlDevices[dev]))
  1426. return false;
  1427. }
  1428. // no problem found
  1429. return true;
  1430. }
  1431. void sdlCheckKeys()
  1432. {
  1433. sdlNumDevices = SDL_NumJoysticks();
  1434. if(sdlNumDevices)
  1435. sdlDevices = (SDL_Joystick **)calloc(1,sdlNumDevices *
  1436. sizeof(SDL_Joystick **));
  1437. int i;
  1438. bool usesJoy = false;
  1439. for(int j = 0; j < 4; j++) {
  1440. for(i = 0; i < 12; i++) {
  1441. int dev = joypad[j][i] >> 12;
  1442. if(dev) {
  1443. dev--;
  1444. bool ok = false;
  1445. if(sdlDevices) {
  1446. if(dev < sdlNumDevices) {
  1447. if(sdlDevices[dev] == NULL) {
  1448. sdlDevices[dev] = SDL_JoystickOpen(dev);
  1449. }
  1450. ok = sdlCheckJoyKey(joypad[j][i]);
  1451. } else
  1452. ok = false;
  1453. }
  1454. if(!ok)
  1455. joypad[j][i] = defaultJoypad[i];
  1456. else
  1457. usesJoy = true;
  1458. }
  1459. }
  1460. }
  1461. for(i = 0; i < 4; i++) {
  1462. int dev = motion[i] >> 12;
  1463. if(dev) {
  1464. dev--;
  1465. bool ok = false;
  1466. if(sdlDevices) {
  1467. if(dev < sdlNumDevices) {
  1468. if(sdlDevices[dev] == NULL) {
  1469. sdlDevices[dev] = SDL_JoystickOpen(dev);
  1470. }
  1471. ok = sdlCheckJoyKey(motion[i]);
  1472. } else
  1473. ok = false;
  1474. }
  1475. if(!ok)
  1476. motion[i] = defaultMotion[i];
  1477. else
  1478. usesJoy = true;
  1479. }
  1480. }
  1481. if(usesJoy)
  1482. SDL_JoystickEventState(SDL_ENABLE);
  1483. }
  1484. void sdlPollEvents()
  1485. {
  1486. SDL_Event event;
  1487. while(SDL_PollEvent(&event)) {
  1488. switch(event.type) {
  1489. case SDL_QUIT:
  1490. emulating = 0;
  1491. break;
  1492. case SDL_ACTIVEEVENT:
  1493. if(pauseWhenInactive && (event.active.state & SDL_APPINPUTFOCUS)) {
  1494. active = event.active.gain;
  1495. if(active) {
  1496. if(!paused) {
  1497. if(emulating)
  1498. soundResume();
  1499. }
  1500. } else {
  1501. wasPaused = true;
  1502. if(pauseWhenInactive) {
  1503. if(emulating)
  1504. soundPause();
  1505. }
  1506. memset(delta,255,sizeof(delta));
  1507. }
  1508. }
  1509. break;
  1510. case SDL_MOUSEMOTION:
  1511. case SDL_MOUSEBUTTONUP:
  1512. case SDL_MOUSEBUTTONDOWN:
  1513. if(fullscreen) {
  1514. SDL_ShowCursor(SDL_ENABLE);
  1515. mouseCounter = 120;
  1516. }
  1517. break;
  1518. case SDL_JOYHATMOTION:
  1519. sdlUpdateJoyHat(event.jhat.which,
  1520. event.jhat.hat,
  1521. event.jhat.value);
  1522. break;
  1523. case SDL_JOYBUTTONDOWN:
  1524. case SDL_JOYBUTTONUP:
  1525. sdlUpdateJoyButton(event.jbutton.which,
  1526. event.jbutton.button,
  1527. event.jbutton.state == SDL_PRESSED);
  1528. break;
  1529. case SDL_JOYAXISMOTION:
  1530. sdlUpdateJoyAxis(event.jaxis.which,
  1531. event.jaxis.axis,
  1532. event.jaxis.value);
  1533. break;
  1534. case SDL_KEYDOWN:
  1535. sdlUpdateKey(event.key.keysym.sym, true);
  1536. break;
  1537. case SDL_KEYUP:
  1538. switch(event.key.keysym.sym) {
  1539. case SDLK_r:
  1540. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1541. (event.key.keysym.mod & KMOD_CTRL)) {
  1542. if(emulating) {
  1543. theEmulator.emuReset(true);
  1544. systemScreenMessage("Reset");
  1545. }
  1546. }
  1547. break;
  1548. case SDLK_b:
  1549. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1550. (event.key.keysym.mod & KMOD_CTRL)) {
  1551. if(emulating && theEmulator.emuReadMemState && rewindMemory
  1552. && rewindCount) {
  1553. rewindPos = --rewindPos & 7;
  1554. theEmulator.emuReadMemState(&rewindMemory[REWIND_SIZE*rewindPos],
  1555. REWIND_SIZE);
  1556. rewindCount--;
  1557. rewindCounter = 0;
  1558. systemScreenMessage("Rewind");
  1559. }
  1560. }
  1561. break;
  1562. case SDLK_p:
  1563. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1564. (event.key.keysym.mod & KMOD_CTRL)) {
  1565. paused = !paused;
  1566. SDL_PauseAudio(paused);
  1567. if(paused)
  1568. wasPaused = true;
  1569. }
  1570. break;
  1571. case SDLK_ESCAPE:
  1572. emulating = 0;
  1573. break;
  1574. case SDLK_F12:
  1575. untilCapture = !untilCapture;
  1576. case SDLK_f:
  1577. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1578. (event.key.keysym.mod & KMOD_CTRL)) {
  1579. int flags = 0;
  1580. fullscreen = !fullscreen;
  1581. if(fullscreen)
  1582. flags |= SDL_FULLSCREEN;
  1583. SDL_SetVideoMode(destWidth, destHeight, systemColorDepth, flags);
  1584. // if(SDL_WM_ToggleFullScreen(surface))
  1585. // fullscreen = !fullscreen;
  1586. }
  1587. break;
  1588. case SDLK_F11:
  1589. if(dbgMain != debuggerMain) {
  1590. if(armState) {
  1591. armNextPC -= 4;
  1592. reg[15].I -= 4;
  1593. } else {
  1594. armNextPC -= 2;
  1595. reg[15].I -= 2;
  1596. }
  1597. }
  1598. debugger = true;
  1599. break;
  1600. case SDLK_F1:
  1601. case SDLK_F2:
  1602. case SDLK_F3:
  1603. case SDLK_F4:
  1604. case SDLK_F5:
  1605. case SDLK_F6:
  1606. case SDLK_F7:
  1607. case SDLK_F8:
  1608. case SDLK_F9:
  1609. case SDLK_F10:
  1610. if(!(event.key.keysym.mod & MOD_NOSHIFT) &&
  1611. (event.key.keysym.mod & KMOD_SHIFT)) {
  1612. sdlWriteState(event.key.keysym.sym-SDLK_F1);
  1613. } else if(!(event.key.keysym.mod & MOD_KEYS)) {
  1614. sdlReadState(event.key.keysym.sym-SDLK_F1);
  1615. }
  1616. break;
  1617. case SDLK_1:
  1618. case SDLK_2:
  1619. case SDLK_3:
  1620. case SDLK_4:
  1621. if(!(event.key.keysym.mod & MOD_NOALT) &&
  1622. (event.key.keysym.mod & KMOD_ALT)) {
  1623. char *disableMessages[4] =
  1624. { "autofire A disabled",
  1625. "autofire B disabled",
  1626. "autofire R disabled",
  1627. "autofire L disabled"};
  1628. char *enableMessages[4] =
  1629. { "autofire A",
  1630. "autofire B",
  1631. "autofire R",
  1632. "autofire L"};
  1633. int mask = 1 << (event.key.keysym.sym - SDLK_1);
  1634. if(event.key.keysym.sym > SDLK_2)
  1635. mask <<= 6;
  1636. if(autoFire & mask) {
  1637. autoFire &= ~mask;
  1638. systemScreenMessage(disableMessages[event.key.keysym.sym - SDLK_1]);
  1639. } else {
  1640. autoFire |= mask;
  1641. systemScreenMessage(enableMessages[event.key.keysym.sym - SDLK_1]);
  1642. }
  1643. } if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1644. (event.key.keysym.mod & KMOD_CTRL)) {
  1645. int mask = 0x0100 << (event.key.keysym.sym - SDLK_1);
  1646. layerSettings ^= mask;
  1647. layerEnable = DISPCNT & layerSettings;
  1648. CPUUpdateRenderBuffers(false);
  1649. }
  1650. break;
  1651. case SDLK_5:
  1652. case SDLK_6:
  1653. case SDLK_7:
  1654. case SDLK_8:
  1655. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1656. (event.key.keysym.mod & KMOD_CTRL)) {
  1657. int mask = 0x0100 << (event.key.keysym.sym - SDLK_1);
  1658. layerSettings ^= mask;
  1659. layerEnable = DISPCNT & layerSettings;
  1660. }
  1661. break;
  1662. case SDLK_n:
  1663. if(!(event.key.keysym.mod & MOD_NOCTRL) &&
  1664. (event.key.keysym.mod & KMOD_CTRL)) {
  1665. if(paused)
  1666. paused = false;
  1667. pauseNextFrame = true;
  1668. }
  1669. break;
  1670. default:
  1671. break;
  1672. }
  1673. sdlUpdateKey(event.key.keysym.sym, false);
  1674. break;
  1675. }
  1676. }
  1677. }
  1678. void usage(char *cmd)
  1679. {
  1680. printf("%s [option ...] file\n", cmd);
  1681. printf("\
  1682. \n\
  1683. Options:\n\
  1684. -1, --video-1x 1x\n\
  1685. -2, --video-2x 2x\n\
  1686. -3, --video-3x 3x\n\
  1687. -4, --video-4x 4x\n\
  1688. -F, --fullscreen Full screen\n\
  1689. -G, --gdb=PROTOCOL GNU Remote Stub mode:\n\
  1690. tcp - use TCP at port 55555\n\
  1691. tcp:PORT - use TCP at port PORT\n\
  1692. pipe - use pipe transport\n\
  1693. -N, --no-debug Don't parse debug information\n\
  1694. -S, --flash-size=SIZE Set the Flash size\n\
  1695. --flash-64k 0 - 64K Flash\n\
  1696. --flash-128k 1 - 128K Flash\n\
  1697. -T, --throttle=THROTTLE Set the desired throttle (5...1000)\n\
  1698. -Y, --yuv=TYPE Use YUV overlay for drawing:\n\
  1699. 0 - YV12\n\
  1700. 1 - UYVY\n\
  1701. 2 - YVYU\n\
  1702. 3 - YUY2\n\
  1703. 4 - IYUV\n\
  1704. -b, --bios=BIOS Use given bios file\n\
  1705. -c, --config=FILE Read the given configuration file\n\
  1706. -d, --debug

Large files files are truncated, but you can click here to view the full file