rlm@1: // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. rlm@1: // Copyright (C) 1999-2003 Forgotten rlm@1: // Copyright (C) 2004 Forgotten and the VBA development team rlm@1: rlm@1: // This program is free software; you can redistribute it and/or modify rlm@1: // it under the terms of the GNU General Public License as published by rlm@1: // the Free Software Foundation; either version 2, or(at your option) rlm@1: // any later version. rlm@1: // rlm@1: // This program is distributed in the hope that it will be useful, rlm@1: // but WITHOUT ANY WARRANTY; without even the implied warranty of rlm@1: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rlm@1: // GNU General Public License for more details. rlm@1: // rlm@1: // You should have received a copy of the GNU General Public License rlm@1: // along with this program; if not, write to the Free Software Foundation, rlm@1: // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. rlm@1: rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: rlm@1: #include rlm@1: #include rlm@1: rlm@1: #include "../common/System.h" rlm@1: #include "../common/Util.h" rlm@1: #include "../gba/GBAGlobals.h" rlm@1: #include "../gb/gbGlobals.h" rlm@1: #include "../gba/GBASound.h" rlm@1: rlm@1: #include "window.h" rlm@1: #include "intl.h" rlm@1: rlm@1: // Required vars, used by the emulator core rlm@1: // rlm@1: int systemRedShift; rlm@1: int systemGreenShift; rlm@1: int systemBlueShift; rlm@1: int systemColorDepth; rlm@1: int systemDebug; rlm@1: int systemVerbose; rlm@1: int systemSaveUpdateCounter; rlm@1: int systemFrameSkip; rlm@1: u32 systemColorMap32[0x10000]; rlm@1: u16 systemColorMap16[0x10000]; rlm@1: u16 systemGbPalette[24]; rlm@1: bool systemSoundOn; rlm@1: rlm@1: char filename[2048]; rlm@1: char biosFileName[2048]; rlm@1: //char captureDir[2048]; rlm@1: char saveDir[2048]; rlm@1: char batteryDir[2048]; rlm@1: rlm@1: int sensorX = 2047; rlm@1: int sensorY = 2047; rlm@1: bool sensorOn = false; rlm@1: rlm@1: int emulating; rlm@1: bool debugger; rlm@1: int RGB_LOW_BITS_MASK; rlm@1: rlm@1: int cartridgeType = 3; rlm@1: int sizeOption = 0; rlm@1: int captureFormat = 0; rlm@1: int throttle = 0; rlm@1: bool paused = false; rlm@1: bool removeIntros = false; rlm@1: int sdlFlashSize = 0; rlm@1: int sdlRtcEnable = 0; rlm@1: rlm@1: int sdlDefaultJoypad = 0; rlm@1: rlm@1: SDL_Joystick **sdlDevices = NULL; rlm@1: rlm@1: u16 motion[4] = { rlm@1: SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 rlm@1: }; rlm@1: rlm@1: struct EmulatedSystem emulator = { rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: NULL, rlm@1: false, rlm@1: 0 rlm@1: }; rlm@1: rlm@1: // Extra vars, only used for the GUI rlm@1: // rlm@1: int systemRenderedFrames; rlm@1: int systemFPS; rlm@1: rlm@1: // Sound stuff rlm@1: // rlm@1: const int iSoundSamples = 2048; rlm@1: const int iSoundTotalLen = iSoundSamples * 4; rlm@1: static u8 auiSoundBuffer[iSoundTotalLen]; rlm@1: static int iSoundLen; rlm@1: static SDL_cond * pstSoundCond; rlm@1: static SDL_mutex * pstSoundMutex; rlm@1: rlm@1: inline VBA::Window * GUI() rlm@1: { rlm@1: return VBA::Window::poGetInstance(); rlm@1: } rlm@1: rlm@1: void systemMessage(int _iId, const char * _csFormat, ...) rlm@1: { rlm@1: va_list args; rlm@1: va_start(args, _csFormat); rlm@1: rlm@1: GUI()->vPopupErrorV(_(_csFormat), args); rlm@1: rlm@1: va_end(args); rlm@1: } rlm@1: rlm@1: void systemDrawScreen() rlm@1: { rlm@1: GUI()->vDrawScreen(); rlm@1: systemRenderedFrames++; rlm@1: } rlm@1: rlm@1: bool systemReadJoypads() rlm@1: { rlm@1: return true; rlm@1: } rlm@1: rlm@1: u32 systemReadJoypad(int,bool) rlm@1: { rlm@1: return GUI()->uiReadJoypad(); rlm@1: } rlm@1: rlm@1: void systemShowSpeed(int _iSpeed) rlm@1: { rlm@1: systemFPS = systemRenderedFrames; rlm@1: systemRenderedFrames = 0; rlm@1: rlm@1: GUI()->vShowSpeed(_iSpeed); rlm@1: } rlm@1: rlm@1: void system10Frames(int _iRate) rlm@1: { rlm@1: GUI()->vComputeFrameskip(_iRate); rlm@1: } rlm@1: rlm@1: void systemFrame(int) rlm@1: { rlm@1: } rlm@1: rlm@1: void systemSetTitle(const char * _csTitle) rlm@1: { rlm@1: GUI()->set_title(_csTitle); rlm@1: } rlm@1: rlm@1: int systemScreenCapture(int _iNum) rlm@1: { rlm@1: GUI()->vCaptureScreen(_iNum); rlm@1: } rlm@1: rlm@1: void systemSoundWriteToBuffer() rlm@1: { rlm@1: if (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING) rlm@1: { rlm@1: SDL_PauseAudio(0); rlm@1: } rlm@1: rlm@1: bool bWait = true; rlm@1: while (bWait && ! speedup && GUI()->iGetThrottle() == 0) rlm@1: { rlm@1: SDL_mutexP(pstSoundMutex); rlm@1: if (iSoundLen < iSoundTotalLen) rlm@1: { rlm@1: bWait = false; rlm@1: } rlm@1: SDL_mutexV(pstSoundMutex); rlm@1: } rlm@1: rlm@1: int iLen = soundBufferLen; rlm@1: int iCopied = 0; rlm@1: if (iSoundLen + iLen >= iSoundTotalLen) rlm@1: { rlm@1: iCopied = iSoundTotalLen - iSoundLen; rlm@1: memcpy(&auiSoundBuffer[iSoundLen], soundFinalWave, iCopied); rlm@1: rlm@1: iSoundLen = iSoundTotalLen; rlm@1: SDL_CondSignal(pstSoundCond); rlm@1: rlm@1: bWait = true; rlm@1: if (! speedup && GUI()->iGetThrottle() == 0) rlm@1: { rlm@1: while(bWait) rlm@1: { rlm@1: SDL_mutexP(pstSoundMutex); rlm@1: if (iSoundLen < iSoundTotalLen) rlm@1: { rlm@1: bWait = false; rlm@1: } rlm@1: SDL_mutexV(pstSoundMutex); rlm@1: } rlm@1: rlm@1: memcpy(auiSoundBuffer, ((u8 *)soundFinalWave) + iCopied, rlm@1: soundBufferLen - iCopied); rlm@1: rlm@1: iSoundLen = soundBufferLen - iCopied; rlm@1: } rlm@1: else rlm@1: { rlm@1: memcpy(auiSoundBuffer, ((u8 *)soundFinalWave) + iCopied, rlm@1: soundBufferLen); rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: memcpy(&auiSoundBuffer[iSoundLen], soundFinalWave, soundBufferLen); rlm@1: iSoundLen += soundBufferLen; rlm@1: } rlm@1: } rlm@1: rlm@1: static void vSoundCallback(void * _pvUserData, u8 * _puiStream, int _iLen) rlm@1: { rlm@1: if (! emulating) rlm@1: { rlm@1: return; rlm@1: } rlm@1: rlm@1: SDL_mutexP(pstSoundMutex); rlm@1: if (! speedup && GUI()->iGetThrottle() == 0) rlm@1: { rlm@1: while (iSoundLen < iSoundTotalLen && emulating) rlm@1: { rlm@1: SDL_CondWait(pstSoundCond, pstSoundMutex); rlm@1: } rlm@1: } rlm@1: if (emulating) rlm@1: { rlm@1: memcpy(_puiStream, auiSoundBuffer, _iLen); rlm@1: } rlm@1: iSoundLen = 0; rlm@1: SDL_mutexV(pstSoundMutex); rlm@1: } rlm@1: rlm@1: bool systemSoundInit() rlm@1: { rlm@1: SDL_AudioSpec stAudio; rlm@1: rlm@1: switch (soundQuality) rlm@1: { rlm@1: case 1: rlm@1: stAudio.freq = 44100; rlm@1: soundBufferLen = 1470 * 2; rlm@1: break; rlm@1: case 2: rlm@1: stAudio.freq = 22050; rlm@1: soundBufferLen = 736 * 2; rlm@1: break; rlm@1: case 4: rlm@1: stAudio.freq = 11025; rlm@1: soundBufferLen = 368 * 2; rlm@1: break; rlm@1: } rlm@1: rlm@1: stAudio.format = AUDIO_S16SYS; rlm@1: stAudio.channels = 2; rlm@1: stAudio.samples = iSoundSamples; rlm@1: stAudio.callback = vSoundCallback; rlm@1: stAudio.userdata = NULL; rlm@1: rlm@1: if (SDL_OpenAudio(&stAudio, NULL) < 0) rlm@1: { rlm@1: fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError()); rlm@1: return false; rlm@1: } rlm@1: rlm@1: pstSoundCond = SDL_CreateCond(); rlm@1: pstSoundMutex = SDL_CreateMutex(); rlm@1: rlm@1: soundBufferTotalLen = soundBufferLen * 10; rlm@1: iSoundLen = 0; rlm@1: systemSoundOn = true; rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: void systemSoundShutdown() rlm@1: { rlm@1: SDL_mutexP(pstSoundMutex); rlm@1: int iSave = emulating; rlm@1: emulating = 0; rlm@1: SDL_CondSignal(pstSoundCond); rlm@1: SDL_mutexV(pstSoundMutex); rlm@1: rlm@1: SDL_DestroyCond(pstSoundCond); rlm@1: pstSoundCond = NULL; rlm@1: rlm@1: SDL_DestroyMutex(pstSoundMutex); rlm@1: pstSoundMutex = NULL; rlm@1: rlm@1: SDL_CloseAudio(); rlm@1: rlm@1: emulating = iSave; rlm@1: systemSoundOn = false; rlm@1: } rlm@1: rlm@1: void systemSoundPause() rlm@1: { rlm@1: SDL_PauseAudio(1); rlm@1: } rlm@1: rlm@1: void systemSoundResume() rlm@1: { rlm@1: SDL_PauseAudio(0); rlm@1: } rlm@1: rlm@1: void systemSoundReset() rlm@1: { rlm@1: } rlm@1: rlm@1: u32 systemGetClock() rlm@1: { rlm@1: return SDL_GetTicks(); rlm@1: } rlm@1: rlm@1: void systemUpdateMotionSensor() rlm@1: { rlm@1: } rlm@1: rlm@1: int systemGetSensorX() rlm@1: { rlm@1: return 0; rlm@1: } rlm@1: rlm@1: int systemGetSensorY() rlm@1: { rlm@1: return 0; rlm@1: } rlm@1: rlm@1: void systemGbPrint(u8 * _puiData, rlm@1: int _iPages, rlm@1: int _iFeed, rlm@1: int _iPalette, rlm@1: int _iContrast) rlm@1: { rlm@1: } rlm@1: rlm@1: void systemScreenMessage(const char * _csMsg, int slot, int duration, const char *colorList) rlm@1: { rlm@1: } rlm@1: rlm@1: bool systemCanChangeSoundQuality() rlm@1: { rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool systemPauseOnFrame() rlm@1: { rlm@1: return false; rlm@1: } rlm@1: rlm@1: void systemGbBorderOn() rlm@1: { rlm@1: } rlm@1: rlm@1: void debuggerMain() rlm@1: { rlm@1: } rlm@1: rlm@1: void debuggerSignal(int, int) rlm@1: { rlm@1: } rlm@1: rlm@1: void debuggerOutput(char *, u32) rlm@1: { rlm@1: } rlm@1: rlm@1: char *sdlGetFilename(char *name) rlm@1: { rlm@1: static char filebuffer[2048]; rlm@1: rlm@1: int len = strlen(name); rlm@1: rlm@1: char *p = name + len - 1; rlm@1: rlm@1: while(true) { rlm@1: if(*p == '/' || rlm@1: *p == '\\') { rlm@1: p++; rlm@1: break; rlm@1: } rlm@1: len--; rlm@1: p--; rlm@1: if(len == 0) rlm@1: break; rlm@1: } rlm@1: rlm@1: if(len == 0) rlm@1: strcpy(filebuffer, name); rlm@1: else rlm@1: strcpy(filebuffer, p); rlm@1: return filebuffer; rlm@1: } rlm@1: rlm@1: bool sdlCheckJoyKey(int key) rlm@1: { rlm@1: int dev = (key >> 12) - 1; rlm@1: int what = key & 0xfff; rlm@1: rlm@1: if(what >= 128) { rlm@1: // joystick button rlm@1: int button = what - 128; rlm@1: rlm@1: if(button >= SDL_JoystickNumButtons(sdlDevices[dev])) rlm@1: return false; rlm@1: } else if (what < 0x20) { rlm@1: // joystick axis rlm@1: what >>= 1; rlm@1: if(what >= SDL_JoystickNumAxes(sdlDevices[dev])) rlm@1: return false; rlm@1: } else if (what < 0x30) { rlm@1: // joystick hat rlm@1: what = (what & 15); rlm@1: what >>= 2; rlm@1: if(what >= SDL_JoystickNumHats(sdlDevices[dev])) rlm@1: return false; rlm@1: } rlm@1: rlm@1: // no problem found rlm@1: return true; rlm@1: } rlm@1: rlm@1: u16 checksumBIOS() rlm@1: { rlm@1: bool hasBIOS = false; rlm@1: u8 * tempBIOS; rlm@1: if(useBios) rlm@1: { rlm@1: tempBIOS = (u8 *)malloc(0x4000); rlm@1: int size = 0x4000; rlm@1: if(utilLoad(biosFileName, rlm@1: utilIsGBABios, rlm@1: tempBIOS, rlm@1: size)) { rlm@1: if(size == 0x4000) rlm@1: hasBIOS = true; rlm@1: } rlm@1: } rlm@1: rlm@1: u16 biosCheck = 0; rlm@1: if(hasBIOS) { rlm@1: for(int i = 0; i < 0x4000; i += 4) rlm@1: biosCheck += *((u32 *)&tempBIOS[i]); rlm@1: free(tempBIOS); rlm@1: } rlm@1: rlm@1: return biosCheck; rlm@1: } rlm@1: rlm@1: void (*dbgMain)() = debuggerMain; rlm@1: void (*dbgSignal)(int, int) = debuggerSignal; rlm@1: void (*dbgOutput)(char *, u32) = debuggerOutput;