diff --git a/doc/License.txt b/doc/License.txt index 55482bd9..e2635cf7 100644 --- a/doc/License.txt +++ b/doc/License.txt @@ -6,7 +6,7 @@ or when stated otherwise in the source file: Copyright for the modifications to the files mentioned above: VisualBoyAdvance-M GB/GBA emulator - Copyright (C) 2007-2008 VBA-M development team + Copyright (C) 2007-2013 VBA-M development team All files excluding gb_apu, modified files from zlib diff --git a/doc/ReadMe.MFC.txt b/doc/ReadMe.MFC.txt index eb46fd17..565d2fb9 100644 --- a/doc/ReadMe.MFC.txt +++ b/doc/ReadMe.MFC.txt @@ -138,6 +138,7 @@ Spacy DJRobX Jonas Quinn kode54 +Normmatt ============== Special Thanks @@ -171,4 +172,7 @@ kode64: shuffle2: - SFML library -- various build fixes \ No newline at end of file +- various build fixes + +Squarepusher +- Libretro merge \ No newline at end of file diff --git a/src/System.h b/src/System.h index 9ec0c859..30c74e84 100644 --- a/src/System.h +++ b/src/System.h @@ -1,45 +1,49 @@ #ifndef SYSTEM_H #define SYSTEM_H - #include "common/Types.h" - #include class SoundDriver; struct EmulatedSystem { - // main emulation function - void (*emuMain)(int); - // reset emulator - void (*emuReset)(); - // clean up memory - void (*emuCleanUp)(); - // load battery file - bool (*emuReadBattery)(const char *); - // write battery file - bool (*emuWriteBattery)(const char *); - // load state - bool (*emuReadState)(const char *); - // save state - bool (*emuWriteState)(const char *); - // load memory state (rewind) - bool (*emuReadMemState)(char *, int); - // write memory state (rewind) - bool (*emuWriteMemState)(char *, int); - // write PNG file - bool (*emuWritePNG)(const char *); - // write BMP file - bool (*emuWriteBMP)(const char *); - // emulator update CPSR (ARM only) - void (*emuUpdateCPSR)(); - // emulator has debugger - bool emuHasDebugger; - // clock ticks to emulate - int emuCount; + // main emulation function + void (*emuMain)(int); + // reset emulator + void (*emuReset)(); + // clean up memory + void (*emuCleanUp)(); + // load battery file + bool (*emuReadBattery)(const char *); + // write battery file + bool (*emuWriteBattery)(const char *); +#ifdef __LIBRETRO__ + // load state + bool (*emuReadState)(const u8*, unsigned); + // load state + unsigned (*emuWriteState)(u8*, unsigned); +#else + // load state + bool (*emuReadState)(const char *); + // save state + bool (*emuWriteState)(const char *); +#endif + // load memory state (rewind) + bool (*emuReadMemState)(char *, int); + // write memory state (rewind) + bool (*emuWriteMemState)(char *, int); + // write PNG file + bool (*emuWritePNG)(const char *); + // write BMP file + bool (*emuWriteBMP)(const char *); + // emulator update CPSR (ARM only) + void (*emuUpdateCPSR)(); + // emulator has debugger + bool emuHasDebugger; + // clock ticks to emulate + int emuCount; }; extern void log(const char *,...); - extern bool systemPauseOnFrame(); extern void systemGbPrint(u8 *,int,int,int,int,int); extern void systemScreenCapture(int); @@ -56,14 +60,13 @@ extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length); extern void systemOnSoundShutdown(); extern void systemScreenMessage(const char *); extern void systemUpdateMotionSensor(); -extern int systemGetSensorX(); -extern int systemGetSensorY(); +extern int systemGetSensorX(); +extern int systemGetSensorY(); extern bool systemCanChangeSoundQuality(); extern void systemShowSpeed(int); extern void system10Frames(int); extern void systemFrame(); extern void systemGbBorderOn(); - extern void Sm60FPS_Init(); extern bool Sm60FPS_CanSkipFrame(); extern void Sm60FPS_Sleep(); @@ -73,10 +76,8 @@ extern void DbgMsg(const char *msg, ...); #else extern void winlog(const char *,...); #endif - extern void (*dbgOutput)(const char *s, u32 addr); extern void (*dbgSignal)(int sig,int number); - extern u16 systemColorMap16[0x10000]; extern u32 systemColorMap32[0x10000]; extern u16 systemGbPalette[24]; @@ -89,8 +90,6 @@ extern int systemVerbose; extern int systemFrameSkip; extern int systemSaveUpdateCounter; extern int systemSpeed; - #define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_NOT_UPDATED 0 - -#endif // SYSTEM_H +#endif // SYSTEM_H diff --git a/src/Util.cpp b/src/Util.cpp index 590b9150..25f3df4b 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -439,6 +439,8 @@ static bool utilIsImage(const char *file) #include #endif +IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]); + IMAGE_TYPE utilFindType(const char *file) { char buffer [2048]; @@ -453,11 +455,10 @@ IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]) pwText = new wchar_t[dwNum]; if(!pwText) { - delete []pwText; + return IMAGE_UNKNOWN; } MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum ); char* file_conv = fex_wide_to_path( pwText); - delete []pwText; // if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead? // { fex_t* fe = scan_arc(file_conv,utilIsImage,buffer); @@ -501,7 +502,7 @@ u8 *utilLoad(const char *file, pwText = new wchar_t[dwNum]; if(!pwText) { - delete []pwText; + return NULL; } MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum ); char* file_conv = fex_wide_to_path( pwText); @@ -718,4 +719,4 @@ bool utilFileExists( const char *filename ) fclose( f ); return true; } -} \ No newline at end of file +} diff --git a/src/Util.h b/src/Util.h index 7393e7a2..1292b85f 100644 --- a/src/Util.h +++ b/src/Util.h @@ -11,23 +11,22 @@ enum IMAGE_TYPE { // save game typedef struct { - void *address; - int size; + void *address; + int size; } variable_desc; - bool utilWritePNGFile(const char *, int, int, u8 *); bool utilWriteBMPFile(const char *, int, int, u8 *); -void utilApplyIPS(const char *ips, u8 **rom, int *size); +void utilApplyIPS(const char *ips, uint8_t **rom, int *size); bool utilIsGBAImage(const char *); bool utilIsGBImage(const char *); bool utilIsGzipFile(const char *); +bool utilIsZipFile(const char *); void utilStripDoubleExtension(const char *, char *); IMAGE_TYPE utilFindType(const char *); -IMAGE_TYPE utilFindType(const char *, char (&)[2048]); -u8 *utilLoad(const char *, bool (*)(const char*), u8 *, int &); +uint8_t *utilLoad(const char *, bool (*)(const char*), uint8_t *, int &); -void utilPutDword(u8 *, u32); -void utilPutWord(u8 *, u16); +void utilPutDword(uint8_t *, uint32_t); +void utilPutWord(uint8_t *, uint16_t); void utilWriteData(gzFile, variable_desc *); void utilReadData(gzFile, variable_desc *); void utilReadDataSkip(gzFile, variable_desc *); @@ -44,4 +43,15 @@ void utilGBAFindSave(const u8 *, const int); void utilUpdateSystemColorMaps(bool lcd = false); bool utilFileExists( const char *filename ); + +#ifdef __LIBRETRO__ +void utilWriteIntMem(uint8_t *& data, int); +void utilWriteMem(uint8_t *& data, const void *in_data, unsigned size); +void utilWriteDataMem(uint8_t *& data, variable_desc *); + +int utilReadIntMem(const uint8_t *& data); +void utilReadMem(void *buf, const uint8_t *& data, unsigned size); +void utilReadDataMem(const uint8_t *& data, variable_desc *); +#endif + #endif // UTIL_H diff --git a/src/common/Patch.cpp b/src/common/Patch.cpp index 3834669f..ac4893a7 100644 --- a/src/common/Patch.cpp +++ b/src/common/Patch.cpp @@ -276,7 +276,7 @@ static bool patchApplyUPS(const char *patchname, u8 **rom, int *size) static int ppfVersion(FILE *f) { fseeko64(f, 0, SEEK_SET); - if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F') + if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F') //-V501 return 0; switch(fgetc(f)){ case '1': return 1; diff --git a/src/common/Port.h b/src/common/Port.h index 7d1ade95..0e134a24 100644 --- a/src/common/Port.h +++ b/src/common/Port.h @@ -1,6 +1,16 @@ #ifndef PORT_H #define PORT_H +#ifdef __CELLOS_LV2__ +/* PlayStation3 */ +#include +#endif + +#ifdef _XBOX360 +/* XBox 360 */ +#include +#endif + #include "Types.h" // swaps a 16-bit value diff --git a/src/common/SoundSDL.cpp b/src/common/SoundSDL.cpp index f49e6f8b..c06daf5e 100644 --- a/src/common/SoundSDL.cpp +++ b/src/common/SoundSDL.cpp @@ -40,12 +40,22 @@ void SoundSDL::read(u16 * stream, int length) if (!_initialized || length <= 0 || !emulating) return; + + /* since this is running in a different thread, speedup and + * throttle can change at any time; save the value so locks + * stay in sync */ + bool lock = (emulating && !speedup) ? true : false; + + if (lock) + SDL_SemWait (_semBufferFull); + SDL_mutexP(_mutex); _rbuf.read(stream, std::min(static_cast(length) / 2, _rbuf.used())); - SDL_CondSignal(_cond); SDL_mutexV(_mutex); + + SDL_SemPost (_semBufferEmpty); } void SoundSDL::write(u16 * finalWave, int length) @@ -63,23 +73,25 @@ void SoundSDL::write(u16 * finalWave, int length) std::size_t avail; while ((avail = _rbuf.avail() / 2) < samples) { + bool lock = (emulating && !speedup) ? true : false; + _rbuf.write(finalWave, avail * 2); finalWave += avail * 2; samples -= avail; - // If emulating and not in speed up mode, synchronize to audio - // by waiting till there is enough room in the buffer - if (emulating && !speedup) + SDL_mutexV(_mutex); + SDL_SemPost(_semBufferFull); + if (lock) { - SDL_CondWait(_cond, _mutex); + SDL_SemWait(_semBufferEmpty); } else { // Drop the remaining of the audio data - SDL_mutexV(_mutex); return; } + SDL_mutexP(_mutex); } _rbuf.write(finalWave, samples * 2); @@ -106,9 +118,10 @@ bool SoundSDL::init(long sampleRate) _rbuf.reset(_delay * sampleRate * 2); - _cond = SDL_CreateCond(); - _mutex = SDL_CreateMutex(); - _initialized = true; + _mutex = SDL_CreateMutex(); + _semBufferFull = SDL_CreateSemaphore (0); + _semBufferEmpty = SDL_CreateSemaphore (1); + _initialized = true; return true; } @@ -121,11 +134,14 @@ SoundSDL::~SoundSDL() SDL_mutexP(_mutex); int iSave = emulating; emulating = 0; - SDL_CondSignal(_cond); + SDL_SemPost(_semBufferFull); + SDL_SemPost(_semBufferEmpty); SDL_mutexV(_mutex); - SDL_DestroyCond(_cond); - _cond = NULL; + SDL_DestroySemaphore(_semBufferFull); + SDL_DestroySemaphore(_semBufferEmpty); + _semBufferFull = NULL; + _semBufferEmpty = NULL; SDL_DestroyMutex(_mutex); _mutex = NULL; diff --git a/src/common/SoundSDL.h b/src/common/SoundSDL.h index 35c92abf..bff5f426 100644 --- a/src/common/SoundSDL.h +++ b/src/common/SoundSDL.h @@ -38,8 +38,9 @@ public: private: RingBuffer _rbuf; - SDL_cond * _cond; SDL_mutex * _mutex; + SDL_sem *_semBufferFull; + SDL_sem *_semBufferEmpty; bool _initialized; diff --git a/src/gb/gbGfx.cpp b/src/gb/gbGfx.cpp index a197405f..67cef3fc 100644 --- a/src/gb/gbGfx.cpp +++ b/src/gb/gbGfx.cpp @@ -234,7 +234,7 @@ void gbRenderLine() if(y >= inUseRegister_WY) { - if (gbWindowLine>143) + if ((gbWindowLine == -1) || (gbWindowLine>144)) gbWindowLine = 0; int wx = register_WX; @@ -266,7 +266,7 @@ void gbRenderLine() //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7); - if ((swx == 7)) + if (swx == 7) { //wx = 0; if ((gbWindowLine>0) || (wy == 0)) diff --git a/src/gb/gbSound.cpp b/src/gb/gbSound.cpp index 3f57496b..a1209c6c 100644 --- a/src/gb/gbSound.cpp +++ b/src/gb/gbSound.cpp @@ -121,6 +121,13 @@ static void reset_apu() static void remake_stereo_buffer() { + // APU + if ( !gb_apu ) + { + gb_apu = new Gb_Apu; // TODO: handle errors + reset_apu(); + } + // Stereo_Buffer delete stereo_buffer; stereo_buffer = 0; @@ -128,20 +135,15 @@ static void remake_stereo_buffer() stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory stereo_buffer->clock_rate( gb_apu->clock_rate ); - - // APU + + // Multi_Buffer static int const chan_types [chan_count] = { Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 }; if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; // TODO: handle errors - reset_apu(); - } - + // Volume Level apply_effects(); apply_volume(); } diff --git a/src/gba/Cheats.cpp b/src/gba/Cheats.cpp index a601fa78..0288800b 100644 --- a/src/gba/Cheats.cpp +++ b/src/gba/Cheats.cpp @@ -1,3 +1,4 @@ +#ifndef __LIBRETRO__ #include #include #include @@ -2896,3 +2897,4 @@ void cheatsWriteByte(u32, u8) #endif #endif } +#endif diff --git a/src/gba/EEprom.cpp b/src/gba/EEprom.cpp index 2d0a259f..4dbb3b81 100644 --- a/src/gba/EEprom.cpp +++ b/src/gba/EEprom.cpp @@ -1,4 +1,5 @@ #include +#include #include "GBA.h" #include "EEprom.h" #include "../Util.h" @@ -9,7 +10,15 @@ int eepromMode = EEPROM_IDLE; int eepromByte = 0; int eepromBits = 0; int eepromAddress = 0; + +#ifdef __LIBRETRO__ +// Workaround for broken-by-design GBA save semantics +extern u8 libretro_save_buf[0x20000 + 0x2000]; +u8 *eepromData = libretro_save_buf + 0x20000; +#else u8 eepromData[0x2000]; +#endif + u8 eepromBuffer[16]; bool eepromInUse = false; int eepromSize = 512; @@ -27,7 +36,11 @@ variable_desc eepromSaveData[] = { void eepromInit() { - memset(eepromData, 255, sizeof(eepromData)); +#ifdef __LIBRETRO__ + memset(eepromData, 255, 0x2000); +#else + memset(eepromData, 255, sizeof(eepromData)); +#endif } void eepromReset() @@ -40,6 +53,26 @@ void eepromReset() eepromSize = 512; } +#ifdef __LIBRETRO__ +void eepromSaveGame(uint8_t *& data) +{ + utilWriteDataMem(data, eepromSaveData); + utilWriteIntMem(data, eepromSize); + utilWriteMem(data, eepromData, 0x2000); +} + +void eepromReadGame(const uint8_t *& data, int version) +{ + utilReadDataMem(data, eepromSaveData); + if (version >= SAVE_GAME_VERSION_3) { + eepromSize = utilReadIntMem(data); + utilReadMem(eepromData, data, 0x2000); + } else { + // prior to 0.7.1, only 4K EEPROM was supported + eepromSize = 512; + } +} +#else void eepromSaveGame(gzFile gzFile) { utilWriteData(gzFile, eepromSaveData); @@ -68,6 +101,7 @@ void eepromReadGameSkip(gzFile gzFile, int version) utilGzSeek(gzFile, 0x2000, SEEK_CUR); } } +#endif int eepromRead(u32 /* address */) { diff --git a/src/gba/EEprom.h b/src/gba/EEprom.h index ac20caa7..e72f5b88 100644 --- a/src/gba/EEprom.h +++ b/src/gba/EEprom.h @@ -1,14 +1,23 @@ #ifndef EEPROM_H #define EEPROM_H +#ifdef __LIBRETRO__ +extern void eepromSaveGame(u8* &data); +extern void eepromReadGame(const u8 *&data, int version); +#else extern void eepromSaveGame(gzFile _gzFile); extern void eepromReadGame(gzFile _gzFile, int version); +#endif extern void eepromReadGameSkip(gzFile _gzFile, int version); extern int eepromRead(u32 address); extern void eepromWrite(u32 address, u8 value); extern void eepromInit(); extern void eepromReset(); +#ifdef __LIBRETRO__ +extern u8 *eepromData; +#else extern u8 eepromData[0x2000]; +#endif extern bool eepromInUse; extern int eepromSize; diff --git a/src/gba/Flash.cpp b/src/gba/Flash.cpp index b689bb48..0b4a17d4 100644 --- a/src/gba/Flash.cpp +++ b/src/gba/Flash.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "GBA.h" #include "Globals.h" @@ -17,7 +18,13 @@ #define FLASH_PROGRAM 8 #define FLASH_SETBANK 9 -u8 flashSaveMemory[FLASH_128K_SZ]; +#ifdef __LIBRETRO__ +extern uint8_t libretro_save_buf[0x20000 + 0x2000]; +uint8_t *flashSaveMemory = libretro_save_buf; +#else +uint8_t flashSaveMemory[FLASH_128K_SZ]; +#endif + int flashState = FLASH_READ_ARRAY; int flashReadState = FLASH_READ_ARRAY; int flashSize = 0x10000; @@ -51,7 +58,11 @@ static variable_desc flashSaveData3[] = { void flashInit() { - memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); +#ifdef __LIBRETRO__ + memset(flashSaveMemory, 0xff, 0x20000); +#else + memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); +#endif } void flashReset() @@ -61,6 +72,17 @@ void flashReset() flashBank = 0; } +#ifdef __LIBRETRO__ +void flashSaveGame(uint8_t *& data) +{ + utilWriteDataMem(data, flashSaveData3); +} + +void flashReadGame(const uint8_t *& data, int) +{ + utilReadDataMem(data, flashSaveData3); +} +#else void flashSaveGame(gzFile gzFile) { utilWriteData(gzFile, flashSaveData3); @@ -90,6 +112,8 @@ void flashReadGameSkip(gzFile gzFile, int version) utilReadDataSkip(gzFile, flashSaveData3); } } +#endif + void flashSetSize(int size) { diff --git a/src/gba/Flash.h b/src/gba/Flash.h index cd23a5c6..73ef1a5e 100644 --- a/src/gba/Flash.h +++ b/src/gba/Flash.h @@ -3,13 +3,22 @@ #define FLASH_128K_SZ 0x20000 +#ifdef __LIBRETRO__ +extern void flashSaveGame(u8 *& data); +extern void flashReadGame(const u8 *& data, int); +#else extern void flashSaveGame(gzFile _gzFile); extern void flashReadGame(gzFile _gzFile, int version); +#endif extern void flashReadGameSkip(gzFile _gzFile, int version); extern u8 flashRead(u32 address); extern void flashWrite(u32 address, u8 byte); extern void flashDelayedWrite(u32 address, u8 byte); +#ifdef __LIBRETRO__ +extern uint8_t *flashSaveMemory; +#else extern u8 flashSaveMemory[FLASH_128K_SZ]; +#endif extern void flashSaveDecide(u32 address, u8 byte); extern void flashReset(); extern void flashSetSize(int size); diff --git a/src/gba/GBA-arm.cpp b/src/gba/GBA-arm.cpp index a0c8033e..732f4474 100644 --- a/src/gba/GBA-arm.cpp +++ b/src/gba/GBA-arm.cpp @@ -356,7 +356,11 @@ static void count(u32 opcode, int cond_res) EMIT2(and, KONST(0x1F), ecx) #define VALUE_LOAD_REG \ EMIT2(and, KONST(0x0F), eax) \ - EMIT2(mov, REGREF2(eax,4), eax) \ + EMIT2(cmp, KONST(0x0F), eax) \ + EMIT2(mov, REGREF2(eax,4), eax) \ + EMIT1(jne, LABELREF(3,f)) \ + EMIT2(add, KONST(4), eax) \ + LABEL(3) \ EMIT2(movzx, ch, ecx) \ EMIT2(and, KONST(0x0F), ecx) \ EMIT2(mov, REGREF2(ecx,4), ecx) @@ -1533,7 +1537,7 @@ static INSN_REGPARM void arm121(u32 opcode) #define OP_LDR reg[dest].I = CPUReadMemory(address) #define OP_LDRH reg[dest].I = CPUReadHalfWord(address) #define OP_LDRB reg[dest].I = CPUReadByte(address) -#define OP_LDRSH reg[dest].I = (s16)CPUReadHalfWordSigned(address) +#define OP_LDRSH reg[dest].I = (u32)CPUReadHalfWordSigned(address) #define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address) #define WRITEBACK_NONE /*nothing*/ @@ -2608,8 +2612,7 @@ static INSN_REGPARM void armA00(u32 opcode) reg[15].I += 4; ARM_PREFETCH; clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; } @@ -2625,8 +2628,7 @@ static INSN_REGPARM void armB00(u32 opcode) reg[15].I += 4; ARM_PREFETCH; clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; } @@ -2644,9 +2646,8 @@ static INSN_REGPARM void armE01(u32 opcode) // SWI static INSN_REGPARM void armF00(u32 opcode) { - clockTicks = codeTicksAccessSeq32(armNextPC) + 1; - clockTicks += 2 + codeTicksAccess32(armNextPC) - + codeTicksAccessSeq32(armNextPC); + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1; busPrefetchCount = 0; CPUSoftwareInterrupt(opcode & 0x00FFFFFF); } @@ -2700,7 +2701,7 @@ static insnfunc_t armInsnTable[4096] = { arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0 arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8 arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0 - arm0F0,arm0F9,arm0F2,arm_UI,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8 + arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8 arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100 arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108 diff --git a/src/gba/GBA-thumb.cpp b/src/gba/GBA-thumb.cpp index 400ebde6..4cec05c1 100644 --- a/src/gba/GBA-thumb.cpp +++ b/src/gba/GBA-thumb.cpp @@ -1421,12 +1421,14 @@ static INSN_REGPARM void thumb45_3(u32 opcode) static INSN_REGPARM void thumb46_0(u32 opcode) { reg[opcode&7].I = reg[((opcode>>3)&7)].I; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; } // MOV Rd, Hs static INSN_REGPARM void thumb46_1(u32 opcode) { reg[opcode&7].I = reg[((opcode>>3)&7)+8].I; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; } // MOV Hd, Rs @@ -1473,16 +1475,14 @@ static INSN_REGPARM void thumb47(u32 opcode) armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) - + codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3; } else { armState = true; reg[15].I &= 0xFFFFFFFC; armNextPC = reg[15].I; reg[15].I += 4; ARM_PREFETCH; - clockTicks = codeTicksAccessSeq32(armNextPC) - + codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3; + clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3; } } @@ -1576,7 +1576,7 @@ static INSN_REGPARM void thumb5E(u32 opcode) if (busPrefetchCount == 0) busPrefetch = busPrefetchEnable; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; - reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address); + reg[opcode&7].I = (u32)CPUReadHalfWordSigned(address); clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); } @@ -1669,6 +1669,7 @@ static INSN_REGPARM void thumbA0(u32 opcode) { u8 regist = (opcode >> 8) & 7; reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + clockTicks = 1 + codeTicksAccess16(armNextPC); } // ADD R0~R7, SP, Imm @@ -1676,6 +1677,7 @@ static INSN_REGPARM void thumbA8(u32 opcode) { u8 regist = (opcode >> 8) & 7; reg[regist].I = reg[13].I + ((opcode&255)<<2); + clockTicks = 1 + codeTicksAccess16(armNextPC); } // ADD SP, Imm @@ -1685,6 +1687,7 @@ static INSN_REGPARM void thumbB0(u32 opcode) if(opcode & 0x80) offset = -offset; reg[13].I += offset; + clockTicks = 1 + codeTicksAccess16(armNextPC); } // Push and pop /////////////////////////////////////////////////////////// @@ -1882,13 +1885,13 @@ static INSN_REGPARM void thumbC8(u32 opcode) static INSN_REGPARM void thumbD0(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1897,13 +1900,13 @@ static INSN_REGPARM void thumbD0(u32 opcode) static INSN_REGPARM void thumbD1(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1912,13 +1915,13 @@ static INSN_REGPARM void thumbD1(u32 opcode) static INSN_REGPARM void thumbD2(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(C_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1927,13 +1930,13 @@ static INSN_REGPARM void thumbD2(u32 opcode) static INSN_REGPARM void thumbD3(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!C_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1942,13 +1945,13 @@ static INSN_REGPARM void thumbD3(u32 opcode) static INSN_REGPARM void thumbD4(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1957,13 +1960,13 @@ static INSN_REGPARM void thumbD4(u32 opcode) static INSN_REGPARM void thumbD5(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!N_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1972,13 +1975,13 @@ static INSN_REGPARM void thumbD5(u32 opcode) static INSN_REGPARM void thumbD6(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -1987,13 +1990,13 @@ static INSN_REGPARM void thumbD6(u32 opcode) static INSN_REGPARM void thumbD7(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2002,13 +2005,13 @@ static INSN_REGPARM void thumbD7(u32 opcode) static INSN_REGPARM void thumbD8(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(C_FLAG && !Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2017,13 +2020,13 @@ static INSN_REGPARM void thumbD8(u32 opcode) static INSN_REGPARM void thumbD9(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!C_FLAG || Z_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2032,13 +2035,13 @@ static INSN_REGPARM void thumbD9(u32 opcode) static INSN_REGPARM void thumbDA(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG == V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2047,13 +2050,13 @@ static INSN_REGPARM void thumbDA(u32 opcode) static INSN_REGPARM void thumbDB(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(N_FLAG != V_FLAG) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2062,13 +2065,13 @@ static INSN_REGPARM void thumbDB(u32 opcode) static INSN_REGPARM void thumbDC(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC) + 1; if(!Z_FLAG && (N_FLAG == V_FLAG)) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2077,13 +2080,13 @@ static INSN_REGPARM void thumbDC(u32 opcode) static INSN_REGPARM void thumbDD(u32 opcode) { UPDATE_OLDREG; + clockTicks = codeTicksAccessSeq16(armNextPC); if(Z_FLAG || (N_FLAG != V_FLAG)) { reg[15].I += ((s8)(opcode & 0xFF)) << 1; armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC)+3; + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2; busPrefetchCount=0; } } @@ -2094,8 +2097,8 @@ static INSN_REGPARM void thumbDD(u32 opcode) static INSN_REGPARM void thumbDF(u32 opcode) { u32 address = 0; - clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) + - codeTicksAccess16(address)+3; + //clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3; + clockTicks = 3; busPrefetchCount=0; CPUSoftwareInterrupt(opcode & 0xFF); } @@ -2110,8 +2113,7 @@ static INSN_REGPARM void thumbE0(u32 opcode) armNextPC = reg[15].I; reg[15].I += 2; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3; busPrefetchCount=0; } @@ -2141,8 +2143,7 @@ static INSN_REGPARM void thumbF8(u32 opcode) reg[15].I += 2; reg[14].I = temp|1; THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(armNextPC) + - codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3; + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3; busPrefetchCount = 0; } diff --git a/src/gba/GBA.cpp b/src/gba/GBA.cpp index 75af7bd1..68bde297 100644 --- a/src/gba/GBA.cpp +++ b/src/gba/GBA.cpp @@ -120,6 +120,9 @@ int capture = 0; int capturePrevious = 0; int captureNumber = 0; +int armOpcodeCount = 0; +int thumbOpcodeCount = 0; + const int TIMER_TICKS[4] = { 0, 6, @@ -574,6 +577,44 @@ void CPUUpdateRenderBuffers(bool force) } } +#ifdef __LIBRETRO__ +#include + +unsigned int CPUWriteState(u8* data, unsigned size) +{ + uint8_t *orig = data; + + utilWriteIntMem(data, SAVE_GAME_VERSION); + utilWriteMem(data, &rom[0xa0], 16); + utilWriteIntMem(data, useBios); + utilWriteMem(data, ®[0], sizeof(reg)); + + utilWriteDataMem(data, saveGameStruct); + + utilWriteIntMem(data, stopState); + utilWriteIntMem(data, IRQTicks); + + utilWriteMem(data, internalRAM, 0x8000); + utilWriteMem(data, paletteRAM, 0x400); + utilWriteMem(data, workRAM, 0x40000); + utilWriteMem(data, vram, 0x20000); + utilWriteMem(data, oam, 0x400); + utilWriteMem(data, pix, 4 * 241 * 162); + utilWriteMem(data, ioMem, 0x400); + + eepromSaveGame(data); + flashSaveGame(data); + soundSaveGame(data); + rtcSaveGame(data); + + return (ptrdiff_t)data - (ptrdiff_t)orig; +} + +bool CPUWriteMemState(char *memory, int available) +{ + return false; +} +#else static bool CPUWriteState(gzFile gzFile) { utilWriteInt(gzFile, SAVE_GAME_VERSION); @@ -627,6 +668,7 @@ bool CPUWriteState(const char *file) return res; } + bool CPUWriteMemState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -646,7 +688,108 @@ bool CPUWriteMemState(char *memory, int available) return res; } +#endif + +#ifdef __LIBRETRO__ +bool CPUReadState(const u8* data, unsigned size) +{ + // Don't really care about version. + int version = utilReadIntMem(data); + if (version != SAVE_GAME_VERSION) + return false; + + char romname[16]; + utilReadMem(romname, data, 16); + if (memcmp(&rom[0xa0], romname, 16) != 0) + return false; + + // Don't care about use bios ... + utilReadIntMem(data); + + utilReadMem(®[0], data, sizeof(reg)); + + utilReadDataMem(data, saveGameStruct); + + stopState = utilReadIntMem(data) ? true : false; + + IRQTicks = utilReadIntMem(data); + if (IRQTicks > 0) + intState = true; + else + { + intState = false; + IRQTicks = 0; + } + + utilReadMem(internalRAM, data, 0x8000); + utilReadMem(paletteRAM, data, 0x400); + utilReadMem(workRAM, data, 0x40000); + utilReadMem(vram, data, 0x20000); + utilReadMem(oam, data, 0x400); + utilReadMem(pix, data, 4*241*162); + utilReadMem(ioMem, data, 0x400); + + eepromReadGame(data, version); + flashReadGame(data, version); + soundReadGame(data, version); + rtcReadGame(data); + + //// Copypasta stuff ... + // set pointers! + layerEnable = layerSettings & DISPCNT; + + CPUUpdateRender(); + + // CPU Update Render Buffers set to true + CLEAR_ARRAY(line0); + CLEAR_ARRAY(line1); + CLEAR_ARRAY(line2); + CLEAR_ARRAY(line3); + // End of CPU Update Render Buffers set to true + + CPUUpdateWindow0(); + CPUUpdateWindow1(); + gbaSaveType = 0; + switch(saveType) { + case 0: + cpuSaveGameFunc = flashSaveDecide; + break; + case 1: + cpuSaveGameFunc = sramWrite; + gbaSaveType = 1; + break; + case 2: + cpuSaveGameFunc = flashWrite; + gbaSaveType = 2; + break; + case 3: + break; + case 5: + gbaSaveType = 5; + break; + default: +#ifdef CELL_VBA_DEBUG + systemMessage(MSG_UNSUPPORTED_SAVE_TYPE, + N_("Unsupported save type %d"), saveType); +#endif + break; + } + if(eepromInUse) + gbaSaveType = 3; + + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } + + CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); + + return true; +} +#else static bool CPUReadState(gzFile gzFile) { int version = utilReadInt(gzFile); @@ -843,6 +986,7 @@ bool CPUReadState(const char * file) return res; } +#endif bool CPUExportEepromFile(const char *fileName) { @@ -934,7 +1078,7 @@ bool CPUReadGSASnapshot(const char *fileName) fseek(file, 0x0, SEEK_SET); fread(&i, 1, 4, file); fseek(file, i, SEEK_CUR); // Skip SharkPortSave - fseek(file, 4, SEEK_CUR); // skip some sort of flag +// fseek(file, 4, SEEK_CUR); // skip some sort of flag fread(&i, 1, 4, file); // name length fseek(file, i, SEEK_CUR); // skip name fread(&i, 1, 4, file); // desc length @@ -1806,8 +1950,8 @@ void CPUSoftwareInterrupt(int comment) case 0x02: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_SWI) { - log("Halt: (VCOUNT = %2d)\n", - VCOUNT); + /*log("Halt: (VCOUNT = %2d)\n", + VCOUNT);*/ } #endif holdState = true; @@ -1817,8 +1961,8 @@ void CPUSoftwareInterrupt(int comment) case 0x03: #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_SWI) { - log("Stop: (VCOUNT = %2d)\n", - VCOUNT); + /*log("Stop: (VCOUNT = %2d)\n", + VCOUNT);*/ } #endif holdState = true; @@ -2073,6 +2217,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) int dw = 0; int sc = c; + cpuDmaHack = true; cpuDmaCount = c; // This is done to get the correct waitstates. if (sm>15) @@ -2141,7 +2286,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) } cpuDmaTicksToUpdate += totalTicks; - + cpuDmaHack = false; } void CPUCheckDMA(int reason, int dmamask) @@ -2184,7 +2329,6 @@ void CPUCheckDMA(int reason, int dmamask) doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, DM0CNT_L ? DM0CNT_L : 0x4000, DM0CNT_H & 0x0400); - cpuDmaHack = true; if(DM0CNT_H & 0x4000) { IF |= 0x0100; @@ -2253,7 +2397,6 @@ void CPUCheckDMA(int reason, int dmamask) DM1CNT_L ? DM1CNT_L : 0x4000, DM1CNT_H & 0x0400); } - cpuDmaHack = true; if(DM1CNT_H & 0x4000) { IF |= 0x0200; @@ -2323,7 +2466,6 @@ void CPUCheckDMA(int reason, int dmamask) DM2CNT_L ? DM2CNT_L : 0x4000, DM2CNT_H & 0x0400); } - cpuDmaHack = true; if(DM2CNT_H & 0x4000) { IF |= 0x0400; @@ -2380,6 +2522,7 @@ void CPUCheckDMA(int reason, int dmamask) doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, DM3CNT_L ? DM3CNT_L : 0x10000, DM3CNT_H & 0x0400); + if(DM3CNT_H & 0x4000) { IF |= 0x0800; UPDATE_REG(0x202, IF); @@ -2426,7 +2569,7 @@ void CPUUpdateRegister(u32 address, u16 value) windowOn = (layerEnable & 0x6000) ? true : false; if(change && !((value & 0x80))) { if(!(DISPSTAT & 1)) { - lcdTicks = 1008; + //lcdTicks = 1008; // VCOUNT = 0; // UPDATE_REG(0x06, VCOUNT); DISPSTAT &= 0xFFFC; @@ -3479,9 +3622,11 @@ void CPULoop(int ticks) if(!holdState && !SWITicks) { if(armState) { + armOpcodeCount++; if (!armExecute()) return; } else { + thumbOpcodeCount++; if (!thumbExecute()) return; } @@ -3504,7 +3649,6 @@ void CPULoop(int ticks) clockTicks = cpuNextEvent; cpuTotalTicks = 0; - cpuDmaHack = false; updateLoop: @@ -3538,7 +3682,7 @@ void CPULoop(int ticks) } } - if(VCOUNT >= 228) { //Reaching last line + if(VCOUNT > 227) { //Reaching last line DISPSTAT &= 0xFFFC; UPDATE_REG(0x04, DISPSTAT); VCOUNT = 0; @@ -3903,7 +4047,6 @@ void CPULoop(int ticks) cpuDmaTicksToUpdate -= clockTicks; if(cpuDmaTicksToUpdate < 0) cpuDmaTicksToUpdate = 0; - cpuDmaHack = true; goto updateLoop; } @@ -3976,6 +4119,256 @@ void CPULoop(int ticks) } } +#ifdef TILED_RENDERING +union u8h +{ + struct + { + /* 0*/ unsigned lo:4; + /* 4*/ unsigned hi:4; + } __attribute__ ((packed)); + u8 val; +}; + +union TileEntry +{ + struct + { + /* 0*/ unsigned tileNum:10; + /*12*/ unsigned hFlip:1; + /*13*/ unsigned vFlip:1; + /*14*/ unsigned palette:4; + }; + u16 val; +}; + +struct TileLine +{ + u32 pixels[8]; +}; + +typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32); + +static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio) +{ + *dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000; +} + +inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) tileY = 7 - tileY; + TileLine tileLine; + + const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8]; + + if (!tile.hFlip) + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio); + } + else + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio); + } + + return tileLine; +} + +inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) +{ + TileEntry tile; + tile.val = READ16LE(screenSource); + + int tileY = yyy & 7; + if (tile.vFlip) tileY = 7 - tileY; + palette += tile.palette * 16; + TileLine tileLine; + + const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4]; + + if (!tile.hFlip) + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio); + } + else + { + gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio); + gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio); + gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio); + } + + return tileLine; +} + +static inline void gfxDrawTile(const TileLine &tileLine, u32 *line) +{ + memcpy(line, tileLine.pixels, sizeof(tileLine.pixels)); +} + +static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w) +{ + memcpy(line, tileLine.pixels + start, w * sizeof(u32)); +} + +template +static void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, + u32 *line) +{ + u16 *palette = (u16 *)paletteRAM; + u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; + u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; + u32 prio = ((control & 3)<<25) + 0x1000000; + int sizeX = 256; + int sizeY = 256; + switch ((control >> 14) & 3) + { + case 0: + break; + case 1: + sizeX = 512; + break; + case 2: + sizeY = 512; + break; + case 3: + sizeX = 512; + sizeY = 512; + break; + } + + int maskX = sizeX-1; + int maskY = sizeY-1; + + bool mosaicOn = (control & 0x40) ? true : false; + + int xxx = hofs & maskX; + int yyy = (vofs + VCOUNT) & maskY; + int mosaicX = (MOSAIC & 0x000F)+1; + int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; + + if (mosaicOn) + { + if ((VCOUNT % mosaicY) != 0) + { + mosaicY = VCOUNT - (VCOUNT % mosaicY); + yyy = (vofs + mosaicY) & maskY; + } + } + + if (yyy > 255 && sizeY > 256) + { + yyy &= 255; + screenBase += 0x400; + if (sizeX > 256) + screenBase += 0x400; + } + + int yshift = ((yyy>>3)<<5); + + u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; + int x = 0; + const int firstTileX = xxx & 7; + + // First tile, if clipped + if (firstTileX) + { + gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX); + screenSource++; + x += 8 - firstTileX; + xxx += 8 - firstTileX; + + if (xxx == 256 && sizeX > 256) + { + screenSource = screenBase + 0x400 + yshift; + } + else if (xxx >= sizeX) + { + xxx = 0; + screenSource = screenBase + yshift; + } + } + + // Middle tiles, full + while (x < 240 - firstTileX) + { + gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]); + screenSource++; + xxx += 8; + x += 8; + + if (xxx == 256 && sizeX > 256) + { + screenSource = screenBase + 0x400 + yshift; + } + else if (xxx >= sizeX) + { + xxx = 0; + screenSource = screenBase + yshift; + } + } + + // Last tile, if clipped + if (firstTileX) + { + gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX); + } + + if (mosaicOn) + { + if (mosaicX > 1) + { + int m = 1; + for (int i = 0; i < 239; i++) + { + line[i+1] = line[i]; + m++; + if (m == mosaicX) + { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line) +{ + if (control & 0x80) // 1 pal / 256 col + gfxDrawTextScreen(control, hofs, vofs, line); + else // 16 pal / 16 col + gfxDrawTextScreen(control, hofs, vofs, line); +} +#endif struct EmulatedSystem GBASystem = { @@ -3994,7 +4387,11 @@ struct EmulatedSystem GBASystem = { // emuWriteState CPUWriteState, // emuReadMemState +#ifdef __LIBRETRO__ + NULL, +#else CPUReadMemState, +#endif // emuWriteMemState CPUWriteMemState, // emuWritePNG diff --git a/src/gba/GBA.h b/src/gba/GBA.h index ec104ad3..7da9df11 100644 --- a/src/gba/GBA.h +++ b/src/gba/GBA.h @@ -90,9 +90,14 @@ extern void CPUCleanUp(); extern void CPUUpdateRender(); extern void CPUUpdateRenderBuffers(bool); extern bool CPUReadMemState(char *, int); -extern bool CPUReadState(const char *); extern bool CPUWriteMemState(char *, int); +#ifdef __LIBRETRO__ +extern bool CPUReadState(const u8*, unsigned); +extern unsigned int CPUWriteState(u8 *data, unsigned int size); +#else +extern bool CPUReadState(const char *); extern bool CPUWriteState(const char *); +#endif extern int CPULoadRom(const char *); extern void doMirroring(bool); extern void CPUUpdateRegister(u32, u16); diff --git a/src/gba/GBAGfx.h b/src/gba/GBAGfx.h index 6d0a557f..e90ef43a 100644 --- a/src/gba/GBAGfx.h +++ b/src/gba/GBAGfx.h @@ -8,7 +8,11 @@ //#define SPRITE_DEBUG +#ifdef TILED_RENDERING +extern void gfxDrawTextScreen(u16, u16, u16, u32 *); +#else static void gfxDrawTextScreen(u16, u16, u16, u32 *); +#endif static void gfxDrawRotScreen(u16, u16, u16, u16, u16, @@ -98,6 +102,7 @@ static inline void gfxClearArray(u32 *array) } } +#ifndef TILED_RENDERING static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line) { @@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, } } } +#endif static inline void gfxDrawRotScreen(u16 control, u16 x_l, u16 x_h, diff --git a/src/gba/GBAinline.h b/src/gba/GBAinline.h index aec55aae..11254f91 100644 --- a/src/gba/GBAinline.h +++ b/src/gba/GBAinline.h @@ -49,11 +49,9 @@ static inline u32 CPUReadMemory(u32 address) u32 value; u32 oldAddress = address; -#ifdef C_CORE if(address & 3) { address &= ~0x03; } -#endif switch(address >> 24) { case 0: @@ -79,18 +77,18 @@ static inline u32 CPUReadMemory(u32 address) value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); break; case 4: - if((address < 0x4000400) && ioReadable[address & 0x3fc]) { - if(ioReadable[(address & 0x3fc) + 2]) { - value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); - if ((address & 0x3fc) == COMM_JOY_RECV_L) - UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV); - } else { - value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); - } - } - else - goto unreadable; - break; + if((address < 0x4000400) && ioReadable[address & 0x3fc]) { + if(ioReadable[(address & 0x3fc) + 2]) { + value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); + if ((address & 0x3fc) == COMM_JOY_RECV_L) + UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV); + } else { + value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); + } + } + else + goto unreadable; + break; case 5: value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); break; @@ -116,14 +114,12 @@ static inline u32 CPUReadMemory(u32 address) value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); break; case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; + value = eepromRead(address); + break; case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); + case 15: + value = flashRead(address) * 0x01010101; + break; // default default: unreadable: @@ -133,18 +129,17 @@ unreadable: armNextPC - 4 : armNextPC - 2); } #endif - - if(cpuDmaHack) { - value = cpuDmaLast; - } else { + if(cpuDmaHack) { + value = cpuDmaLast; + } else { if(armState) { - value = CPUReadMemoryQuick(reg[15].I); + return CPUReadMemoryQuick(reg[15].I); } else { - value = CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; + return CPUReadHalfWordQuick(reg[15].I) | + CPUReadHalfWordQuick(reg[15].I) << 16; } - } - return value; + } + break; } if(oldAddress & 3) { @@ -187,11 +182,9 @@ static inline u32 CPUReadHalfWord(u32 address) u32 value; u32 oldAddress = address; -//#ifdef C_CORE if(address & 1) { address &= ~0x01; } -//#endif switch(address >> 24) { case 0: @@ -233,6 +226,10 @@ static inline u32 CPUReadHalfWord(u32 address) value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); } } + else if((address < 0x4000400) && ioReadable[address & 0x3fc]) + { + value = 0; + } else goto unreadable; break; case 5: @@ -263,34 +260,30 @@ static inline u32 CPUReadHalfWord(u32 address) value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); break; case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; + value = eepromRead(address); + break; case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); + case 15: + value = flashRead(address) * 0x0101; + break; // default default: unreadable: -#ifdef GBA_LOGGING - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", oldAddress, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - if(cpuDmaHack) { - value = cpuDmaLast & 0xFFFF; - } else { + if(cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; + } else { if(armState) { - value = CPUReadMemoryQuick(reg[15].I); + value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); } else { - value = CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; + value = CPUReadHalfWordQuick(reg[15].I); } - } - return value; + } +#ifdef GBA_LOGGING + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal halfword read: %08x at %08x (%08x)\n", oldAddress, reg[15].I, value); + } +#endif + return value; } if(oldAddress & 1) { @@ -306,24 +299,19 @@ unreadable: return value; } -static inline u16 CPUReadHalfWordSigned(u32 address) +static inline s16 CPUReadHalfWordSigned(u32 address) { - u32 oldAddress = address; - if(address & 1) { - address &= ~0x01; - } - u16 value = CPUReadHalfWord(address); - if((oldAddress & 1)) + s32 value = (s32)CPUReadHalfWord(address); + if((address & 1)) { - value = (s8)value; #ifdef GBA_LOGGING if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ? + log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", address, armMode ? armNextPC - 4 : armNextPC - 2, value); } #endif } - return value; + return (s16)value; } static inline u8 CPUReadByte(u32 address) @@ -368,24 +356,24 @@ static inline u8 CPUReadByte(u32 address) case 12: return rom[address & 0x1FFFFFF]; case 13: - if(cpuEEPROMEnabled) - return eepromRead(address); - goto unreadable; + return eepromRead(address); case 14: - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } + case 15: + { + if (cpuEEPROMSensorEnabled) { + switch (address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8) | 0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + return flashRead(address); + } // default default: unreadable: @@ -395,17 +383,15 @@ unreadable: armNextPC - 4 : armNextPC - 2); } #endif - if(cpuDmaHack) { - return cpuDmaLast & 0xFF; - } else { + if(cpuDmaHack) { + return cpuDmaLast & 0xFF; + } else { if(armState) { - return CPUReadMemoryQuick(reg[15].I); + return CPUReadByteQuick(reg[15].I + (address & 3)); } else { - return CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; + return CPUReadByteQuick(reg[15].I + (address & 1)); } - } - break; + } } } @@ -423,6 +409,8 @@ static inline void CPUWriteMemory(u32 address, u32 value) } #endif + address &= 0xFFFFFFFC; + switch(address >> 24) { case 0x02: #ifdef BKPT_SUPPORT @@ -488,6 +476,7 @@ static inline void CPUWriteMemory(u32 address, u32 value) } goto unwritable; case 0x0E: + case 0x0F: if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { (*cpuSaveGameFunc)(address, (u8)value); break; @@ -520,6 +509,8 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) } #endif + address &= 0xFFFFFFFE; + switch(address >> 24) { case 2: #ifdef BKPT_SUPPORT @@ -590,6 +581,7 @@ static inline void CPUWriteHalfWord(u32 address, u16 value) } goto unwritable; case 14: + case 15: if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { (*cpuSaveGameFunc)(address, (u8)value); break; @@ -726,6 +718,7 @@ static inline void CPUWriteByte(u32 address, u8 b) } goto unwritable; case 14: + case 15: if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) { //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) { diff --git a/src/gba/RTC.cpp b/src/gba/RTC.cpp index 21d0a2de..bc060ac7 100644 --- a/src/gba/RTC.cpp +++ b/src/gba/RTC.cpp @@ -7,8 +7,15 @@ #include #include +#include -enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; +enum RTCSTATE +{ + IDLE = 0, + COMMAND, + DATA, + READDATA +}; typedef struct { u8 byte0; @@ -197,6 +204,17 @@ void rtcReset() rtcClockData.state = IDLE; } +#ifdef __LIBRETRO__ +void rtcSaveGame(u8 *&data) +{ + utilWriteMem(data, &rtcClockData, sizeof(rtcClockData)); +} + +void rtcReadGame(const u8 *&data) +{ + utilReadMem(&rtcClockData, data, sizeof(rtcClockData)); +} +#else void rtcSaveGame(gzFile gzFile) { utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData)); @@ -206,3 +224,4 @@ void rtcReadGame(gzFile gzFile) { utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData)); } +#endif diff --git a/src/gba/RTC.h b/src/gba/RTC.h index 8bedd68e..a125a623 100644 --- a/src/gba/RTC.h +++ b/src/gba/RTC.h @@ -7,7 +7,12 @@ void rtcEnable(bool); bool rtcIsEnabled(); void rtcReset(); +#ifdef __LIBRETRO__ +void rtcReadGame(const u8 *&data); +void rtcSaveGame(u8 *&data); +#else void rtcReadGame(gzFile gzFile); void rtcSaveGame(gzFile gzFile); +#endif #endif // RTC_H diff --git a/src/gba/Sound.cpp b/src/gba/Sound.cpp index e8f7523f..442c2034 100644 --- a/src/gba/Sound.cpp +++ b/src/gba/Sound.cpp @@ -183,15 +183,19 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer ) { if ( which_timer == timer && enabled ) { - if ( count <= 16 ) + /* Mother 3 fix, refined to not break Metroid Fusion */ + if ( count == 16 || count == 0 ) { // Need to fill FIFO + int saved_count = count; CPUCheckDMA( 3, which ? 4 : 2 ); - if ( count <= 16 ) + if ( saved_count == 0 && count == 16 ) + CPUCheckDMA( 3, which ? 4 : 2 ); + if ( count == 0 ) { // Not filled by DMA, so fill with 16 bytes of silence int reg = which ? FIFOB_L : FIFOA_L; - for ( int n = 4; n--; ) + for ( int n = 8; n--; ) { soundEvent(reg , (u16)0); soundEvent(reg+2, (u16)0); @@ -348,6 +352,11 @@ static void end_frame( blip_time_t time ) void flush_samples(Multi_Buffer * buffer) { +#ifdef __LIBRETRO__ + int numSamples = buffer->read_samples( (blip_sample_t*) soundFinalWave, buffer->samples_avail() ); + soundDriver->write(soundFinalWave, numSamples); + systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples); +#else // We want to write the data frame by frame to support legacy audio drivers // that don't use the length parameter of the write method. // TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the @@ -370,6 +379,7 @@ void flush_samples(Multi_Buffer * buffer) soundDriver->write(soundFinalWave, soundBufferLen); systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen); } +#endif } static void apply_filtering() @@ -446,6 +456,13 @@ static void remake_stereo_buffer() pcm [0].pcm.init(); pcm [1].pcm.init(); + // APU + if ( !gb_apu ) + { + gb_apu = new Gb_Apu; // TODO: handle out of memory + reset_apu(); + } + // Stereo_Buffer delete stereo_buffer; stereo_buffer = 0; @@ -459,13 +476,7 @@ static void remake_stereo_buffer() pcm [1].which = 1; apply_filtering(); - // APU - if ( !gb_apu ) - { - gb_apu = new Gb_Apu; // TODO: handle out of memory - reset_apu(); - } - + // Volume Level apply_muting(); apply_volume(); } @@ -743,16 +754,25 @@ static void skip_read( gzFile in, int count ) } } +#ifdef __LIBRETRO__ +void soundSaveGame( u8 *&out ) +#else void soundSaveGame( gzFile out ) +#endif { gb_apu->save_state( &state.apu ); // Be sure areas for expansion get written as zero memset( dummy_state, 0, sizeof dummy_state ); +#ifdef __LIBRETRO__ + utilWriteDataMem( out, gba_state ); +#else utilWriteData( out, gba_state ); +#endif } +#ifndef __LIBRETRO__ static void soundReadGameOld( gzFile in, int version ) { // Read main data @@ -787,19 +807,28 @@ static void soundReadGameOld( gzFile in, int version ) (void) utilReadInt( in ); // ignore quality } +#endif #include +#ifdef __LIBRETRO__ +void soundReadGame(const u8*& in, int version ) +#else void soundReadGame( gzFile in, int version ) +#endif { // Prepare APU and default state reset_apu(); gb_apu->save_state( &state.apu ); if ( version > SAVE_GAME_VERSION_9 ) +#ifdef __LIBRETRO__ + utilReadDataMem( in, gba_state ); +#else utilReadData( in, gba_state ); else soundReadGameOld( in, version ); +#endif gb_apu->load_state( state.apu ); write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F ); diff --git a/src/gba/Sound.h b/src/gba/Sound.h index f6661930..47750a77 100644 --- a/src/gba/Sound.h +++ b/src/gba/Sound.h @@ -74,8 +74,13 @@ extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to so extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called // Saves/loads emulator state +#ifdef __LIBRETRO__ +void soundSaveGame( u8 *& ); +void soundReadGame(const u8*& in, int version ); +#else void soundSaveGame( gzFile ); void soundReadGame( gzFile, int version ); +#endif class Multi_Buffer; diff --git a/src/gba/elf.cpp b/src/gba/elf.cpp index 3b0cf2f3..27331858 100644 --- a/src/gba/elf.cpp +++ b/src/gba/elf.cpp @@ -1058,7 +1058,7 @@ void elfParseCFA(u8 *top) if(id == 0xffffffff) { // skip version - *data++; + (*data)++; ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie)); diff --git a/src/gba/remote.cpp b/src/gba/remote.cpp index 0dc58856..6e31edf0 100644 --- a/src/gba/remote.cpp +++ b/src/gba/remote.cpp @@ -1,3 +1,4 @@ +#ifndef __LIBRETRO__ #include #include #include @@ -75,7 +76,11 @@ bool remoteTcpInit() remoteListenSocket = s; +#ifdef _WIN32 + if(s == INVALID_SOCKET) { +#else if(s < 0) { +#endif fprintf(stderr,"Error opening socket\n"); exit(-1); } @@ -719,3 +724,4 @@ void remoteCleanUp() if(remoteCleanUpFnc) remoteCleanUpFnc(); } +#endif diff --git a/src/gtk/directoriesconfig.cpp b/src/gtk/directoriesconfig.cpp index adff4e2b..28f3a50d 100644 --- a/src/gtk/directoriesconfig.cpp +++ b/src/gtk/directoriesconfig.cpp @@ -30,6 +30,7 @@ const DirectoriesConfigDialog::SDirEntry DirectoriesConfigDialog::m_astDirs[] = { "gba_roms", N_("GBA roms :"), "GBARomsDirEntry" }, { "gb_roms", N_("GB roms :"), "GBRomsDirEntry" }, { "batteries", N_("Batteries :"), "BatteriesDirEntry" }, + { "cheats", N_("Cheats :"), "CheatsDirEntry" }, { "saves", N_("Saves :"), "SavesDirEntry" }, { "captures", N_("Captures :"), "CapturesDirEntry" } }; diff --git a/src/gtk/directoriesconfig.h b/src/gtk/directoriesconfig.h index f1f4a2d9..74477842 100644 --- a/src/gtk/directoriesconfig.h +++ b/src/gtk/directoriesconfig.h @@ -47,7 +47,7 @@ private: Config::Section * m_poConfig; static const SDirEntry m_astDirs[]; - Gtk::FileChooserButton * m_poButtons[5]; + Gtk::FileChooserButton * m_poButtons[6]; }; } // namespace VBA diff --git a/src/gtk/gameboyconfig.cpp b/src/gtk/gameboyconfig.cpp index c415fad7..57bc667d 100644 --- a/src/gtk/gameboyconfig.cpp +++ b/src/gtk/gameboyconfig.cpp @@ -27,6 +27,16 @@ namespace VBA { +static const VBA::Window::EEmulatorType aEmulatorType[] = +{ + VBA::Window::EmulatorAuto, + VBA::Window::EmulatorCGB, + VBA::Window::EmulatorSGB, + VBA::Window::EmulatorGB, + VBA::Window::EmulatorGBA, + VBA::Window::EmulatorSGB2 +}; + GameBoyConfigDialog::GameBoyConfigDialog(GtkDialog* _pstDialog, const Glib::RefPtr& refBuilder) : Gtk::Dialog(_pstDialog), m_poConfig(0) @@ -49,8 +59,6 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window * m_poConfig = _poConfig; m_poWindow = _poWindow; - const int aEmulatorType[] = { 0, 2, 3, 5, 1, 4 }; - VBA::Window::EEmulatorType eDefaultEmulatorType = (VBA::Window::EEmulatorType)m_poConfig->oGetKey("emulator_type"); m_poSystemComboBox->set_active(aEmulatorType[eDefaultEmulatorType]); @@ -70,17 +78,7 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window * void GameBoyConfigDialog::vOnSystemChanged() { - const VBA::Window::EEmulatorType aEmulatorType[] = - { - VBA::Window::EmulatorAuto, - VBA::Window::EmulatorCGB, - VBA::Window::EmulatorSGB, - VBA::Window::EmulatorGB, - VBA::Window::EmulatorGBA, - VBA::Window::EmulatorSGB2 - }; - - int iSystem = m_poSystemComboBox->get_active_row_number(); + int iSystem = m_poSystemComboBox->get_active_row_number(); m_poConfig->vSetKey("emulator_type", aEmulatorType[iSystem]); m_poWindow->vApplyConfigGBSystem(); diff --git a/src/gtk/gvbam.desktop b/src/gtk/gvbam.desktop index 2b78ba89..e3d050ff 100644 --- a/src/gtk/gvbam.desktop +++ b/src/gtk/gvbam.desktop @@ -1,11 +1,10 @@ -[Desktop Entry] -Version=1.0 -Encoding=UTF-8 -Type=Application -Name=VBA-M -GenericName=GameBoy Advance Emulator -Comment=Nindendo GameBoy Advance Emulator -Exec=gvbam -Icon=vbam -Categories=Application;Game;Emulator;GTK -MimeType=application/x-gameboy-rom;application/x-gameboy-advance-rom;application/x-dmg-rom;application/x-agb-rom;application/x-gb-rom;application/x-gba-rom +[Desktop Entry] +Version=1.0 +Type=Application +Name=VBA-M +GenericName=GameBoy Advance Emulator +Comment=Nindendo GameBoy Advance Emulator +Exec=gvbam %f +Icon=vbam +Categories=Game;Emulator;GTK; +MimeType=application/x-gameboy-rom;application/x-gameboy-advance-rom;application/x-dmg-rom;application/x-agb-rom;application/x-gb-rom;application/x-gba-rom; diff --git a/src/gtk/joypadconfig.cpp b/src/gtk/joypadconfig.cpp index 3a009d11..b12e2121 100644 --- a/src/gtk/joypadconfig.cpp +++ b/src/gtk/joypadconfig.cpp @@ -49,10 +49,10 @@ JoypadConfigDialog::JoypadConfigDialog(Config::Section * _poConfig) : m_oTitleLabel(_("Joypad :"), Gtk::ALIGN_RIGHT), m_oDefaultJoypad(_("Default joypad")), m_oTable(G_N_ELEMENTS(m_astKeys), 2, false), + m_iCurrentEntry(-1), m_bUpdating(false), m_ePad(PAD_MAIN), - m_poConfig(_poConfig), - m_iCurrentEntry(-1) + m_poConfig(_poConfig) { // Joypad selection m_oTitleCombo.append_text("1"); @@ -115,7 +115,7 @@ void JoypadConfigDialog::vUpdateEntries() for (guint i = 0; i < m_oEntries.size(); i++) { - const char * csName = 0; + std::string csName; guint uiKeyval = inputGetKeymap(m_ePad, m_astKeys[i].m_eKeyFlag); int dev = uiKeyval >> 16; @@ -158,10 +158,10 @@ void JoypadConfigDialog::vUpdateEntries() } } - csName = os.str().c_str(); + csName = os.str(); } - if (csName == 0) + if (csName.empty()) { m_oEntries[i]->set_text(_("")); } diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 3daf24b1..96b0803a 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -504,6 +504,7 @@ void Window::vInitConfig() m_poDirConfig->vSetKey("gb_roms", Glib::get_home_dir()); m_poDirConfig->vSetKey("gba_roms", Glib::get_home_dir()); m_poDirConfig->vSetKey("batteries", m_sUserDataDir); + m_poDirConfig->vSetKey("cheats", m_sUserDataDir); m_poDirConfig->vSetKey("saves", m_sUserDataDir); m_poDirConfig->vSetKey("captures", m_sUserDataDir); @@ -588,6 +589,11 @@ void Window::vCheckConfig() { m_poDirConfig->vSetKey("batteries", m_sUserDataDir); } + sValue = m_poDirConfig->sGetKey("cheats"); + if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR)) + { + m_poDirConfig->vSetKey("cheats", m_sUserDataDir); + } sValue = m_poDirConfig->sGetKey("saves"); if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR)) { @@ -1078,6 +1084,7 @@ bool Window::bLoadROM(const std::string & _rsFile) } vLoadBattery(); + vLoadCheats(); vUpdateScreen(); emulating = 1; @@ -1342,6 +1349,30 @@ void Window::vLoadBattery() } } +void Window::vLoadCheats() +{ + std::string sCheats; + std::string sDir = m_poDirConfig->sGetKey("cheats"); + if (sDir == "") + { + sDir = m_sUserDataDir; + } + + sCheats = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".clt"; + + if (Glib::file_test(sCheats, Glib::FILE_TEST_EXISTS)) + { + if (m_eCartridge == CartridgeGB) + { + gbCheatsLoadCheatList(sCheats.c_str()); + } + else if (m_eCartridge == CartridgeGBA) + { + cheatsLoadCheatList(sCheats.c_str()); + } + } +} + void Window::vSaveBattery() { std::string sBattery; @@ -1359,6 +1390,27 @@ void Window::vSaveBattery() } } +void Window::vSaveCheats() +{ + std::string sCheats; + std::string sDir = m_poDirConfig->sGetKey("cheats"); + if (sDir == "") + { + sDir = m_sUserDataDir; + } + + sCheats = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".clt"; + + if (m_eCartridge == CartridgeGB) + { + gbCheatsSaveCheatList(sCheats.c_str()); + } + else if (m_eCartridge == CartridgeGBA) + { + cheatsSaveCheatList(sCheats.c_str()); + } +} + void Window::vStartEmu() { if (m_oEmuSig.connected()) diff --git a/src/gtk/window.h b/src/gtk/window.h index 2488ebfb..77652499 100644 --- a/src/gtk/window.h +++ b/src/gtk/window.h @@ -272,7 +272,9 @@ private: void vSetDefaultTitle(); void vCreateFileOpenDialog(); void vLoadBattery(); + void vLoadCheats(); void vSaveBattery(); + void vSaveCheats(); void vStartEmu(); void vStopEmu(); void vUpdateGameSlots(); diff --git a/src/gtk/windowcallbacks.cpp b/src/gtk/windowcallbacks.cpp index 1380bffb..9396b99a 100644 --- a/src/gtk/windowcallbacks.cpp +++ b/src/gtk/windowcallbacks.cpp @@ -335,6 +335,7 @@ void Window::vOnFileClose() vSetDefaultTitle(); vDrawDefaultScreen(); vSaveBattery(); + vSaveCheats(); m_stEmulator.emuCleanUp(); m_eCartridge = CartridgeNone; emulating = 0; diff --git a/src/sdl/SDL.cpp b/src/sdl/SDL.cpp index 932cc680..910e93e6 100644 --- a/src/sdl/SDL.cpp +++ b/src/sdl/SDL.cpp @@ -125,6 +125,7 @@ int desktopHeight = 0; Filter filter = kStretch2x; u8 *delta = NULL; +static const int delta_size = 322*242*4; int filter_enlarge = 2; @@ -1395,7 +1396,7 @@ void sdlPollEvents() soundPause(); } - memset(delta,255,sizeof(delta)); + memset(delta,255,delta_size); } } break; @@ -2311,8 +2312,8 @@ int main(int argc, char **argv) utilUpdateSystemColorMaps(); if(delta == NULL) { - delta = (u8*)malloc(322*242*4); - memset(delta, 255, 322*242*4); + delta = (u8*)malloc(delta_size); + memset(delta, 255, delta_size); } ifbFunction = initIFBFilter(ifbType, systemColorDepth); diff --git a/src/win32/OpenGL.cpp b/src/win32/OpenGL.cpp index 4ff19d98..ba6cc546 100644 --- a/src/win32/OpenGL.cpp +++ b/src/win32/OpenGL.cpp @@ -345,9 +345,9 @@ bool OpenGLDisplay::initialize() cpu_mmx = 0; #endif - systemRedShift = 3; + systemRedShift = 19; systemGreenShift = 11; - systemBlueShift = 19; + systemBlueShift = 3; systemColorDepth = 32; theApp.fsColorDepth = 32; @@ -401,7 +401,7 @@ void OpenGLDisplay::render() } else { glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 ); } - glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data ); + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,data ); glBegin( GL_QUADS ); diff --git a/src/win32/XAudio2.cpp b/src/win32/XAudio2.cpp index ffd48849..0541d7fd 100644 --- a/src/win32/XAudio2.cpp +++ b/src/win32/XAudio2.cpp @@ -287,9 +287,9 @@ bool XAudio2_Output::init(long sampleRate) // Initialize XAudio2 UINT32 flags = 0; -#ifdef _DEBUG - flags = XAUDIO2_DEBUG_ENGINE; -#endif +//#ifdef _DEBUG +// flags = XAUDIO2_DEBUG_ENGINE; +//#endif hr = XAudio2Create( &xaud, flags ); if( hr != S_OK ) { diff --git a/src/win32/rpi.cpp b/src/win32/rpi.cpp index 73ad0600..c5ae7744 100644 --- a/src/win32/rpi.cpp +++ b/src/win32/rpi.cpp @@ -138,7 +138,7 @@ void rpiFilter(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, *(pOCur++) = ((*pICur & 0xF800) << rshiftDiff) | ((*pICur & 0x07E0) << gshiftDiff) | ((*pICur & 0x001F) << bshiftDiff); - *pICur++; + *(pICur++); } pI = pICur = (u16 *)((char *)pI + dstPitch); pO = pOCur = (u32 *)((char *)pO + dstPitch); @@ -157,7 +157,7 @@ void rpiFilter(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, *(pOCur++) = ((*pICur & 0xF800) >> rshiftDiff) | ((*pICur & 0x07E0) << gshiftDiff) | ((*pICur & 0x001F) << bshiftDiff); - *pICur++; + *(pICur++); } pI = pICur = (u16 *)((char *)pI + dstPitch); pO = pOCur = (u32 *)((char *)pO + dstPitch);