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..ff5051fc 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]; 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/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/gb/gbGfx.cpp b/src/gb/gbGfx.cpp index 72e65598..a197405f 100644 --- a/src/gb/gbGfx.cpp +++ b/src/gb/gbGfx.cpp @@ -234,7 +234,7 @@ void gbRenderLine() if(y >= inUseRegister_WY) { - if ((gbWindowLine == -1) || (gbWindowLine>144)) + if (gbWindowLine>143) gbWindowLine = 0; int wx = register_WX; 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..aa866e15 100644 --- a/src/gba/EEprom.cpp +++ b/src/gba/EEprom.cpp @@ -9,7 +9,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 +35,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 +52,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 +100,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..71e039ce 100644 --- a/src/gba/Flash.cpp +++ b/src/gba/Flash.cpp @@ -17,7 +17,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 +57,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 +71,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 +111,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.cpp b/src/gba/GBA.cpp index d383fbe5..a87d044a 100644 --- a/src/gba/GBA.cpp +++ b/src/gba/GBA.cpp @@ -577,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); @@ -630,6 +668,7 @@ bool CPUWriteState(const char *file) return res; } + bool CPUWriteMemState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -649,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); @@ -846,6 +986,7 @@ bool CPUReadState(const char * file) return res; } +#endif bool CPUExportEepromFile(const char *fileName) { @@ -3999,7 +4140,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/GBAinline.h b/src/gba/GBAinline.h index 2a473e02..80b7e866 100644 --- a/src/gba/GBAinline.h +++ b/src/gba/GBAinline.h @@ -77,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; @@ -121,11 +121,14 @@ static inline u32 CPUReadMemory(u32 address) case 14: case 15: if(cpuFlashEnabled | cpuSramEnabled) - { - // no need to swap this - value = flashRead(address) * 0x01010101; - break; + { // no need to swap this + #ifdef __libretro__ + return flashRead(address); + #else + value = flashRead(address) * 0x01010101; + #endif } + break; // default default: unreadable: @@ -145,6 +148,7 @@ unreadable: CPUReadHalfWordQuick(reg[15].I) << 16; } } + break; } if(oldAddress & 3) { @@ -272,10 +276,13 @@ static inline u32 CPUReadHalfWord(u32 address) case 14: case 15: if(cpuFlashEnabled | cpuSramEnabled) - { // no need to swap this - value = flashRead(address) * 0x0101; - break; + { + #ifdef __libretro__ + return flashRead(address); + #else + value = flashRead(address) * 0x0101; + #endif } // default default: diff --git a/src/gba/RTC.cpp b/src/gba/RTC.cpp index 21d0a2de..4075f371 100644 --- a/src/gba/RTC.cpp +++ b/src/gba/RTC.cpp @@ -8,7 +8,13 @@ #include #include -enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; +enum RTCSTATE +{ + IDLE = 0, + COMMAND, + DATA, + READDATA +}; typedef struct { u8 byte0; @@ -197,6 +203,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 +223,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 441573d1..39ada686 100644 --- a/src/gba/Sound.cpp +++ b/src/gba/Sound.cpp @@ -348,6 +348,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 +375,7 @@ void flush_samples(Multi_Buffer * buffer) soundDriver->write(soundFinalWave, soundBufferLen); systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen); } +#endif } static void apply_filtering() @@ -744,16 +750,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 @@ -788,19 +803,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/remote.cpp b/src/gba/remote.cpp index a292fb36..6e31edf0 100644 --- a/src/gba/remote.cpp +++ b/src/gba/remote.cpp @@ -1,3 +1,4 @@ +#ifndef __LIBRETRO__ #include #include #include @@ -723,3 +724,4 @@ void remoteCleanUp() if(remoteCleanUpFnc) remoteCleanUpFnc(); } +#endif diff --git a/src/libretro/Makefile b/src/libretro/Makefile new file mode 100644 index 00000000..0888bddd --- /dev/null +++ b/src/libretro/Makefile @@ -0,0 +1,68 @@ +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx +endif +endif + +ifeq ($(platform), unix) + TARGET := libvbam-retro.so + fpic := -fPIC + SHARED := -shared +else ifeq ($(platform), osx) + TARGET := libvbam-retro.dylib + fpic := -fPIC + SHARED := -dynamiclib +else + TARGET := vbam-retro.dll + LDFLAGS += -Wl,-no-undefined -Wl,--version-script=link.T + CC = gcc + CXX = g++ + SHARED := -shared -static-libgcc -static-libstdc++ +endif + +VBA_DIR := ../ + +VBA_SRC_DIRS := $(VBA_DIR)/gba $(VBA_DIR)/apu + +VBA_CXXSRCS := $(foreach dir,$(VBA_SRC_DIRS),$(wildcard $(dir)/*.cpp)) +VBA_CXXOBJ := $(VBA_CXXSRCS:.cpp=.o) ../common/Patch.o +VBA_CSRCS := $(foreach dir,$(VBA_SRC_DIRS),$(wildcard $(dir)/*.c)) +VBA_COBJ := $(VBA_CSRCS:.c=.o) +UTIL_SOURCES := $(wildcard ../common/utils/zlib/*.c) +UTIL_OBJS := $(UTIL_SOURCES:.c=.o) + +OBJS := $(VBA_COBJ) $(VBA_CXXOBJ) $(UTIL_OBJS) libretro.o UtilRetro.o SoundRetro.o scrc32.o + +VBA_DEFINES := -D__LIBRETRO__ -DFINAL_VERSION -DC_CORE -DUSE_GBA_ONLY -DNO_LINK +VBA_DEFINES += -DFRONTEND_SUPPORTS_RGB565 + +CFLAGS += -O3 -std=gnu99 $(fpic) $(VBA_DEFINES) -I../common/utils/zlib +CXXFLAGS += -O3 $(fpic) $(VBA_DEFINES) -I../common/utils/zlib + + +INCDIRS := -I$(VBA_DIR) +LIBS := + +$(TARGET): $(OBJS) + $(CXX) -o $@ $(SHARED) $(OBJS) $(LDFLAGS) $(LIBS) + +%.o: %.cpp + $(CXX) -c -o $@ $< $(CXXFLAGS) $(INCDIRS) + +%.o: %.c + $(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS) + +clean: + rm -f $(OBJS) + rm -f $(TARGET) + +.PHONY: clean + + diff --git a/src/libretro/SoundRetro.cpp b/src/libretro/SoundRetro.cpp new file mode 100644 index 00000000..c604b919 --- /dev/null +++ b/src/libretro/SoundRetro.cpp @@ -0,0 +1,58 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#include "libretro.h" +#include "SoundRetro.h" +unsigned g_audio_frames; +extern retro_audio_sample_batch_t audio_batch_cb; + +SoundRetro::SoundRetro() +{ +} + +void SoundRetro::write(u16 * finalWave, int length) +{ + const int16_t* wave = (const int16_t*)finalWave; + int frames = length >> 1; + audio_batch_cb(wave, frames); + + g_audio_frames += frames; +} + + +bool SoundRetro::init(long sampleRate) +{ + g_audio_frames = 0; + + return true; +} + +SoundRetro::~SoundRetro() +{ +} + +void SoundRetro::pause() +{ +} + +void SoundRetro::resume() +{ +} + +void SoundRetro::reset() +{ +} diff --git a/src/libretro/SoundRetro.h b/src/libretro/SoundRetro.h new file mode 100644 index 00000000..3aa3774e --- /dev/null +++ b/src/libretro/SoundRetro.h @@ -0,0 +1,36 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 2008 VBA-M development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef __VBA_SOUND_RETRO_H__ +#define __VBA_SOUND_RETRO_H__ + +#include "../common/SoundDriver.h" + +class SoundRetro: public SoundDriver +{ +public: + SoundRetro(); + virtual ~SoundRetro(); + + virtual bool init(long sampleRate); + virtual void pause(); + virtual void reset(); + virtual void resume(); + virtual void write(u16 * finalWave, int length); +}; + +#endif // __VBA_SOUND_RETRO_H__ diff --git a/src/libretro/UtilRetro.cpp b/src/libretro/UtilRetro.cpp new file mode 100644 index 00000000..22c58fc7 --- /dev/null +++ b/src/libretro/UtilRetro.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include + +#include "System.h" +#include "NLS.h" +#include "Util.h" +#include "gba/Flash.h" +#include "gba/GBA.h" +#include "gba/Globals.h" +#include "gba/RTC.h" +#include "common/Port.h" + +#include "gba/gbafilter.h" +#include "gb/gbGlobals.h" + +#ifndef _MSC_VER +#define _stricmp strcasecmp +#endif // ! _MSC_VER + +extern int systemColorDepth; +extern int systemRedShift; +extern int systemGreenShift; +extern int systemBlueShift; + +extern uint16_t systemColorMap16[0x10000]; +extern uint32_t systemColorMap32[0x10000]; + +bool utilWritePNGFile(const char *fileName, int w, int h, uint8_t *pix) +{ + return false; +} + +void utilPutDword(u8 *p, u32 value) +{ + *p++ = value & 255; + *p++ = (value >> 8) & 255; + *p++ = (value >> 16) & 255; + *p = (value >> 24) & 255; +} + +void utilPutWord(uint8_t *p, uint16_t value) +{ + *p++ = value & 255; + *p = (value >> 8) & 255; +} + +bool utilWriteBMPFile(const char *fileName, int w, int h, uint8_t *pix) +{ + return false; +} + +extern bool cpuIsMultiBoot; + +bool utilIsGBAImage(const char * file) +{ + cpuIsMultiBoot = false; + if(strlen(file) > 4) { + const char * p = strrchr(file,'.'); + + if(p != NULL) { + if((_stricmp(p, ".agb") == 0) || + (_stricmp(p, ".gba") == 0) || + (_stricmp(p, ".bin") == 0) || + (_stricmp(p, ".elf") == 0)) + return true; + if(_stricmp(p, ".mb") == 0) { + cpuIsMultiBoot = true; + return true; + } + } + } + + return false; +} + +bool utilIsGBImage(const char * file) +{ + if(strlen(file) > 4) { + const char * p = strrchr(file,'.'); + + if(p != NULL) { + if((_stricmp(p, ".dmg") == 0) || + (_stricmp(p, ".gb") == 0) || + (_stricmp(p, ".gbc") == 0) || + (_stricmp(p, ".cgb") == 0) || + (_stricmp(p, ".sgb") == 0)) + return true; + } + } + + return false; +} + +bool utilIsGzipFile(const char *file) +{ + if(strlen(file) > 3) { + const char * p = strrchr(file,'.'); + + if(p != NULL) { + if(_stricmp(p, ".gz") == 0) + return true; + if(_stricmp(p, ".z") == 0) + return true; + } + } + + return false; +} + +// strip .gz or .z off end +void utilStripDoubleExtension(const char *file, char *buffer) +{ + if(buffer != file) // allows conversion in place + strcpy(buffer, file); + + if(utilIsGzipFile(file)) { + char *p = strrchr(buffer, '.'); + + if(p) + *p = 0; + } +} + +static bool utilIsImage(const char *file) +{ + return utilIsGBAImage(file) || utilIsGBImage(file); +} + +uint32_t utilFindType(const char *file) +{ + char buffer [2048]; + if ( !utilIsImage( file ) ) // TODO: utilIsArchive() instead? + { + return IMAGE_UNKNOWN; + } + return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB; +} + +static int utilGetSize(int size) +{ + int res = 1; + while(res < size) + res <<= 1; + return res; +} + +uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data, int &size) +{ + FILE *fp = NULL; + char *buf = NULL; + + fp = fopen(file,"rb"); + fseek(fp, 0, SEEK_END); //go to end + size = ftell(fp); // get position at end (length) + rewind(fp); + + uint8_t *image = data; + if(image == NULL) + { + //allocate buffer memory if none was passed to the function + image = (uint8_t *)malloc(utilGetSize(size)); + if(image == NULL) + { + systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), + "data"); + return NULL; + } + } + + fread(image, 1, size, fp); // read into buffer + fclose(fp); + return image; +} + +void utilGBAFindSave(const uint8_t *data, const int size) +{ + uint32_t *p = (uint32_t *)data; + uint32_t *end = (uint32_t *)(data + size); + int saveType = 0; + int flashSize = 0x10000; + bool rtcFound = false; + + while(p < end) { + uint32_t d = READ32LE(p); + + if(d == 0x52504545) { + if(memcmp(p, "EEPROM_", 7) == 0) { + if(saveType == 0) + saveType = 3; + } + } else if (d == 0x4D415253) { + if(memcmp(p, "SRAM_", 5) == 0) { + if(saveType == 0) + saveType = 1; + } + } else if (d == 0x53414C46) { + if(memcmp(p, "FLASH1M_", 8) == 0) { + if(saveType == 0) { + saveType = 2; + flashSize = 0x20000; + } + } else if(memcmp(p, "FLASH", 5) == 0) { + if(saveType == 0) { + saveType = 2; + flashSize = 0x10000; + } + } + } else if (d == 0x52494953) { + if(memcmp(p, "SIIRTC_V", 8) == 0) + rtcFound = true; + } + p++; + } + // if no matches found, then set it to NONE + if(saveType == 0) { + saveType = 5; + } + + rtcEnable(rtcFound); + cpuSaveType = saveType; + flashSetSize(flashSize); +} + +void utilUpdateSystemColorMaps(bool lcd) +{ + switch(systemColorDepth) { + case 16: + { + for(int i = 0; i < 0x10000; i++) { + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if (lcd) gbafilter_pal(systemColorMap16, 0x10000); + } + break; + case 24: + case 32: + { + for(int i = 0; i < 0x10000; i++) { + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | + (((i & 0x3e0) >> 5) << systemGreenShift) | + (((i & 0x7c00) >> 10) << systemBlueShift); + } + if (lcd) gbafilter_pal32(systemColorMap32, 0x10000); + } + break; + } +} + +// Check for existence of file. +bool utilFileExists( const char *filename ) +{ + FILE *f = fopen( filename, "r" ); + if( f == NULL ) { + return false; + } else { + fclose( f ); + return true; + } +} + +// Not endian safe, but VBA itself doesn't seem to care, so hey <_< +void utilWriteIntMem(uint8_t *& data, int val) +{ + memcpy(data, &val, sizeof(int)); + data += sizeof(int); +} + +void utilWriteMem(uint8_t *& data, const void *in_data, unsigned size) +{ + memcpy(data, in_data, size); + data += size; +} + +void utilWriteDataMem(uint8_t *& data, variable_desc *desc) +{ + while (desc->address) + { + utilWriteMem(data, desc->address, desc->size); + desc++; + } +} + +int utilReadIntMem(const uint8_t *& data) +{ + int res; + memcpy(&res, data, sizeof(int)); + data += sizeof(int); + return res; +} + +void utilReadMem(void *buf, const uint8_t *& data, unsigned size) +{ + memcpy(buf, data, size); + data += size; +} + +void utilReadDataMem(const uint8_t *& data, variable_desc *desc) +{ + while (desc->address) + { + utilReadMem(desc->address, data, desc->size); + desc++; + } +} diff --git a/src/libretro/gbaconv/gbaconv.c b/src/libretro/gbaconv/gbaconv.c new file mode 100644 index 00000000..ae73a6cc --- /dev/null +++ b/src/libretro/gbaconv/gbaconv.c @@ -0,0 +1,216 @@ +#include +#include +#ifndef __CELLOS_LV2__ +#include +#endif +#include +#include +#include +#include + +enum save_type +{ + EEPROM_512B, + EEPROM_8K, + FLASH_64K, + FLASH_128K, + SAVE_UNKNOWN +}; + +static const char *save_type_to_string(enum save_type type) +{ + switch (type) + { + case EEPROM_512B: + return "EEPROM 4kbit"; + case EEPROM_8K: + return "EEPROM 64kbit"; + case FLASH_64K: + return "FLASH 512kbit"; + case FLASH_128K: + return "FLASH 1MBit"; + + default: + return "Unknown type"; + } +} + +static bool scan_section(const uint8_t *data, unsigned size) +{ + for (unsigned i = 0; i < size; i++) + { + if (data[i] != 0xff) + return true; + } + + return false; +} + +static enum save_type detect_save_type(const uint8_t *data, unsigned size) +{ + if (size == 512) + return EEPROM_512B; + if (size == 0x2000) + return EEPROM_8K; + if (size == 0x10000) + return FLASH_64K; + if (size == 0x20000) + return FLASH_128K; + + if (size == (0x20000 + 0x2000)) + { + if (scan_section(data, 0x10000) && !scan_section(data + 0x10000, 0x10000)) + return FLASH_64K; + if (scan_section(data, 0x20000)) + return FLASH_128K; + + if (scan_section(data + 0x20000, 512) && !scan_section(data + 0x20000 + 512, 0x20000 - 512)) + return EEPROM_512B; + if (scan_section(data + 0x20000, 0x2000)) + return EEPROM_8K; + } + + return SAVE_UNKNOWN; +} + +static void dump_srm(FILE *file, const uint8_t *data, enum save_type type) +{ + void *buf = malloc(0x20000 + 0x2000); + memset(buf, 0xff, 0x20000 + 0x2000); + + switch (type) + { + case EEPROM_512B: + fwrite(buf, 1, 0x20000, file); + fwrite(data, 1, 512, file); + fwrite(buf, 1, 0x2000 - 512, file); + break; + + case EEPROM_8K: + fwrite(buf, 1, 0x20000, file); + fwrite(data, 1, 0x2000, file); + break; + + case FLASH_64K: + fwrite(data, 1, 0x10000, file); + fwrite(buf, 1, 0x20000 + 0x2000 - 0x10000, file); + break; + + case FLASH_128K: + fwrite(data, 1, 0x20000, file); + fwrite(buf, 1, 0x2000, file); + break; + + default: + break; + } + + free(buf); +} + +static void dump_sav(FILE *file, const uint8_t *data, enum save_type type) +{ + switch (type) + { + case EEPROM_512B: + fwrite(data + 0x20000, 1, 512, file); + break; + + case EEPROM_8K: + fwrite(data + 0x20000, 1, 0x2000, file); + break; + + case FLASH_64K: + fwrite(data, 1, 0x10000, file); + break; + + case FLASH_128K: + fwrite(data, 1, 0x20000, file); + break; + + default: + break; + } +} + +// One shot cowboy code :) + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + FILE *file = fopen(argv[1], "rb"); + if (!file) + { + fprintf(stderr, "Failed to open file \"%s\"\n", argv[1]); + goto error; + } + + fseek(file, 0, SEEK_END); + long len = ftell(file); + rewind(file); + + uint8_t *buffer = malloc(len); + if (!buffer) + { + fprintf(stderr, "Failed to allocate memory!\n"); + goto error; + } + fread(buffer, 1, len, file); + fclose(file); + file = NULL; + + char *out_path = strdup(argv[1]); + char *split = strrchr(out_path, '.'); + const char *ext = NULL; + + if (split) + { + *split = '\0'; + ext = split + 1; + + if (strcasecmp(ext, "srm") == 0) + strcat(out_path, ".sav"); + else if (strlen(ext) >= 3) + strcat(out_path, ".srm"); + else + ext = NULL; + } + + if (!ext) + { + fprintf(stderr, "Cannot detect extension!\n"); + goto error; + } + + enum save_type type = detect_save_type(buffer, len); + printf("Detected save type: %s\n", save_type_to_string(type)); + + if (type == SAVE_UNKNOWN) + { + fprintf(stderr, "Cannot infer save type ...\n"); + goto error; + } + + file = fopen(out_path, "wb"); + if (!file) + goto error; + + if (len == (0x20000 + 0x2000)) + dump_sav(file, buffer, type); + else + dump_srm(file, buffer, type); + fclose(file); + + return 0; + +error: + if (file) + fclose(file); + return 1; +} + diff --git a/src/libretro/jni/Android.mk b/src/libretro/jni/Android.mk new file mode 100644 index 00000000..cb233d94 --- /dev/null +++ b/src/libretro/jni/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +ifeq ($(TARGET_ARCH),arm) +LOCAL_CFLAGS += -DANDROID_ARM +LOCAL_ARM_MODE := arm +endif + +ifeq ($(TARGET_ARCH),x86) +LOCAL_CFLAGS += -DANDROID_X86 +endif + +ifeq ($(TARGET_ARCH),mips) +LOCAL_CFLAGS += -DANDROID_MIPS +endif + +LOCAL_MODULE := libretro +LOCAL_SRC_FILES = ../../src/gba.cpp ../../src/memory.cpp ../../src/sound.cpp ../../libretro/libretro.cpp +LOCAL_CFLAGS = -DINLINE=inline -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DSPEEDHAX -DLSB_FIRST -D__LIBRETRO__ -DFRONTEND_SUPPORTS_RGB565 +LOCAL_C_INCLUDES = ../src + +include $(BUILD_SHARED_LIBRARY) diff --git a/src/libretro/jni/Application.mk b/src/libretro/jni/Application.mk new file mode 100644 index 00000000..a252a72d --- /dev/null +++ b/src/libretro/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := all diff --git a/src/libretro/libretro.cpp b/src/libretro/libretro.cpp new file mode 100644 index 00000000..4e8e03cb --- /dev/null +++ b/src/libretro/libretro.cpp @@ -0,0 +1,627 @@ +#include +#include +#include + +#include "libretro.h" +#include "SoundRetro.h" + +#include "../Util.h" +#include "../System.h" +#include "../common/Port.h" +#include "../common/Types.h" +#include "../gba/RTC.h" +#include "../gba/GBAGfx.h" +#include "../gba/bios.h" +#include "../gba/Flash.h" +#include "../gba/EEprom.h" +#include "../gba/Sound.h" +#include "../apu/Blip_Buffer.h" +#include "../apu/Gb_Oscs.h" +#include "../apu/Gb_Apu.h" +#include "../gba/Globals.h" + +static retro_video_refresh_t video_cb; +static retro_input_poll_t poll_cb; +static retro_input_state_t input_cb; +retro_audio_sample_batch_t audio_batch_cb; +static retro_environment_t environ_cb; + +bool enableRtc; +extern uint64_t joy; +static bool can_dupe; +unsigned device_type = 0; +int emulating = 0; + +uint8_t libretro_save_buf[0x20000 + 0x2000]; /* Workaround for broken-by-design GBA save semantics. */ + +static unsigned libretro_save_size = sizeof(libretro_save_buf); + +int RGB_LOW_BITS_MASK = 0; + +u16 systemColorMap16[0x10000]; +u32 systemColorMap32[0x10000]; +u16 systemGbPalette[24]; +int systemRedShift = 0; +int systemBlueShift = 0; +int systemGreenShift = 0; +int systemColorDepth = 32; +int systemDebug = 0; +int systemVerbose = 0; +int systemFrameSkip = 0; +int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; +int systemSpeed = 0; + +u64 startTime = 0; +u32 renderedFrames = 0; + +void (*dbgOutput)(const char *s, u32 addr); +void (*dbgSignal)(int sig, int number); + +void *retro_get_memory_data(unsigned id) +{ + if (id != RETRO_MEMORY_SAVE_RAM) + return 0; + + return libretro_save_buf; +} + +size_t retro_get_memory_size(unsigned id) +{ + if (id != RETRO_MEMORY_SAVE_RAM) + return 0; + + return libretro_save_size; +} + +static bool scan_area(const uint8_t *data, unsigned size) +{ + for (unsigned i = 0; i < size; i++) + if (data[i] != 0xff) + return true; + + return false; +} + +static void adjust_save_ram() +{ + if (scan_area(libretro_save_buf, 512) && + !scan_area(libretro_save_buf + 512, sizeof(libretro_save_buf) - 512)) + { + libretro_save_size = 512; + fprintf(stderr, "Detecting EEprom 8kbit\n"); + } + else if (scan_area(libretro_save_buf, 0x2000) && + !scan_area(libretro_save_buf + 0x2000, sizeof(libretro_save_buf) - 0x2000)) + { + libretro_save_size = 0x2000; + fprintf(stderr, "Detecting EEprom 64kbit\n"); + } + + else if (scan_area(libretro_save_buf, 0x10000) && + !scan_area(libretro_save_buf + 0x10000, sizeof(libretro_save_buf) - 0x10000)) + { + libretro_save_size = 0x10000; + fprintf(stderr, "Detecting Flash 512kbit\n"); + } + else if (scan_area(libretro_save_buf, 0x20000) && + !scan_area(libretro_save_buf + 0x20000, sizeof(libretro_save_buf) - 0x20000)) + { + libretro_save_size = 0x20000; + fprintf(stderr, "Detecting Flash 1Mbit\n"); + } + else + fprintf(stderr, "Did not detect any particular SRAM type.\n"); + + if (libretro_save_size == 512 || libretro_save_size == 0x2000) + eepromData = libretro_save_buf; + else if (libretro_save_size == 0x10000 || libretro_save_size == 0x20000) + flashSaveMemory = libretro_save_buf; +} + + +unsigned retro_api_version(void) +{ + return RETRO_API_VERSION; +} + +void retro_set_video_refresh(retro_video_refresh_t cb) +{ + video_cb = cb; +} + +void retro_set_audio_sample(retro_audio_sample_t cb) +{ } + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + audio_batch_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) +{ + poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) +{ + input_cb = cb; +} + +void retro_set_controller_port_device(unsigned port, unsigned device) +{ } + +void retro_set_environment(retro_environment_t cb) +{ + environ_cb = cb; + + struct retro_variable variables[] = { + { "vbam-next-gamepad", + "Button layout; original|reversed" }, + { NULL, NULL }, + }; + + cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); +} + +void retro_get_system_info(struct retro_system_info *info) +{ + info->need_fullpath = true; + info->valid_extensions = "gba"; + info->library_version = "v1.0.2"; + info->library_name = "VBA-M"; + info->block_extract = false; +} + +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + info->geometry.base_width = 240; + info->geometry.base_height = 160; + info->geometry.max_width = 240; + info->geometry.max_height = 160; + info->timing.fps = 16777216.0 / 280896.0; + info->timing.sample_rate = 32000.0; +} + +void retro_init(void) +{ + memset(libretro_save_buf, 0xff, sizeof(libretro_save_buf)); + adjust_save_ram(); + environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &can_dupe); + +#ifdef FRONTEND_SUPPORTS_RGB565 + enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565; + if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565)) + fprintf(stderr, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); +#else + enum retro_pixel_format rgb8888 = RETRO_PIXEL_FORMAT_XRGB8888; + if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb8888)) + fprintf(stderr, "Frontend supports XRGB8888 - will use that instead of XRGB1555.\n"); +#endif +} + +static unsigned serialize_size = 0; + +typedef struct { + char romtitle[256]; + char romid[5]; + int flashSize; + int saveType; + int rtcEnabled; + int mirroringEnabled; + int useBios; +} ini_t; + +static const ini_t gbaover[256] = { + //romtitle, romid flash save rtc mirror bios + {"2 Games in 1 - Dragon Ball Z - The Legacy of Goku I & II (USA)", "BLFE", 0, 1, 0, 0, 0}, + {"2 Games in 1 - Dragon Ball Z - Buu's Fury + Dragon Ball GT - Transformation (USA)", "BUFE", 0, 1, 0, 0, 0}, + {"Boktai - The Sun Is in Your Hand (Europe)(En,Fr,De,Es,It)", "U3IP", 0, 0, 1, 0, 0}, + {"Boktai - The Sun Is in Your Hand (USA)", "U3IE", 0, 0, 1, 0, 0}, + {"Boktai 2 - Solar Boy Django (USA)", "U32E", 0, 0, 1, 0, 0}, + {"Boktai 2 - Solar Boy Django (Europe)(En,Fr,De,Es,It)", "U32P", 0, 0, 1, 0, 0}, + {"Bokura no Taiyou - Taiyou Action RPG (Japan)", "U3IJ", 0, 0, 1, 0, 0}, + {"Card e-Reader+ (Japan)", "PSAJ", 131072, 0, 0, 0, 0}, + {"Classic NES Series - Bomberman (USA, Europe)", "FBME", 0, 1, 0, 1, 0}, + {"Classic NES Series - Castlevania (USA, Europe)", "FADE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Donkey Kong (USA, Europe)", "FDKE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Dr. Mario (USA, Europe)", "FDME", 0, 1, 0, 1, 0}, + {"Classic NES Series - Excitebike (USA, Europe)", "FEBE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Legend of Zelda (USA, Europe)", "FZLE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Ice Climber (USA, Europe)", "FICE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Metroid (USA, Europe)", "FMRE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Pac-Man (USA, Europe)", "FP7E", 0, 1, 0, 1, 0}, + {"Classic NES Series - Super Mario Bros. (USA, Europe)", "FSME", 0, 1, 0, 1, 0}, + {"Classic NES Series - Xevious (USA, Europe)", "FXVE", 0, 1, 0, 1, 0}, + {"Classic NES Series - Zelda II - The Adventure of Link (USA, Europe)", "FLBE", 0, 1, 0, 1, 0}, + {"Digi Communication 2 - Datou! Black Gemagema Dan (Japan)", "BDKJ", 0, 1, 0, 0, 0}, + {"e-Reader (USA)", "PSAE", 131072, 0, 0, 0, 0}, + {"Dragon Ball GT - Transformation (USA)", "BT4E", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - Buu's Fury (USA)", "BG3E", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - Taiketsu (Europe)(En,Fr,De,Es,It)", "BDBP", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - Taiketsu (USA)", "BDBE", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - The Legacy of Goku II International (Japan)", "ALFJ", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - The Legacy of Goku II (Europe)(En,Fr,De,Es,It)", "ALFP", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - The Legacy of Goku II (USA)", "ALFE", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - The Legacy Of Goku (Europe)(En,Fr,De,Es,It)", "ALGP", 0, 1, 0, 0, 0}, + {"Dragon Ball Z - The Legacy of Goku (USA)", "ALGE", 131072, 1, 0, 0, 0}, + {"F-Zero - Climax (Japan)", "BFTJ", 131072, 0, 0, 0, 0}, + {"Famicom Mini Vol. 01 - Super Mario Bros. (Japan)", "FMBJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 12 - Clu Clu Land (Japan)", "FCLJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 13 - Balloon Fight (Japan)", "FBFJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 14 - Wrecking Crew (Japan)", "FWCJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 15 - Dr. Mario (Japan)", "FDMJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 16 - Dig Dug (Japan)", "FTBJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 17 - Takahashi Meijin no Boukenjima (Japan)", "FTBJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 18 - Makaimura (Japan)", "FMKJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 19 - Twin Bee (Japan)", "FTWJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 20 - Ganbare Goemon! Karakuri Douchuu (Japan)", "FGGJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 21 - Super Mario Bros. 2 (Japan)", "FM2J", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 22 - Nazo no Murasame Jou (Japan)", "FNMJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 23 - Metroid (Japan)", "FMRJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 24 - Hikari Shinwa - Palthena no Kagami (Japan)", "FPTJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 25 - The Legend of Zelda 2 - Link no Bouken (Japan)","FLBJ",0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 26 - Famicom Mukashi Banashi - Shin Onigashima - Zen Kou Hen (Japan)","FFMJ",0,1,0, 1, 0}, + {"Famicom Mini Vol. 27 - Famicom Tantei Club - Kieta Koukeisha - Zen Kou Hen (Japan)","FTKJ",0,1,0, 1, 0}, + {"Famicom Mini Vol. 28 - Famicom Tantei Club Part II - Ushiro ni Tatsu Shoujo - Zen Kou Hen (Japan)","FTUJ",0,1,0,1,0}, + {"Famicom Mini Vol. 29 - Akumajou Dracula (Japan)", "FADJ", 0, 1, 0, 1, 0}, + {"Famicom Mini Vol. 30 - SD Gundam World - Gachapon Senshi Scramble Wars (Japan)","FSDJ",0,1, 0, 1, 0}, + {"Game Boy Wars Advance 1+2 (Japan)", "BGWJ", 131072, 0, 0, 0, 0}, + {"Golden Sun - The Lost Age (USA)", "AGFE", 65536, 0, 0, 1, 0}, + {"Golden Sun (USA)", "AGSE", 65536, 0, 0, 1, 0}, + {"Koro Koro Puzzle - Happy Panechu! (Japan)", "KHPJ", 0, 4, 0, 0, 0}, + {"Mario vs. Donkey Kong (Europe)", "BM5P", 0, 3, 0, 0, 0}, + {"Pocket Monsters - Emerald (Japan)", "BPEJ", 131072, 0, 1, 0, 0}, + {"Pocket Monsters - Fire Red (Japan)", "BPRJ", 131072, 0, 0, 0, 0}, + {"Pocket Monsters - Leaf Green (Japan)", "BPGJ", 131072, 0, 0, 0, 0}, + {"Pocket Monsters - Ruby (Japan)", "AXVJ", 131072, 0, 1, 0, 0}, + {"Pocket Monsters - Sapphire (Japan)", "AXPJ", 131072, 0, 1, 0, 0}, + {"Pokemon Mystery Dungeon - Red Rescue Team (USA, Australia)", "B24E", 131072, 0, 0, 0, 0}, + {"Pokemon Mystery Dungeon - Red Rescue Team (En,Fr,De,Es,It)", "B24P", 131072, 0, 0, 0, 0}, + {"Pokemon - Blattgruene Edition (Germany)", "BPGD", 131072, 0, 0, 0, 0}, + {"Pokemon - Edicion Rubi (Spain)", "AXVS", 131072, 0, 1, 0, 0}, + {"Pokemon - Edicion Esmeralda (Spain)", "BPES", 131072, 0, 1, 0, 0}, + {"Pokemon - Edicion Rojo Fuego (Spain)", "BPRS", 131072, 1, 0, 0, 0}, + {"Pokemon - Edicion Verde Hoja (Spain)", "BPGS", 131072, 1, 0, 0, 0}, + {"Pokemon - Eidicion Zafiro (Spain)", "AXPS", 131072, 0, 1, 0, 0}, + {"Pokemon - Emerald Version (USA, Europe)", "BPEE", 131072, 0, 1, 0, 0}, + {"Pokemon - Feuerrote Edition (Germany)", "BPRD", 131072, 0, 0, 0, 0}, + {"Pokemon - Fire Red Version (USA, Europe)", "BPRE", 131072, 0, 0, 0, 0}, + {"Pokemon - Leaf Green Version (USA, Europe)", "BPGE", 131072, 0, 0, 0, 0}, + {"Pokemon - Rubin Edition (Germany)", "AXVD", 131072, 0, 1, 0, 0}, + {"Pokemon - Ruby Version (USA, Europe)", "AXVE", 131072, 0, 1, 0, 0}, + {"Pokemon - Sapphire Version (USA, Europe)", "AXPE", 131072, 0, 1, 0, 0}, + {"Pokemon - Saphir Edition (Germany)", "AXPD", 131072, 0, 1, 0, 0}, + {"Pokemon - Smaragd Edition (Germany)", "BPED", 131072, 0, 1, 0, 0}, + {"Pokemon - Version Emeraude (France)", "BPEF", 131072, 0, 1, 0, 0}, + {"Pokemon - Version Rouge Feu (France)", "BPRF", 131072, 0, 0, 0, 0}, + {"Pokemon - Version Rubis (France)", "AXVF", 131072, 0, 1, 0, 0}, + {"Pokemon - Version Saphir (France)", "AXPF", 131072, 0, 1, 0, 0}, + {"Pokemon - Version Vert Feuille (France)", "BPGF", 131072, 0, 0, 0, 0}, + {"Pokemon - Versione Rubino (Italy)", "AXVI", 131072, 0, 1, 0, 0}, + {"Pokemon - Versione Rosso Fuoco (Italy)", "BPRI", 131072, 0, 0, 0, 0}, + {"Pokemon - Versione Smeraldo (Italy)", "BPEI", 131072, 0, 1, 0, 0}, + {"Pokemon - Versione Verde Foglia (Italy)", "BPGI", 131072, 0, 0, 0, 0}, + {"Pokemon - Versione Zaffiro (Italy)", "AXPI", 131072, 0, 1, 0, 0}, + {"Rockman EXE 4.5 - Real Operation (Japan)", "BR4J", 0, 0, 1, 0, 0}, + {"Rocky (Europe)(En,Fr,De,Es,It)", "AROP", 0, 1, 0, 0, 0}, + {"Sennen Kazoku (Japan)", "BKAJ", 131072, 0, 1, 0, 0}, + {"Shin Bokura no Taiyou - Gyakushuu no Sabata (Japan)", "U33J", 0, 1, 1, 0, 0}, + {"Super Mario Advance 4 (Japan)", "AX4J", 131072, 0, 0, 0, 0}, + {"Super Mario Advance 4 - Super Mario Bros. 3 (Europe)(En,Fr,De,Es,It)","AX4P", 131072, 0, 0, 0, 0}, + {"Super Mario Advance 4 - Super Mario Bros 3 - Super Mario Advance 4 v1.1 (USA)","AX4E",131072,0,0,0,0}, + {"Top Gun - Combat Zones (USA)(En,Fr,De,Es,It)", "A2YE", 0, 5, 0, 0, 0}, + {"Yoshi no Banyuuinryoku (Japan)", "KYGJ", 0, 4, 0, 0, 0}, + {"Yoshi - Topsy-Turvy (USA)", "KYGE", 0, 1, 0, 0, 0}, + {"Yu-Gi-Oh! GX - Duel Academy (USA)", "BYGE", 0, 2, 0, 0, 1}, + {"Yu-Gi-Oh! - Ultimate Masters - 2006 (Europe)(En,Jp,Fr,De,Es,It)", "BY6P", 0, 2, 0, 0, 0}, + {"Zoku Bokura no Taiyou - Taiyou Shounen Django (Japan)", "U32J", 0, 0, 1, 0, 0} +}; + +static void load_image_preferences (void) +{ + char buffer[5]; + buffer[0] = rom[0xac]; + buffer[1] = rom[0xad]; + buffer[2] = rom[0xae]; + buffer[3] = rom[0xaf]; + buffer[4] = 0; + fprintf(stderr, "GameID in ROM is: %s\n", buffer); + + bool found = false; + int found_no = 0; + + for(int i = 0; i < 256; i++) + { + if(!strcmp(gbaover[i].romid, buffer)) + { + found = true; + found_no = i; + break; + } + } + + if(found) + { + fprintf(stderr, "Found ROM in vba-over list.\n"); + + enableRtc = gbaover[found_no].rtcEnabled; + + if(gbaover[found_no].flashSize != 0) + flashSize = gbaover[found_no].flashSize; + else + flashSize = 65536; + + cpuSaveType = gbaover[found_no].saveType; + + mirroringEnable = gbaover[found_no].mirroringEnabled; + } + + fprintf(stderr, "RTC = %d.\n", enableRtc); + fprintf(stderr, "flashSize = %d.\n", flashSize); + fprintf(stderr, "cpuSaveType = %d.\n", cpuSaveType); + fprintf(stderr, "mirroringEnable = %d.\n", mirroringEnable); +} + +static void gba_init(void) +{ + cpuSaveType = 0; + flashSize = 0x10000; + enableRtc = false; + mirroringEnable = false; +#ifdef FRONTEND_SUPPORTS_RGB565 + systemColorDepth = 16; + systemRedShift = 11; + systemGreenShift = 6; + systemBlueShift = 0; +#else + systemColorDepth = 32; + systemRedShift = 19; + systemGreenShift = 11; + systemBlueShift = 3; +#endif + + + utilUpdateSystemColorMaps(false); + + load_image_preferences(); + + if(flashSize == 0x10000 || flashSize == 0x20000) + flashSetSize(flashSize); + + if(enableRtc) + rtcEnable(enableRtc); + + doMirroring(mirroringEnable); + + soundInit(); + soundSetSampleRate(32000); + + CPUInit(0, false); + CPUReset(); + + soundReset(); + + uint8_t * state_buf = (uint8_t*)malloc(2000000); + serialize_size = CPUWriteState(state_buf, 2000000); + free(state_buf); + + emulating = 1; +} + +void retro_deinit(void) +{ + emulating = 0; +} + +void retro_reset(void) +{ + CPUReset(); +} + +static const unsigned binds[] = { + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_START, + RETRO_DEVICE_ID_JOYPAD_RIGHT, + RETRO_DEVICE_ID_JOYPAD_LEFT, + RETRO_DEVICE_ID_JOYPAD_UP, + RETRO_DEVICE_ID_JOYPAD_DOWN, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_L +}; + +static const unsigned binds2[] = { + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_START, + RETRO_DEVICE_ID_JOYPAD_RIGHT, + RETRO_DEVICE_ID_JOYPAD_LEFT, + RETRO_DEVICE_ID_JOYPAD_UP, + RETRO_DEVICE_ID_JOYPAD_DOWN, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_L +}; + +static unsigned has_frame; + +static void update_variables(void) +{ + struct retro_variable var; + + var.key = "vbam-next-gamepad"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) + { + if (strcmp(var.value, "original") == 0) + device_type = 0; + else if (strcmp(var.value, "reversed") == 0) + device_type = 1; + } +} + +#ifdef FINAL_VERSION +#define TICKS 250000 +#else +#define TICKS 5000 +#endif + +void retro_run(void) +{ + bool updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + update_variables(); + + poll_cb(); + + + has_frame = 0; + + do{ + CPULoop(TICKS); + }while(!has_frame); +} + +size_t retro_serialize_size(void) +{ + return serialize_size; +} + +bool retro_serialize(void *data, size_t size) +{ + return CPUWriteState((uint8_t*)data, size); +} + +bool retro_unserialize(const void *data, size_t size) +{ + return CPUReadState((uint8_t*)data, size); +} + +void retro_cheat_reset(void) +{} + +void retro_cheat_set(unsigned, bool, const char*) +{} + +bool retro_load_game(const struct retro_game_info *game) +{ + update_variables(); + + bool ret = CPULoadRom(game->path); + + gba_init(); + + return ret; +} + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +) +{ return false; } + +extern unsigned g_audio_frames; +static unsigned g_video_frames; + +void retro_unload_game(void) +{ + fprintf(stderr, "[VBA] Sync stats: Audio frames: %u, Video frames: %u, AF/VF: %.2f\n", + g_audio_frames, g_video_frames, (float)g_audio_frames / g_video_frames); + g_audio_frames = 0; + g_video_frames = 0; +} + +unsigned retro_get_region(void) +{ + return RETRO_REGION_NTSC; +} + +void systemOnWriteDataToSoundBuffer(const u16 *finalWave, int length) +{ +} + +void systemOnSoundShutdown() {} +bool systemCanChangeSoundQuality() { return true; } + +#ifdef FRONTEND_SUPPORTS_RGB565 +#define GBA_PITCH 484 +#else +#define GBA_PITCH 964 +#endif + +void systemDrawScreen() +{ + video_cb(pix, 240, 160, GBA_PITCH); + g_video_frames++; + has_frame = 1; +} + +void systemFrame() {} + +void systemMessage(int, const char* str, ...) +{ + fprintf(stderr, "%s", str); +} + +void systemMessage(const char* str, ...) +{ + fprintf(stderr, "%s", str); +} + +int systemGetSensorX(void) +{ + return 0; +} + +int systemGetSensorY(void) +{ + return 0; +} + +u32 systemReadJoypad(int which) +{ + if (which == -1) + which = 0; + + u32 J = 0; + + for (unsigned i = 0; i < 10; i++) + J |= input_cb(which, RETRO_DEVICE_JOYPAD, 0, device_type ? binds2[i] : binds[i]) << i; + + return J; +} + +bool systemReadJoypads() { return true; } + +void systemUpdateMotionSensor() {} + +bool systemPauseOnFrame() { return false; } +void systemGbPrint(u8 *data,int pages, int feed, int palette, int contrast) {} +void systemScreenCapture(int a) {} +void systemScreenMessage(const char*msg) +{ + fprintf(stderr, "DEBUG: %s\n", msg); +} + +void systemSetTitle(const char *title) {} +void systemShowSpeed(int speed) {} +void system10Frames(int rate) {} + +u32 systemGetClock() +{ + return 0; +} + +int cheatsCheckKeys(u32 keys, u32 extended) +{ + return 0; +} + +SoundDriver *systemSoundInit() +{ + soundShutdown(); + + return new SoundRetro(); +} diff --git a/src/libretro/libretro.h b/src/libretro/libretro.h new file mode 100755 index 00000000..b02855ae --- /dev/null +++ b/src/libretro/libretro.h @@ -0,0 +1,758 @@ +#ifndef LIBRETRO_H__ +#define LIBRETRO_H__ + +#include +#include +#include + +// Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. +#ifdef __cplusplus +extern "C" { +#else +#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) && !defined(__cplusplus) +#define bool unsigned char +#define true 1 +#define false 0 +#else +#include +#endif +#endif + +// Used for checking API/ABI mismatches that can break libretro implementations. +// It is not incremented for compatible changes to the API. +#define RETRO_API_VERSION 1 + +// Libretro's fundamental device abstractions. +#define RETRO_DEVICE_MASK 0xff +#define RETRO_DEVICE_NONE 0 + +// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller, +// but with additional L2/R2/L3/R3 buttons, similar to a PS1 DualShock. +#define RETRO_DEVICE_JOYPAD 1 + +// The mouse is a simple mouse, similar to Super Nintendo's mouse. +// X and Y coordinates are reported relatively to last poll (poll callback). +// It is up to the libretro implementation to keep track of where the mouse pointer is supposed to be on the screen. +// The frontend must make sure not to interfere with its own hardware mouse pointer. +#define RETRO_DEVICE_MOUSE 2 + +// KEYBOARD device lets one poll for raw key pressed. +// It is poll based, so input callback will return with the current pressed state. +#define RETRO_DEVICE_KEYBOARD 3 + +// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse. +#define RETRO_DEVICE_LIGHTGUN 4 + +// The ANALOG device is an extension to JOYPAD (RetroPad). +// Similar to DualShock it adds two analog sticks. +// This is treated as a separate device type as it returns values in the full analog range +// of [-0x8000, 0x7fff]. Positive X axis is right. Positive Y axis is down. +// Only use ANALOG type when polling for analog values of the axes. +#define RETRO_DEVICE_ANALOG 5 + +// Abstracts the concept of a pointing mechanism, e.g. touch. +// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed. +// For a touch centric device, coordinates reported are the coordinates of the press. +// +// Coordinates in X and Y are reported as: +// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, +// and 0x7fff corresponds to the far right/bottom of the screen. +// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor. +// The frontend is free to scale/resize this screen as it sees fit, however, +// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc. +// +// To check if the pointer coordinates are valid (e.g. a touch display actually being touched), +// PRESSED returns 1 or 0. +// If using a mouse, PRESSED will usually correspond to the left mouse button. +// PRESSED will only return 1 if the pointer is inside the game screen. +// +// For multi-touch, the index variable can be used to successively query more presses. +// If index = 0 returns true for _PRESSED, coordinates can be extracted +// with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with index = 1, and so on. +// Eventually _PRESSED will return false for an index. No further presses are registered at this point. +#define RETRO_DEVICE_POINTER 6 + +// These device types are specializations of the base types above. +// They should only be used in retro_set_controller_type() to inform libretro implementations +// about use of a very specific device type. +// +// In input state callback, however, only the base type should be used in the 'device' field. +#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) +#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) + +// Buttons for the RetroPad (JOYPAD). +// The placement of these is equivalent to placements on the Super Nintendo controller. +// L2/R2/L3/R3 buttons correspond to the PS1 DualShock. +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 +#define RETRO_DEVICE_ID_JOYPAD_L2 12 +#define RETRO_DEVICE_ID_JOYPAD_R2 13 +#define RETRO_DEVICE_ID_JOYPAD_L3 14 +#define RETRO_DEVICE_ID_JOYPAD_R3 15 + +// Index / Id values for ANALOG device. +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 + +// Id values for MOUSE. +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 + +// Id values for LIGHTGUN types. +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +// Id values for POINTER. +#define RETRO_DEVICE_ID_POINTER_X 0 +#define RETRO_DEVICE_ID_POINTER_Y 1 +#define RETRO_DEVICE_ID_POINTER_PRESSED 2 + +// Returned from retro_get_region(). +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +// Passed to retro_get_memory_data/size(). +// If the memory type doesn't apply to the implementation NULL/0 can be returned. +#define RETRO_MEMORY_MASK 0xff + +// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery. +// If save game data is too complex for a single memory buffer, +// the SYSTEM_DIRECTORY environment callback can be used. +#define RETRO_MEMORY_SAVE_RAM 0 + +// Some games have a built-in clock to keep track of time. +// This memory is usually just a couple of bytes to keep track of time. +#define RETRO_MEMORY_RTC 1 + +// System ram lets a frontend peek into a game systems main RAM. +#define RETRO_MEMORY_SYSTEM_RAM 2 + +// Video ram lets a frontend peek into a game systems video RAM (VRAM). +#define RETRO_MEMORY_VIDEO_RAM 3 + +// Special memory types. +#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC) + +// Special game types passed into retro_load_game_special(). +// Only used when multiple ROMs are required. +#define RETRO_GAME_TYPE_BSX 0x101 +#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102 +#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103 +#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104 + +// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. +enum retro_key +{ + RETROK_UNKNOWN = 0, + RETROK_FIRST = 0, + RETROK_BACKSPACE = 8, + RETROK_TAB = 9, + RETROK_CLEAR = 12, + RETROK_RETURN = 13, + RETROK_PAUSE = 19, + RETROK_ESCAPE = 27, + RETROK_SPACE = 32, + RETROK_EXCLAIM = 33, + RETROK_QUOTEDBL = 34, + RETROK_HASH = 35, + RETROK_DOLLAR = 36, + RETROK_AMPERSAND = 38, + RETROK_QUOTE = 39, + RETROK_LEFTPAREN = 40, + RETROK_RIGHTPAREN = 41, + RETROK_ASTERISK = 42, + RETROK_PLUS = 43, + RETROK_COMMA = 44, + RETROK_MINUS = 45, + RETROK_PERIOD = 46, + RETROK_SLASH = 47, + RETROK_0 = 48, + RETROK_1 = 49, + RETROK_2 = 50, + RETROK_3 = 51, + RETROK_4 = 52, + RETROK_5 = 53, + RETROK_6 = 54, + RETROK_7 = 55, + RETROK_8 = 56, + RETROK_9 = 57, + RETROK_COLON = 58, + RETROK_SEMICOLON = 59, + RETROK_LESS = 60, + RETROK_EQUALS = 61, + RETROK_GREATER = 62, + RETROK_QUESTION = 63, + RETROK_AT = 64, + RETROK_LEFTBRACKET = 91, + RETROK_BACKSLASH = 92, + RETROK_RIGHTBRACKET = 93, + RETROK_CARET = 94, + RETROK_UNDERSCORE = 95, + RETROK_BACKQUOTE = 96, + RETROK_a = 97, + RETROK_b = 98, + RETROK_c = 99, + RETROK_d = 100, + RETROK_e = 101, + RETROK_f = 102, + RETROK_g = 103, + RETROK_h = 104, + RETROK_i = 105, + RETROK_j = 106, + RETROK_k = 107, + RETROK_l = 108, + RETROK_m = 109, + RETROK_n = 110, + RETROK_o = 111, + RETROK_p = 112, + RETROK_q = 113, + RETROK_r = 114, + RETROK_s = 115, + RETROK_t = 116, + RETROK_u = 117, + RETROK_v = 118, + RETROK_w = 119, + RETROK_x = 120, + RETROK_y = 121, + RETROK_z = 122, + RETROK_DELETE = 127, + + RETROK_KP0 = 256, + RETROK_KP1 = 257, + RETROK_KP2 = 258, + RETROK_KP3 = 259, + RETROK_KP4 = 260, + RETROK_KP5 = 261, + RETROK_KP6 = 262, + RETROK_KP7 = 263, + RETROK_KP8 = 264, + RETROK_KP9 = 265, + RETROK_KP_PERIOD = 266, + RETROK_KP_DIVIDE = 267, + RETROK_KP_MULTIPLY = 268, + RETROK_KP_MINUS = 269, + RETROK_KP_PLUS = 270, + RETROK_KP_ENTER = 271, + RETROK_KP_EQUALS = 272, + + RETROK_UP = 273, + RETROK_DOWN = 274, + RETROK_RIGHT = 275, + RETROK_LEFT = 276, + RETROK_INSERT = 277, + RETROK_HOME = 278, + RETROK_END = 279, + RETROK_PAGEUP = 280, + RETROK_PAGEDOWN = 281, + + RETROK_F1 = 282, + RETROK_F2 = 283, + RETROK_F3 = 284, + RETROK_F4 = 285, + RETROK_F5 = 286, + RETROK_F6 = 287, + RETROK_F7 = 288, + RETROK_F8 = 289, + RETROK_F9 = 290, + RETROK_F10 = 291, + RETROK_F11 = 292, + RETROK_F12 = 293, + RETROK_F13 = 294, + RETROK_F14 = 295, + RETROK_F15 = 296, + + RETROK_NUMLOCK = 300, + RETROK_CAPSLOCK = 301, + RETROK_SCROLLOCK = 302, + RETROK_RSHIFT = 303, + RETROK_LSHIFT = 304, + RETROK_RCTRL = 305, + RETROK_LCTRL = 306, + RETROK_RALT = 307, + RETROK_LALT = 308, + RETROK_RMETA = 309, + RETROK_LMETA = 310, + RETROK_LSUPER = 311, + RETROK_RSUPER = 312, + RETROK_MODE = 313, + RETROK_COMPOSE = 314, + + RETROK_HELP = 315, + RETROK_PRINT = 316, + RETROK_SYSREQ = 317, + RETROK_BREAK = 318, + RETROK_MENU = 319, + RETROK_POWER = 320, + RETROK_EURO = 321, + RETROK_UNDO = 322, + + RETROK_LAST, + + RETROK_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) +}; + +enum retro_mod +{ + RETROKMOD_NONE = 0x0000, + + RETROKMOD_SHIFT = 0x01, + RETROKMOD_CTRL = 0x02, + RETROKMOD_ALT = 0x04, + RETROKMOD_META = 0x08, + + RETROKMOD_NUMLOCK = 0x10, + RETROKMOD_CAPSLOCK = 0x20, + RETROKMOD_SCROLLOCK = 0x40, + + RETROKMOD_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) +}; + +// If set, this call is not part of the public libretro API yet. It can change or be removed at any time. +#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 + +// Environment commands. +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- + // Sets screen rotation of graphics. + // Is only implemented if rotation can be accelerated by hardware. + // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees + // counter-clockwise respectively. + // +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. + // +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- + // Boolean value whether or not frontend supports frame duping, + // passing NULL to video frame callback. + // +// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash. +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- + // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + // Should not be used for trivial messages, which should simply be logged to stderr. +#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) -- + // Requests the frontend to shutdown. + // Should only be used if game has a specific + // way to shutdown the game from a menu item or similar. + // +#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 + // const unsigned * -- + // Gives a hint to the frontend how demanding this implementation + // is on a system. E.g. reporting a level of 2 means + // this implementation should run decently on all frontends + // of level 2 and up. + // + // It can be used by the frontend to potentially warn + // about too demanding implementations. + // + // The levels are "floating", but roughly defined as: + // 0: Low-powered embedded devices such as Raspberry Pi + // 1: 6th generation consoles, such as Wii/Xbox 1, and phones, tablets, etc. + // 2: 7th generation consoles, such as PS3/360, with sub-par CPUs. + // 3: Modern desktop/laptops with reasonably powerful CPUs. + // 4: High-end desktops with very powerful CPUs. + // + // This function can be called on a per-game basis, + // as certain games an implementation can play might be + // particularily demanding. + // If called, it should be called in retro_load_game(). + // +#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 + // const char ** -- + // Returns the "system" directory of the frontend. + // This directory can be used to store system specific ROMs such as BIOSes, configuration data, etc. + // The returned value can be NULL. + // If so, no such directory is defined, + // and it's up to the implementation to find a suitable directory. + // +#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 + // const enum retro_pixel_format * -- + // Sets the internal pixel format used by the implementation. + // The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. + // This pixel format however, is deprecated (see enum retro_pixel_format). + // If the call returns false, the frontend does not support this pixel format. + // This function should be called inside retro_load_game() or retro_get_system_av_info(). + // +#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 + // const struct retro_input_descriptor * -- + // Sets an array of retro_input_descriptors. + // It is up to the frontend to present this in a usable way. + // The array is terminated by retro_input_descriptor::description being set to NULL. + // This function can be called at any time, but it is recommended to call it as early as possible. +#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 + // const struct retro_keyboard_callback * -- + // Sets a callback function used to notify core about keyboard events. + // +#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 + // const struct retro_disk_control_callback * -- + // Sets an interface which frontend can use to eject and insert disk images. + // This is used for games which consist of multiple images and must be manually + // swapped out by the user (e.g. PSX). +#define RETRO_ENVIRONMENT_SET_HW_RENDER (14 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_hw_render_callback * -- + // NOTE: This call is currently very experimental, and should not be considered part of the public API. + // The interface could be changed or removed at any time. + // Sets an interface to let a libretro core render with hardware acceleration. + // Should be called in retro_load_game(). + // If successful, libretro cores will be able to render to a frontend-provided framebuffer. + // The size of this framebuffer will be at least as large as max_width/max_height provided in get_av_info(). + // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t. +#define RETRO_ENVIRONMENT_GET_VARIABLE 15 + // struct retro_variable * -- + // Interface to aquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // 'key' should be set to a key which has already been set by SET_VARIABLES. + // 'data' will be set to a value or NULL. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 16 + // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // This allows the frontend to present these variables to a user dynamically. + // This should be called as early as possible (ideally in retro_set_environment). + // + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::key should be namespaced to not collide with other implementations' keys. E.g. A core called 'foo' should use keys named as 'foo_option'. + // retro_variable::value should contain a human readable description of the key as well as a '|' delimited list of expected values. + // The number of possible options should be very limited, i.e. it should be feasible to cycle through options without a keyboard. + // First entry should be treated as a default. + // + // Example entry: + // { "foo_option", "Speed hack coprocessor X; false|true" } + // + // Text before first ';' is description. This ';' must be followed by a space, and followed by a list of possible values split up with '|'. + // Only strings are operated on. The possible values will generally be displayed and stored as-is by the frontend. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 + // bool * -- + // Result is set to true if some variables are updated by + // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + // Variables should be queried with GET_VARIABLE. + +// Pass this to retro_video_refresh_t if rendering to hardware. +// Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) + +// Invalidates the current HW context. +// If called, all GPU resources must be reinitialized. +// Usually called when frontend reinits video driver. +// Also called first time video driver is initialized, allowing libretro core to init resources. +typedef void (*retro_hw_context_reset_t)(void); +// Gets current framebuffer which is to be rendered to. Could change every frame potentially. +typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); + +// Get a symbol from HW context. +typedef void (*retro_proc_address_t)(void); +typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); + +enum retro_hw_context_type +{ + RETRO_HW_CONTEXT_NONE = 0, + RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. + RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0 + + RETRO_HW_CONTEXT_DUMMY = INT_MAX +}; + +struct retro_hw_render_callback +{ + enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. + retro_hw_context_reset_t context_reset; // Set by libretro core. + retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. + retro_hw_get_proc_address_t get_proc_address; // Set by frontend. + bool depth; // Set if render buffers should have depth component attached. +}; + +// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events. +// down is set if the key is being pressed, or false if it is being released. +// keycode is the RETROK value of the char. +// character is the text character of the pressed key. (UTF-32). +// key_modifiers is a set of RETROKMOD values or'ed together. +typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); + +struct retro_keyboard_callback +{ + retro_keyboard_event_t callback; +}; + +// Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. +// Should be set for implementations which can swap out multiple disk images in runtime. +// If the implementation can do this automatically, it should strive to do so. +// However, there are cases where the user must manually do so. +// +// Overview: To swap a disk image, eject the disk image with set_eject_state(true). +// Set the disk index with set_image_index(index). Insert the disk again with set_eject_state(false). + +// If ejected is true, "ejects" the virtual disk tray. +// When ejected, the disk image index can be set. +typedef bool (*retro_set_eject_state_t)(bool ejected); +// Gets current eject state. The initial state is 'not ejected'. +typedef bool (*retro_get_eject_state_t)(void); +// Gets current disk index. First disk is index 0. +// If return value is >= get_num_images(), no disk is currently inserted. +typedef unsigned (*retro_get_image_index_t)(void); +// Sets image index. Can only be called when disk is ejected. +// The implementation supports setting "no disk" by using an index >= get_num_images(). +typedef bool (*retro_set_image_index_t)(unsigned index); +// Gets total number of images which are available to use. +typedef unsigned (*retro_get_num_images_t)(void); +// +// Replaces the disk image associated with index. +// Arguments to pass in info have same requirements as retro_load_game(). +// Virtual disk tray must be ejected when calling this. +// Replacing a disk image with info = NULL will remove the disk image from the internal list. +// As a result, calls to get_image_index() can change. +// +// E.g. replace_image_index(1, NULL), and previous get_image_index() returned 4 before. +// Index 1 will be removed, and the new index is 3. +struct retro_game_info; +typedef bool (*retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); +// Adds a new valid index (get_num_images()) to the internal disk list. +// This will increment subsequent return values from get_num_images() by 1. +// This image index cannot be used until a disk image has been set with replace_image_index. +typedef bool (*retro_add_image_index_t)(void); + +struct retro_disk_control_callback +{ + retro_set_eject_state_t set_eject_state; + retro_get_eject_state_t get_eject_state; + + retro_get_image_index_t get_image_index; + retro_set_image_index_t set_image_index; + retro_get_num_images_t get_num_images; + + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; +}; + +enum retro_pixel_format +{ + // 0RGB1555, native endian. 0 bit must be set to 0. + // This pixel format is default for compatibility concerns only. + // If a 15/16-bit pixel format is desired, consider using RGB565. + RETRO_PIXEL_FORMAT_0RGB1555 = 0, + + // XRGB8888, native endian. X bits are ignored. + RETRO_PIXEL_FORMAT_XRGB8888 = 1, + + // RGB565, native endian. This pixel format is the recommended format to use if a 15/16-bit format is desired + // as it is the pixel format that is typically available on a wide range of low-power devices. + // It is also natively supported in APIs like OpenGL ES. + RETRO_PIXEL_FORMAT_RGB565 = 2, + + // Ensure sizeof() == sizeof(int). + RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX +}; + +struct retro_message +{ + const char *msg; // Message to be displayed. + unsigned frames; // Duration in frames of message. +}; + +// Describes how the libretro implementation maps a libretro input bind +// to its internal input system through a human readable string. +// This string can be used to better let a user configure input. +struct retro_input_descriptor +{ + // Associates given parameters with a description. + unsigned port; + unsigned device; + unsigned index; + unsigned id; + + const char *description; // Human readable description for parameters. + // The pointer must remain valid until retro_unload_game() is called. +}; + +struct retro_system_info +{ + // All pointers are owned by libretro implementation, and pointers must remain valid until retro_deinit() is called. + + const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc. + const char *library_version; // Descriptive version of core. + + const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe. + // I.e. "bin|rom|iso". + // Typically used for a GUI to filter out extensions. + + bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path. + // ::data and ::size are both invalid. + // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid. + // This is typically set to true for libretro implementations that must load from file. + // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc. + + bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real ROM. + // Necessary for certain libretro implementations that load games from zipped archives. +}; + +struct retro_game_geometry +{ + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. + + float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, + // an aspect ratio of base_width / base_height is assumed. + // A frontend could override this setting if desired. +}; + +struct retro_system_timing +{ + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + // If NULL, obtains the complete environment string if more complex parsing is necessary. + // The environment string is formatted as key-value pairs delimited by semicolons as so: + // "key1=value1;key2=value2;..." + const char *value; // Value to be obtained. If key does not exist, it is set to NULL. +}; + +struct retro_game_info +{ + const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. + // May be NULL if rom was loaded from stdin or similar. + // retro_system_info::need_fullpath guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. +}; + +// Callbacks +// +// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. +typedef bool (*retro_environment_t)(unsigned cmd, void *data); + +// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). +// Width and height specify dimensions of buffer. +// Pitch specifices length in bytes between two lines in buffer. +// For performance reasons, it is highly recommended to have a frame that is packed in memory, i.e. pitch == width * byte_per_pixel. +// Certain graphic APIs, such as OpenGL ES, do not like textures that are not packed in memory. +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); + +// Renders a single audio frame. Should only be used if implementation generates a single sample at a time. +// Format is signed 16-bit native endian. +typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved. +// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. +// Only one of the audio callbacks must ever be used. +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); + +// Polls input. +typedef void (*retro_input_poll_t)(void); +// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK. +// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device() +// will still use the higher level RETRO_DEVICE_JOYPAD to request input. +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); + +// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init(). +// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made. +void retro_set_environment(retro_environment_t); +void retro_set_video_refresh(retro_video_refresh_t); +void retro_set_audio_sample(retro_audio_sample_t); +void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +void retro_set_input_poll(retro_input_poll_t); +void retro_set_input_state(retro_input_state_t); + +// Library global initialization/deinitialization. +void retro_init(void); +void retro_deinit(void); + +// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised. +unsigned retro_api_version(void); + +// Gets statically known system info. Pointers provided in *info must be statically allocated. +// Can be called at any time, even before retro_init(). +void retro_get_system_info(struct retro_system_info *info); + +// Gets information about system audio/video timings and geometry. +// Can be called only after retro_load_game() has successfully completed. +// NOTE: The implementation of this function might not initialize every variable if needed. +// E.g. geom.aspect_ratio might not be initialized if core doesn't desire a particular aspect ratio. +void retro_get_system_av_info(struct retro_system_av_info *info); + +// Sets device to be used for player 'port'. +void retro_set_controller_port_device(unsigned port, unsigned device); + +// Resets the current game. +void retro_reset(void); + +// Runs the game for one video frame. +// During retro_run(), input_poll callback must be called at least once. +// +// If a frame is not rendered for reasons where a game "dropped" a frame, +// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true. +// In this case, the video callback can take a NULL argument for data. +void retro_run(void); + +// Returns the amount of data the implementation requires to serialize internal state (save states). +// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to +// ensure that the frontend can allocate a save state buffer once. +size_t retro_serialize_size(void); + +// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise. +bool retro_serialize(void *data, size_t size); +bool retro_unserialize(const void *data, size_t size); + +void retro_cheat_reset(void); +void retro_cheat_set(unsigned index, bool enabled, const char *code); + +// Loads a game. +bool retro_load_game(const struct retro_game_info *game); + +// Loads a "special" kind of game. Should not be used except in extreme cases. +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +// Unloads a currently loaded game. +void retro_unload_game(void); + +// Gets region of game. +unsigned retro_get_region(void); + +// Gets region of memory. +void *retro_get_memory_data(unsigned id); +size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libretro/link.T b/src/libretro/link.T new file mode 100644 index 00000000..9e82b5dd --- /dev/null +++ b/src/libretro/link.T @@ -0,0 +1,4 @@ +{ + global: retro_*; + local: *; +}; diff --git a/src/libretro/msvc/msvc-2003-xbox1.bat b/src/libretro/msvc/msvc-2003-xbox1.bat new file mode 100644 index 00000000..44db3003 --- /dev/null +++ b/src/libretro/msvc/msvc-2003-xbox1.bat @@ -0,0 +1,47 @@ +@SET VSINSTALLDIR=C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE +@SET VCINSTALLDIR=C:\Program Files\Microsoft Visual Studio .NET 2003 +@SET FrameworkDir=C:\WINDOWS\Microsoft.NET\Framework +@SET FrameworkVersion=v1.1.4322 +@SET FrameworkSDKDir=C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1 +@rem Root of Visual Studio common files. + +@if "%VSINSTALLDIR%"=="" goto Usage +@if "%VCINSTALLDIR%"=="" set VCINSTALLDIR=%VSINSTALLDIR% + +@rem +@rem Root of Visual Studio ide installed files. +@rem +@set DevEnvDir=%VSINSTALLDIR% + +@rem +@rem Root of Visual C++ installed files. +@rem +@set MSVCDir=%VCINSTALLDIR%\VC7 + +@rem +@echo Setting environment for using Microsoft Visual Studio .NET 2003 tools. +@echo (If you have another version of Visual Studio or Visual C++ installed and wish +@echo to use its tools from the command line, run vcvars32.bat for that version.) +@rem + +@REM %VCINSTALLDIR%\Common7\Tools dir is added only for real setup. + +@set PATH=%DevEnvDir%;%MSVCDir%\BIN;%VCINSTALLDIR%\Common7\Tools;%VCINSTALLDIR%\Common7\Tools\bin\prerelease;%VCINSTALLDIR%\Common7\Tools\bin;%FrameworkSDKDir%\bin;%FrameworkDir%\%FrameworkVersion%;%PATH%; +@set INCLUDE=%MSVCDir%\ATLMFC\INCLUDE;%MSVCDir%\INCLUDE;%FrameworkSDKDir%\include;%INCLUDE%;%XDK%\xbox\include +@set LIB=%MSVCDir%\ATLMFC\LIB;%MSVCDir%\LIB;%MSVCDir%\PlatformSDK\lib;%XDK%\lib;%XDK%\xbox\lib;%LIB% + +@goto end + +:Usage + +@echo. VSINSTALLDIR variable is not set. +@echo. +@echo SYNTAX: %0 + +@goto end + +:end + +devenv /clean Release msvc-2003-xbox1.sln +devenv /build Release msvc-2003-xbox1.sln +exit diff --git a/src/libretro/msvc/msvc-2003-xbox1.sln b/src/libretro/msvc/msvc-2003-xbox1.sln new file mode 100644 index 00000000..f52e31b5 --- /dev/null +++ b/src/libretro/msvc/msvc-2003-xbox1.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vbanext-msvc2003-xbox1", "msvc-2003-xbox1/msvc-2003-xbox1.vcproj", "{BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Profile = Profile + Profile_FastCap = Profile_FastCap + Release = Release + Release_LTCG = Release_LTCG + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Debug.ActiveCfg = Debug|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Debug.Build.0 = Debug|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Profile.ActiveCfg = Profile|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Profile.Build.0 = Profile|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Release.ActiveCfg = Release|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Release.Build.0 = Release|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox + {BDCB70E0-EEBB-404A-9874-9A2E22A4A2B3}.Release_LTCG.Build.0 = Release_LTCG|Xbox + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/src/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj b/src/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj new file mode 100644 index 00000000..ecc0de8e --- /dev/null +++ b/src/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libretro/msvc/msvc-2003-xbox1/stdint.h b/src/libretro/msvc/msvc-2003-xbox1/stdint.h new file mode 100644 index 00000000..9d8fe7b0 --- /dev/null +++ b/src/libretro/msvc/msvc-2003-xbox1/stdint.h @@ -0,0 +1,249 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef __RARCH_STDINT_H +#define __RARCH_STDINT_H + +#if _MSC_VER && (_MSC_VER < 1600) +//pre-MSVC 2010 needs an implementation of stdint.h + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + +#else +//sanity for everything else +#include +#endif + +#endif diff --git a/src/libretro/msvc/msvc-2010-360.bat b/src/libretro/msvc/msvc-2010-360.bat new file mode 100644 index 00000000..0e5fde55 --- /dev/null +++ b/src/libretro/msvc/msvc-2010-360.bat @@ -0,0 +1,124 @@ +@echo off + +@echo Setting environment for using Microsoft Visual Studio 2010 x86 tools. + +@call :GetVSCommonToolsDir +@if "%VS100COMNTOOLS%"=="" goto error_no_VS100COMNTOOLSDIR + +@call "%VS100COMNTOOLS%VCVarsQueryRegistry.bat" 32bit No64bit + +@if "%VSINSTALLDIR%"=="" goto error_no_VSINSTALLDIR +@if "%FrameworkDir32%"=="" goto error_no_FrameworkDIR32 +@if "%FrameworkVersion32%"=="" goto error_no_FrameworkVer32 +@if "%Framework35Version%"=="" goto error_no_Framework35Version + +@set FrameworkDir=%FrameworkDir32% +@set FrameworkVersion=%FrameworkVersion32% + +@if not "%WindowsSdkDir%" == "" ( + @set "PATH=%WindowsSdkDir%bin\NETFX 4.0 Tools;%WindowsSdkDir%bin;%PATH%" + @set "INCLUDE=%WindowsSdkDir%include;%INCLUDE%" + @set "LIB=%WindowsSdkDir%lib;%LIB%" +) + +@rem +@rem Root of Visual Studio IDE installed files. +@rem +@set DevEnvDir=%VSINSTALLDIR%Common7\IDE\ + +@rem PATH +@rem ---- +@if exist "%VSINSTALLDIR%Team Tools\Performance Tools" ( + @set "PATH=%VSINSTALLDIR%Team Tools\Performance Tools;%PATH%" +) +@if exist "%ProgramFiles%\HTML Help Workshop" set PATH=%ProgramFiles%\HTML Help Workshop;%PATH% +@if exist "%ProgramFiles(x86)%\HTML Help Workshop" set PATH=%ProgramFiles(x86)%\HTML Help Workshop;%PATH% +@if exist "%VCINSTALLDIR%VCPackages" set PATH=%VCINSTALLDIR%VCPackages;%PATH% +@set PATH=%FrameworkDir%%Framework35Version%;%PATH% +@set PATH=%FrameworkDir%%FrameworkVersion%;%PATH% +@set PATH=%VSINSTALLDIR%Common7\Tools;%PATH% +@if exist "%VCINSTALLDIR%BIN" set PATH=%VCINSTALLDIR%BIN;%PATH% +@set PATH=%DevEnvDir%;%PATH% + +@if exist "%VSINSTALLDIR%VSTSDB\Deploy" ( + @set "PATH=%VSINSTALLDIR%VSTSDB\Deploy;%PATH%" +) + +@if not "%FSHARPINSTALLDIR%" == "" ( + @set "PATH=%FSHARPINSTALLDIR%;%PATH%" +) + +@rem INCLUDE +@rem ------- +@if exist "%VCINSTALLDIR%ATLMFC\INCLUDE" set INCLUDE=%VCINSTALLDIR%ATLMFC\INCLUDE;%INCLUDE% +@if exist "%VCINSTALLDIR%INCLUDE" set INCLUDE=%VCINSTALLDIR%INCLUDE;%INCLUDE% + +@rem LIB +@rem --- +@if exist "%VCINSTALLDIR%ATLMFC\LIB" set LIB=%VCINSTALLDIR%ATLMFC\LIB;%LIB% +@if exist "%VCINSTALLDIR%LIB" set LIB=%VCINSTALLDIR%LIB;%LIB% + +@rem LIBPATH +@rem ------- +@if exist "%VCINSTALLDIR%ATLMFC\LIB" set LIBPATH=%VCINSTALLDIR%ATLMFC\LIB;%LIBPATH% +@if exist "%VCINSTALLDIR%LIB" set LIBPATH=%VCINSTALLDIR%LIB;%LIBPATH% +@set LIBPATH=%FrameworkDir%%Framework35Version%;%LIBPATH% +@set LIBPATH=%FrameworkDir%%FrameworkVersion%;%LIBPATH% + +@goto end + +@REM ----------------------------------------------------------------------- +:GetVSCommonToolsDir +@set VS100COMNTOOLS= +@call :GetVSCommonToolsDirHelper32 HKLM > nul 2>&1 +@if errorlevel 1 call :GetVSCommonToolsDirHelper32 HKCU > nul 2>&1 +@if errorlevel 1 call :GetVSCommonToolsDirHelper64 HKLM > nul 2>&1 +@if errorlevel 1 call :GetVSCommonToolsDirHelper64 HKCU > nul 2>&1 +@exit /B 0 + +:GetVSCommonToolsDirHelper32 +@for /F "tokens=1,2*" %%i in ('reg query "%1\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v "10.0"') DO ( + @if "%%i"=="10.0" ( + @SET "VS100COMNTOOLS=%%k" + ) +) +@if "%VS100COMNTOOLS%"=="" exit /B 1 +@SET "VS100COMNTOOLS=%VS100COMNTOOLS%Common7\Tools\" +@exit /B 0 + +:GetVSCommonToolsDirHelper64 +@for /F "tokens=1,2*" %%i in ('reg query "%1\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7" /v "10.0"') DO ( + @if "%%i"=="10.0" ( + @SET "VS100COMNTOOLS=%%k" + ) +) +@if "%VS100COMNTOOLS%"=="" exit /B 1 +@SET "VS100COMNTOOLS=%VS100COMNTOOLS%Common7\Tools\" +@exit /B 0 + +@REM ----------------------------------------------------------------------- +:error_no_VS100COMNTOOLSDIR +@echo ERROR: Cannot determine the location of the VS Common Tools folder. +@goto end + +:error_no_VSINSTALLDIR +@echo ERROR: Cannot determine the location of the VS installation. +@goto end + +:error_no_FrameworkDIR32 +@echo ERROR: Cannot determine the location of the .NET Framework 32bit installation. +@goto end + +:error_no_FrameworkVer32 +@echo ERROR: Cannot determine the version of the .NET Framework 32bit installation. +@goto end + +:error_no_Framework35Version +@echo ERROR: Cannot determine the .NET Framework 3.5 version. +@goto end + +:end + +msbuild msvc-2010-360.sln /p:Configuration=Release /target:clean +msbuild msvc-2010-360.sln /p:Configuration=Release +exit diff --git a/src/libretro/msvc/msvc-2010-360.sln b/src/libretro/msvc/msvc-2010-360.sln new file mode 100644 index 00000000..9978fb3b --- /dev/null +++ b/src/libretro/msvc/msvc-2010-360.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mvc-2010-360", "msvc-2010-360/msvc-2010-360.vcxproj", "{DB17AF79-EB79-4062-ACA8-F82864712DA0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + CodeAnalysis|Xbox 360 = CodeAnalysis|Xbox 360 + Debug|Xbox 360 = Debug|Xbox 360 + Profile_FastCap|Xbox 360 = Profile_FastCap|Xbox 360 + Profile|Xbox 360 = Profile|Xbox 360 + Release_LTCG|Xbox 360 = Release_LTCG|Xbox 360 + Release|Xbox 360 = Release|Xbox 360 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.CodeAnalysis|Xbox 360.ActiveCfg = CodeAnalysis|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.CodeAnalysis|Xbox 360.Build.0 = CodeAnalysis|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Debug|Xbox 360.ActiveCfg = Debug|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Debug|Xbox 360.Build.0 = Debug|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Profile_FastCap|Xbox 360.ActiveCfg = Profile_FastCap|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Profile_FastCap|Xbox 360.Build.0 = Profile_FastCap|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Profile|Xbox 360.ActiveCfg = Profile|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Profile|Xbox 360.Build.0 = Profile|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Release_LTCG|Xbox 360.ActiveCfg = Release_LTCG|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Release_LTCG|Xbox 360.Build.0 = Release_LTCG|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Release|Xbox 360.ActiveCfg = Release|Xbox 360 + {DB17AF79-EB79-4062-ACA8-F82864712DA0}.Release|Xbox 360.Build.0 = Release|Xbox 360 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj b/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj new file mode 100644 index 00000000..08c128ea --- /dev/null +++ b/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj @@ -0,0 +1,254 @@ + + + + + CodeAnalysis + Xbox 360 + + + Debug + Xbox 360 + + + Profile + Xbox 360 + + + Profile_FastCap + Xbox 360 + + + Release + Xbox 360 + + + Release_LTCG + Xbox 360 + + + + + + + + + + + + + + + + + + + + + {DB17AF79-EB79-4062-ACA8-F82864712DA0} + Xbox360Proj + vba-next-libretro-360 + + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + true + + + StaticLibrary + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + $(OutDir)vba_next_libretro_xdk360$(TargetExt) + + + + NotUsing + Level3 + ProgramDatabase + Disabled + false + true + false + $(OutDir)$(ProjectName).pch + MultiThreadedDebug + _DEBUG;_XBOX;_LIB;;__LIBRETRO__;SPEEDHAX;__POWERPC__;__ppc__;WORDS_BIGENDIAN;BLARGG_BIG_ENDIAN;INLINE=_inline;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + Callcap + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + true + + + + + NotUsing + Level4 + ProgramDatabase + Disabled + false + true + AnalyzeOnly + false + $(OutDir)$(ProjectName).pch + MultiThreadedDebug + _DEBUG;_XBOX;_LIB;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + Callcap + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + true + + + + + Level3 + NotUsing + Full + true + false + true + ProgramDatabase + Size + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;PROFILE;_LIB;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + Callcap + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + true + false + xapilib.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + Level3 + NotUsing + Full + true + false + true + ProgramDatabase + Fastcap + Size + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;PROFILE;FASTCAP;_LIB;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + true + false + true + + + + + Level3 + NotUsing + Full + true + true + ProgramDatabase + Speed + false + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;_LIB;__LIBRETRO__;SPEEDHAX;__POWERPC__;__ppc__;WORDS_BIGENDIAN;BLARGG_BIG_ENDIAN;INLINE=_inline;USE_CACHE_PREFETCH;BRANCHLESS_GBA_GFX;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + true + true + + + true + true + true + + + + + Level3 + NotUsing + Full + true + true + ProgramDatabase + Size + false + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;LTCG;_LIB;__LIBRETRO__;USE_CACHE_PREFETCH;BRANCHLESS_GBA_GFX;SPEEDHAX;__POWERPC__;__ppc__;WORDS_BIGENDIAN;BLARGG_BIG_ENDIAN;INLINE=_inline;%(PreprocessorDefinitions);_XBOX360;FRONTEND_SUPPORTS_RGB565 + $(SolutionDir)\..\libretro;$(SolutionDir)\..\src;$(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + true + + + true + true + true + + + + + + diff --git a/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters b/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters new file mode 100644 index 00000000..c93fc424 --- /dev/null +++ b/src/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {d19de43b-0337-4673-9b9e-1892d348647d} + + + {becd444c-3df5-4a9e-9885-8a181058095d} + + + + + Header Files\libretro + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files\libretro + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/libretro/msvc/msvc-2010.sln b/src/libretro/msvc/msvc-2010.sln new file mode 100644 index 00000000..d7ef2d09 --- /dev/null +++ b/src/libretro/msvc/msvc-2010.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2010", "msvc-2010/msvc-2010.vcxproj", "{C461207F-8F4F-4BFB-A90D-25298F37B47D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C461207F-8F4F-4BFB-A90D-25298F37B47D}.Debug|Win32.ActiveCfg = Debug|Win32 + {C461207F-8F4F-4BFB-A90D-25298F37B47D}.Debug|Win32.Build.0 = Debug|Win32 + {C461207F-8F4F-4BFB-A90D-25298F37B47D}.Release|Win32.ActiveCfg = Release|Win32 + {C461207F-8F4F-4BFB-A90D-25298F37B47D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/libretro/msvc/msvc-2010/libretro.def b/src/libretro/msvc/msvc-2010/libretro.def new file mode 100644 index 00000000..2a71c098 --- /dev/null +++ b/src/libretro/msvc/msvc-2010/libretro.def @@ -0,0 +1,27 @@ +LIBRARY "libretro-prboom msvc2010" +EXPORTS +retro_set_environment +retro_set_video_refresh +retro_set_audio_sample +retro_set_audio_sample_batch +retro_set_input_poll +retro_set_input_state +retro_init +retro_deinit +retro_api_version +retro_get_system_info +retro_get_system_av_info +retro_set_controller_port_device +retro_reset +retro_run +retro_serialize_size +retro_serialize +retro_unserialize +retro_cheat_reset +retro_cheat_set +retro_load_game +retro_load_game_special +retro_unload_game +retro_get_region +retro_get_memory_data +retro_get_memory_size diff --git a/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj b/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj new file mode 100644 index 00000000..828f8983 --- /dev/null +++ b/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj @@ -0,0 +1,105 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C461207F-8F4F-4BFB-A90D-25298F37B47D} + Win32Proj + msvc2010 + vba-next + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + true + libretro + + + false + libretro + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;_CRT_SECURE_NO_WARNINGS;LSB_FIRST;SPEEDHAX=1;__LIBRETRO__;INLINE=_inline;%(PreprocessorDefinitions);FRONTEND_SUPPORTS_RGB565 + $(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\src\;$(SolutionDir)\..\libretro;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + Windows + true + libretro.def + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;_CRT_SECURE_NO_WARNINGS;LSB_FIRST;SPEEDHAX=1;__LIBRETRO__;INLINE=_inline;%(PreprocessorDefinitions);FRONTEND_SUPPORTS_RGB565 + $(SolutionDir)\..\src\common;$(SolutionDir)\..\src\gb;$(SolutionDir)\..\src\gba;$(SolutionDir)\..\src\;$(SolutionDir)\..\libretro;$(SolutionDir)\..\utils\zlib;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + libretro.def + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters b/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters new file mode 100644 index 00000000..543d7d22 --- /dev/null +++ b/src/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters @@ -0,0 +1,78 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {3ed03eb4-3d22-42ca-b2ab-1058e771db27} + + + {01290b17-a062-4772-8a90-1fb347398419} + + + {9553246f-4fb1-41ce-807d-bd3c3dc6f564} + + + {d5a23baf-0d6e-4d49-a81e-f1320c3186cc} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files\gba + + + Header Files\gba + + + Header Files\gba + + + Header Files\gba + + + Header Files\libretro + + + Header Files\gba + + + Header Files\common + + + Header Files\common + + + + + Source Files\libretro + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/libretro/qnx/playbook/.cproject b/src/libretro/qnx/playbook/.cproject new file mode 100644 index 00000000..9c4fde66 --- /dev/null +++ b/src/libretro/qnx/playbook/.cproject @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libretro/qnx/playbook/.project b/src/libretro/qnx/playbook/.project new file mode 100644 index 00000000..dad9adc9 --- /dev/null +++ b/src/libretro/qnx/playbook/.project @@ -0,0 +1,85 @@ + + + vba-next + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -C../../.. -f Makefile.libretro platform=qnx + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + false + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + com.qnx.tools.ide.bbt.core.bbtnature + org.eclipse.cdt.core.ccnature + + diff --git a/src/libretro/scrc32.cpp b/src/libretro/scrc32.cpp new file mode 100644 index 00000000..6c30a9c2 --- /dev/null +++ b/src/libretro/scrc32.cpp @@ -0,0 +1,88 @@ +#ifndef _S_CRC32_H +#define _S_CRC32_H + +#ifdef __cplusplus +extern "C" { +#endif + +static const unsigned long crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +#define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf); +#define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf); +#define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf); + +unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len) +{ + if (buf == 0) return 0L; + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8_CRC32(buf); + len -= 8; + } + if (len) do { + DO1_CRC32(buf); + } while (--len); + return crc ^ 0xffffffffL; +} + +#ifdef __cplusplus +} +#endif + +#endif +