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: #include rlm@1: #include rlm@1: #include rlm@1: rlm@1: #include "AutoBuild.h" rlm@1: rlm@1: #include "SDL.h" rlm@1: #include "debugger.h" rlm@1: #include "common/System.h" rlm@1: #include "common/unzip.h" rlm@1: #include "common/Util.h" rlm@1: #include "gba/GBA.h" rlm@1: #include "gba/GBAGlobals.h" rlm@1: #include "gba/GBASound.h" rlm@1: #include "gb/GB.h" rlm@1: #include "gb/gbGlobals.h" rlm@1: rlm@1: #ifndef WIN32 rlm@1: # include rlm@1: # define GETCWD getcwd rlm@1: #else // WIN32 rlm@1: # include rlm@1: # define GETCWD _getcwd rlm@1: #endif // WIN32 rlm@1: rlm@1: #ifdef MMX rlm@1: extern "C" bool cpu_mmx; rlm@1: #endif rlm@1: extern bool8 soundEcho; rlm@1: extern bool8 soundLowPass; rlm@1: extern bool8 soundReverse; rlm@1: rlm@1: extern void remoteInit(); rlm@1: extern void remoteCleanUp(); rlm@1: extern void remoteStubMain(); rlm@1: extern void remoteStubSignal(int,int); rlm@1: extern void remoteOutput(char *, u32); rlm@1: extern void remoteSetProtocol(int); rlm@1: extern void remoteSetPort(int); rlm@1: extern void debuggerOutput(char *, u32); rlm@1: rlm@1: struct EmulatedSystem emulator; rlm@1: rlm@1: int systemRedShift = 0; rlm@1: int systemBlueShift = 16; rlm@1: int systemGreenShift = 8; rlm@1: int systemColorDepth = 32; rlm@1: int systemDebug = 0; rlm@1: int systemVerbose = 0; rlm@1: int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; rlm@1: rlm@1: int sensorX = 2047; rlm@1: int sensorY = 2047; rlm@1: bool sensorOn = false; rlm@1: rlm@1: int cartridgeType = 3; rlm@1: int captureFormat = 0; rlm@1: rlm@1: int emulating = 0; rlm@1: int RGB_LOW_BITS_MASK=0x821; rlm@1: int systemFrameSkip = 0; rlm@1: u32 systemColorMap32[0x10000]; rlm@1: u16 systemColorMap16[0x10000]; rlm@1: u16 systemGbPalette[24]; 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 throttle = 0; rlm@1: rlm@1: bool paused = false; rlm@1: bool debugger = true; rlm@1: bool debuggerStub = false; rlm@1: bool systemSoundOn = false; rlm@1: bool removeIntros = false; rlm@1: int sdlFlashSize = 0; rlm@1: int sdlAutoIPS = 1; rlm@1: int sdlRtcEnable = 0; rlm@1: int sdlAgbPrint = 0; rlm@1: rlm@1: int sdlDefaultJoypad = 0; rlm@1: rlm@1: u16 motion[4] = { rlm@1: SDLK_KP4, SDLK_KP6, SDLK_KP8, SDLK_KP2 rlm@1: }; rlm@1: rlm@1: extern void debuggerSignal(int,int); rlm@1: rlm@1: void (*dbgMain)() = debuggerMain; rlm@1: void (*dbgSignal)(int,int) = debuggerSignal; rlm@1: void (*dbgOutput)(char *, u32) = debuggerOutput; 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: void usage(char *cmd) rlm@1: { rlm@1: printf("%s file-name\n",cmd); rlm@1: } rlm@1: rlm@1: int main(int argc, char **argv) rlm@1: { rlm@1: fprintf(stderr,"VisualBoyAdvance-Test version %s\n", VERSION); rlm@1: rlm@1: captureDir[0] = 0; rlm@1: saveDir[0] = 0; rlm@1: batteryDir[0] = 0; rlm@1: rlm@1: char buffer[1024]; rlm@1: rlm@1: systemFrameSkip = frameSkip = 2; rlm@1: gbBorderOn = 0; rlm@1: rlm@1: parseDebug = true; rlm@1: rlm@1: if(!debuggerStub) { rlm@1: if(argc <= 1) { rlm@1: systemMessage(0,"Missing image name"); rlm@1: usage(argv[0]); rlm@1: exit(-1); rlm@1: } rlm@1: } rlm@1: rlm@1: for(int i = 0; i < 24;) { rlm@1: systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10); rlm@1: systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10); rlm@1: systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10); rlm@1: systemGbPalette[i++] = 0; rlm@1: } rlm@1: rlm@1: if(argc == 2) { rlm@1: char *szFile = argv[optind]; rlm@1: bool failed = false; rlm@1: if(utilIsZipFile(szFile)) { rlm@1: unzFile unz = unzOpen(szFile); rlm@1: rlm@1: if(unz == NULL) { rlm@1: systemMessage(0, "Cannot open file %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: int r = unzGoToFirstFile(unz); rlm@1: rlm@1: if(r != UNZ_OK) { rlm@1: unzClose(unz); rlm@1: systemMessage(0, "Bad ZIP file %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: rlm@1: bool found = false; rlm@1: rlm@1: unz_file_info info; rlm@1: rlm@1: while(true) { rlm@1: r = unzGetCurrentFileInfo(unz, rlm@1: &info, rlm@1: buffer, rlm@1: sizeof(buffer), rlm@1: NULL, rlm@1: 0, rlm@1: NULL, rlm@1: 0); rlm@1: rlm@1: if(r != UNZ_OK) { rlm@1: unzClose(unz); rlm@1: systemMessage(0,"Bad ZIP file %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: rlm@1: if(utilIsGBImage(buffer)) { rlm@1: found = true; rlm@1: cartridgeType = 1; rlm@1: break; rlm@1: } rlm@1: if(utilIsGBAImage(buffer)) { rlm@1: found = true; rlm@1: cartridgeType = 0; rlm@1: break; rlm@1: } rlm@1: rlm@1: r = unzGoToNextFile(unz); rlm@1: rlm@1: if(r != UNZ_OK) rlm@1: break; rlm@1: } rlm@1: rlm@1: if(!found) { rlm@1: unzClose(unz); rlm@1: systemMessage(0, "No image found on ZIP file %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: rlm@1: unzClose(unz); rlm@1: } rlm@1: rlm@1: if(utilIsGBImage(szFile) || cartridgeType == 1) { rlm@1: failed = !gbLoadRom(szFile); rlm@1: cartridgeType = 1; rlm@1: emulator = GBSystem; rlm@1: } else if(utilIsGBAImage(szFile) || cartridgeType == 0) { rlm@1: failed = !CPULoadRom(szFile); rlm@1: cartridgeType = 0; rlm@1: emulator = GBASystem; rlm@1: rlm@1: //CPUInit(biosFileName, useBios); rlm@1: CPUInit(); rlm@1: CPUReset(); rlm@1: } else { rlm@1: systemMessage(0, "Unknown file type %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: rlm@1: if(failed) { rlm@1: systemMessage(0, "Failed to load file %s", szFile); rlm@1: exit(-1); rlm@1: } rlm@1: strcpy(filename, szFile); rlm@1: char *p = strrchr(filename, '.'); rlm@1: rlm@1: if(p) rlm@1: *p = 0; rlm@1: } else { rlm@1: cartridgeType = 0; rlm@1: strcpy(filename, "gnu_stub"); rlm@1: rom = (u8 *)malloc(0x2000000); rlm@1: workRAM = (u8 *)calloc(1, 0x40000); rlm@1: bios = (u8 *)calloc(1,0x4000); rlm@1: internalRAM = (u8 *)calloc(1,0x8000); rlm@1: paletteRAM = (u8 *)calloc(1,0x400); rlm@1: vram = (u8 *)calloc(1, 0x20000); rlm@1: oam = (u8 *)calloc(1, 0x400); rlm@1: pix = (u8 *)calloc(1, 4 * 240 * 160); rlm@1: ioMem = (u8 *)calloc(1, 0x400); rlm@1: rlm@1: emulator = GBASystem; rlm@1: rlm@1: //CPUInit(biosFileName, useBios); rlm@1: CPUInit(); rlm@1: CPUReset(); rlm@1: } rlm@1: rlm@1: if(debuggerStub) rlm@1: remoteInit(); rlm@1: rlm@1: if(cartridgeType == 0) { rlm@1: } else if (cartridgeType == 1) { rlm@1: if(gbBorderOn) { rlm@1: gbBorderLineSkip = 256; rlm@1: gbBorderColumnSkip = 48; rlm@1: gbBorderRowSkip = 40; rlm@1: } else { rlm@1: gbBorderLineSkip = 160; rlm@1: gbBorderColumnSkip = 0; rlm@1: gbBorderRowSkip = 0; rlm@1: } rlm@1: } else { rlm@1: } rlm@1: rlm@1: for(int i = 0; i < 0x10000; i++) { rlm@1: systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | rlm@1: (((i & 0x3e0) >> 5) << systemGreenShift) | rlm@1: (((i & 0x7c00) >> 10) << systemBlueShift); rlm@1: } rlm@1: rlm@1: emulating = 1; rlm@1: soundInit(); rlm@1: rlm@1: while(emulating) { rlm@1: if(!paused) { rlm@1: if(debugger && emulator.emuHasDebugger) rlm@1: dbgMain(); rlm@1: else rlm@1: emulator.emuMain(emulator.emuCount); rlm@1: } rlm@1: } rlm@1: emulating = 0; rlm@1: fprintf(stderr,"Shutting down\n"); rlm@1: remoteCleanUp(); rlm@1: soundShutdown(); rlm@1: rlm@1: if(gbRom != NULL || rom != NULL) { rlm@1: emulator.emuCleanUp(); rlm@1: } rlm@1: rlm@1: return 0; rlm@1: } rlm@1: rlm@1: void systemMessage(int num, const char *msg, ...) rlm@1: { rlm@1: char buffer[2048]; rlm@1: va_list valist; rlm@1: rlm@1: va_start(valist, msg); rlm@1: vsprintf(buffer, msg, valist); rlm@1: rlm@1: fprintf(stderr, "%s\n", buffer); rlm@1: va_end(valist); rlm@1: } rlm@1: rlm@1: void systemDrawScreen() rlm@1: { 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 0; rlm@1: } rlm@1: rlm@1: void systemShowSpeed(int speed) rlm@1: { rlm@1: } rlm@1: rlm@1: void system10Frames(int rate) rlm@1: { rlm@1: } rlm@1: rlm@1: void systemFrame(int) rlm@1: { rlm@1: } rlm@1: rlm@1: void systemSetTitle(const char *title) rlm@1: { rlm@1: } rlm@1: rlm@1: int systemScreenCapture(int a) rlm@1: { rlm@1: char buffer[2048]; rlm@1: rlm@1: if(captureFormat) { rlm@1: if(captureDir[0]) rlm@1: sprintf(buffer, "%s/%s%02d.bmp", captureDir, sdlGetFilename(filename), a); rlm@1: else rlm@1: sprintf(buffer, "%s%02d.bmp", filename, a); rlm@1: rlm@1: emulator.emuWriteBMP(buffer); rlm@1: } else { rlm@1: if(captureDir[0]) rlm@1: sprintf(buffer, "%s/%s%02d.png", captureDir, sdlGetFilename(filename), a); rlm@1: else rlm@1: sprintf(buffer, "%s%02d.png", filename, a); rlm@1: emulator.emuWritePNG(buffer); rlm@1: } rlm@1: rlm@1: systemScreenMessage("Screen capture"); rlm@1: } rlm@1: rlm@1: u32 systemReadJoypadExtended() rlm@1: { rlm@1: return 0; rlm@1: } rlm@1: rlm@1: void systemWriteDataToSoundBuffer() rlm@1: { rlm@1: } rlm@1: rlm@1: bool systemSoundInit() rlm@1: { rlm@1: return true; rlm@1: } rlm@1: rlm@1: void systemSoundShutdown() rlm@1: { rlm@1: } rlm@1: rlm@1: void systemSoundPause() rlm@1: { rlm@1: } rlm@1: rlm@1: void systemSoundResume() rlm@1: { rlm@1: } rlm@1: rlm@1: void systemSoundReset() rlm@1: { rlm@1: } rlm@1: rlm@1: static int ticks = 0; rlm@1: rlm@1: u32 systemGetClock() rlm@1: { rlm@1: return ticks++; 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 *data,int pages,int feed,int palette, int contrast) rlm@1: { rlm@1: } rlm@1: rlm@1: void systemScreenMessage(const char *msg, int slot, int duration, const char *colorList) rlm@1: { rlm@1: } rlm@1: rlm@1: bool systemCanChangeSoundQuality() rlm@1: { rlm@1: return false; 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: bool sdlCheckJoyKey(int) rlm@1: { 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: }