annotate src/gtk/system.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
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 <stdio.h>
rlm@1 20 #include <stdarg.h>
rlm@1 21 #include <string.h>
rlm@1 22
rlm@1 23 #include <SDL.h>
rlm@1 24 #include <SDL_thread.h>
rlm@1 25
rlm@1 26 #include "../common/System.h"
rlm@1 27 #include "../common/Util.h"
rlm@1 28 #include "../gba/GBAGlobals.h"
rlm@1 29 #include "../gb/gbGlobals.h"
rlm@1 30 #include "../gba/GBASound.h"
rlm@1 31
rlm@1 32 #include "window.h"
rlm@1 33 #include "intl.h"
rlm@1 34
rlm@1 35 // Required vars, used by the emulator core
rlm@1 36 //
rlm@1 37 int systemRedShift;
rlm@1 38 int systemGreenShift;
rlm@1 39 int systemBlueShift;
rlm@1 40 int systemColorDepth;
rlm@1 41 int systemDebug;
rlm@1 42 int systemVerbose;
rlm@1 43 int systemSaveUpdateCounter;
rlm@1 44 int systemFrameSkip;
rlm@1 45 u32 systemColorMap32[0x10000];
rlm@1 46 u16 systemColorMap16[0x10000];
rlm@1 47 u16 systemGbPalette[24];
rlm@1 48 bool systemSoundOn;
rlm@1 49
rlm@1 50 char filename[2048];
rlm@1 51 char biosFileName[2048];
rlm@1 52 //char captureDir[2048];
rlm@1 53 char saveDir[2048];
rlm@1 54 char batteryDir[2048];
rlm@1 55
rlm@1 56 int sensorX = 2047;
rlm@1 57 int sensorY = 2047;
rlm@1 58 bool sensorOn = false;
rlm@1 59
rlm@1 60 int emulating;
rlm@1 61 bool debugger;
rlm@1 62 int RGB_LOW_BITS_MASK;
rlm@1 63
rlm@1 64 int cartridgeType = 3;
rlm@1 65 int sizeOption = 0;
rlm@1 66 int captureFormat = 0;
rlm@1 67 int throttle = 0;
rlm@1 68 bool paused = false;
rlm@1 69 bool removeIntros = false;
rlm@1 70 int sdlFlashSize = 0;
rlm@1 71 int sdlRtcEnable = 0;
rlm@1 72
rlm@1 73 int sdlDefaultJoypad = 0;
rlm@1 74
rlm@1 75 SDL_Joystick **sdlDevices = NULL;
rlm@1 76
rlm@1 77 u16 motion[4] = {
rlm@1 78 SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2
rlm@1 79 };
rlm@1 80
rlm@1 81 struct EmulatedSystem emulator = {
rlm@1 82 NULL,
rlm@1 83 NULL,
rlm@1 84 NULL,
rlm@1 85 NULL,
rlm@1 86 NULL,
rlm@1 87 NULL,
rlm@1 88 NULL,
rlm@1 89 NULL,
rlm@1 90 NULL,
rlm@1 91 NULL,
rlm@1 92 NULL,
rlm@1 93 NULL,
rlm@1 94 false,
rlm@1 95 0
rlm@1 96 };
rlm@1 97
rlm@1 98 // Extra vars, only used for the GUI
rlm@1 99 //
rlm@1 100 int systemRenderedFrames;
rlm@1 101 int systemFPS;
rlm@1 102
rlm@1 103 // Sound stuff
rlm@1 104 //
rlm@1 105 const int iSoundSamples = 2048;
rlm@1 106 const int iSoundTotalLen = iSoundSamples * 4;
rlm@1 107 static u8 auiSoundBuffer[iSoundTotalLen];
rlm@1 108 static int iSoundLen;
rlm@1 109 static SDL_cond * pstSoundCond;
rlm@1 110 static SDL_mutex * pstSoundMutex;
rlm@1 111
rlm@1 112 inline VBA::Window * GUI()
rlm@1 113 {
rlm@1 114 return VBA::Window::poGetInstance();
rlm@1 115 }
rlm@1 116
rlm@1 117 void systemMessage(int _iId, const char * _csFormat, ...)
rlm@1 118 {
rlm@1 119 va_list args;
rlm@1 120 va_start(args, _csFormat);
rlm@1 121
rlm@1 122 GUI()->vPopupErrorV(_(_csFormat), args);
rlm@1 123
rlm@1 124 va_end(args);
rlm@1 125 }
rlm@1 126
rlm@1 127 void systemDrawScreen()
rlm@1 128 {
rlm@1 129 GUI()->vDrawScreen();
rlm@1 130 systemRenderedFrames++;
rlm@1 131 }
rlm@1 132
rlm@1 133 bool systemReadJoypads()
rlm@1 134 {
rlm@1 135 return true;
rlm@1 136 }
rlm@1 137
rlm@1 138 u32 systemReadJoypad(int,bool)
rlm@1 139 {
rlm@1 140 return GUI()->uiReadJoypad();
rlm@1 141 }
rlm@1 142
rlm@1 143 void systemShowSpeed(int _iSpeed)
rlm@1 144 {
rlm@1 145 systemFPS = systemRenderedFrames;
rlm@1 146 systemRenderedFrames = 0;
rlm@1 147
rlm@1 148 GUI()->vShowSpeed(_iSpeed);
rlm@1 149 }
rlm@1 150
rlm@1 151 void system10Frames(int _iRate)
rlm@1 152 {
rlm@1 153 GUI()->vComputeFrameskip(_iRate);
rlm@1 154 }
rlm@1 155
rlm@1 156 void systemFrame(int)
rlm@1 157 {
rlm@1 158 }
rlm@1 159
rlm@1 160 void systemSetTitle(const char * _csTitle)
rlm@1 161 {
rlm@1 162 GUI()->set_title(_csTitle);
rlm@1 163 }
rlm@1 164
rlm@1 165 int systemScreenCapture(int _iNum)
rlm@1 166 {
rlm@1 167 GUI()->vCaptureScreen(_iNum);
rlm@1 168 }
rlm@1 169
rlm@1 170 void systemSoundWriteToBuffer()
rlm@1 171 {
rlm@1 172 if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)
rlm@1 173 {
rlm@1 174 SDL_PauseAudio(0);
rlm@1 175 }
rlm@1 176
rlm@1 177 bool bWait = true;
rlm@1 178 while (bWait && ! speedup && GUI()->iGetThrottle() == 0)
rlm@1 179 {
rlm@1 180 SDL_mutexP(pstSoundMutex);
rlm@1 181 if (iSoundLen < iSoundTotalLen)
rlm@1 182 {
rlm@1 183 bWait = false;
rlm@1 184 }
rlm@1 185 SDL_mutexV(pstSoundMutex);
rlm@1 186 }
rlm@1 187
rlm@1 188 int iLen = soundBufferLen;
rlm@1 189 int iCopied = 0;
rlm@1 190 if (iSoundLen + iLen >= iSoundTotalLen)
rlm@1 191 {
rlm@1 192 iCopied = iSoundTotalLen - iSoundLen;
rlm@1 193 memcpy(&auiSoundBuffer[iSoundLen], soundFinalWave, iCopied);
rlm@1 194
rlm@1 195 iSoundLen = iSoundTotalLen;
rlm@1 196 SDL_CondSignal(pstSoundCond);
rlm@1 197
rlm@1 198 bWait = true;
rlm@1 199 if (! speedup && GUI()->iGetThrottle() == 0)
rlm@1 200 {
rlm@1 201 while(bWait)
rlm@1 202 {
rlm@1 203 SDL_mutexP(pstSoundMutex);
rlm@1 204 if (iSoundLen < iSoundTotalLen)
rlm@1 205 {
rlm@1 206 bWait = false;
rlm@1 207 }
rlm@1 208 SDL_mutexV(pstSoundMutex);
rlm@1 209 }
rlm@1 210
rlm@1 211 memcpy(auiSoundBuffer, ((u8 *)soundFinalWave) + iCopied,
rlm@1 212 soundBufferLen - iCopied);
rlm@1 213
rlm@1 214 iSoundLen = soundBufferLen - iCopied;
rlm@1 215 }
rlm@1 216 else
rlm@1 217 {
rlm@1 218 memcpy(auiSoundBuffer, ((u8 *)soundFinalWave) + iCopied,
rlm@1 219 soundBufferLen);
rlm@1 220 }
rlm@1 221 }
rlm@1 222 else
rlm@1 223 {
rlm@1 224 memcpy(&auiSoundBuffer[iSoundLen], soundFinalWave, soundBufferLen);
rlm@1 225 iSoundLen += soundBufferLen;
rlm@1 226 }
rlm@1 227 }
rlm@1 228
rlm@1 229 static void vSoundCallback(void * _pvUserData, u8 * _puiStream, int _iLen)
rlm@1 230 {
rlm@1 231 if (! emulating)
rlm@1 232 {
rlm@1 233 return;
rlm@1 234 }
rlm@1 235
rlm@1 236 SDL_mutexP(pstSoundMutex);
rlm@1 237 if (! speedup && GUI()->iGetThrottle() == 0)
rlm@1 238 {
rlm@1 239 while (iSoundLen < iSoundTotalLen && emulating)
rlm@1 240 {
rlm@1 241 SDL_CondWait(pstSoundCond, pstSoundMutex);
rlm@1 242 }
rlm@1 243 }
rlm@1 244 if (emulating)
rlm@1 245 {
rlm@1 246 memcpy(_puiStream, auiSoundBuffer, _iLen);
rlm@1 247 }
rlm@1 248 iSoundLen = 0;
rlm@1 249 SDL_mutexV(pstSoundMutex);
rlm@1 250 }
rlm@1 251
rlm@1 252 bool systemSoundInit()
rlm@1 253 {
rlm@1 254 SDL_AudioSpec stAudio;
rlm@1 255
rlm@1 256 switch (soundQuality)
rlm@1 257 {
rlm@1 258 case 1:
rlm@1 259 stAudio.freq = 44100;
rlm@1 260 soundBufferLen = 1470 * 2;
rlm@1 261 break;
rlm@1 262 case 2:
rlm@1 263 stAudio.freq = 22050;
rlm@1 264 soundBufferLen = 736 * 2;
rlm@1 265 break;
rlm@1 266 case 4:
rlm@1 267 stAudio.freq = 11025;
rlm@1 268 soundBufferLen = 368 * 2;
rlm@1 269 break;
rlm@1 270 }
rlm@1 271
rlm@1 272 stAudio.format = AUDIO_S16SYS;
rlm@1 273 stAudio.channels = 2;
rlm@1 274 stAudio.samples = iSoundSamples;
rlm@1 275 stAudio.callback = vSoundCallback;
rlm@1 276 stAudio.userdata = NULL;
rlm@1 277
rlm@1 278 if (SDL_OpenAudio(&stAudio, NULL) < 0)
rlm@1 279 {
rlm@1 280 fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError());
rlm@1 281 return false;
rlm@1 282 }
rlm@1 283
rlm@1 284 pstSoundCond = SDL_CreateCond();
rlm@1 285 pstSoundMutex = SDL_CreateMutex();
rlm@1 286
rlm@1 287 soundBufferTotalLen = soundBufferLen * 10;
rlm@1 288 iSoundLen = 0;
rlm@1 289 systemSoundOn = true;
rlm@1 290
rlm@1 291 return true;
rlm@1 292 }
rlm@1 293
rlm@1 294 void systemSoundShutdown()
rlm@1 295 {
rlm@1 296 SDL_mutexP(pstSoundMutex);
rlm@1 297 int iSave = emulating;
rlm@1 298 emulating = 0;
rlm@1 299 SDL_CondSignal(pstSoundCond);
rlm@1 300 SDL_mutexV(pstSoundMutex);
rlm@1 301
rlm@1 302 SDL_DestroyCond(pstSoundCond);
rlm@1 303 pstSoundCond = NULL;
rlm@1 304
rlm@1 305 SDL_DestroyMutex(pstSoundMutex);
rlm@1 306 pstSoundMutex = NULL;
rlm@1 307
rlm@1 308 SDL_CloseAudio();
rlm@1 309
rlm@1 310 emulating = iSave;
rlm@1 311 systemSoundOn = false;
rlm@1 312 }
rlm@1 313
rlm@1 314 void systemSoundPause()
rlm@1 315 {
rlm@1 316 SDL_PauseAudio(1);
rlm@1 317 }
rlm@1 318
rlm@1 319 void systemSoundResume()
rlm@1 320 {
rlm@1 321 SDL_PauseAudio(0);
rlm@1 322 }
rlm@1 323
rlm@1 324 void systemSoundReset()
rlm@1 325 {
rlm@1 326 }
rlm@1 327
rlm@1 328 u32 systemGetClock()
rlm@1 329 {
rlm@1 330 return SDL_GetTicks();
rlm@1 331 }
rlm@1 332
rlm@1 333 void systemUpdateMotionSensor()
rlm@1 334 {
rlm@1 335 }
rlm@1 336
rlm@1 337 int systemGetSensorX()
rlm@1 338 {
rlm@1 339 return 0;
rlm@1 340 }
rlm@1 341
rlm@1 342 int systemGetSensorY()
rlm@1 343 {
rlm@1 344 return 0;
rlm@1 345 }
rlm@1 346
rlm@1 347 void systemGbPrint(u8 * _puiData,
rlm@1 348 int _iPages,
rlm@1 349 int _iFeed,
rlm@1 350 int _iPalette,
rlm@1 351 int _iContrast)
rlm@1 352 {
rlm@1 353 }
rlm@1 354
rlm@1 355 void systemScreenMessage(const char * _csMsg, int slot, int duration, const char *colorList)
rlm@1 356 {
rlm@1 357 }
rlm@1 358
rlm@1 359 bool systemCanChangeSoundQuality()
rlm@1 360 {
rlm@1 361 return true;
rlm@1 362 }
rlm@1 363
rlm@1 364 bool systemPauseOnFrame()
rlm@1 365 {
rlm@1 366 return false;
rlm@1 367 }
rlm@1 368
rlm@1 369 void systemGbBorderOn()
rlm@1 370 {
rlm@1 371 }
rlm@1 372
rlm@1 373 void debuggerMain()
rlm@1 374 {
rlm@1 375 }
rlm@1 376
rlm@1 377 void debuggerSignal(int, int)
rlm@1 378 {
rlm@1 379 }
rlm@1 380
rlm@1 381 void debuggerOutput(char *, u32)
rlm@1 382 {
rlm@1 383 }
rlm@1 384
rlm@1 385 char *sdlGetFilename(char *name)
rlm@1 386 {
rlm@1 387 static char filebuffer[2048];
rlm@1 388
rlm@1 389 int len = strlen(name);
rlm@1 390
rlm@1 391 char *p = name + len - 1;
rlm@1 392
rlm@1 393 while(true) {
rlm@1 394 if(*p == '/' ||
rlm@1 395 *p == '\\') {
rlm@1 396 p++;
rlm@1 397 break;
rlm@1 398 }
rlm@1 399 len--;
rlm@1 400 p--;
rlm@1 401 if(len == 0)
rlm@1 402 break;
rlm@1 403 }
rlm@1 404
rlm@1 405 if(len == 0)
rlm@1 406 strcpy(filebuffer, name);
rlm@1 407 else
rlm@1 408 strcpy(filebuffer, p);
rlm@1 409 return filebuffer;
rlm@1 410 }
rlm@1 411
rlm@1 412 bool sdlCheckJoyKey(int key)
rlm@1 413 {
rlm@1 414 int dev = (key >> 12) - 1;
rlm@1 415 int what = key & 0xfff;
rlm@1 416
rlm@1 417 if(what >= 128) {
rlm@1 418 // joystick button
rlm@1 419 int button = what - 128;
rlm@1 420
rlm@1 421 if(button >= SDL_JoystickNumButtons(sdlDevices[dev]))
rlm@1 422 return false;
rlm@1 423 } else if (what < 0x20) {
rlm@1 424 // joystick axis
rlm@1 425 what >>= 1;
rlm@1 426 if(what >= SDL_JoystickNumAxes(sdlDevices[dev]))
rlm@1 427 return false;
rlm@1 428 } else if (what < 0x30) {
rlm@1 429 // joystick hat
rlm@1 430 what = (what & 15);
rlm@1 431 what >>= 2;
rlm@1 432 if(what >= SDL_JoystickNumHats(sdlDevices[dev]))
rlm@1 433 return false;
rlm@1 434 }
rlm@1 435
rlm@1 436 // no problem found
rlm@1 437 return true;
rlm@1 438 }
rlm@1 439
rlm@1 440 u16 checksumBIOS()
rlm@1 441 {
rlm@1 442 bool hasBIOS = false;
rlm@1 443 u8 * tempBIOS;
rlm@1 444 if(useBios)
rlm@1 445 {
rlm@1 446 tempBIOS = (u8 *)malloc(0x4000);
rlm@1 447 int size = 0x4000;
rlm@1 448 if(utilLoad(biosFileName,
rlm@1 449 utilIsGBABios,
rlm@1 450 tempBIOS,
rlm@1 451 size)) {
rlm@1 452 if(size == 0x4000)
rlm@1 453 hasBIOS = true;
rlm@1 454 }
rlm@1 455 }
rlm@1 456
rlm@1 457 u16 biosCheck = 0;
rlm@1 458 if(hasBIOS) {
rlm@1 459 for(int i = 0; i < 0x4000; i += 4)
rlm@1 460 biosCheck += *((u32 *)&tempBIOS[i]);
rlm@1 461 free(tempBIOS);
rlm@1 462 }
rlm@1 463
rlm@1 464 return biosCheck;
rlm@1 465 }
rlm@1 466
rlm@1 467 void (*dbgMain)() = debuggerMain;
rlm@1 468 void (*dbgSignal)(int, int) = debuggerSignal;
rlm@1 469 void (*dbgOutput)(char *, u32) = debuggerOutput;