PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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 Enter debugger\n\
  1707. -f, --filter=FILTER Select filter:\n\
  1708. --filter-normal 0 - normal mode\n\
  1709. --filter-tv-mode 1 - TV Mode\n\
  1710. --filter-2xsai 2 - 2xSaI\n\
  1711. --filter-super-2xsai 3 - Super 2xSaI\n\
  1712. --filter-super-eagle 4 - Super Eagle\n\
  1713. --filter-pixelate 5 - Pixelate\n\
  1714. --filter-motion-blur 6 - Motion Blur\n\
  1715. --filter-advmame 7 - AdvanceMAME Scale2x\n\
  1716. --filter-simple2x 8 - Simple2x\n\
  1717. --filter-bilinear 9 - Bilinear\n\
  1718. --filter-bilinear+ 10 - Bilinear Plus\n\
  1719. --filter-scanlines 11 - Scanlines\n\
  1720. --filter-hq2x 12 - hq2x\n\
  1721. --filter-lq2x 13 - lq2x\n\
  1722. -h, --help Print this help\n\
  1723. -i, --ips=PATCH Apply given IPS patch\n\
  1724. -P, --profile=[HERTZ] Enable profiling\n\
  1725. -s, --frameskip=FRAMESKIP Set frame skip (0...9)\n\
  1726. ");
  1727. printf("\
  1728. -t, --save-type=TYPE Set the available save type\n\
  1729. --save-auto 0 - Automatic (EEPROM, SRAM, FLASH)\n\
  1730. --save-eeprom 1 - EEPROM\n\
  1731. --save-sram 2 - SRAM\n\
  1732. --save-flash 3 - FLASH\n\
  1733. --save-sensor 4 - EEPROM+Sensor\n\
  1734. --save-none 5 - NONE\n\
  1735. -v, --verbose=VERBOSE Set verbose logging (trace.log)\n\
  1736. 1 - SWI\n\
  1737. 2 - Unaligned memory access\n\
  1738. 4 - Illegal memory write\n\
  1739. 8 - Illegal memory read\n\
  1740. 16 - DMA 0\n\
  1741. 32 - DMA 1\n\
  1742. 64 - DMA 2\n\
  1743. 128 - DMA 3\n\
  1744. 256 - Undefined instruction\n\
  1745. 512 - AGBPrint messages\n\
  1746. \n\
  1747. Long options only:\n\
  1748. --agb-print Enable AGBPrint support\n\
  1749. --auto-frameskip Enable auto frameskipping\n\
  1750. --ifb-none No interframe blending\n\
  1751. --ifb-motion-blur Interframe motion blur\n\
  1752. --ifb-smart Smart interframe blending\n\
  1753. --no-agb-print Disable AGBPrint support\n\
  1754. --no-auto-frameskip Disable auto frameskipping\n\
  1755. --no-ips Do not apply IPS patch\n\
  1756. --no-mmx Disable MMX support\n\
  1757. --no-pause-when-inactive Don't pause when inactive\n\
  1758. --no-rtc Disable RTC support\n\
  1759. --no-show-speed Don't show emulation speed\n\
  1760. --no-throttle Disable thrrotle\n\
  1761. --pause-when-inactive Pause when inactive\n\
  1762. --rtc Enable RTC support\n\
  1763. --show-speed-normal Show emulation speed\n\
  1764. --show-speed-detailed Show detailed speed data\n\
  1765. ");
  1766. printf("\
  1767. -r, --recordmovie=filename Start recording input movie\n\
  1768. -p, --playmovie=filename Play input movie non-read-only\n\
  1769. -w, --watchmovie=filename Play input movie in read-only mode\n\
  1770. ");
  1771. }
  1772. static char *szFile;
  1773. void file_run()
  1774. {
  1775. //printf("RLM: file_run\n");
  1776. utilGetBaseName(szFile, filename);
  1777. char *p = strrchr(filename, '.');
  1778. if(p)
  1779. *p = 0;
  1780. if(ipsname[0] == 0)
  1781. sprintf(ipsname, "%s.ips", filename);
  1782. bool failed = false;
  1783. IMAGE_TYPE type = utilFindType(szFile);
  1784. if(type == IMAGE_UNKNOWN) {
  1785. systemMessage(0, "Unknown file type %s", szFile);
  1786. exit(-1);
  1787. }
  1788. systemCartridgeType = (int)type;
  1789. if(type == IMAGE_GB) {
  1790. failed = !gbLoadRom(szFile);
  1791. if(!failed) {
  1792. systemCartridgeType = 1;
  1793. //printf("RLM: choosing GBSystem\n");
  1794. theEmulator = GBSystem;
  1795. if(sdlAutoIPS) {
  1796. int size = gbRomSize;
  1797. utilApplyIPS(ipsname, &gbRom, &size);
  1798. if(size != gbRomSize) {
  1799. extern bool gbUpdateSizes();
  1800. gbUpdateSizes();
  1801. gbReset();
  1802. }
  1803. }
  1804. }
  1805. } else if(type == IMAGE_GBA) {
  1806. int size = CPULoadRom(szFile);
  1807. failed = (size == 0);
  1808. if(!failed) {
  1809. // if(cpuEnhancedDetection && cpuSaveType == 0) {
  1810. // utilGBAFindSave(rom, size);
  1811. // }
  1812. sdlApplyPerImagePreferences();
  1813. systemCartridgeType = 0;
  1814. theEmulator = GBASystem;
  1815. /* disabled due to problems
  1816. if(removeIntros && rom != NULL) {
  1817. WRITE32LE(&rom[0], 0xea00002e);
  1818. }
  1819. */
  1820. //CPUInit(biosFileName, useBios);
  1821. CPUInit();
  1822. CPUReset();
  1823. if(sdlAutoIPS) {
  1824. int size = 0x2000000;
  1825. utilApplyIPS(ipsname, &rom, &size);
  1826. if(size != 0x2000000) {
  1827. CPUReset();
  1828. }
  1829. }
  1830. }
  1831. }
  1832. if(failed) {
  1833. systemMessage(0, "Failed to load file %s", szFile);
  1834. exit(-1);
  1835. }
  1836. emulating = 1;
  1837. renderedFrames = 0;
  1838. }
  1839. void shutdown () {
  1840. fprintf(stderr,"Shutting down\n");
  1841. remoteCleanUp();
  1842. soundShutdown();
  1843. if(gbRom != NULL || rom != NULL) {
  1844. sdlWriteBattery();
  1845. theEmulator.emuCleanUp();
  1846. }
  1847. if(delta) {
  1848. free(delta);
  1849. delta = NULL;
  1850. }
  1851. SDL_Quit();
  1852. }
  1853. int tick () {
  1854. int ret;
  1855. ret = theEmulator.emuMain(theEmulator.emuCount);
  1856. // enable user input while ticking.
  1857. if (ret) { sdlPollEvents(); }
  1858. }
  1859. void step () {
  1860. if(!paused && active) {
  1861. //printf("RLM: emulator main\n");
  1862. int frameComplete = 0;
  1863. while (!(frameComplete)){
  1864. frameComplete = theEmulator.emuMain(theEmulator.emuCount);
  1865. }
  1866. //printf("RLM: emulator main called\n");
  1867. } else {
  1868. //SDL_Delay(500);
  1869. // kanzure: wtf! trying to get throttling to work.
  1870. }
  1871. sdlPollEvents();
  1872. SDL_ShowCursor(SDL_DISABLE);
  1873. }
  1874. void step(int keymask){
  1875. currentButtons[0] = keymask;
  1876. if (keymask == 0x0800){
  1877. theEmulator.emuReset(true);
  1878. }
  1879. else {
  1880. step();
  1881. }
  1882. currentButtons[0] = keymask;
  1883. }
  1884. // let the player control the game until he decides he hates it. This is particularly useful for playing from the repl.
  1885. void stepUntilCapture() {
  1886. untilCapture = true;
  1887. //currentButtons[0] = 0;
  1888. //systemClearJoypads();
  1889. //sdlUpdateKey(SDLK_F12, false);
  1890. //while (currentButtons[0] != 2048) {
  1891. while (untilCapture) {
  1892. /* if (currentButtons[0] != 0) {
  1893. printf("currentButtons[o] is %d\n", currentButtons[0]);
  1894. } */
  1895. step();
  1896. }
  1897. // reset the buttons so that this function can be called in the future
  1898. //currentButtons[0] = 0;
  1899. //systemClearJoypads();
  1900. //sdlUpdateKey(SDLK_F12, false);
  1901. }
  1902. int main(int argc, char **argv)
  1903. {
  1904. fprintf(stderr, "VisualBoyAdvance version %s [SDL]\n", PACKAGE_VERSION);
  1905. arg0 = argv[0];
  1906. captureDir[0] = 0;
  1907. saveDir[0] = 0;
  1908. batteryDir[0] = 0;
  1909. ipsname[0] = 0;
  1910. int op = -1;
  1911. frameSkip = 2;
  1912. gbBorderOn = 0;
  1913. parseDebug = true;
  1914. sdlReadPreferences();
  1915. sdlPrintUsage = 0;
  1916. while((op = getopt_long(argc,
  1917. argv,
  1918. "FNT:Y:G:D:b:c:df:hi:p::s:t:v:1234",
  1919. sdlOptions,
  1920. NULL)) != -1) {
  1921. switch(op) {
  1922. case 0:
  1923. // long option already processed by getopt_long
  1924. break;
  1925. case 'b':
  1926. useBios = true;
  1927. if(optarg == NULL) {
  1928. fprintf(stderr, "Missing BIOS file name\n");
  1929. exit(-1);
  1930. }
  1931. strcpy(biosFileName, optarg);
  1932. break;
  1933. case 'c':
  1934. {
  1935. if(optarg == NULL) {
  1936. fprintf(stderr, "Missing config file name\n");
  1937. exit(-1);
  1938. }
  1939. FILE *f = fopen(optarg, "r");
  1940. if(f == NULL) {
  1941. fprintf(stderr, "File not found %s\n", optarg);
  1942. exit(-1);
  1943. }
  1944. sdlReadPreferences(f);
  1945. fclose(f);
  1946. }
  1947. break;
  1948. case 'd':
  1949. debugger = true;
  1950. break;
  1951. case 'h':
  1952. sdlPrintUsage = 1;
  1953. break;
  1954. case 'i':
  1955. if(optarg == NULL) {
  1956. fprintf(stderr, "Missing IPS name\n");
  1957. exit(-1);
  1958. strcpy(ipsname, optarg);
  1959. }
  1960. break;
  1961. case 'Y':
  1962. yuv = true;
  1963. if(optarg) {
  1964. yuvType = atoi(optarg);
  1965. switch(yuvType) {
  1966. case 0:
  1967. yuvType = SDL_YV12_OVERLAY;
  1968. break;
  1969. case 1:
  1970. yuvType = SDL_UYVY_OVERLAY;
  1971. break;
  1972. case 2:
  1973. yuvType = SDL_YVYU_OVERLAY;
  1974. break;
  1975. case 3:
  1976. yuvType = SDL_YUY2_OVERLAY;
  1977. break;
  1978. case 4:
  1979. yuvType = SDL_IYUV_OVERLAY;
  1980. break;
  1981. default:
  1982. yuvType = SDL_YV12_OVERLAY;
  1983. }
  1984. } else
  1985. yuvType = SDL_YV12_OVERLAY;
  1986. break;
  1987. case 'G':
  1988. dbgMain = remoteStubMain;
  1989. dbgSignal = remoteStubSignal;
  1990. dbgOutput = remoteOutput;
  1991. debugger = true;
  1992. debuggerStub = true;
  1993. if(optarg) {
  1994. char *s = optarg;
  1995. if(strncmp(s,"tcp:", 4) == 0) {
  1996. s+=4;
  1997. int port = atoi(s);
  1998. remoteSetProtocol(0);
  1999. remoteSetPort(port);
  2000. } else if(strcmp(s,"tcp") == 0) {
  2001. remoteSetProtocol(0);
  2002. } else if(strcmp(s, "pipe") == 0) {
  2003. remoteSetProtocol(1);
  2004. } else {
  2005. fprintf(stderr, "Unknown protocol %s\n", s);
  2006. exit(-1);
  2007. }
  2008. } else {
  2009. remoteSetProtocol(0);
  2010. }
  2011. break;
  2012. case 'N':
  2013. parseDebug = false;
  2014. break;
  2015. case 'D':
  2016. if(optarg) {
  2017. systemDebug = atoi(optarg);
  2018. } else {
  2019. systemDebug = 1;
  2020. }
  2021. break;
  2022. case 'F':
  2023. fullscreen = 1;
  2024. mouseCounter = 120;
  2025. break;
  2026. case 'f':
  2027. if(optarg) {
  2028. filter = atoi(optarg);
  2029. } else {
  2030. filter = 0;
  2031. }
  2032. break;
  2033. case 'r':
  2034. if(optarg == NULL) {
  2035. fprintf(stderr, "ERROR: --recordmovie ('r') needs movie filename as option\n");
  2036. exit(-1);
  2037. }
  2038. strcpy(movieFileName, optarg);
  2039. useMovie = 1;
  2040. break;
  2041. case 'p': // play without read-only (editable)
  2042. fprintf (stderr, "-p got called!\n");
  2043. if(optarg == NULL) {
  2044. fprintf(stderr, "ERROR: --playmovie ('p') needs movie filename as option\n");
  2045. exit(-1);
  2046. }
  2047. strcpy(movieFileName, optarg);
  2048. useMovie = 2;
  2049. break;
  2050. case 'w': // play with read-only
  2051. fprintf (stderr, "-w got called!\n");
  2052. if(optarg == NULL) {
  2053. fprintf(stderr, "ERROR: --watchmovie ('w') needs movie filename as option\n");
  2054. exit(-1);
  2055. }
  2056. strcpy(movieFileName, optarg);
  2057. useMovie = 3;
  2058. break;
  2059. case 'P':
  2060. #ifdef PROFILING
  2061. if(optarg) {
  2062. cpuEnableProfiling(atoi(optarg));
  2063. } else
  2064. cpuEnableProfiling(100);
  2065. #endif
  2066. break;
  2067. case 'S':
  2068. sdlFlashSize = atoi(optarg);
  2069. if(sdlFlashSize < 0 || sdlFlashSize > 1)
  2070. sdlFlashSize = 0;
  2071. break;
  2072. case 's':
  2073. if(optarg) {
  2074. int a = atoi(optarg);
  2075. if(a >= 0 && a <= 9) {
  2076. gbFrameSkip = a;
  2077. frameSkip = a;
  2078. }
  2079. } else {
  2080. frameSkip = 2;
  2081. gbFrameSkip = 0;
  2082. }
  2083. break;
  2084. case 't':
  2085. if(optarg) {
  2086. int a = atoi(optarg);
  2087. if(a < 0 || a > 5)
  2088. a = 0;
  2089. cpuSaveType = a;
  2090. }
  2091. break;
  2092. case 'T':
  2093. if(optarg) {
  2094. int t = atoi(optarg);
  2095. throttle = t;
  2096. }
  2097. break;
  2098. case 'v':
  2099. if(optarg) {
  2100. systemVerbose = atoi(optarg);
  2101. } else
  2102. systemVerbose = 0;
  2103. break;
  2104. case '1':
  2105. sizeOption = 0;
  2106. break;
  2107. case '2':
  2108. sizeOption = 1;
  2109. break;
  2110. case '3':
  2111. sizeOption = 2;
  2112. break;
  2113. case '4':
  2114. sizeOption = 3;
  2115. break;
  2116. case '?':
  2117. sdlPrintUsage = 1;
  2118. break;
  2119. }
  2120. }
  2121. //printf("RLM: derpy loves you!\n");
  2122. //printf("RLM: useMovie: %d (1 is record)\n", useMovie);
  2123. if(sdlPrintUsage) {
  2124. usage(argv[0]);
  2125. exit(-1);
  2126. }
  2127. #ifdef MMX
  2128. if(disableMMX)
  2129. cpu_mmx = 0;
  2130. #endif
  2131. if(rewindTimer)
  2132. rewindMemory = (char *)malloc(8*REWIND_SIZE);
  2133. if(sdlFlashSize == 0)
  2134. flashSetSize(0x10000);
  2135. else
  2136. flashSetSize(0x20000);
  2137. rtcEnable(sdlRtcEnable ? true : false);
  2138. agbPrintEnable(sdlAgbPrint ? true : false);
  2139. if(!debuggerStub) {
  2140. if(optind >= argc) {
  2141. systemMessage(0,"Missing image name");
  2142. usage(argv[0]);
  2143. exit(-1);
  2144. }
  2145. }
  2146. if(filter) {
  2147. sizeOption = 1;
  2148. }
  2149. for(int i = 0; i < 24;) {
  2150. systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
  2151. systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
  2152. systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
  2153. systemGbPalette[i++] = 0;
  2154. }
  2155. systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
  2156. if(optind < argc)
  2157. {
  2158. szFile = argv[optind];
  2159. file_run();
  2160. //printf("RLM: file_run() done\n");
  2161. }
  2162. else
  2163. {
  2164. systemCartridgeType = 0;
  2165. strcpy(filename, "gnu_stub");
  2166. rom = (u8 *)malloc(0x2000000);
  2167. workRAM = (u8 *)calloc(1, 0x40000);
  2168. bios = (u8 *)calloc(1,0x4000);
  2169. internalRAM = (u8 *)calloc(1,0x8000);
  2170. paletteRAM = (u8 *)calloc(1,0x400);
  2171. vram = (u8 *)calloc(1, 0x20000);
  2172. oam = (u8 *)calloc(1, 0x400);
  2173. pix = (u8 *)calloc(1, 4 * 240 * 160);
  2174. ioMem = (u8 *)calloc(1, 0x400);
  2175. theEmulator = GBASystem;
  2176. //CPUInit(biosFileName, useBios);
  2177. CPUInit();
  2178. CPUReset();
  2179. }
  2180. if(debuggerStub)
  2181. remoteInit();
  2182. int flags = SDL_INIT_VIDEO|SDL_INIT_AUDIO|
  2183. SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE;
  2184. if(soundOffFlag)
  2185. flags ^= SDL_INIT_AUDIO;
  2186. if(SDL_Init(flags)) {
  2187. systemMessage(0, "Failed to init SDL: %s", SDL_GetError());
  2188. exit(-1);
  2189. }
  2190. if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
  2191. systemMessage(0, "Failed to init joystick support: %s", SDL_GetError());
  2192. }
  2193. sdlCheckKeys();
  2194. if(systemCartridgeType == 0) {
  2195. srcWidth = 240;
  2196. srcHeight = 160;
  2197. systemFrameSkip = frameSkip;
  2198. } else if (systemCartridgeType == 1) {
  2199. if(gbBorderOn) {
  2200. srcWidth = 256;
  2201. srcHeight = 224;
  2202. gbBorderLineSkip = 256;
  2203. gbBorderColumnSkip = 48;
  2204. gbBorderRowSkip = 40;
  2205. } else {
  2206. srcWidth = 160;
  2207. srcHeight = 144;
  2208. gbBorderLineSkip = 160;
  2209. gbBorderColumnSkip = 0;
  2210. gbBorderRowSkip = 0;
  2211. }
  2212. systemFrameSkip = gbFrameSkip;
  2213. } else {
  2214. srcWidth = 320;
  2215. srcHeight = 240;
  2216. }
  2217. destWidth = (sizeOption+1)*srcWidth;
  2218. destHeight = (sizeOption+1)*srcHeight;
  2219. surface = SDL_SetVideoMode(destWidth, destHeight, 16,
  2220. SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|
  2221. (fullscreen ? SDL_FULLSCREEN : 0));
  2222. if(surface == NULL) {
  2223. systemMessage(0, "Failed to set video mode");
  2224. SDL_Quit();
  2225. exit(-1);
  2226. }
  2227. systemRedShift = sdlCalculateShift(surface->format->Rmask);
  2228. systemGreenShift = sdlCalculateShift(surface->format->Gmask);
  2229. systemBlueShift = sdlCalculateShift(surface->format->Bmask);
  2230. systemColorDepth = surface->format->BitsPerPixel;
  2231. if(systemColorDepth == 15)
  2232. systemColorDepth = 16;
  2233. if(yuv) {
  2234. Init_Overlay(surface, yuvType);
  2235. systemColorDepth = 32;
  2236. systemRedShift = 3;
  2237. systemGreenShift = 11;
  2238. systemBlueShift = 19;
  2239. }
  2240. if(systemColorDepth != 16 && systemColorDepth != 24 &&
  2241. systemColorDepth != 32) {
  2242. fprintf(stderr,"Unsupported color depth '%d'.\nOnly 16, 24 and 32 bit color depths are supported\n", systemColorDepth);
  2243. exit(-1);
  2244. }
  2245. #ifndef C_CORE
  2246. sdlMakeStretcher(srcWidth);
  2247. #else
  2248. switch(systemColorDepth) {
  2249. case 16:
  2250. sdlStretcher = sdlStretcher16[sizeOption];
  2251. break;
  2252. case 24:
  2253. sdlStretcher = sdlStretcher24[sizeOption];
  2254. break;
  2255. case 32:
  2256. sdlStretcher = sdlStretcher32[sizeOption];
  2257. break;
  2258. default:
  2259. fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth);
  2260. exit(-1);
  2261. }
  2262. #endif
  2263. fprintf(stderr,"Color depth: %d\n", systemColorDepth);
  2264. if(systemColorDepth == 16) {
  2265. if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) {
  2266. Init_2xSaI(565);
  2267. RGB_LOW_BITS_MASK = 0x821;
  2268. } else {
  2269. Init_2xSaI(555);
  2270. RGB_LOW_BITS_MASK = 0x421;
  2271. }
  2272. if(systemCartridgeType == 2) {
  2273. for(int i = 0; i < 0x10000; i++) {
  2274. systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) |
  2275. (((i & 0x7c0) >> 6) << systemGreenShift) |
  2276. (((i & 0xf800) >> 11) << systemRedShift);
  2277. }
  2278. } else {
  2279. for(int i = 0; i < 0x10000; i++) {
  2280. systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
  2281. (((i & 0x3e0) >> 5) << systemGreenShift) |
  2282. (((i & 0x7c00) >> 10) << systemBlueShift);
  2283. }
  2284. }
  2285. srcPitch = srcWidth * 2+4;
  2286. } else {
  2287. if(systemColorDepth != 32)
  2288. filterFunction = NULL;
  2289. RGB_LOW_BITS_MASK = 0x010101;
  2290. if(systemColorDepth == 32) {
  2291. Init_2xSaI(32);
  2292. }
  2293. for(int i = 0; i < 0x10000; i++) {
  2294. systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
  2295. (((i & 0x3e0) >> 5) << systemGreenShift) |
  2296. (((i & 0x7c00) >> 10) << systemBlueShift);
  2297. }
  2298. if(systemColorDepth == 32)
  2299. srcPitch = srcWidth*4 + 4;
  2300. else
  2301. srcPitch = srcWidth*3;
  2302. }
  2303. if(systemColorDepth != 32) {
  2304. switch(filter) {
  2305. case 0:
  2306. filterFunction = NULL;
  2307. break;
  2308. case 1:
  2309. filterFunction = ScanlinesTV;
  2310. break;
  2311. case 2:
  2312. filterFunction = _2xSaI;
  2313. break;
  2314. case 3:
  2315. filterFunction = Super2xSaI;
  2316. break;
  2317. case 4:
  2318. filterFunction = SuperEagle;
  2319. break;
  2320. case 5:
  2321. filterFunction = Pixelate2x16;
  2322. break;
  2323. case 6:
  2324. filterFunction = MotionBlur;
  2325. break;
  2326. case 7:
  2327. filterFunction = AdMame2x;
  2328. break;
  2329. case 8:
  2330. filterFunction = Simple2x16;
  2331. break;
  2332. case 9:
  2333. filterFunction = Bilinear;
  2334. break;
  2335. case 10:
  2336. filterFunction = BilinearPlus;
  2337. break;
  2338. case 11:
  2339. filterFunction = Scanlines;
  2340. break;
  2341. case 12:
  2342. filterFunction = hq2x;
  2343. break;
  2344. case 13:
  2345. filterFunction = lq2x;
  2346. break;
  2347. default:
  2348. filterFunction = NULL;
  2349. break;
  2350. }
  2351. } else {
  2352. switch(filter) {
  2353. case 0:
  2354. filterFunction = NULL;
  2355. break;
  2356. case 1:
  2357. filterFunction = ScanlinesTV32;
  2358. break;
  2359. case 2:
  2360. filterFunction = _2xSaI32;
  2361. break;
  2362. case 3:
  2363. filterFunction = Super2xSaI32;
  2364. break;
  2365. case 4:
  2366. filterFunction = SuperEagle32;
  2367. break;
  2368. case 5:
  2369. filterFunction = Pixelate2x32;
  2370. break;
  2371. case 6:
  2372. filterFunction = MotionBlur32;
  2373. break;
  2374. case 7:
  2375. filterFunction = AdMame2x32;
  2376. break;
  2377. case 8:
  2378. filterFunction = Simple2x32;
  2379. break;
  2380. case 9:
  2381. filterFunction = Bilinear32;
  2382. break;
  2383. case 10:
  2384. filterFunction = BilinearPlus32;
  2385. break;
  2386. case 11:
  2387. filterFunction = Scanlines32;
  2388. break;
  2389. case 12:
  2390. filterFunction = hq2x32;
  2391. break;
  2392. case 13:
  2393. filterFunction = lq2x32;
  2394. break;
  2395. default:
  2396. filterFunction = NULL;
  2397. break;
  2398. }
  2399. }
  2400. if(systemColorDepth == 16) {
  2401. switch(ifbType) {
  2402. case 0:
  2403. default:
  2404. ifbFunction = NULL;
  2405. break;
  2406. case 1:
  2407. ifbFunction = MotionBlurIB;
  2408. break;
  2409. case 2:
  2410. ifbFunction = SmartIB;
  2411. break;
  2412. }
  2413. } else if(systemColorDepth == 32) {
  2414. switch(ifbType) {
  2415. case 0:
  2416. default:
  2417. ifbFunction = NULL;
  2418. break;
  2419. case 1:
  2420. ifbFunction = MotionBlurIB32;
  2421. break;
  2422. case 2:
  2423. ifbFunction = SmartIB32;
  2424. break;
  2425. }
  2426. } else
  2427. ifbFunction = NULL;
  2428. if(delta == NULL) {
  2429. delta = (u8*)malloc(322*242*4);
  2430. memset(delta, 255, 322*242*4);
  2431. }
  2432. if(!soundOffFlag)
  2433. soundInit();
  2434. // kanzure: trying to fix throttling
  2435. //autoFrameSkipLastTime = throttleLastTime = systemGetClock();
  2436. //printf("RLM: and now for the movie part!\n");
  2437. switch(useMovie)
  2438. {
  2439. case 1: // --recordMovie
  2440. VBAMovieCreate(movieFileName,
  2441. /*authorInfo*/"",
  2442. /*startFlags*/0,
  2443. /*controllerFlags*/MOVIE_CONTROLLER(0),
  2444. /*typeFlags*/(systemCartridgeType==IMAGE_GBA)?(MOVIE_TYPE_GBA):(GBC_CAPABLE?MOVIE_TYPE_GBC:MOVIE_TYPE_SGB));
  2445. break;
  2446. case 2: // --playMovie
  2447. VBAMovieOpen(movieFileName, false);
  2448. break;
  2449. case 3: // --watchMovie
  2450. VBAMovieOpen(movieFileName, true);
  2451. break;
  2452. default:
  2453. sdlReadBattery();
  2454. break;
  2455. }
  2456. //printf("RLM: still alive after movie switch\n");
  2457. SDL_WM_SetCaption("VisualBoyAdvance", NULL);
  2458. char *moviefile = getenv("AUTODEMO");
  2459. fprintf (stderr, "Checking for AUTODEMO...\n");
  2460. if (moviefile)
  2461. {
  2462. fprintf (stderr, "I got a filename OMG!\nCalling VBAMovieOpen...\n");
  2463. VBAMovieOpen(moviefile, true);
  2464. }
  2465. //step();
  2466. return 0;
  2467. }
  2468. // RLM
  2469. int runVBA(int argc, char **argv){
  2470. return main(argc, argv);
  2471. }
  2472. void systemMessage(int num, const char *msg, ...)
  2473. {
  2474. char buffer[2048];
  2475. va_list valist;
  2476. va_start(valist, msg);
  2477. vsprintf(buffer, msg, valist);
  2478. fprintf(stderr, "%s\n", buffer);
  2479. va_end(valist);
  2480. }
  2481. //On WIN32, this function messages requesting
  2482. //the window to be redrawn. Can this be ignored here?
  2483. void systemRefreshScreen(){}
  2484. void systemRenderFrame()
  2485. {
  2486. renderedFrames++;
  2487. VBAUpdateFrameCountDisplay();
  2488. VBAUpdateButtonPressDisplay();
  2489. if(yuv) {
  2490. Draw_Overlay(surface, sizeOption+1);
  2491. return;
  2492. }
  2493. SDL_LockSurface(surface);
  2494. for(int slot = 0 ; slot < 8 ; slot++)
  2495. {
  2496. if(screenMessage[slot]) {
  2497. if(systemCartridgeType == 1 && gbBorderOn) {
  2498. gbSgbRenderBorder();
  2499. }
  2500. if(((systemGetClock() - screenMessageTime[slot]) < screenMessageDuration[slot]) &&
  2501. !disableStatusMessages) {
  2502. drawText(pix, srcPitch, 10, srcHeight - 20*(slot+1),
  2503. screenMessageBuffer[slot]);
  2504. } else {
  2505. screenMessage[slot] = false;
  2506. }
  2507. }
  2508. }
  2509. if(ifbFunction) {
  2510. if(systemColorDepth == 16)
  2511. ifbFunction(pix+destWidth+4, destWidth+4, srcWidth, srcHeight);
  2512. else
  2513. ifbFunction(pix+destWidth*2+4, destWidth*2+4, srcWidth, srcHeight);
  2514. }
  2515. if(filterFunction) {
  2516. if(systemColorDepth == 16)
  2517. filterFunction(pix+destWidth+4,destWidth+4, delta,
  2518. (u8*)surface->pixels,surface->pitch,
  2519. srcWidth,
  2520. srcHeight);
  2521. else
  2522. filterFunction(pix+destWidth*2+4,
  2523. destWidth*2+4,
  2524. delta,
  2525. (u8*)surface->pixels,
  2526. surface->pitch,
  2527. srcWidth,
  2528. srcHeight);
  2529. } else {
  2530. int destPitch = surface->pitch;
  2531. u8 *src = pix;
  2532. u8 *dest = (u8*)surface->pixels;
  2533. int i;
  2534. u32 *stretcher = (u32 *)sdlStretcher;
  2535. if(systemColorDepth == 16)
  2536. src += srcPitch;
  2537. int option = sizeOption;
  2538. if(yuv)
  2539. option = 0;
  2540. switch(sizeOption) {
  2541. case 0:
  2542. for(i = 0; i < srcHeight; i++) {
  2543. SDL_CALL_STRETCHER;
  2544. src += srcPitch;
  2545. dest += destPitch;
  2546. }
  2547. break;
  2548. case 1:
  2549. for(i = 0; i < srcHeight; i++) {
  2550. SDL_CALL_STRETCHER;
  2551. dest += destPitch;
  2552. SDL_CALL_STRETCHER;
  2553. src += srcPitch;
  2554. dest += destPitch;
  2555. }
  2556. break;
  2557. case 2:
  2558. for(i = 0; i < srcHeight; i++) {
  2559. SDL_CALL_STRETCHER;
  2560. dest += destPitch;
  2561. SDL_CALL_STRETCHER;
  2562. dest += destPitch;
  2563. SDL_CALL_STRETCHER;
  2564. src += srcPitch;
  2565. dest += destPitch;
  2566. }
  2567. break;
  2568. case 3:
  2569. for(i = 0; i < srcHeight; i++) {
  2570. SDL_CALL_STRETCHER;
  2571. dest += destPitch;
  2572. SDL_CALL_STRETCHER;
  2573. dest += destPitch;
  2574. SDL_CALL_STRETCHER;
  2575. dest += destPitch;
  2576. SDL_CALL_STRETCHER;
  2577. src += srcPitch;
  2578. dest += destPitch;
  2579. }
  2580. break;
  2581. }
  2582. }
  2583. if(showSpeed && fullscreen) {
  2584. char buffer[50];
  2585. if(showSpeed == 1)
  2586. sprintf(buffer, "%d%%", systemSpeed);
  2587. else
  2588. sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
  2589. systemFrameSkip,
  2590. showRenderedFrames);
  2591. if(showSpeedTransparent)
  2592. drawTextTransp((u8*)surface->pixels,
  2593. surface->pitch,
  2594. 10,
  2595. surface->h-20,
  2596. buffer);
  2597. else
  2598. drawText((u8*)surface->pixels,
  2599. surface->pitch,
  2600. 10,
  2601. surface->h-20,
  2602. buffer);
  2603. }
  2604. SDL_UnlockSurface(surface);
  2605. // SDL_UpdateRect(surface, 0, 0, destWidth, destHeight);
  2606. SDL_Flip(surface);
  2607. }
  2608. bool systemReadJoypads()
  2609. {
  2610. return true;
  2611. }
  2612. // Kludge to make Lua call the right function.
  2613. u32 systemGetOriginalJoypad(int which, bool sensor){
  2614. return systemGetJoypad(which,sensor);
  2615. }
  2616. u32 systemGetJoypad(int which, bool sensor)
  2617. {
  2618. sensorOn = sensor;
  2619. if(which < 0 || which > 3)
  2620. which = sdlDefaultJoypad;
  2621. //VBAMovieUpdate(which);
  2622. //VBAMovieUpdateState();
  2623. u32 res = 0;
  2624. //----------------------------//
  2625. if (VBAMoviePlaying()){
  2626. // VBAMovieRead() overwrites currentButtons[i]
  2627. VBAMovieRead(which, sensor);
  2628. res = currentButtons[which];
  2629. return res;
  2630. }
  2631. //---------------------------//
  2632. //Temporary implementation, not sure if it's correct --Felipe
  2633. /*
  2634. if(sdlButtons[which][KEY_BUTTON_A])
  2635. res |= BUTTON_MASK_A;
  2636. if(sdlButtons[which][KEY_BUTTON_B])
  2637. res |= BUTTON_MASK_B;
  2638. if(sdlButtons[which][KEY_BUTTON_SELECT])
  2639. res |= BUTTON_MASK_SELECT;
  2640. if(sdlButtons[which][KEY_BUTTON_START])
  2641. res |= BUTTON_MASK_START;
  2642. if(sdlButtons[which][KEY_RIGHT])
  2643. res |= BUTTON_MASK_RIGHT;
  2644. if(sdlButtons[which][KEY_LEFT])
  2645. res |= BUTTON_MASK_LEFT;
  2646. if(sdlButtons[which][KEY_UP])
  2647. res |= BUTTON_MASK_UP;
  2648. if(sdlButtons[which][KEY_DOWN])
  2649. res |= BUTTON_MASK_DOWN;
  2650. if(sdlButtons[which][KEY_BUTTON_R])
  2651. res |= BUTTON_MASK_R;
  2652. if(sdlButtons[which][KEY_BUTTON_L])
  2653. res |= BUTTON_MASK_L;
  2654. */
  2655. /*
  2656. // disallow L+R or U+D of being pressed at the same time
  2657. if((res & 48) == 48)
  2658. res &= ~16;
  2659. if((res & 192) == 192)
  2660. res &= ~128;
  2661. */
  2662. /* if(sdlbuttons[which][KEY_BUTTON_SPEED])
  2663. res |= 1024;
  2664. if(sdlButtons[which][KEY_BUTTON_CAPTURE])
  2665. res |= 2048;
  2666. */
  2667. res = currentButtons[which];
  2668. if(autoFire) {
  2669. res &= (~autoFire);
  2670. if(autoFireToggle)
  2671. res |= autoFire;
  2672. autoFireToggle = !autoFireToggle;
  2673. }
  2674. //if (res) fprintf(stdout,"%x\n",res);
  2675. return res;
  2676. }
  2677. void systemSetJoypad(int which, u32 buttons)
  2678. {
  2679. if(which < 0 || which > 3)
  2680. which = sdlDefaultJoypad;
  2681. /*
  2682. sdlButtons[which][KEY_BUTTON_A] = (buttons & 1) != 0;
  2683. sdlButtons[which][KEY_BUTTON_B] = (buttons & 2) != 0;
  2684. sdlButtons[which][KEY_BUTTON_SELECT] = (buttons & 4) != 0;
  2685. sdlButtons[which][KEY_BUTTON_START] = (buttons & 8) != 0;
  2686. sdlButtons[which][KEY_RIGHT] = (buttons & 16) != 0;
  2687. sdlButtons[which][KEY_LEFT] = (buttons & 32) != 0;
  2688. sdlButtons[which][KEY_UP] = (buttons & 64) != 0;
  2689. sdlButtons[which][KEY_DOWN] = (buttons & 128) != 0;
  2690. sdlButtons[which][KEY_BUTTON_R] = (buttons & 256) != 0;
  2691. sdlButtons[which][KEY_BUTTON_L] = (buttons & 512) != 0;
  2692. */
  2693. currentButtons[which]= buttons & 0x3ff;
  2694. }
  2695. void systemClearJoypads()
  2696. {
  2697. for (int i = 0; i < 4; ++i)
  2698. currentButtons[i] = 0;
  2699. //lastKeys = 0;
  2700. }
  2701. void systemSetTitle(const char *title)
  2702. {
  2703. SDL_WM_SetCaption(title, NULL);
  2704. }
  2705. void systemShowSpeed(int speed)
  2706. {
  2707. systemSpeed = speed;
  2708. showRenderedFrames = renderedFrames;
  2709. renderedFrames = 0;
  2710. if(!fullscreen && showSpeed) {
  2711. char buffer[80];
  2712. if(showSpeed == 1)
  2713. sprintf(buffer, "VisualBoyAdvance-%3d%%", systemSpeed);
  2714. else
  2715. sprintf(buffer, "VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed,
  2716. systemFrameSkip,
  2717. showRenderedFrames);
  2718. systemSetTitle(buffer);
  2719. }
  2720. }
  2721. // FIXME: the timing
  2722. void systemFrame(/*int rate*/) //Looking at System.cpp, it looks like rate should be 600
  2723. {
  2724. u32 time = systemGetClock();
  2725. if(!wasPaused && autoFrameSkip && !throttle) {
  2726. u32 diff = time - autoFrameSkipLastTime;
  2727. int speed = 100;
  2728. if(diff)
  2729. speed = (1000000/600)/diff;
  2730. if(speed >= 98) {
  2731. frameskipadjust++;
  2732. if(frameskipadjust >= 3) {
  2733. frameskipadjust=0;
  2734. if(systemFrameSkip > 0)
  2735. systemFrameSkip--;
  2736. }
  2737. } else {
  2738. if(speed < 80)
  2739. frameskipadjust -= (90 - speed)/5;
  2740. else if(systemFrameSkip < 9)
  2741. frameskipadjust--;
  2742. if(frameskipadjust <= -2) {
  2743. frameskipadjust += 2;
  2744. if(systemFrameSkip < 9)
  2745. systemFrameSkip++;
  2746. }
  2747. }
  2748. }
  2749. if(!wasPaused && throttle) {
  2750. /*if(!speedup) {
  2751. u32 diff = time - throttleLastTime;
  2752. int target = (1000000.0/(600*throttle));
  2753. int d = (target - diff);
  2754. if(d > 0) {
  2755. SDL_Delay(d);
  2756. }
  2757. }
  2758. throttleLastTime = systemGetClock();
  2759. */
  2760. }
  2761. if(rewindMemory) {
  2762. if(++rewindCounter >= rewindTimer) {
  2763. rewindSaveNeeded = true;
  2764. rewindCounter = 0;
  2765. }
  2766. }
  2767. if(systemSaveUpdateCounter) {
  2768. if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
  2769. sdlWriteBattery();
  2770. systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
  2771. }
  2772. }
  2773. wasPaused = false;
  2774. autoFrameSkipLastTime = time;
  2775. }
  2776. int systemFramesToSkip(){
  2777. return systemFrameSkip;
  2778. }
  2779. int systemScreenCapture(int a)
  2780. {
  2781. char buffer[2048];
  2782. if(captureFormat) {
  2783. if(captureDir[0])
  2784. sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a);
  2785. else
  2786. sprintf(buffer, "%s%02d.bmp", filename, a);
  2787. theEmulator.emuWriteBMP(buffer);
  2788. } else {
  2789. if(captureDir[0])
  2790. sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a);
  2791. else
  2792. sprintf(buffer, "%s%02d.png", filename, a);
  2793. theEmulator.emuWritePNG(buffer);
  2794. }
  2795. systemScreenMessage("Screen capture");
  2796. return a;
  2797. }
  2798. void soundCallback(void *,u8 *stream,int len){}
  2799. int writeCounter = 0;
  2800. u8 soundCopyBuffer[1470 * 2];
  2801. void systemSoundWriteToBuffer(){
  2802. //printf("sound write counter (len) : %07d (%d)\n",
  2803. //writeCounter++, soundBufferLen);
  2804. //int i;
  2805. //u8* soundBytes = (u8*) soundFinalWave;
  2806. //for (i = 0; i < 1470 * 2; i++){
  2807. // soundCopyBuffer[i] = soundBytes[i];
  2808. //}
  2809. soundDriver->write(soundFinalWave, soundBufferLen);
  2810. }
  2811. void systemSoundClearBuffer()
  2812. {
  2813. SDL_mutexP(mutex);
  2814. memset(sdlBuffer,0,soundBufferTotalLen);
  2815. sdlSoundLen=0;
  2816. printf("Hi\n");
  2817. SDL_mutexV(mutex);
  2818. }
  2819. bool systemSoundInit(){
  2820. systemSoundShutdown();
  2821. soundDriver = new SoundSDL();
  2822. if ( !soundDriver )
  2823. return false;
  2824. if (!soundDriver->init()) //<-- sound sample rate
  2825. return false;
  2826. if (!(soundDriver->setThrottle(throttle))){
  2827. fprintf(stderr,"Failed to set desired throttle, defaulting to 100 %%.\n");
  2828. if (!soundDriver->setThrottle(100)) return false;
  2829. }
  2830. soundPaused = true;
  2831. systemSoundOn = true;
  2832. return true;
  2833. }
  2834. void systemSoundShutdown(){
  2835. if (soundDriver)
  2836. {
  2837. delete soundDriver;
  2838. soundDriver = 0;
  2839. }
  2840. }
  2841. void systemSoundPause()
  2842. {
  2843. SDL_PauseAudio(1);
  2844. }
  2845. void systemSoundResume()
  2846. {
  2847. SDL_PauseAudio(0);
  2848. }
  2849. void systemSoundReset()
  2850. {
  2851. }
  2852. u32 systemGetClock()
  2853. {
  2854. return SDL_GetTicks();
  2855. }
  2856. void systemUpdateMotionSensor()
  2857. {
  2858. if(sdlMotionButtons[KEY_LEFT]) {
  2859. sensorX += 3;
  2860. if(sensorX > 2197)
  2861. sensorX = 2197;
  2862. if(sensorX < 2047)
  2863. sensorX = 2057;
  2864. } else if(sdlMotionButtons[KEY_RIGHT]) {
  2865. sensorX -= 3;
  2866. if(sensorX < 1897)
  2867. sensorX = 1897;
  2868. if(sensorX > 2047)
  2869. sensorX = 2037;
  2870. } else if(sensorX > 2047) {
  2871. sensorX -= 2;
  2872. if(sensorX < 2047)
  2873. sensorX = 2047;
  2874. } else {
  2875. sensorX += 2;
  2876. if(sensorX > 2047)
  2877. sensorX = 2047;
  2878. }
  2879. if(sdlMotionButtons[KEY_UP]) {
  2880. sensorY += 3;
  2881. if(sensorY > 2197)
  2882. sensorY = 2197;
  2883. if(sensorY < 2047)
  2884. sensorY = 2057;
  2885. } else if(sdlMotionButtons[KEY_DOWN]) {
  2886. sensorY -= 3;
  2887. if(sensorY < 1897)
  2888. sensorY = 1897;
  2889. if(sensorY > 2047)
  2890. sensorY = 2037;
  2891. } else if(sensorY > 2047) {
  2892. sensorY -= 2;
  2893. if(sensorY < 2047)
  2894. sensorY = 2047;
  2895. } else {
  2896. sensorY += 2;
  2897. if(sensorY > 2047)
  2898. sensorY = 2047;
  2899. }
  2900. }
  2901. void systemResetSensor()
  2902. {
  2903. sensorX = sensorY = INITIAL_SENSOR_VALUE;
  2904. }
  2905. int systemGetSensorX()
  2906. {
  2907. return sensorX;
  2908. }
  2909. int systemGetSensorY()
  2910. {
  2911. return sensorY;
  2912. }
  2913. void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
  2914. {
  2915. }
  2916. void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList)
  2917. {
  2918. screenMessage[slot] = true;
  2919. screenMessageTime[slot] = systemGetClock();
  2920. screenMessageDuration[slot] = duration;
  2921. if(strlen(msg) > 20) {
  2922. strncpy(screenMessageBuffer[slot], msg, 20);
  2923. screenMessageBuffer[slot][20] = 0;
  2924. } else
  2925. strcpy(screenMessageBuffer[slot], msg);
  2926. }
  2927. bool systemSoundCanChangeQuality()
  2928. {
  2929. return false;
  2930. }
  2931. bool systemSoundSetQuality(int quality)
  2932. {
  2933. if (systemCartridgeType == 0)
  2934. soundSetQuality(quality);
  2935. else
  2936. gbSoundSetQuality(quality);
  2937. return true;
  2938. }
  2939. bool systemPauseOnFrame()
  2940. {
  2941. if(pauseNextFrame) {
  2942. paused = true;
  2943. pauseNextFrame = false;
  2944. return true;
  2945. }
  2946. return false;
  2947. }
  2948. // Code donated by Niels Wagenaar (BoycottAdvance)
  2949. // GBA screensize.
  2950. #define GBA_WIDTH 240
  2951. #define GBA_HEIGHT 160
  2952. void Init_Overlay(SDL_Surface *gbascreen, int overlaytype)
  2953. {
  2954. overlay = SDL_CreateYUVOverlay( GBA_WIDTH,
  2955. GBA_HEIGHT,
  2956. overlaytype, gbascreen);
  2957. fprintf(stderr, "Created %dx%dx%d %s %s overlay\n",
  2958. overlay->w,overlay->h,overlay->planes,
  2959. overlay->hw_overlay?"hardware":"software",
  2960. overlay->format==SDL_YV12_OVERLAY?"YV12":
  2961. overlay->format==SDL_IYUV_OVERLAY?"IYUV":
  2962. overlay->format==SDL_YUY2_OVERLAY?"YUY2":
  2963. overlay->format==SDL_UYVY_OVERLAY?"UYVY":
  2964. overlay->format==SDL_YVYU_OVERLAY?"YVYU":
  2965. "Unknown");
  2966. }
  2967. void Quit_Overlay(void)
  2968. {
  2969. SDL_FreeYUVOverlay(overlay);
  2970. }
  2971. /* NOTE: These RGB conversion functions are not intended for speed,
  2972. only as examples.
  2973. */
  2974. inline void RGBtoYUV(Uint8 *rgb, int *yuv)
  2975. {
  2976. yuv[0] = (int)((0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16);
  2977. yuv[1] = (int)(128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]));
  2978. yuv[2] = (int)(128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]));
  2979. }
  2980. inline void ConvertRGBtoYV12(SDL_Overlay *o)
  2981. {
  2982. int x,y;
  2983. int yuv[3];
  2984. Uint8 *p,*op[3];
  2985. SDL_LockYUVOverlay(o);
  2986. /* Black initialization */
  2987. /*
  2988. memset(o->pixels[0],0,o->pitches[0]*o->h);
  2989. memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
  2990. memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
  2991. */
  2992. /* Convert */
  2993. for(y=0; y<160 && y<o->h; y++) {
  2994. p=(Uint8 *)pix+srcPitch*y;
  2995. op[0]=o->pixels[0]+o->pitches[0]*y;
  2996. op[1]=o->pixels[1]+o->pitches[1]*(y/2);
  2997. op[2]=o->pixels[2]+o->pitches[2]*(y/2);
  2998. for(x=0; x<240 && x<o->w; x++) {
  2999. RGBtoYUV(p,yuv);
  3000. *(op[0]++)=yuv[0];
  3001. if(x%2==0 && y%2==0) {
  3002. *(op[1]++)=yuv[2];
  3003. *(op[2]++)=yuv[1];
  3004. }
  3005. p+=4;//s->format->BytesPerPixel;
  3006. }
  3007. }
  3008. SDL_UnlockYUVOverlay(o);
  3009. }
  3010. inline void ConvertRGBtoIYUV(SDL_Overlay *o)
  3011. {
  3012. int x,y;
  3013. int yuv[3];
  3014. Uint8 *p,*op[3];
  3015. SDL_LockYUVOverlay(o);
  3016. /* Black initialization */
  3017. /*
  3018. memset(o->pixels[0],0,o->pitches[0]*o->h);
  3019. memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
  3020. memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
  3021. */
  3022. /* Convert */
  3023. for(y=0; y<160 && y<o->h; y++) {
  3024. p=(Uint8 *)pix+srcPitch*y;
  3025. op[0]=o->pixels[0]+o->pitches[0]*y;
  3026. op[1]=o->pixels[1]+o->pitches[1]*(y/2);
  3027. op[2]=o->pixels[2]+o->pitches[2]*(y/2);
  3028. for(x=0; x<240 && x<o->w; x++) {
  3029. RGBtoYUV(p,yuv);
  3030. *(op[0]++)=yuv[0];
  3031. if(x%2==0 && y%2==0) {
  3032. *(op[1]++)=yuv[1];
  3033. *(op[2]++)=yuv[2];
  3034. }
  3035. p+=4; //s->format->BytesPerPixel;
  3036. }
  3037. }
  3038. SDL_UnlockYUVOverlay(o);
  3039. }
  3040. inline void ConvertRGBtoUYVY(SDL_Overlay *o)
  3041. {
  3042. int x,y;
  3043. int yuv[3];
  3044. Uint8 *p,*op;
  3045. SDL_LockYUVOverlay(o);
  3046. for(y=0; y<160 && y<o->h; y++) {
  3047. p=(Uint8 *)pix+srcPitch*y;
  3048. op=o->pixels[0]+o->pitches[0]*y;
  3049. for(x=0; x<240 && x<o->w; x++) {
  3050. RGBtoYUV(p,yuv);
  3051. if(x%2==0) {
  3052. *(op++)=yuv[1];
  3053. *(op++)=yuv[0];
  3054. *(op++)=yuv[2];
  3055. } else
  3056. *(op++)=yuv[0];
  3057. p+=4; //s->format->BytesPerPixel;
  3058. }
  3059. }
  3060. SDL_UnlockYUVOverlay(o);
  3061. }
  3062. inline void ConvertRGBtoYVYU(SDL_Overlay *o)
  3063. {
  3064. int x,y;
  3065. int yuv[3];
  3066. Uint8 *p,*op;
  3067. SDL_LockYUVOverlay(o);
  3068. for(y=0; y<160 && y<o->h; y++) {
  3069. p=(Uint8 *)pix+srcPitch*y;
  3070. op=o->pixels[0]+o->pitches[0]*y;
  3071. for(x=0; x<240 && x<o->w; x++) {
  3072. RGBtoYUV(p,yuv);
  3073. if(x%2==0) {
  3074. *(op++)=yuv[0];
  3075. *(op++)=yuv[2];
  3076. op[1]=yuv[1];
  3077. } else {
  3078. *op=yuv[0];
  3079. op+=2;
  3080. }
  3081. p+=4; //s->format->BytesPerPixel;
  3082. }
  3083. }
  3084. SDL_UnlockYUVOverlay(o);
  3085. }
  3086. inline void ConvertRGBtoYUY2(SDL_Overlay *o)
  3087. {
  3088. int x,y;
  3089. int yuv[3];
  3090. Uint8 *p,*op;
  3091. SDL_LockYUVOverlay(o);
  3092. for(y=0; y<160 && y<o->h; y++) {
  3093. p=(Uint8 *)pix+srcPitch*y;
  3094. op=o->pixels[0]+o->pitches[0]*y;
  3095. for(x=0; x<240 && x<o->w; x++) {
  3096. RGBtoYUV(p,yuv);
  3097. if(x%2==0) {
  3098. *(op++)=yuv[0];
  3099. *(op++)=yuv[1];
  3100. op[1]=yuv[2];
  3101. } else {
  3102. *op=yuv[0];
  3103. op+=2;
  3104. }
  3105. p+=4; //s->format->BytesPerPixel;
  3106. }
  3107. }
  3108. SDL_UnlockYUVOverlay(o);
  3109. }
  3110. inline void Convert32bit(SDL_Surface *display)
  3111. {
  3112. switch(overlay->format) {
  3113. case SDL_YV12_OVERLAY:
  3114. ConvertRGBtoYV12(overlay);
  3115. break;
  3116. case SDL_UYVY_OVERLAY:
  3117. ConvertRGBtoUYVY(overlay);
  3118. break;
  3119. case SDL_YVYU_OVERLAY:
  3120. ConvertRGBtoYVYU(overlay);
  3121. break;
  3122. case SDL_YUY2_OVERLAY:
  3123. ConvertRGBtoYUY2(overlay);
  3124. break;
  3125. case SDL_IYUV_OVERLAY:
  3126. ConvertRGBtoIYUV(overlay);
  3127. break;
  3128. default:
  3129. fprintf(stderr, "cannot convert RGB picture to obtained YUV format!\n");
  3130. exit(1);
  3131. break;
  3132. }
  3133. }
  3134. inline void Draw_Overlay(SDL_Surface *display, int size)
  3135. {
  3136. SDL_LockYUVOverlay(overlay);
  3137. Convert32bit(display);
  3138. overlay_rect.x = 0;
  3139. overlay_rect.y = 0;
  3140. overlay_rect.w = GBA_WIDTH * size;
  3141. overlay_rect.h = GBA_HEIGHT * size;
  3142. SDL_DisplayYUVOverlay(overlay, &overlay_rect);
  3143. SDL_UnlockYUVOverlay(overlay);
  3144. }
  3145. bool systemIsEmulating()
  3146. {
  3147. return emulating != 0;
  3148. }
  3149. void systemGbBorderOn()
  3150. {
  3151. srcWidth = 256;
  3152. srcHeight = 224;
  3153. gbBorderLineSkip = 256;
  3154. gbBorderColumnSkip = 48;
  3155. gbBorderRowSkip = 40;
  3156. destWidth = (sizeOption+1)*srcWidth;
  3157. destHeight = (sizeOption+1)*srcHeight;
  3158. surface = SDL_SetVideoMode(destWidth, destHeight, 16,
  3159. SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|
  3160. (fullscreen ? SDL_FULLSCREEN : 0));
  3161. #ifndef C_CORE
  3162. sdlMakeStretcher(srcWidth);
  3163. #else
  3164. switch(systemColorDepth) {
  3165. case 16:
  3166. sdlStretcher = sdlStretcher16[sizeOption];
  3167. break;
  3168. case 24:
  3169. sdlStretcher = sdlStretcher24[sizeOption];
  3170. break;
  3171. case 32:
  3172. sdlStretcher = sdlStretcher32[sizeOption];
  3173. break;
  3174. default:
  3175. fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth);
  3176. exit(-1);
  3177. }
  3178. #endif
  3179. if(systemColorDepth == 16) {
  3180. if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) {
  3181. Init_2xSaI(565);
  3182. RGB_LOW_BITS_MASK = 0x821;
  3183. } else {
  3184. Init_2xSaI(555);
  3185. RGB_LOW_BITS_MASK = 0x421;
  3186. }
  3187. if(systemCartridgeType == 2) {
  3188. for(int i = 0; i < 0x10000; i++) {
  3189. systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) |
  3190. (((i & 0x7c0) >> 6) << systemGreenShift) |
  3191. (((i & 0xf800) >> 11) << systemRedShift);
  3192. }
  3193. } else {
  3194. for(int i = 0; i < 0x10000; i++) {
  3195. systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
  3196. (((i & 0x3e0) >> 5) << systemGreenShift) |
  3197. (((i & 0x7c00) >> 10) << systemBlueShift);
  3198. }
  3199. }
  3200. srcPitch = srcWidth * 2+4;
  3201. } else {
  3202. if(systemColorDepth != 32)
  3203. filterFunction = NULL;
  3204. RGB_LOW_BITS_MASK = 0x010101;
  3205. if(systemColorDepth == 32) {
  3206. Init_2xSaI(32);
  3207. }
  3208. for(int i = 0; i < 0x10000; i++) {
  3209. systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
  3210. (((i & 0x3e0) >> 5) << systemGreenShift) |
  3211. (((i & 0x7c00) >> 10) << systemBlueShift);
  3212. }
  3213. if(systemColorDepth == 32)
  3214. srcPitch = srcWidth*4 + 4;
  3215. else
  3216. srcPitch = srcWidth*3;
  3217. }
  3218. }
  3219. bool systemIsRunningGBA()
  3220. {
  3221. return (rom != NULL);
  3222. }
  3223. int systemGetDefaultJoypad()
  3224. {
  3225. return sdlDefaultJoypad;
  3226. }
  3227. bool systemIsPaused()
  3228. {
  3229. return paused;
  3230. }
  3231. void systemSetPause(bool pause)
  3232. {
  3233. paused = pause;
  3234. if (pause)
  3235. systemSoundPause();
  3236. else
  3237. systemSoundResume();
  3238. }
  3239. u16 checksumBIOS()
  3240. {
  3241. bool hasBIOS = false;
  3242. u8 * tempBIOS;
  3243. if(useBios)
  3244. {
  3245. tempBIOS = (u8 *)malloc(0x4000);
  3246. int size = 0x4000;
  3247. if(utilLoad(biosFileName,
  3248. utilIsGBABios,
  3249. tempBIOS,
  3250. size)) {
  3251. if(size == 0x4000)
  3252. hasBIOS = true;
  3253. }
  3254. }
  3255. u16 biosCheck = 0;
  3256. if(hasBIOS) {
  3257. for(int i = 0; i < 0x4000; i += 4)
  3258. biosCheck += *((u32 *)&tempBIOS[i]);
  3259. free(tempBIOS);
  3260. }
  3261. return biosCheck;
  3262. }
  3263. EmulatedSystemCounters systemCounters = {
  3264. 0, //framecount
  3265. 0, //lagcount
  3266. 0, //extracount
  3267. true, //lagged
  3268. true //laggedLast
  3269. };
  3270. void VBAOnEnteringFrameBoundary()
  3271. {
  3272. //printf("RLM: Entering Frame Boundary\n");
  3273. CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION);
  3274. if (VBALuaRunning())
  3275. {
  3276. VBALuaFrameBoundary();
  3277. }
  3278. //printf("RLM: Movie state update pending\n");
  3279. VBAMovieUpdateState();
  3280. //printf("RLM: Movie state updated\n");
  3281. }
  3282. void VBAOnExitingFrameBoundary()
  3283. {
  3284. ;
  3285. }