annotate src/sdl/SDL.cpp @ 165:8f1b32d3f229

need to determine how colormaps for pokemon work.
author Robert McIntyre <rlm@mit.edu>
date Tue, 20 Mar 2012 18:07:42 -0500
parents 1ff2c546f5ad
children 95b2758dd517
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@92 2065 int tick () {
rlm@92 2066 return theEmulator.emuMain(theEmulator.emuCount);
rlm@92 2067 }
rlm@53 2068
rlm@53 2069 void step () {
rlm@53 2070 if(!paused && active) {
rlm@92 2071 //printf("RLM: emulator main\n");
rlm@92 2072 int frameComplete = 0;
rlm@92 2073 while (!(frameComplete)){
rlm@92 2074 frameComplete = theEmulator.emuMain(theEmulator.emuCount);
rlm@53 2075 }
rlm@92 2076 //printf("RLM: emulator main called\n");
rlm@53 2077 } else {
rlm@53 2078 SDL_Delay(500);
rlm@53 2079 }
rlm@53 2080 sdlPollEvents();
rlm@55 2081 SDL_ShowCursor(SDL_DISABLE);
rlm@53 2082 }
rlm@53 2083
rlm@55 2084 void step(int keymask){
rlm@55 2085 currentButtons[0] = keymask;
rlm@66 2086 if (keymask == 0x0800){
rlm@66 2087 theEmulator.emuReset(true);
rlm@66 2088 }
rlm@66 2089 else {
rlm@66 2090 step();
rlm@66 2091 }
rlm@55 2092 currentButtons[0] = keymask;
rlm@55 2093 }
rlm@55 2094
rlm@55 2095
rlm@55 2096
rlm@1 2097 int main(int argc, char **argv)
rlm@1 2098 {
rlm@30 2099 fprintf(stderr, "VisualBoyAdvance version %s [SDL]\n", PACKAGE_VERSION);
rlm@1 2100
rlm@1 2101 arg0 = argv[0];
rlm@1 2102
rlm@1 2103 captureDir[0] = 0;
rlm@1 2104 saveDir[0] = 0;
rlm@1 2105 batteryDir[0] = 0;
rlm@1 2106 ipsname[0] = 0;
rlm@1 2107
rlm@1 2108 int op = -1;
rlm@1 2109
rlm@1 2110 frameSkip = 2;
rlm@1 2111 gbBorderOn = 0;
rlm@1 2112
rlm@1 2113 parseDebug = true;
rlm@1 2114
rlm@1 2115 sdlReadPreferences();
rlm@1 2116
rlm@1 2117 sdlPrintUsage = 0;
rlm@1 2118
rlm@1 2119 while((op = getopt_long(argc,
rlm@1 2120 argv,
rlm@1 2121 "FNT:Y:G:D:b:c:df:hi:p::s:t:v:1234",
rlm@1 2122 sdlOptions,
rlm@1 2123 NULL)) != -1) {
rlm@1 2124 switch(op) {
rlm@1 2125 case 0:
rlm@1 2126 // long option already processed by getopt_long
rlm@1 2127 break;
rlm@1 2128 case 'b':
rlm@1 2129 useBios = true;
rlm@1 2130 if(optarg == NULL) {
rlm@1 2131 fprintf(stderr, "Missing BIOS file name\n");
rlm@1 2132 exit(-1);
rlm@1 2133 }
rlm@1 2134 strcpy(biosFileName, optarg);
rlm@1 2135 break;
rlm@1 2136 case 'c':
rlm@1 2137 {
rlm@1 2138 if(optarg == NULL) {
rlm@1 2139 fprintf(stderr, "Missing config file name\n");
rlm@1 2140 exit(-1);
rlm@1 2141 }
rlm@1 2142 FILE *f = fopen(optarg, "r");
rlm@1 2143 if(f == NULL) {
rlm@1 2144 fprintf(stderr, "File not found %s\n", optarg);
rlm@1 2145 exit(-1);
rlm@1 2146 }
rlm@1 2147 sdlReadPreferences(f);
rlm@1 2148 fclose(f);
rlm@1 2149 }
rlm@1 2150 break;
rlm@1 2151 case 'd':
rlm@1 2152 debugger = true;
rlm@1 2153 break;
rlm@1 2154 case 'h':
rlm@1 2155 sdlPrintUsage = 1;
rlm@1 2156 break;
rlm@1 2157 case 'i':
rlm@1 2158 if(optarg == NULL) {
rlm@1 2159 fprintf(stderr, "Missing IPS name\n");
rlm@1 2160 exit(-1);
rlm@1 2161 strcpy(ipsname, optarg);
rlm@1 2162 }
rlm@1 2163 break;
rlm@1 2164 case 'Y':
rlm@1 2165 yuv = true;
rlm@1 2166 if(optarg) {
rlm@1 2167 yuvType = atoi(optarg);
rlm@1 2168 switch(yuvType) {
rlm@1 2169 case 0:
rlm@1 2170 yuvType = SDL_YV12_OVERLAY;
rlm@1 2171 break;
rlm@1 2172 case 1:
rlm@1 2173 yuvType = SDL_UYVY_OVERLAY;
rlm@1 2174 break;
rlm@1 2175 case 2:
rlm@1 2176 yuvType = SDL_YVYU_OVERLAY;
rlm@1 2177 break;
rlm@1 2178 case 3:
rlm@1 2179 yuvType = SDL_YUY2_OVERLAY;
rlm@1 2180 break;
rlm@1 2181 case 4:
rlm@1 2182 yuvType = SDL_IYUV_OVERLAY;
rlm@1 2183 break;
rlm@1 2184 default:
rlm@1 2185 yuvType = SDL_YV12_OVERLAY;
rlm@1 2186 }
rlm@1 2187 } else
rlm@1 2188 yuvType = SDL_YV12_OVERLAY;
rlm@1 2189 break;
rlm@1 2190 case 'G':
rlm@1 2191 dbgMain = remoteStubMain;
rlm@1 2192 dbgSignal = remoteStubSignal;
rlm@1 2193 dbgOutput = remoteOutput;
rlm@1 2194 debugger = true;
rlm@1 2195 debuggerStub = true;
rlm@1 2196 if(optarg) {
rlm@1 2197 char *s = optarg;
rlm@1 2198 if(strncmp(s,"tcp:", 4) == 0) {
rlm@1 2199 s+=4;
rlm@1 2200 int port = atoi(s);
rlm@1 2201 remoteSetProtocol(0);
rlm@1 2202 remoteSetPort(port);
rlm@1 2203 } else if(strcmp(s,"tcp") == 0) {
rlm@1 2204 remoteSetProtocol(0);
rlm@1 2205 } else if(strcmp(s, "pipe") == 0) {
rlm@1 2206 remoteSetProtocol(1);
rlm@1 2207 } else {
rlm@1 2208 fprintf(stderr, "Unknown protocol %s\n", s);
rlm@1 2209 exit(-1);
rlm@1 2210 }
rlm@1 2211 } else {
rlm@1 2212 remoteSetProtocol(0);
rlm@1 2213 }
rlm@1 2214 break;
rlm@1 2215 case 'N':
rlm@1 2216 parseDebug = false;
rlm@1 2217 break;
rlm@1 2218 case 'D':
rlm@1 2219 if(optarg) {
rlm@1 2220 systemDebug = atoi(optarg);
rlm@1 2221 } else {
rlm@1 2222 systemDebug = 1;
rlm@1 2223 }
rlm@1 2224 break;
rlm@1 2225 case 'F':
rlm@1 2226 fullscreen = 1;
rlm@1 2227 mouseCounter = 120;
rlm@1 2228 break;
rlm@1 2229 case 'f':
rlm@1 2230 if(optarg) {
rlm@1 2231 filter = atoi(optarg);
rlm@1 2232 } else {
rlm@1 2233 filter = 0;
rlm@1 2234 }
rlm@1 2235 break;
rlm@1 2236
rlm@1 2237 case 'r':
rlm@1 2238 if(optarg == NULL) {
rlm@33 2239 fprintf(stderr, "ERROR: --recordmovie ('r') needs movie filename as option\n");
rlm@1 2240 exit(-1);
rlm@1 2241 }
rlm@1 2242 strcpy(movieFileName, optarg);
rlm@1 2243 useMovie = 1;
rlm@1 2244 break;
rlm@1 2245 case 'p': // play without read-only (editable)
rlm@1 2246 fprintf (stderr, "-p got called!\n");
rlm@1 2247 if(optarg == NULL) {
rlm@33 2248 fprintf(stderr, "ERROR: --playmovie ('p') needs movie filename as option\n");
rlm@1 2249 exit(-1);
rlm@1 2250 }
rlm@1 2251 strcpy(movieFileName, optarg);
rlm@1 2252 useMovie = 2;
rlm@1 2253 break;
rlm@1 2254 case 'w': // play with read-only
rlm@1 2255 fprintf (stderr, "-w got called!\n");
rlm@1 2256 if(optarg == NULL) {
rlm@33 2257 fprintf(stderr, "ERROR: --watchmovie ('w') needs movie filename as option\n");
rlm@1 2258 exit(-1);
rlm@1 2259 }
rlm@1 2260 strcpy(movieFileName, optarg);
rlm@1 2261 useMovie = 3;
rlm@1 2262 break;
rlm@1 2263
rlm@1 2264 case 'P':
rlm@1 2265 #ifdef PROFILING
rlm@1 2266 if(optarg) {
rlm@1 2267 cpuEnableProfiling(atoi(optarg));
rlm@1 2268 } else
rlm@1 2269 cpuEnableProfiling(100);
rlm@1 2270 #endif
rlm@1 2271 break;
rlm@1 2272 case 'S':
rlm@1 2273 sdlFlashSize = atoi(optarg);
rlm@1 2274 if(sdlFlashSize < 0 || sdlFlashSize > 1)
rlm@1 2275 sdlFlashSize = 0;
rlm@1 2276 break;
rlm@1 2277 case 's':
rlm@1 2278 if(optarg) {
rlm@1 2279 int a = atoi(optarg);
rlm@1 2280 if(a >= 0 && a <= 9) {
rlm@1 2281 gbFrameSkip = a;
rlm@1 2282 frameSkip = a;
rlm@1 2283 }
rlm@1 2284 } else {
rlm@1 2285 frameSkip = 2;
rlm@1 2286 gbFrameSkip = 0;
rlm@1 2287 }
rlm@1 2288 break;
rlm@1 2289 case 't':
rlm@1 2290 if(optarg) {
rlm@1 2291 int a = atoi(optarg);
rlm@1 2292 if(a < 0 || a > 5)
rlm@1 2293 a = 0;
rlm@1 2294 cpuSaveType = a;
rlm@1 2295 }
rlm@1 2296 break;
rlm@1 2297 case 'T':
rlm@1 2298 if(optarg) {
rlm@1 2299 int t = atoi(optarg);
rlm@1 2300 throttle = t;
rlm@1 2301 }
rlm@1 2302 break;
rlm@1 2303 case 'v':
rlm@1 2304 if(optarg) {
rlm@1 2305 systemVerbose = atoi(optarg);
rlm@1 2306 } else
rlm@1 2307 systemVerbose = 0;
rlm@1 2308 break;
rlm@1 2309 case '1':
rlm@1 2310 sizeOption = 0;
rlm@1 2311 break;
rlm@1 2312 case '2':
rlm@1 2313 sizeOption = 1;
rlm@1 2314 break;
rlm@1 2315 case '3':
rlm@1 2316 sizeOption = 2;
rlm@1 2317 break;
rlm@1 2318 case '4':
rlm@1 2319 sizeOption = 3;
rlm@1 2320 break;
rlm@1 2321 case '?':
rlm@1 2322 sdlPrintUsage = 1;
rlm@1 2323 break;
rlm@1 2324 }
rlm@1 2325 }
rlm@1 2326
rlm@39 2327 //printf("RLM: derpy loves you!\n");
rlm@39 2328 //printf("RLM: useMovie: %d (1 is record)\n", useMovie);
rlm@1 2329 if(sdlPrintUsage) {
rlm@1 2330 usage(argv[0]);
rlm@1 2331 exit(-1);
rlm@1 2332 }
rlm@1 2333
rlm@1 2334 #ifdef MMX
rlm@1 2335 if(disableMMX)
rlm@1 2336 cpu_mmx = 0;
rlm@1 2337 #endif
rlm@1 2338
rlm@1 2339 if(rewindTimer)
rlm@1 2340 rewindMemory = (char *)malloc(8*REWIND_SIZE);
rlm@1 2341
rlm@1 2342 if(sdlFlashSize == 0)
rlm@1 2343 flashSetSize(0x10000);
rlm@1 2344 else
rlm@1 2345 flashSetSize(0x20000);
rlm@1 2346
rlm@1 2347 rtcEnable(sdlRtcEnable ? true : false);
rlm@1 2348 agbPrintEnable(sdlAgbPrint ? true : false);
rlm@1 2349
rlm@1 2350 if(!debuggerStub) {
rlm@1 2351 if(optind >= argc) {
rlm@1 2352 systemMessage(0,"Missing image name");
rlm@1 2353 usage(argv[0]);
rlm@1 2354 exit(-1);
rlm@1 2355 }
rlm@1 2356 }
rlm@1 2357
rlm@1 2358 if(filter) {
rlm@1 2359 sizeOption = 1;
rlm@1 2360 }
rlm@1 2361
rlm@1 2362 for(int i = 0; i < 24;) {
rlm@1 2363 systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
rlm@1 2364 systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
rlm@1 2365 systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
rlm@1 2366 systemGbPalette[i++] = 0;
rlm@1 2367 }
rlm@1 2368
rlm@1 2369 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
rlm@1 2370
rlm@1 2371 if(optind < argc)
rlm@1 2372 {
rlm@1 2373 szFile = argv[optind];
rlm@1 2374 file_run();
rlm@39 2375 //printf("RLM: file_run() done\n");
rlm@1 2376 }
rlm@1 2377 else
rlm@1 2378 {
rlm@1 2379 systemCartridgeType = 0;
rlm@1 2380 strcpy(filename, "gnu_stub");
rlm@1 2381 rom = (u8 *)malloc(0x2000000);
rlm@1 2382 workRAM = (u8 *)calloc(1, 0x40000);
rlm@1 2383 bios = (u8 *)calloc(1,0x4000);
rlm@1 2384 internalRAM = (u8 *)calloc(1,0x8000);
rlm@1 2385 paletteRAM = (u8 *)calloc(1,0x400);
rlm@1 2386 vram = (u8 *)calloc(1, 0x20000);
rlm@1 2387 oam = (u8 *)calloc(1, 0x400);
rlm@1 2388 pix = (u8 *)calloc(1, 4 * 240 * 160);
rlm@1 2389 ioMem = (u8 *)calloc(1, 0x400);
rlm@1 2390
rlm@1 2391 theEmulator = GBASystem;
rlm@1 2392
rlm@1 2393 //CPUInit(biosFileName, useBios);
rlm@1 2394 CPUInit();
rlm@33 2395 CPUReset();
rlm@1 2396 }
rlm@1 2397
rlm@1 2398 if(debuggerStub)
rlm@1 2399 remoteInit();
rlm@1 2400
rlm@1 2401 int flags = SDL_INIT_VIDEO|SDL_INIT_AUDIO|
rlm@1 2402 SDL_INIT_TIMER|SDL_INIT_NOPARACHUTE;
rlm@1 2403
rlm@1 2404 if(soundOffFlag)
rlm@1 2405 flags ^= SDL_INIT_AUDIO;
rlm@1 2406
rlm@1 2407 if(SDL_Init(flags)) {
rlm@1 2408 systemMessage(0, "Failed to init SDL: %s", SDL_GetError());
rlm@1 2409 exit(-1);
rlm@1 2410 }
rlm@1 2411
rlm@1 2412 if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
rlm@1 2413 systemMessage(0, "Failed to init joystick support: %s", SDL_GetError());
rlm@1 2414 }
rlm@1 2415
rlm@1 2416 sdlCheckKeys();
rlm@1 2417
rlm@1 2418 if(systemCartridgeType == 0) {
rlm@1 2419 srcWidth = 240;
rlm@1 2420 srcHeight = 160;
rlm@1 2421 systemFrameSkip = frameSkip;
rlm@1 2422 } else if (systemCartridgeType == 1) {
rlm@1 2423 if(gbBorderOn) {
rlm@1 2424 srcWidth = 256;
rlm@1 2425 srcHeight = 224;
rlm@1 2426 gbBorderLineSkip = 256;
rlm@1 2427 gbBorderColumnSkip = 48;
rlm@1 2428 gbBorderRowSkip = 40;
rlm@1 2429 } else {
rlm@1 2430 srcWidth = 160;
rlm@1 2431 srcHeight = 144;
rlm@1 2432 gbBorderLineSkip = 160;
rlm@1 2433 gbBorderColumnSkip = 0;
rlm@1 2434 gbBorderRowSkip = 0;
rlm@1 2435 }
rlm@1 2436 systemFrameSkip = gbFrameSkip;
rlm@1 2437 } else {
rlm@1 2438 srcWidth = 320;
rlm@1 2439 srcHeight = 240;
rlm@1 2440 }
rlm@1 2441
rlm@1 2442 destWidth = (sizeOption+1)*srcWidth;
rlm@1 2443 destHeight = (sizeOption+1)*srcHeight;
rlm@1 2444
rlm@1 2445 surface = SDL_SetVideoMode(destWidth, destHeight, 16,
rlm@1 2446 SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|
rlm@1 2447 (fullscreen ? SDL_FULLSCREEN : 0));
rlm@1 2448
rlm@1 2449 if(surface == NULL) {
rlm@1 2450 systemMessage(0, "Failed to set video mode");
rlm@1 2451 SDL_Quit();
rlm@1 2452 exit(-1);
rlm@1 2453 }
rlm@1 2454
rlm@1 2455 systemRedShift = sdlCalculateShift(surface->format->Rmask);
rlm@1 2456 systemGreenShift = sdlCalculateShift(surface->format->Gmask);
rlm@1 2457 systemBlueShift = sdlCalculateShift(surface->format->Bmask);
rlm@1 2458
rlm@1 2459 systemColorDepth = surface->format->BitsPerPixel;
rlm@1 2460 if(systemColorDepth == 15)
rlm@1 2461 systemColorDepth = 16;
rlm@1 2462
rlm@1 2463 if(yuv) {
rlm@1 2464 Init_Overlay(surface, yuvType);
rlm@1 2465 systemColorDepth = 32;
rlm@1 2466 systemRedShift = 3;
rlm@1 2467 systemGreenShift = 11;
rlm@1 2468 systemBlueShift = 19;
rlm@1 2469 }
rlm@1 2470
rlm@1 2471 if(systemColorDepth != 16 && systemColorDepth != 24 &&
rlm@1 2472 systemColorDepth != 32) {
rlm@1 2473 fprintf(stderr,"Unsupported color depth '%d'.\nOnly 16, 24 and 32 bit color depths are supported\n", systemColorDepth);
rlm@1 2474 exit(-1);
rlm@1 2475 }
rlm@1 2476
rlm@1 2477 #ifndef C_CORE
rlm@1 2478 sdlMakeStretcher(srcWidth);
rlm@1 2479 #else
rlm@1 2480 switch(systemColorDepth) {
rlm@1 2481 case 16:
rlm@1 2482 sdlStretcher = sdlStretcher16[sizeOption];
rlm@1 2483 break;
rlm@1 2484 case 24:
rlm@1 2485 sdlStretcher = sdlStretcher24[sizeOption];
rlm@1 2486 break;
rlm@1 2487 case 32:
rlm@1 2488 sdlStretcher = sdlStretcher32[sizeOption];
rlm@1 2489 break;
rlm@1 2490 default:
rlm@1 2491 fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth);
rlm@1 2492 exit(-1);
rlm@1 2493 }
rlm@1 2494 #endif
rlm@1 2495
rlm@1 2496 fprintf(stderr,"Color depth: %d\n", systemColorDepth);
rlm@1 2497
rlm@1 2498 if(systemColorDepth == 16) {
rlm@1 2499 if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) {
rlm@1 2500 Init_2xSaI(565);
rlm@1 2501 RGB_LOW_BITS_MASK = 0x821;
rlm@1 2502 } else {
rlm@1 2503 Init_2xSaI(555);
rlm@1 2504 RGB_LOW_BITS_MASK = 0x421;
rlm@1 2505 }
rlm@1 2506 if(systemCartridgeType == 2) {
rlm@1 2507 for(int i = 0; i < 0x10000; i++) {
rlm@1 2508 systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) |
rlm@1 2509 (((i & 0x7c0) >> 6) << systemGreenShift) |
rlm@1 2510 (((i & 0xf800) >> 11) << systemRedShift);
rlm@1 2511 }
rlm@1 2512 } else {
rlm@1 2513 for(int i = 0; i < 0x10000; i++) {
rlm@1 2514 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
rlm@1 2515 (((i & 0x3e0) >> 5) << systemGreenShift) |
rlm@1 2516 (((i & 0x7c00) >> 10) << systemBlueShift);
rlm@1 2517 }
rlm@1 2518 }
rlm@1 2519 srcPitch = srcWidth * 2+4;
rlm@1 2520 } else {
rlm@1 2521 if(systemColorDepth != 32)
rlm@1 2522 filterFunction = NULL;
rlm@1 2523 RGB_LOW_BITS_MASK = 0x010101;
rlm@1 2524 if(systemColorDepth == 32) {
rlm@1 2525 Init_2xSaI(32);
rlm@1 2526 }
rlm@1 2527 for(int i = 0; i < 0x10000; i++) {
rlm@1 2528 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
rlm@1 2529 (((i & 0x3e0) >> 5) << systemGreenShift) |
rlm@1 2530 (((i & 0x7c00) >> 10) << systemBlueShift);
rlm@1 2531 }
rlm@1 2532 if(systemColorDepth == 32)
rlm@1 2533 srcPitch = srcWidth*4 + 4;
rlm@1 2534 else
rlm@1 2535 srcPitch = srcWidth*3;
rlm@1 2536 }
rlm@1 2537
rlm@1 2538 if(systemColorDepth != 32) {
rlm@1 2539 switch(filter) {
rlm@1 2540 case 0:
rlm@1 2541 filterFunction = NULL;
rlm@1 2542 break;
rlm@1 2543 case 1:
rlm@1 2544 filterFunction = ScanlinesTV;
rlm@1 2545 break;
rlm@1 2546 case 2:
rlm@1 2547 filterFunction = _2xSaI;
rlm@1 2548 break;
rlm@1 2549 case 3:
rlm@1 2550 filterFunction = Super2xSaI;
rlm@1 2551 break;
rlm@1 2552 case 4:
rlm@1 2553 filterFunction = SuperEagle;
rlm@1 2554 break;
rlm@1 2555 case 5:
rlm@1 2556 filterFunction = Pixelate2x16;
rlm@1 2557 break;
rlm@1 2558 case 6:
rlm@1 2559 filterFunction = MotionBlur;
rlm@1 2560 break;
rlm@1 2561 case 7:
rlm@1 2562 filterFunction = AdMame2x;
rlm@1 2563 break;
rlm@1 2564 case 8:
rlm@1 2565 filterFunction = Simple2x16;
rlm@1 2566 break;
rlm@1 2567 case 9:
rlm@1 2568 filterFunction = Bilinear;
rlm@1 2569 break;
rlm@1 2570 case 10:
rlm@1 2571 filterFunction = BilinearPlus;
rlm@1 2572 break;
rlm@1 2573 case 11:
rlm@1 2574 filterFunction = Scanlines;
rlm@1 2575 break;
rlm@1 2576 case 12:
rlm@1 2577 filterFunction = hq2x;
rlm@1 2578 break;
rlm@1 2579 case 13:
rlm@1 2580 filterFunction = lq2x;
rlm@1 2581 break;
rlm@1 2582 default:
rlm@1 2583 filterFunction = NULL;
rlm@1 2584 break;
rlm@1 2585 }
rlm@1 2586 } else {
rlm@1 2587 switch(filter) {
rlm@1 2588 case 0:
rlm@1 2589 filterFunction = NULL;
rlm@1 2590 break;
rlm@1 2591 case 1:
rlm@1 2592 filterFunction = ScanlinesTV32;
rlm@1 2593 break;
rlm@1 2594 case 2:
rlm@1 2595 filterFunction = _2xSaI32;
rlm@1 2596 break;
rlm@1 2597 case 3:
rlm@1 2598 filterFunction = Super2xSaI32;
rlm@1 2599 break;
rlm@1 2600 case 4:
rlm@1 2601 filterFunction = SuperEagle32;
rlm@1 2602 break;
rlm@1 2603 case 5:
rlm@1 2604 filterFunction = Pixelate2x32;
rlm@1 2605 break;
rlm@1 2606 case 6:
rlm@1 2607 filterFunction = MotionBlur32;
rlm@1 2608 break;
rlm@1 2609 case 7:
rlm@1 2610 filterFunction = AdMame2x32;
rlm@1 2611 break;
rlm@1 2612 case 8:
rlm@1 2613 filterFunction = Simple2x32;
rlm@1 2614 break;
rlm@1 2615 case 9:
rlm@1 2616 filterFunction = Bilinear32;
rlm@1 2617 break;
rlm@1 2618 case 10:
rlm@1 2619 filterFunction = BilinearPlus32;
rlm@1 2620 break;
rlm@1 2621 case 11:
rlm@1 2622 filterFunction = Scanlines32;
rlm@1 2623 break;
rlm@1 2624 case 12:
rlm@1 2625 filterFunction = hq2x32;
rlm@1 2626 break;
rlm@1 2627 case 13:
rlm@1 2628 filterFunction = lq2x32;
rlm@1 2629 break;
rlm@1 2630 default:
rlm@1 2631 filterFunction = NULL;
rlm@1 2632 break;
rlm@1 2633 }
rlm@1 2634 }
rlm@1 2635
rlm@1 2636 if(systemColorDepth == 16) {
rlm@1 2637 switch(ifbType) {
rlm@1 2638 case 0:
rlm@1 2639 default:
rlm@1 2640 ifbFunction = NULL;
rlm@1 2641 break;
rlm@1 2642 case 1:
rlm@1 2643 ifbFunction = MotionBlurIB;
rlm@1 2644 break;
rlm@1 2645 case 2:
rlm@1 2646 ifbFunction = SmartIB;
rlm@1 2647 break;
rlm@1 2648 }
rlm@1 2649 } else if(systemColorDepth == 32) {
rlm@1 2650 switch(ifbType) {
rlm@1 2651 case 0:
rlm@1 2652 default:
rlm@1 2653 ifbFunction = NULL;
rlm@1 2654 break;
rlm@1 2655 case 1:
rlm@1 2656 ifbFunction = MotionBlurIB32;
rlm@1 2657 break;
rlm@1 2658 case 2:
rlm@1 2659 ifbFunction = SmartIB32;
rlm@1 2660 break;
rlm@1 2661 }
rlm@1 2662 } else
rlm@1 2663 ifbFunction = NULL;
rlm@1 2664
rlm@1 2665 if(delta == NULL) {
rlm@1 2666 delta = (u8*)malloc(322*242*4);
rlm@1 2667 memset(delta, 255, 322*242*4);
rlm@1 2668 }
rlm@1 2669
rlm@1 2670 if(!soundOffFlag)
rlm@1 2671 soundInit();
rlm@1 2672
rlm@1 2673 autoFrameSkipLastTime = throttleLastTime = systemGetClock();
rlm@39 2674 //printf("RLM: and now for the movie part!\n");
rlm@1 2675
rlm@1 2676 switch(useMovie)
rlm@1 2677 {
rlm@1 2678 case 1: // --recordMovie
rlm@1 2679 VBAMovieCreate(movieFileName,
rlm@1 2680 /*authorInfo*/"",
rlm@1 2681 /*startFlags*/0,
rlm@1 2682 /*controllerFlags*/MOVIE_CONTROLLER(0),
rlm@1 2683 /*typeFlags*/(systemCartridgeType==IMAGE_GBA)?(MOVIE_TYPE_GBA):(GBC_CAPABLE?MOVIE_TYPE_GBC:MOVIE_TYPE_SGB));
rlm@1 2684 break;
rlm@1 2685 case 2: // --playMovie
rlm@1 2686 VBAMovieOpen(movieFileName, false);
rlm@1 2687 break;
rlm@1 2688 case 3: // --watchMovie
rlm@1 2689 VBAMovieOpen(movieFileName, true);
rlm@1 2690 break;
rlm@1 2691 default:
rlm@1 2692 sdlReadBattery();
rlm@1 2693 break;
rlm@1 2694 }
rlm@39 2695 //printf("RLM: still alive after movie switch\n");
rlm@1 2696 SDL_WM_SetCaption("VisualBoyAdvance", NULL);
rlm@1 2697
rlm@1 2698 char *moviefile = getenv("AUTODEMO");
rlm@33 2699 fprintf (stderr, "Checking for AUTODEMO...\n");
rlm@1 2700 if (moviefile)
rlm@1 2701 {
rlm@33 2702 fprintf (stderr, "I got a filename OMG!\nCalling VBAMovieOpen...\n");
rlm@1 2703 VBAMovieOpen(moviefile, true);
rlm@1 2704 }
rlm@70 2705 //step();
rlm@1 2706 return 0;
rlm@1 2707 }
rlm@1 2708
rlm@49 2709 // RLM
rlm@49 2710 int runVBA(int argc, char **argv){
rlm@49 2711 return main(argc, argv);
rlm@49 2712 }
rlm@49 2713
rlm@49 2714
rlm@53 2715
rlm@53 2716
rlm@53 2717
rlm@53 2718
rlm@53 2719
rlm@1 2720 void systemMessage(int num, const char *msg, ...)
rlm@1 2721 {
rlm@1 2722 char buffer[2048];
rlm@1 2723 va_list valist;
rlm@1 2724
rlm@1 2725 va_start(valist, msg);
rlm@1 2726 vsprintf(buffer, msg, valist);
rlm@1 2727
rlm@1 2728 fprintf(stderr, "%s\n", buffer);
rlm@1 2729 va_end(valist);
rlm@1 2730 }
rlm@1 2731
rlm@1 2732 //On WIN32, this function messages requesting
rlm@1 2733 //the window to be redrawn. Can this be ignored here?
rlm@1 2734 void systemRefreshScreen(){}
rlm@1 2735
rlm@1 2736 void systemRenderFrame()
rlm@1 2737 {
rlm@1 2738 renderedFrames++;
rlm@1 2739 VBAUpdateFrameCountDisplay();
rlm@1 2740 VBAUpdateButtonPressDisplay();
rlm@1 2741
rlm@1 2742 if(yuv) {
rlm@1 2743 Draw_Overlay(surface, sizeOption+1);
rlm@1 2744 return;
rlm@1 2745 }
rlm@1 2746
rlm@1 2747 SDL_LockSurface(surface);
rlm@1 2748
rlm@1 2749 for(int slot = 0 ; slot < 8 ; slot++)
rlm@1 2750 {
rlm@1 2751 if(screenMessage[slot]) {
rlm@1 2752 if(systemCartridgeType == 1 && gbBorderOn) {
rlm@1 2753 gbSgbRenderBorder();
rlm@1 2754 }
rlm@1 2755 if(((systemGetClock() - screenMessageTime[slot]) < screenMessageDuration[slot]) &&
rlm@1 2756 !disableStatusMessages) {
rlm@1 2757 drawText(pix, srcPitch, 10, srcHeight - 20*(slot+1),
rlm@1 2758 screenMessageBuffer[slot]);
rlm@1 2759 } else {
rlm@1 2760 screenMessage[slot] = false;
rlm@1 2761 }
rlm@1 2762 }
rlm@1 2763 }
rlm@1 2764
rlm@1 2765 if(ifbFunction) {
rlm@1 2766 if(systemColorDepth == 16)
rlm@1 2767 ifbFunction(pix+destWidth+4, destWidth+4, srcWidth, srcHeight);
rlm@1 2768 else
rlm@1 2769 ifbFunction(pix+destWidth*2+4, destWidth*2+4, srcWidth, srcHeight);
rlm@1 2770 }
rlm@1 2771
rlm@1 2772 if(filterFunction) {
rlm@1 2773 if(systemColorDepth == 16)
rlm@1 2774 filterFunction(pix+destWidth+4,destWidth+4, delta,
rlm@1 2775 (u8*)surface->pixels,surface->pitch,
rlm@1 2776 srcWidth,
rlm@1 2777 srcHeight);
rlm@1 2778 else
rlm@1 2779 filterFunction(pix+destWidth*2+4,
rlm@1 2780 destWidth*2+4,
rlm@1 2781 delta,
rlm@1 2782 (u8*)surface->pixels,
rlm@1 2783 surface->pitch,
rlm@1 2784 srcWidth,
rlm@1 2785 srcHeight);
rlm@1 2786 } else {
rlm@1 2787 int destPitch = surface->pitch;
rlm@1 2788 u8 *src = pix;
rlm@1 2789 u8 *dest = (u8*)surface->pixels;
rlm@1 2790 int i;
rlm@1 2791 u32 *stretcher = (u32 *)sdlStretcher;
rlm@1 2792 if(systemColorDepth == 16)
rlm@1 2793 src += srcPitch;
rlm@1 2794 int option = sizeOption;
rlm@1 2795 if(yuv)
rlm@1 2796 option = 0;
rlm@1 2797 switch(sizeOption) {
rlm@1 2798 case 0:
rlm@1 2799 for(i = 0; i < srcHeight; i++) {
rlm@1 2800 SDL_CALL_STRETCHER;
rlm@1 2801 src += srcPitch;
rlm@1 2802 dest += destPitch;
rlm@1 2803 }
rlm@1 2804 break;
rlm@1 2805 case 1:
rlm@1 2806 for(i = 0; i < srcHeight; i++) {
rlm@1 2807 SDL_CALL_STRETCHER;
rlm@1 2808 dest += destPitch;
rlm@1 2809 SDL_CALL_STRETCHER;
rlm@1 2810 src += srcPitch;
rlm@1 2811 dest += destPitch;
rlm@1 2812 }
rlm@1 2813 break;
rlm@1 2814 case 2:
rlm@1 2815 for(i = 0; i < srcHeight; i++) {
rlm@1 2816 SDL_CALL_STRETCHER;
rlm@1 2817 dest += destPitch;
rlm@1 2818 SDL_CALL_STRETCHER;
rlm@1 2819 dest += destPitch;
rlm@1 2820 SDL_CALL_STRETCHER;
rlm@1 2821 src += srcPitch;
rlm@1 2822 dest += destPitch;
rlm@1 2823 }
rlm@1 2824 break;
rlm@1 2825 case 3:
rlm@1 2826 for(i = 0; i < srcHeight; i++) {
rlm@1 2827 SDL_CALL_STRETCHER;
rlm@1 2828 dest += destPitch;
rlm@1 2829 SDL_CALL_STRETCHER;
rlm@1 2830 dest += destPitch;
rlm@1 2831 SDL_CALL_STRETCHER;
rlm@1 2832 dest += destPitch;
rlm@1 2833 SDL_CALL_STRETCHER;
rlm@1 2834 src += srcPitch;
rlm@1 2835 dest += destPitch;
rlm@1 2836 }
rlm@1 2837 break;
rlm@1 2838 }
rlm@1 2839 }
rlm@1 2840
rlm@1 2841 if(showSpeed && fullscreen) {
rlm@1 2842 char buffer[50];
rlm@1 2843 if(showSpeed == 1)
rlm@1 2844 sprintf(buffer, "%d%%", systemSpeed);
rlm@1 2845 else
rlm@1 2846 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
rlm@1 2847 systemFrameSkip,
rlm@1 2848 showRenderedFrames);
rlm@1 2849 if(showSpeedTransparent)
rlm@1 2850 drawTextTransp((u8*)surface->pixels,
rlm@1 2851 surface->pitch,
rlm@1 2852 10,
rlm@1 2853 surface->h-20,
rlm@1 2854 buffer);
rlm@1 2855 else
rlm@1 2856 drawText((u8*)surface->pixels,
rlm@1 2857 surface->pitch,
rlm@1 2858 10,
rlm@1 2859 surface->h-20,
rlm@1 2860 buffer);
rlm@1 2861 }
rlm@1 2862
rlm@1 2863 SDL_UnlockSurface(surface);
rlm@1 2864 // SDL_UpdateRect(surface, 0, 0, destWidth, destHeight);
rlm@1 2865 SDL_Flip(surface);
rlm@1 2866 }
rlm@1 2867
rlm@1 2868 bool systemReadJoypads()
rlm@1 2869 {
rlm@1 2870 return true;
rlm@1 2871 }
rlm@1 2872
rlm@1 2873 // Kludge to make Lua call the right function.
rlm@1 2874 u32 systemGetOriginalJoypad(int which, bool sensor){
rlm@1 2875 return systemGetJoypad(which,sensor);
rlm@1 2876 }
rlm@1 2877
rlm@1 2878 u32 systemGetJoypad(int which, bool sensor)
rlm@1 2879 {
rlm@1 2880 sensorOn = sensor;
rlm@1 2881 if(which < 0 || which > 3)
rlm@1 2882 which = sdlDefaultJoypad;
rlm@1 2883
rlm@1 2884 //VBAMovieUpdate(which);
rlm@1 2885 //VBAMovieUpdateState();
rlm@1 2886 u32 res = 0;
rlm@1 2887
rlm@1 2888 //----------------------------//
rlm@1 2889 if (VBAMoviePlaying()){
rlm@1 2890 // VBAMovieRead() overwrites currentButtons[i]
rlm@1 2891 VBAMovieRead(which, sensor);
rlm@1 2892 res = currentButtons[which];
rlm@1 2893 return res;
rlm@1 2894 }
rlm@1 2895 //---------------------------//
rlm@1 2896 //Temporary implementation, not sure if it's correct --Felipe
rlm@1 2897
rlm@1 2898 /*
rlm@1 2899 if(sdlButtons[which][KEY_BUTTON_A])
rlm@1 2900 res |= BUTTON_MASK_A;
rlm@1 2901 if(sdlButtons[which][KEY_BUTTON_B])
rlm@1 2902 res |= BUTTON_MASK_B;
rlm@1 2903 if(sdlButtons[which][KEY_BUTTON_SELECT])
rlm@1 2904 res |= BUTTON_MASK_SELECT;
rlm@1 2905 if(sdlButtons[which][KEY_BUTTON_START])
rlm@1 2906 res |= BUTTON_MASK_START;
rlm@1 2907 if(sdlButtons[which][KEY_RIGHT])
rlm@1 2908 res |= BUTTON_MASK_RIGHT;
rlm@1 2909 if(sdlButtons[which][KEY_LEFT])
rlm@1 2910 res |= BUTTON_MASK_LEFT;
rlm@1 2911 if(sdlButtons[which][KEY_UP])
rlm@1 2912 res |= BUTTON_MASK_UP;
rlm@1 2913 if(sdlButtons[which][KEY_DOWN])
rlm@1 2914 res |= BUTTON_MASK_DOWN;
rlm@1 2915 if(sdlButtons[which][KEY_BUTTON_R])
rlm@1 2916 res |= BUTTON_MASK_R;
rlm@1 2917 if(sdlButtons[which][KEY_BUTTON_L])
rlm@1 2918 res |= BUTTON_MASK_L;
rlm@1 2919 */
rlm@1 2920 /*
rlm@1 2921 // disallow L+R or U+D of being pressed at the same time
rlm@1 2922 if((res & 48) == 48)
rlm@1 2923 res &= ~16;
rlm@1 2924 if((res & 192) == 192)
rlm@1 2925 res &= ~128;
rlm@1 2926 */
rlm@1 2927 /*
rlm@1 2928 if(sdlbuttons[which][KEY_BUTTON_SPEED])
rlm@1 2929 res |= 1024;
rlm@1 2930 if(sdlButtons[which][KEY_BUTTON_CAPTURE])
rlm@1 2931 res |= 2048;
rlm@1 2932 */
rlm@1 2933 res = currentButtons[which];
rlm@1 2934
rlm@1 2935 if(autoFire) {
rlm@1 2936 res &= (~autoFire);
rlm@1 2937 if(autoFireToggle)
rlm@1 2938 res |= autoFire;
rlm@1 2939 autoFireToggle = !autoFireToggle;
rlm@1 2940 }
rlm@1 2941
rlm@1 2942 //if (res) fprintf(stdout,"%x\n",res);
rlm@1 2943
rlm@1 2944 return res;
rlm@1 2945 }
rlm@1 2946
rlm@1 2947 void systemSetJoypad(int which, u32 buttons)
rlm@1 2948 {
rlm@1 2949 if(which < 0 || which > 3)
rlm@1 2950 which = sdlDefaultJoypad;
rlm@1 2951 /*
rlm@1 2952 sdlButtons[which][KEY_BUTTON_A] = (buttons & 1) != 0;
rlm@1 2953 sdlButtons[which][KEY_BUTTON_B] = (buttons & 2) != 0;
rlm@1 2954 sdlButtons[which][KEY_BUTTON_SELECT] = (buttons & 4) != 0;
rlm@1 2955 sdlButtons[which][KEY_BUTTON_START] = (buttons & 8) != 0;
rlm@1 2956 sdlButtons[which][KEY_RIGHT] = (buttons & 16) != 0;
rlm@1 2957 sdlButtons[which][KEY_LEFT] = (buttons & 32) != 0;
rlm@1 2958 sdlButtons[which][KEY_UP] = (buttons & 64) != 0;
rlm@1 2959 sdlButtons[which][KEY_DOWN] = (buttons & 128) != 0;
rlm@1 2960 sdlButtons[which][KEY_BUTTON_R] = (buttons & 256) != 0;
rlm@1 2961 sdlButtons[which][KEY_BUTTON_L] = (buttons & 512) != 0;
rlm@1 2962 */
rlm@1 2963 currentButtons[which]= buttons & 0x3ff;
rlm@1 2964 }
rlm@1 2965
rlm@1 2966 void systemClearJoypads()
rlm@1 2967 {
rlm@1 2968 for (int i = 0; i < 4; ++i)
rlm@1 2969 currentButtons[i] = 0;
rlm@1 2970
rlm@1 2971 //lastKeys = 0;
rlm@1 2972 }
rlm@1 2973
rlm@1 2974 void systemSetTitle(const char *title)
rlm@1 2975 {
rlm@1 2976 SDL_WM_SetCaption(title, NULL);
rlm@1 2977 }
rlm@1 2978
rlm@1 2979 void systemShowSpeed(int speed)
rlm@1 2980 {
rlm@1 2981 systemSpeed = speed;
rlm@1 2982
rlm@1 2983 showRenderedFrames = renderedFrames;
rlm@1 2984 renderedFrames = 0;
rlm@1 2985
rlm@1 2986 if(!fullscreen && showSpeed) {
rlm@1 2987 char buffer[80];
rlm@1 2988 if(showSpeed == 1)
rlm@1 2989 sprintf(buffer, "VisualBoyAdvance-%3d%%", systemSpeed);
rlm@1 2990 else
rlm@1 2991 sprintf(buffer, "VisualBoyAdvance-%3d%%(%d, %d fps)", systemSpeed,
rlm@1 2992 systemFrameSkip,
rlm@1 2993 showRenderedFrames);
rlm@1 2994
rlm@1 2995 systemSetTitle(buffer);
rlm@1 2996 }
rlm@1 2997 }
rlm@1 2998
rlm@1 2999 // FIXME: the timing
rlm@1 3000 void systemFrame(/*int rate*/) //Looking at System.cpp, it looks like rate should be 600
rlm@1 3001 {
rlm@1 3002 u32 time = systemGetClock();
rlm@1 3003 if(!wasPaused && autoFrameSkip && !throttle) {
rlm@1 3004 u32 diff = time - autoFrameSkipLastTime;
rlm@1 3005 int speed = 100;
rlm@1 3006
rlm@1 3007 if(diff)
rlm@1 3008 speed = (1000000/600)/diff;
rlm@1 3009
rlm@1 3010 if(speed >= 98) {
rlm@1 3011 frameskipadjust++;
rlm@1 3012
rlm@1 3013 if(frameskipadjust >= 3) {
rlm@1 3014 frameskipadjust=0;
rlm@1 3015 if(systemFrameSkip > 0)
rlm@1 3016 systemFrameSkip--;
rlm@1 3017 }
rlm@1 3018 } else {
rlm@1 3019 if(speed < 80)
rlm@1 3020 frameskipadjust -= (90 - speed)/5;
rlm@1 3021 else if(systemFrameSkip < 9)
rlm@1 3022 frameskipadjust--;
rlm@1 3023
rlm@1 3024 if(frameskipadjust <= -2) {
rlm@1 3025 frameskipadjust += 2;
rlm@1 3026 if(systemFrameSkip < 9)
rlm@1 3027 systemFrameSkip++;
rlm@1 3028 }
rlm@1 3029 }
rlm@1 3030 }
rlm@1 3031 if(!wasPaused && throttle) {
rlm@1 3032 /*if(!speedup) {
rlm@1 3033 u32 diff = time - throttleLastTime;
rlm@1 3034
rlm@1 3035 int target = (1000000.0/(600*throttle));
rlm@1 3036 int d = (target - diff);
rlm@1 3037
rlm@1 3038 if(d > 0) {
rlm@1 3039 SDL_Delay(d);
rlm@1 3040 }
rlm@1 3041 }
rlm@1 3042 throttleLastTime = systemGetClock();
rlm@1 3043 */
rlm@1 3044 }
rlm@1 3045 if(rewindMemory) {
rlm@1 3046 if(++rewindCounter >= rewindTimer) {
rlm@1 3047 rewindSaveNeeded = true;
rlm@1 3048 rewindCounter = 0;
rlm@1 3049 }
rlm@1 3050 }
rlm@1 3051
rlm@1 3052 if(systemSaveUpdateCounter) {
rlm@1 3053 if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
rlm@1 3054 sdlWriteBattery();
rlm@1 3055 systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
rlm@1 3056 }
rlm@1 3057 }
rlm@1 3058
rlm@1 3059 wasPaused = false;
rlm@1 3060 autoFrameSkipLastTime = time;
rlm@1 3061 }
rlm@1 3062
rlm@1 3063 int systemFramesToSkip(){
rlm@1 3064 return systemFrameSkip;
rlm@1 3065 }
rlm@1 3066
rlm@1 3067 int systemScreenCapture(int a)
rlm@1 3068 {
rlm@1 3069 char buffer[2048];
rlm@1 3070
rlm@1 3071 if(captureFormat) {
rlm@1 3072 if(captureDir[0])
rlm@1 3073 sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a);
rlm@1 3074 else
rlm@1 3075 sprintf(buffer, "%s%02d.bmp", filename, a);
rlm@1 3076
rlm@1 3077 theEmulator.emuWriteBMP(buffer);
rlm@1 3078 } else {
rlm@1 3079 if(captureDir[0])
rlm@1 3080 sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a);
rlm@1 3081 else
rlm@1 3082 sprintf(buffer, "%s%02d.png", filename, a);
rlm@1 3083 theEmulator.emuWritePNG(buffer);
rlm@1 3084 }
rlm@1 3085
rlm@1 3086 systemScreenMessage("Screen capture");
rlm@1 3087 return a;
rlm@1 3088 }
rlm@1 3089
rlm@1 3090 void soundCallback(void *,u8 *stream,int len){}
rlm@1 3091
rlm@1 3092 void systemSoundWriteToBuffer(){
rlm@1 3093 soundDriver->write(soundFinalWave, soundBufferLen);
rlm@1 3094 }
rlm@1 3095
rlm@1 3096 void systemSoundClearBuffer()
rlm@1 3097 {
rlm@1 3098 SDL_mutexP(mutex);
rlm@1 3099 memset(sdlBuffer,0,soundBufferTotalLen);
rlm@1 3100 sdlSoundLen=0;
rlm@1 3101 printf("Hi\n");
rlm@1 3102 SDL_mutexV(mutex);
rlm@1 3103 }
rlm@1 3104
rlm@1 3105 bool systemSoundInit(){
rlm@1 3106 systemSoundShutdown();
rlm@1 3107 soundDriver = new SoundSDL();
rlm@1 3108 if ( !soundDriver )
rlm@1 3109 return false;
rlm@1 3110
rlm@1 3111 if (!soundDriver->init()) //<-- sound sample rate
rlm@1 3112 return false;
rlm@1 3113
rlm@1 3114 if (!(soundDriver->setThrottle(throttle))){
rlm@1 3115 fprintf(stderr,"Failed to set desired throttle, defaulting to 100 %%.\n");
rlm@1 3116 if (!soundDriver->setThrottle(100)) return false;
rlm@1 3117 }
rlm@1 3118 soundPaused = true;
rlm@1 3119 systemSoundOn = true;
rlm@1 3120 return true;
rlm@1 3121 }
rlm@1 3122
rlm@1 3123 void systemSoundShutdown(){
rlm@1 3124 if (soundDriver)
rlm@1 3125 {
rlm@1 3126 delete soundDriver;
rlm@1 3127 soundDriver = 0;
rlm@1 3128 }
rlm@1 3129 }
rlm@1 3130
rlm@1 3131 void systemSoundPause()
rlm@1 3132 {
rlm@1 3133 SDL_PauseAudio(1);
rlm@1 3134 }
rlm@1 3135
rlm@1 3136 void systemSoundResume()
rlm@1 3137 {
rlm@1 3138 SDL_PauseAudio(0);
rlm@1 3139 }
rlm@1 3140
rlm@1 3141 void systemSoundReset()
rlm@1 3142 {
rlm@1 3143 }
rlm@1 3144
rlm@1 3145 u32 systemGetClock()
rlm@1 3146 {
rlm@1 3147 return SDL_GetTicks();
rlm@1 3148 }
rlm@1 3149
rlm@1 3150 void systemUpdateMotionSensor()
rlm@1 3151 {
rlm@1 3152 if(sdlMotionButtons[KEY_LEFT]) {
rlm@1 3153 sensorX += 3;
rlm@1 3154 if(sensorX > 2197)
rlm@1 3155 sensorX = 2197;
rlm@1 3156 if(sensorX < 2047)
rlm@1 3157 sensorX = 2057;
rlm@1 3158 } else if(sdlMotionButtons[KEY_RIGHT]) {
rlm@1 3159 sensorX -= 3;
rlm@1 3160 if(sensorX < 1897)
rlm@1 3161 sensorX = 1897;
rlm@1 3162 if(sensorX > 2047)
rlm@1 3163 sensorX = 2037;
rlm@1 3164 } else if(sensorX > 2047) {
rlm@1 3165 sensorX -= 2;
rlm@1 3166 if(sensorX < 2047)
rlm@1 3167 sensorX = 2047;
rlm@1 3168 } else {
rlm@1 3169 sensorX += 2;
rlm@1 3170 if(sensorX > 2047)
rlm@1 3171 sensorX = 2047;
rlm@1 3172 }
rlm@1 3173
rlm@1 3174 if(sdlMotionButtons[KEY_UP]) {
rlm@1 3175 sensorY += 3;
rlm@1 3176 if(sensorY > 2197)
rlm@1 3177 sensorY = 2197;
rlm@1 3178 if(sensorY < 2047)
rlm@1 3179 sensorY = 2057;
rlm@1 3180 } else if(sdlMotionButtons[KEY_DOWN]) {
rlm@1 3181 sensorY -= 3;
rlm@1 3182 if(sensorY < 1897)
rlm@1 3183 sensorY = 1897;
rlm@1 3184 if(sensorY > 2047)
rlm@1 3185 sensorY = 2037;
rlm@1 3186 } else if(sensorY > 2047) {
rlm@1 3187 sensorY -= 2;
rlm@1 3188 if(sensorY < 2047)
rlm@1 3189 sensorY = 2047;
rlm@1 3190 } else {
rlm@1 3191 sensorY += 2;
rlm@1 3192 if(sensorY > 2047)
rlm@1 3193 sensorY = 2047;
rlm@1 3194 }
rlm@1 3195 }
rlm@1 3196
rlm@1 3197 void systemResetSensor()
rlm@1 3198 {
rlm@1 3199 sensorX = sensorY = INITIAL_SENSOR_VALUE;
rlm@1 3200 }
rlm@1 3201
rlm@1 3202 int systemGetSensorX()
rlm@1 3203 {
rlm@1 3204 return sensorX;
rlm@1 3205 }
rlm@1 3206
rlm@1 3207 int systemGetSensorY()
rlm@1 3208 {
rlm@1 3209 return sensorY;
rlm@1 3210 }
rlm@1 3211
rlm@1 3212 void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
rlm@1 3213 {
rlm@1 3214 }
rlm@1 3215
rlm@1 3216 void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList)
rlm@1 3217 {
rlm@1 3218 screenMessage[slot] = true;
rlm@1 3219 screenMessageTime[slot] = systemGetClock();
rlm@1 3220 screenMessageDuration[slot] = duration;
rlm@1 3221 if(strlen(msg) > 20) {
rlm@1 3222 strncpy(screenMessageBuffer[slot], msg, 20);
rlm@1 3223 screenMessageBuffer[slot][20] = 0;
rlm@1 3224 } else
rlm@1 3225 strcpy(screenMessageBuffer[slot], msg);
rlm@1 3226 }
rlm@1 3227
rlm@1 3228 bool systemSoundCanChangeQuality()
rlm@1 3229 {
rlm@1 3230 return false;
rlm@1 3231 }
rlm@1 3232
rlm@1 3233 bool systemSoundSetQuality(int quality)
rlm@1 3234 {
rlm@1 3235 if (systemCartridgeType == 0)
rlm@1 3236 soundSetQuality(quality);
rlm@1 3237 else
rlm@1 3238 gbSoundSetQuality(quality);
rlm@1 3239
rlm@1 3240 return true;
rlm@1 3241 }
rlm@1 3242
rlm@1 3243 bool systemPauseOnFrame()
rlm@1 3244 {
rlm@1 3245 if(pauseNextFrame) {
rlm@1 3246 paused = true;
rlm@1 3247 pauseNextFrame = false;
rlm@1 3248 return true;
rlm@1 3249 }
rlm@1 3250 return false;
rlm@1 3251 }
rlm@1 3252
rlm@1 3253 // Code donated by Niels Wagenaar (BoycottAdvance)
rlm@1 3254
rlm@1 3255 // GBA screensize.
rlm@1 3256 #define GBA_WIDTH 240
rlm@1 3257 #define GBA_HEIGHT 160
rlm@1 3258
rlm@1 3259 void Init_Overlay(SDL_Surface *gbascreen, int overlaytype)
rlm@1 3260 {
rlm@1 3261
rlm@1 3262 overlay = SDL_CreateYUVOverlay( GBA_WIDTH,
rlm@1 3263 GBA_HEIGHT,
rlm@1 3264 overlaytype, gbascreen);
rlm@1 3265 fprintf(stderr, "Created %dx%dx%d %s %s overlay\n",
rlm@1 3266 overlay->w,overlay->h,overlay->planes,
rlm@1 3267 overlay->hw_overlay?"hardware":"software",
rlm@1 3268 overlay->format==SDL_YV12_OVERLAY?"YV12":
rlm@1 3269 overlay->format==SDL_IYUV_OVERLAY?"IYUV":
rlm@1 3270 overlay->format==SDL_YUY2_OVERLAY?"YUY2":
rlm@1 3271 overlay->format==SDL_UYVY_OVERLAY?"UYVY":
rlm@1 3272 overlay->format==SDL_YVYU_OVERLAY?"YVYU":
rlm@1 3273 "Unknown");
rlm@1 3274 }
rlm@1 3275
rlm@1 3276 void Quit_Overlay(void)
rlm@1 3277 {
rlm@1 3278
rlm@1 3279 SDL_FreeYUVOverlay(overlay);
rlm@1 3280 }
rlm@1 3281
rlm@1 3282 /* NOTE: These RGB conversion functions are not intended for speed,
rlm@1 3283 only as examples.
rlm@1 3284 */
rlm@1 3285 inline void RGBtoYUV(Uint8 *rgb, int *yuv)
rlm@1 3286 {
rlm@1 3287 yuv[0] = (int)((0.257 * rgb[0]) + (0.504 * rgb[1]) + (0.098 * rgb[2]) + 16);
rlm@1 3288 yuv[1] = (int)(128 - (0.148 * rgb[0]) - (0.291 * rgb[1]) + (0.439 * rgb[2]));
rlm@1 3289 yuv[2] = (int)(128 + (0.439 * rgb[0]) - (0.368 * rgb[1]) - (0.071 * rgb[2]));
rlm@1 3290 }
rlm@1 3291
rlm@1 3292 inline void ConvertRGBtoYV12(SDL_Overlay *o)
rlm@1 3293 {
rlm@1 3294 int x,y;
rlm@1 3295 int yuv[3];
rlm@1 3296 Uint8 *p,*op[3];
rlm@1 3297
rlm@1 3298 SDL_LockYUVOverlay(o);
rlm@1 3299
rlm@1 3300 /* Black initialization */
rlm@1 3301 /*
rlm@1 3302 memset(o->pixels[0],0,o->pitches[0]*o->h);
rlm@1 3303 memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
rlm@1 3304 memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
rlm@1 3305 */
rlm@1 3306
rlm@1 3307 /* Convert */
rlm@1 3308 for(y=0; y<160 && y<o->h; y++) {
rlm@1 3309 p=(Uint8 *)pix+srcPitch*y;
rlm@1 3310 op[0]=o->pixels[0]+o->pitches[0]*y;
rlm@1 3311 op[1]=o->pixels[1]+o->pitches[1]*(y/2);
rlm@1 3312 op[2]=o->pixels[2]+o->pitches[2]*(y/2);
rlm@1 3313 for(x=0; x<240 && x<o->w; x++) {
rlm@1 3314 RGBtoYUV(p,yuv);
rlm@1 3315 *(op[0]++)=yuv[0];
rlm@1 3316 if(x%2==0 && y%2==0) {
rlm@1 3317 *(op[1]++)=yuv[2];
rlm@1 3318 *(op[2]++)=yuv[1];
rlm@1 3319 }
rlm@1 3320 p+=4;//s->format->BytesPerPixel;
rlm@1 3321 }
rlm@1 3322 }
rlm@1 3323
rlm@1 3324 SDL_UnlockYUVOverlay(o);
rlm@1 3325 }
rlm@1 3326
rlm@1 3327 inline void ConvertRGBtoIYUV(SDL_Overlay *o)
rlm@1 3328 {
rlm@1 3329 int x,y;
rlm@1 3330 int yuv[3];
rlm@1 3331 Uint8 *p,*op[3];
rlm@1 3332
rlm@1 3333 SDL_LockYUVOverlay(o);
rlm@1 3334
rlm@1 3335 /* Black initialization */
rlm@1 3336 /*
rlm@1 3337 memset(o->pixels[0],0,o->pitches[0]*o->h);
rlm@1 3338 memset(o->pixels[1],128,o->pitches[1]*((o->h+1)/2));
rlm@1 3339 memset(o->pixels[2],128,o->pitches[2]*((o->h+1)/2));
rlm@1 3340 */
rlm@1 3341
rlm@1 3342 /* Convert */
rlm@1 3343 for(y=0; y<160 && y<o->h; y++) {
rlm@1 3344 p=(Uint8 *)pix+srcPitch*y;
rlm@1 3345 op[0]=o->pixels[0]+o->pitches[0]*y;
rlm@1 3346 op[1]=o->pixels[1]+o->pitches[1]*(y/2);
rlm@1 3347 op[2]=o->pixels[2]+o->pitches[2]*(y/2);
rlm@1 3348 for(x=0; x<240 && x<o->w; x++) {
rlm@1 3349 RGBtoYUV(p,yuv);
rlm@1 3350 *(op[0]++)=yuv[0];
rlm@1 3351 if(x%2==0 && y%2==0) {
rlm@1 3352 *(op[1]++)=yuv[1];
rlm@1 3353 *(op[2]++)=yuv[2];
rlm@1 3354 }
rlm@1 3355 p+=4; //s->format->BytesPerPixel;
rlm@1 3356 }
rlm@1 3357 }
rlm@1 3358
rlm@1 3359 SDL_UnlockYUVOverlay(o);
rlm@1 3360 }
rlm@1 3361
rlm@1 3362 inline void ConvertRGBtoUYVY(SDL_Overlay *o)
rlm@1 3363 {
rlm@1 3364 int x,y;
rlm@1 3365 int yuv[3];
rlm@1 3366 Uint8 *p,*op;
rlm@1 3367
rlm@1 3368 SDL_LockYUVOverlay(o);
rlm@1 3369
rlm@1 3370 for(y=0; y<160 && y<o->h; y++) {
rlm@1 3371 p=(Uint8 *)pix+srcPitch*y;
rlm@1 3372 op=o->pixels[0]+o->pitches[0]*y;
rlm@1 3373 for(x=0; x<240 && x<o->w; x++) {
rlm@1 3374 RGBtoYUV(p,yuv);
rlm@1 3375 if(x%2==0) {
rlm@1 3376 *(op++)=yuv[1];
rlm@1 3377 *(op++)=yuv[0];
rlm@1 3378 *(op++)=yuv[2];
rlm@1 3379 } else
rlm@1 3380 *(op++)=yuv[0];
rlm@1 3381
rlm@1 3382 p+=4; //s->format->BytesPerPixel;
rlm@1 3383 }
rlm@1 3384 }
rlm@1 3385
rlm@1 3386 SDL_UnlockYUVOverlay(o);
rlm@1 3387 }
rlm@1 3388
rlm@1 3389 inline void ConvertRGBtoYVYU(SDL_Overlay *o)
rlm@1 3390 {
rlm@1 3391 int x,y;
rlm@1 3392 int yuv[3];
rlm@1 3393 Uint8 *p,*op;
rlm@1 3394
rlm@1 3395 SDL_LockYUVOverlay(o);
rlm@1 3396
rlm@1 3397 for(y=0; y<160 && y<o->h; y++) {
rlm@1 3398 p=(Uint8 *)pix+srcPitch*y;
rlm@1 3399 op=o->pixels[0]+o->pitches[0]*y;
rlm@1 3400 for(x=0; x<240 && x<o->w; x++) {
rlm@1 3401 RGBtoYUV(p,yuv);
rlm@1 3402 if(x%2==0) {
rlm@1 3403 *(op++)=yuv[0];
rlm@1 3404 *(op++)=yuv[2];
rlm@1 3405 op[1]=yuv[1];
rlm@1 3406 } else {
rlm@1 3407 *op=yuv[0];
rlm@1 3408 op+=2;
rlm@1 3409 }
rlm@1 3410
rlm@1 3411 p+=4; //s->format->BytesPerPixel;
rlm@1 3412 }
rlm@1 3413 }
rlm@1 3414
rlm@1 3415 SDL_UnlockYUVOverlay(o);
rlm@1 3416 }
rlm@1 3417
rlm@1 3418 inline void ConvertRGBtoYUY2(SDL_Overlay *o)
rlm@1 3419 {
rlm@1 3420 int x,y;
rlm@1 3421 int yuv[3];
rlm@1 3422 Uint8 *p,*op;
rlm@1 3423
rlm@1 3424 SDL_LockYUVOverlay(o);
rlm@1 3425
rlm@1 3426 for(y=0; y<160 && y<o->h; y++) {
rlm@1 3427 p=(Uint8 *)pix+srcPitch*y;
rlm@1 3428 op=o->pixels[0]+o->pitches[0]*y;
rlm@1 3429 for(x=0; x<240 && x<o->w; x++) {
rlm@1 3430 RGBtoYUV(p,yuv);
rlm@1 3431 if(x%2==0) {
rlm@1 3432 *(op++)=yuv[0];
rlm@1 3433 *(op++)=yuv[1];
rlm@1 3434 op[1]=yuv[2];
rlm@1 3435 } else {
rlm@1 3436 *op=yuv[0];
rlm@1 3437 op+=2;
rlm@1 3438 }
rlm@1 3439
rlm@1 3440 p+=4; //s->format->BytesPerPixel;
rlm@1 3441 }
rlm@1 3442 }
rlm@1 3443
rlm@1 3444 SDL_UnlockYUVOverlay(o);
rlm@1 3445 }
rlm@1 3446
rlm@1 3447 inline void Convert32bit(SDL_Surface *display)
rlm@1 3448 {
rlm@1 3449 switch(overlay->format) {
rlm@1 3450 case SDL_YV12_OVERLAY:
rlm@1 3451 ConvertRGBtoYV12(overlay);
rlm@1 3452 break;
rlm@1 3453 case SDL_UYVY_OVERLAY:
rlm@1 3454 ConvertRGBtoUYVY(overlay);
rlm@1 3455 break;
rlm@1 3456 case SDL_YVYU_OVERLAY:
rlm@1 3457 ConvertRGBtoYVYU(overlay);
rlm@1 3458 break;
rlm@1 3459 case SDL_YUY2_OVERLAY:
rlm@1 3460 ConvertRGBtoYUY2(overlay);
rlm@1 3461 break;
rlm@1 3462 case SDL_IYUV_OVERLAY:
rlm@1 3463 ConvertRGBtoIYUV(overlay);
rlm@1 3464 break;
rlm@1 3465 default:
rlm@1 3466 fprintf(stderr, "cannot convert RGB picture to obtained YUV format!\n");
rlm@1 3467 exit(1);
rlm@1 3468 break;
rlm@1 3469 }
rlm@1 3470
rlm@1 3471 }
rlm@1 3472
rlm@1 3473
rlm@1 3474 inline void Draw_Overlay(SDL_Surface *display, int size)
rlm@1 3475 {
rlm@1 3476 SDL_LockYUVOverlay(overlay);
rlm@1 3477
rlm@1 3478 Convert32bit(display);
rlm@1 3479
rlm@1 3480 overlay_rect.x = 0;
rlm@1 3481 overlay_rect.y = 0;
rlm@1 3482 overlay_rect.w = GBA_WIDTH * size;
rlm@1 3483 overlay_rect.h = GBA_HEIGHT * size;
rlm@1 3484
rlm@1 3485 SDL_DisplayYUVOverlay(overlay, &overlay_rect);
rlm@1 3486 SDL_UnlockYUVOverlay(overlay);
rlm@1 3487 }
rlm@1 3488
rlm@1 3489 bool systemIsEmulating()
rlm@1 3490 {
rlm@1 3491 return emulating != 0;
rlm@1 3492 }
rlm@1 3493
rlm@1 3494 void systemGbBorderOn()
rlm@1 3495 {
rlm@1 3496 srcWidth = 256;
rlm@1 3497 srcHeight = 224;
rlm@1 3498 gbBorderLineSkip = 256;
rlm@1 3499 gbBorderColumnSkip = 48;
rlm@1 3500 gbBorderRowSkip = 40;
rlm@1 3501
rlm@1 3502 destWidth = (sizeOption+1)*srcWidth;
rlm@1 3503 destHeight = (sizeOption+1)*srcHeight;
rlm@1 3504
rlm@1 3505 surface = SDL_SetVideoMode(destWidth, destHeight, 16,
rlm@1 3506 SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|
rlm@1 3507 (fullscreen ? SDL_FULLSCREEN : 0));
rlm@1 3508 #ifndef C_CORE
rlm@1 3509 sdlMakeStretcher(srcWidth);
rlm@1 3510 #else
rlm@1 3511 switch(systemColorDepth) {
rlm@1 3512 case 16:
rlm@1 3513 sdlStretcher = sdlStretcher16[sizeOption];
rlm@1 3514 break;
rlm@1 3515 case 24:
rlm@1 3516 sdlStretcher = sdlStretcher24[sizeOption];
rlm@1 3517 break;
rlm@1 3518 case 32:
rlm@1 3519 sdlStretcher = sdlStretcher32[sizeOption];
rlm@1 3520 break;
rlm@1 3521 default:
rlm@1 3522 fprintf(stderr, "Unsupported resolution: %d\n", systemColorDepth);
rlm@1 3523 exit(-1);
rlm@1 3524 }
rlm@1 3525 #endif
rlm@1 3526
rlm@1 3527 if(systemColorDepth == 16) {
rlm@1 3528 if(sdlCalculateMaskWidth(surface->format->Gmask) == 6) {
rlm@1 3529 Init_2xSaI(565);
rlm@1 3530 RGB_LOW_BITS_MASK = 0x821;
rlm@1 3531 } else {
rlm@1 3532 Init_2xSaI(555);
rlm@1 3533 RGB_LOW_BITS_MASK = 0x421;
rlm@1 3534 }
rlm@1 3535 if(systemCartridgeType == 2) {
rlm@1 3536 for(int i = 0; i < 0x10000; i++) {
rlm@1 3537 systemColorMap16[i] = (((i >> 1) & 0x1f) << systemBlueShift) |
rlm@1 3538 (((i & 0x7c0) >> 6) << systemGreenShift) |
rlm@1 3539 (((i & 0xf800) >> 11) << systemRedShift);
rlm@1 3540 }
rlm@1 3541 } else {
rlm@1 3542 for(int i = 0; i < 0x10000; i++) {
rlm@1 3543 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
rlm@1 3544 (((i & 0x3e0) >> 5) << systemGreenShift) |
rlm@1 3545 (((i & 0x7c00) >> 10) << systemBlueShift);
rlm@1 3546 }
rlm@1 3547 }
rlm@1 3548 srcPitch = srcWidth * 2+4;
rlm@1 3549 } else {
rlm@1 3550 if(systemColorDepth != 32)
rlm@1 3551 filterFunction = NULL;
rlm@1 3552 RGB_LOW_BITS_MASK = 0x010101;
rlm@1 3553 if(systemColorDepth == 32) {
rlm@1 3554 Init_2xSaI(32);
rlm@1 3555 }
rlm@1 3556 for(int i = 0; i < 0x10000; i++) {
rlm@1 3557 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
rlm@1 3558 (((i & 0x3e0) >> 5) << systemGreenShift) |
rlm@1 3559 (((i & 0x7c00) >> 10) << systemBlueShift);
rlm@1 3560 }
rlm@1 3561 if(systemColorDepth == 32)
rlm@1 3562 srcPitch = srcWidth*4 + 4;
rlm@1 3563 else
rlm@1 3564 srcPitch = srcWidth*3;
rlm@1 3565 }
rlm@1 3566 }
rlm@1 3567
rlm@1 3568 bool systemIsRunningGBA()
rlm@1 3569 {
rlm@1 3570 return (rom != NULL);
rlm@1 3571 }
rlm@1 3572
rlm@1 3573 int systemGetDefaultJoypad()
rlm@1 3574 {
rlm@1 3575 return sdlDefaultJoypad;
rlm@1 3576 }
rlm@1 3577
rlm@1 3578 bool systemIsPaused()
rlm@1 3579 {
rlm@1 3580 return paused;
rlm@1 3581 }
rlm@1 3582
rlm@1 3583 void systemSetPause(bool pause)
rlm@1 3584 {
rlm@1 3585 paused = pause;
rlm@1 3586 if (pause)
rlm@1 3587 systemSoundPause();
rlm@1 3588 else
rlm@1 3589 systemSoundResume();
rlm@1 3590 }
rlm@1 3591
rlm@1 3592 u16 checksumBIOS()
rlm@1 3593 {
rlm@1 3594 bool hasBIOS = false;
rlm@1 3595 u8 * tempBIOS;
rlm@1 3596 if(useBios)
rlm@1 3597 {
rlm@1 3598 tempBIOS = (u8 *)malloc(0x4000);
rlm@1 3599 int size = 0x4000;
rlm@1 3600 if(utilLoad(biosFileName,
rlm@1 3601 utilIsGBABios,
rlm@1 3602 tempBIOS,
rlm@1 3603 size)) {
rlm@1 3604 if(size == 0x4000)
rlm@1 3605 hasBIOS = true;
rlm@1 3606 }
rlm@1 3607 }
rlm@1 3608
rlm@1 3609 u16 biosCheck = 0;
rlm@1 3610 if(hasBIOS) {
rlm@1 3611 for(int i = 0; i < 0x4000; i += 4)
rlm@1 3612 biosCheck += *((u32 *)&tempBIOS[i]);
rlm@1 3613 free(tempBIOS);
rlm@1 3614 }
rlm@1 3615
rlm@1 3616 return biosCheck;
rlm@1 3617 }
rlm@1 3618
rlm@1 3619 EmulatedSystemCounters systemCounters = {
rlm@1 3620 0, //framecount
rlm@1 3621 0, //lagcount
rlm@1 3622 0, //extracount
rlm@1 3623 true, //lagged
rlm@1 3624 true //laggedLast
rlm@1 3625 };
rlm@1 3626
rlm@1 3627 void VBAOnEnteringFrameBoundary()
rlm@1 3628 {
rlm@39 3629 //printf("RLM: Entering Frame Boundary\n");
rlm@33 3630 CallRegisteredLuaFunctions(LUACALL_AFTEREMULATION);
rlm@33 3631
rlm@33 3632 if (VBALuaRunning())
rlm@33 3633 {
rlm@33 3634 VBALuaFrameBoundary();
rlm@33 3635 }
rlm@33 3636
rlm@39 3637 //printf("RLM: Movie state update pending\n");
rlm@33 3638 VBAMovieUpdateState();
rlm@39 3639 //printf("RLM: Movie state updated\n");
rlm@1 3640 }
rlm@1 3641
rlm@1 3642 void VBAOnExitingFrameBoundary()
rlm@1 3643 {
rlm@1 3644 ;
rlm@1 3645 }
rlm@1 3646
rlm@1 3647