annotate src/sdl/SDL.cpp @ 65:60c768964937

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