diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index a678d5ae10..ad9c7bb599 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -424,13 +424,13 @@ namespace BizHawk.Client.Common case "GBA": if (false) { - var gba = new GBA(nextComm); + var gba = new GBA(nextComm); // meteor gba.Load(rom.RomData); nextEmulator = gba; } else { - var gba = new VBANext(rom.RomData, nextComm); + var gba = new VBANext(rom.RomData, nextComm, game); nextEmulator = gba; } break; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs index 335e7f57cf..5e9f9d5d06 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs @@ -27,6 +27,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA L = 512 } + [StructLayout(LayoutKind.Sequential)] + public struct FrontEndSettings + { + public enum SaveType : int + { + auto = 0, + eeprom = 1, + sram = 2, + flash = 3, + eeprom_sensor = 4, + none = 5 + } + public enum FlashSize : int + { + small = 0x10000, + big = 0x20000 + } + public SaveType saveType; + public FlashSize flashSize; + public bool enableRtc; + public bool mirroringEnable; + public bool skipBios; + + public static FrontEndSettings GetDefaults() + { + return new FrontEndSettings + { + flashSize = FlashSize.big + }; + } + } + /// /// create a new context /// @@ -51,7 +83,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA /// /// success [DllImport(dllname, CallingConvention = cc)] - public static extern bool LoadRom(IntPtr g, byte[] romfile, uint romfilelen, byte[] biosfile, uint biosfilelen); + public static extern bool LoadRom(IntPtr g, byte[] romfile, uint romfilelen, byte[] biosfile, uint biosfilelen, [In]ref FrontEndSettings settings); /// /// hard reset @@ -82,5 +114,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public static extern void TxtStateSave(IntPtr g, [In]ref TextStateFPtrs ff); [DllImport(dllname, CallingConvention = cc)] public static extern void TxtStateLoad(IntPtr g, [In]ref TextStateFPtrs ff); + + [DllImport(dllname, CallingConvention = cc)] + public static extern int SaveRamSize(IntPtr g); + [DllImport(dllname, CallingConvention = cc)] + public static extern bool SaveRamSave(IntPtr g, byte[] data, int length); + [DllImport(dllname, CallingConvention = cc)] + public static extern bool SaveRamLoad(IntPtr g, byte[] data, int length); + } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs index 637933fb0c..7898b2d6df 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs @@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA { IntPtr Core; - public VBANext(byte[] romfile, CoreComm nextComm) + public VBANext(byte[] romfile, CoreComm nextComm, GameInfo gi) { CoreComm = nextComm; byte[] biosfile = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory."); @@ -26,12 +26,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA if (biosfile.Length != 16 * 1024) throw new ArgumentException("BIOS file is not exactly 16K!"); + LibVBANext.FrontEndSettings FES; + FES.saveType = (LibVBANext.FrontEndSettings.SaveType)gi.GetInt("saveType", 0); + FES.flashSize = (LibVBANext.FrontEndSettings.FlashSize)gi.GetInt("flashSize", 0x10000); + FES.enableRtc = gi.GetInt("enableRtc", 0) != 0; + FES.mirroringEnable = gi.GetInt("mirroringEnable", 0) != 0; + FES.skipBios = false; // todo: hook me up as a syncsetting + Core = LibVBANext.Create(); if (Core == IntPtr.Zero) throw new InvalidOperationException("Create() returned nullptr!"); try { - if (!LibVBANext.LoadRom(Core, romfile, (uint)romfile.Length, biosfile, (uint)biosfile.Length)) + if (!LibVBANext.LoadRom(Core, romfile, (uint)romfile.Length, biosfile, (uint)biosfile.Length, ref FES)) throw new InvalidOperationException("LoadRom() returned false!"); CoreComm.VsyncNum = 262144; @@ -52,9 +59,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA } } - - - public void FrameAdvance(bool render, bool rendersound = true) { Frame++; diff --git a/output/dll/libvbanext.dll b/output/dll/libvbanext.dll index 24f2b01f65..f1b70ead99 100644 Binary files a/output/dll/libvbanext.dll and b/output/dll/libvbanext.dll differ diff --git a/vbanext/instance.cpp b/vbanext/instance.cpp index 4cf2918bab..e92a883c0b 100644 --- a/vbanext/instance.cpp +++ b/vbanext/instance.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -48,12 +49,7 @@ class Gigazoid #define FLASH_PROGRAM 8 #define FLASH_SETBANK 9 -#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; @@ -64,11 +60,7 @@ int flashBank; // = 0; void flashInit (void) { -#ifdef __LIBRETRO__ - memset(flashSaveMemory, 0xff, 0x20000); -#else memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); -#endif } void flashReset() @@ -78,22 +70,6 @@ void flashReset() flashBank = 0; } -void flashSetSize(int size) -{ - if(size == 0x10000) { - flashDeviceID = 0x1b; - flashManufacturerID = 0x32; - } else { - flashDeviceID = 0x13; //0x09; - flashManufacturerID = 0x62; //0xc2; - } - // Added to make 64k saves compatible with 128k ones - // (allow wrongfuly set 64k saves to work for Pokemon games) - if ((size == 0x20000) && (flashSize == 0x10000)) - memcpy((uint8_t *)(flashSaveMemory+0x10000), (uint8_t *)(flashSaveMemory), 0x10000); - flashSize = size; -} - uint8_t flashRead(uint32_t address) { address &= 0xFFFF; @@ -122,24 +98,14 @@ uint8_t flashRead(uint32_t address) void flashSaveDecide(uint32_t address, uint8_t byte) { - if(address == 0x0e005555) { - saveType = 2; + if (address == 0x0e005555) cpuSaveGameFunc = &Gigazoid::flashWrite; - } else { - saveType = 1; + else cpuSaveGameFunc = &Gigazoid::sramWrite; - } (this->*cpuSaveGameFunc)(address, byte); } -void flashDelayedWrite(uint32_t address, uint8_t byte) -{ - saveType = 2; - cpuSaveGameFunc = &Gigazoid::flashWrite; - flashWrite(address, byte); -} - void flashWrite(uint32_t address, uint8_t byte) { address &= 0xFFFF; @@ -243,13 +209,7 @@ 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; @@ -257,11 +217,7 @@ int eepromSize; // = 512; void eepromInit (void) { -#ifdef __LIBRETRO__ - memset(eepromData, 255, 0x2000); -#else memset(eepromData, 255, sizeof(eepromData)); -#endif } void eepromReset (void) @@ -401,18 +357,15 @@ u8 sramRead(u32 address) return flashSaveMemory[address & 0xFFFF]; } -void sramDelayedWrite(u32 address, u8 byte) -{ - saveType = 1; - cpuSaveGameFunc = &Gigazoid::sramWrite; - sramWrite(address, byte); -} - void sramWrite(u32 address, u8 byte) { flashSaveMemory[address & 0xFFFF] = byte; } +void dummyWrite(u32 address, u8 byte) +{ +} + /*============================================================ RTC ============================================================ */ @@ -437,32 +390,19 @@ typedef struct RTCCLOCKDATA rtcClockData; bool rtcEnabled; // = false; -void rtcEnable(bool e) -{ - rtcEnabled = e; -} - -bool rtcIsEnabled (void) -{ - return rtcEnabled; -} - u16 rtcRead(u32 address) { - if(rtcEnabled) + switch(address) { - switch(address) - { - case 0x80000c8: - return rtcClockData.byte2; - case 0x80000c6: - return rtcClockData.byte1; - case 0x80000c4: - return rtcClockData.byte0; - } + case 0x80000c8: + return rtcClockData.byte2; + case 0x80000c6: + return rtcClockData.byte1; + case 0x80000c4: + return rtcClockData.byte0; + default: + return 0; } - - return READ16LE((&rom[address & 0x1FFFFFE])); } static u8 toBCD(u8 value) @@ -2764,7 +2704,6 @@ int gfxBG3X; int gfxBG3Y; bool ioReadable[0x400]; -int gbaSaveType; // used to remember the save type on reset //int gfxLastVCOUNT = 0; @@ -3054,7 +2993,7 @@ INLINE u32 CPUReadHalfWord(u32 address) case 10: case 11: case 12: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) + if(rtcEnabled && (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)) value = rtcRead(address); else value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); @@ -3194,14 +3133,11 @@ INLINE void CPUWriteMemory(u32 address, u32 value) WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); break; case 0x0D: - if(cpuEEPROMEnabled) { + if (cpuEEPROMEnabled) eepromWrite(value); - break; - } break; case 0x0E: - if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) - (this->*cpuSaveGameFunc)(address, (u8)value); + (this->*cpuSaveGameFunc)(address, (u8)value); break; default: break; @@ -3247,8 +3183,7 @@ INLINE void CPUWriteHalfWord(u32 address, u16 value) eepromWrite((u8)value); break; case 14: - if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) - (this->*cpuSaveGameFunc)(address, (u8)value); + (this->*cpuSaveGameFunc)(address, (u8)value); break; default: break; @@ -3362,11 +3297,8 @@ INLINE void CPUWriteByte(u32 address, u8 b) eepromWrite(b); break; case 14: - if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) - { - (this->*cpuSaveGameFunc)(address, b); - break; - } + (this->*cpuSaveGameFunc)(address, b); + break; default: break; } @@ -8860,14 +8792,14 @@ INLINE u32 gfxDecreaseBrightness(u32 color, int coeff) /*============================================================ GBA.CPP ============================================================ */ -int saveType; static const bool useBios = true; bool skipBios; -bool cpuIsMultiBoot; -int cpuSaveType; +// it's a few bytes in the linkscript to make a multiboot image work in normal boot as well, +// and most of the ones i've seen have done that, so this is not terribly useful +static const bool cpuIsMultiBoot = false; +int cpuSaveType; // used only in init() to set up function pointers bool enableRtc; bool mirroringEnable; -bool skipSaveGameBattery; int cpuDmaCount; @@ -8880,10 +8812,8 @@ u16 pix[2 * PIX_BUFFER_SCREEN_WIDTH * 160]; uint8_t oam[0x400]; uint8_t ioMem[0x400]; -bool cpuSramEnabled; // = true; -bool cpuFlashEnabled; // = true; -bool cpuEEPROMEnabled; // = true; -bool cpuEEPROMSensorEnabled; // = false; +bool cpuEEPROMEnabled; // true to process writes to EEPROM at 0dxxxxxx +bool cpuEEPROMSensorEnabled; // eeprom motion sensor? code is mostly disabled #ifndef LSB_FIRST bool cpuBiosSwapped = false; @@ -8955,97 +8885,6 @@ INLINE int CPUUpdateTicks (void) graphics.layerEnable = io_registers[REG_DISPCNT]; \ } -// TODO: Batteryram stuffs -/* -bool CPUWriteBatteryFile(const char *fileName) -{ - if(gbaSaveType == 0) - { - if(eepromInUse) - gbaSaveType = 3; - else - switch(saveType) - { - case 1: - gbaSaveType = 1; - break; - case 2: - gbaSaveType = 2; - break; - } - } - - if((gbaSaveType) && (gbaSaveType!=5)) - { - FILE *file = fopen(fileName, "wb"); - - if(!file) { - systemMessage("Error creating file %s", fileName); - return false; - } - - // only save if Flash/Sram in use or EEprom in use - if(gbaSaveType != 3) { - if(gbaSaveType == 2) { - if(fwrite(flashSaveMemory, 1, flashSize, file) != (size_t)flashSize) { - fclose(file); - return false; - } - } else { - if(fwrite(flashSaveMemory, 1, 0x10000, file) != 0x10000) { - fclose(file); - return false; - } - } - } else { - if(fwrite(eepromData, 1, eepromSize, file) != (size_t)eepromSize) { - fclose(file); - return false; - } - } - fclose(file); - } - return true; -} - -bool CPUReadBatteryFile(const char *fileName) -{ - FILE *file = fopen(fileName, "rb"); - - if(!file) - return false; - - // check file size to know what we should read - fseek(file, 0, SEEK_END); - - long size = ftell(file); - fseek(file, 0, SEEK_SET); - - if(size == 512 || size == 0x2000) { - if(fread(eepromData, 1, size, file) != (size_t)size) { - fclose(file); - return false; - } - } else { - if(size == 0x20000) { - if(fread(flashSaveMemory, 1, 0x20000, file) != 0x20000) { - fclose(file); - return false; - } - flashSetSize(0x20000); - } else { - if(fread(flashSaveMemory, 1, 0x10000, file) != 0x10000) { - fclose(file); - return false; - } - flashSetSize(0x10000); - } - } - fclose(file); - return true; -} -*/ - int CPULoadRom(const u8 *romfile, const u32 romfilelen) { if (cpuIsMultiBoot) @@ -12155,17 +11994,41 @@ void CPUUpdateRegister(uint32_t address, uint16_t value) void CPUInit(const u8 *biosfile, const u32 biosfilelen) { -#ifndef LSB_FIRST - if(!cpuBiosSwapped) { - for(unsigned int i = 0; i < sizeof(myROM)/4; i++) { - WRITE32LE(&myROM[i], myROM[i]); - } - cpuBiosSwapped = true; + eepromInUse = false; + switch(cpuSaveType) + { + case 0: // automatic + default: + cpuEEPROMEnabled = true; + cpuEEPROMSensorEnabled = false; + cpuSaveGameFunc = &Gigazoid::flashSaveDecide; // EEPROM usage is automatically detected + break; + case 1: // EEPROM + cpuEEPROMEnabled = true; + cpuEEPROMSensorEnabled = false; + cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected + break; + case 2: // SRAM + cpuEEPROMEnabled = false; + cpuEEPROMSensorEnabled = false; + cpuSaveGameFunc = &Gigazoid::sramWrite; + break; + case 3: // FLASH + cpuEEPROMEnabled = false; + cpuEEPROMSensorEnabled = false; + cpuSaveGameFunc = &Gigazoid::flashWrite; + break; + case 4: // EEPROM+Sensor + cpuEEPROMEnabled = true; + cpuEEPROMSensorEnabled = true; + cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected + break; + case 5: // NONE + cpuEEPROMEnabled = false; + cpuEEPROMSensorEnabled = false; + cpuSaveGameFunc = &Gigazoid::dummyWrite; + break; } -#endif - gbaSaveType = 0; - eepromInUse = 0; - saveType = 0; memcpy(bios, biosfile, 16384); @@ -12225,6 +12088,7 @@ void CPUInit(const u8 *biosfile, const u32 biosfilelen) for(i = 0x304; i < 0x400; i++) ioReadable[i] = false; + // what is this? if(romSize < 0x1fe2000) { *((uint16_t *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA *((uint16_t *)&rom[0x1fe209e]) = 0x4770; // BX LR @@ -12259,29 +12123,14 @@ void CPUInit(const u8 *biosfile, const u32 biosfilelen) address_lut[0x32] = &io_registers[REG_BG3PB]; address_lut[0x34] = &io_registers[REG_BG3PC]; address_lut[0x36] = &io_registers[REG_BG3PD]; - address_lut[0x40] = &io_registers[REG_WIN0H]; - address_lut[0x42] = &io_registers[REG_WIN1H]; - address_lut[0x44] = &io_registers[REG_WIN0V]; - address_lut[0x46] = &io_registers[REG_WIN1V]; + address_lut[0x40] = &io_registers[REG_WIN0H]; + address_lut[0x42] = &io_registers[REG_WIN1H]; + address_lut[0x44] = &io_registers[REG_WIN0V]; + address_lut[0x46] = &io_registers[REG_WIN1V]; } void CPUReset (void) { - if(gbaSaveType == 0) - { - if(eepromInUse) - gbaSaveType = 3; - else - switch(saveType) - { - case 1: - gbaSaveType = 1; - break; - case 2: - gbaSaveType = 2; - break; - } - } rtcReset(); memset(&bus.reg[0], 0, sizeof(bus.reg)); // clean registers memset(oam, 0, 0x400); // clean OAM @@ -12450,11 +12299,9 @@ void CPUReset (void) dma2Dest = 0; dma3Source = 0; dma3Dest = 0; - cpuSaveGameFunc = &Gigazoid::flashSaveDecide; renderLine = &Gigazoid::mode0RenderLine; fxOn = false; windowOn = false; - saveType = 0; graphics.layerEnable = io_registers[REG_DISPCNT]; memset(line[0], -1, 240 * sizeof(u32)); @@ -12505,57 +12352,9 @@ void CPUReset (void) BIOS_RegisterRamReset(0xfe); else if(!useBios && !cpuIsMultiBoot) BIOS_RegisterRamReset(0xff); + else if (skipBios) + BIOS_RegisterRamReset(0xff); // ?? - switch(cpuSaveType) { - case 0: // automatic - cpuSramEnabled = true; - cpuFlashEnabled = true; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - saveType = gbaSaveType = 0; - break; - case 1: // EEPROM - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - saveType = gbaSaveType = 3; - // EEPROM usage is automatically detected - break; - case 2: // SRAM - cpuSramEnabled = true; - cpuFlashEnabled = false; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::sramDelayedWrite; // to insure we detect the write - saveType = gbaSaveType = 1; - break; - case 3: // FLASH - cpuSramEnabled = false; - cpuFlashEnabled = true; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::flashDelayedWrite; // to insure we detect the write - saveType = gbaSaveType = 2; - break; - case 4: // EEPROM+Sensor - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = true; - // EEPROM usage is automatically detected - saveType = gbaSaveType = 3; - break; - case 5: // NONE - cpuSramEnabled = false; - cpuFlashEnabled = false; - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - // no save at all - saveType = gbaSaveType = 5; - break; - } - ARM_PREFETCH; } @@ -13030,8 +12829,6 @@ void Gigazoid_Init() eepromInUse = false; eepromSize = 512; - rtcEnabled = false; - // this is constant now // soundSampleRate = 22050; @@ -13041,14 +12838,6 @@ void Gigazoid_Init() armIrqEnable = true; armMode = 0x1f; - romSize = 0x2000000; - - cpuSramEnabled = true; - cpuFlashEnabled = true; - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - - cpuSaveGameFunc = &Gigazoid::flashSaveDecide; renderLine = &Gigazoid::mode0RenderLine; #define ARRAYINIT(n) memcpy((n), (n##_init), sizeof(n)) @@ -13205,8 +12994,7 @@ templatevoid SyncState(NewState *ns) EVS(cpuSaveGameFunc, &Gigazoid::flashWrite, 1); EVS(cpuSaveGameFunc, &Gigazoid::sramWrite, 2); EVS(cpuSaveGameFunc, &Gigazoid::flashSaveDecide, 3); - EVS(cpuSaveGameFunc, &Gigazoid::flashDelayedWrite, 4); - EVS(cpuSaveGameFunc, &Gigazoid::sramDelayedWrite, 5); + EVS(cpuSaveGameFunc, &Gigazoid::dummyWrite, 4); EES(cpuSaveGameFunc, nullptr); NSS(fxOn); @@ -13237,7 +13025,6 @@ templatevoid SyncState(NewState *ns) NSS(gfxBG3Y); NSS(ioReadable); - NSS(gbaSaveType); NSS(stopState); @@ -13261,13 +13048,10 @@ templatevoid SyncState(NewState *ns) NSS(timer3Reload); NSS(timer3ClockReload); - NSS(saveType); NSS(skipBios); - NSS(cpuIsMultiBoot); NSS(cpuSaveType); NSS(enableRtc); NSS(mirroringEnable); - NSS(skipSaveGameBattery); NSS(cpuDmaCount); @@ -13278,8 +13062,6 @@ templatevoid SyncState(NewState *ns) NSS(oam); NSS(ioMem); - NSS(cpuSramEnabled); - NSS(cpuFlashEnabled); NSS(cpuEEPROMEnabled); NSS(cpuEEPROMSensorEnabled); @@ -13311,6 +13093,63 @@ templatevoid SyncState(NewState *ns) NSS(lagged); } +// load a legacy battery ram file to a place where it might work, who knows +void LoadLegacyBatteryRam(const u8 *data, int len) +{ + std::memcpy(eepromData, data, std::min(len, sizeof(eepromData))); + std::memcpy(flashSaveMemory, data, std::min(len, sizeof(flashSaveMemory))); + if (len <= 0x10000) + { + // can salvage broken pokeymans saves in some cases + std::memcpy(flashSaveMemory + 0x10000, data, std::min(len, 0x10000)); + } +} + +templatebool SyncBatteryRam(NewState *ns) +{ + // if we were given a positive ID from the gamedb, we can choose to save/load only that type + // else, we save\load everything -- even if we used our knowledge of the current state to + // save only what was needed, we'd have to save that metadata as well for load + + // since we may get other people's crap, try to detect that here + char batteryramid[16]; + if (!isReader) + { + std::memcpy(batteryramid, "BIZVBANEXTBATTRY", 16); + } + NSS(batteryramid); + if (isReader) + { + if (std::memcmp(batteryramid, "BIZVBANEXTBATTRY", 16) != 0) + return false; + } + + switch (cpuSaveType) + { + default: + case 0: // auto + NSS(flashSaveMemory); + NSS(eepromData); + break; + case 1: + case 4: // eeprom + PSS(eepromData, eepromSize); + break; + case 2: // sram + // should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?), + // and for 64K flash where the program never issues any flash commands + PSS(flashSaveMemory, 0x10000); + break; + case 3: // flash + PSS(flashSaveMemory, flashSize); + break; + case 5: // none + break; + } + + return true; +} + Gigazoid() { Gigazoid_Init(); @@ -13320,25 +13159,31 @@ templatevoid SyncState(NewState *ns) { } - bool LoadRom(const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen) + bool LoadRom(const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings &settings) { if (biosfilelen != 16384) return false; - // todo: set cpuismultiboot if (!CPULoadRom(romfile, romfilelen)) return false; - // todo: populate these 4 variables from a syncsetting or a gamedb (vba_over.ini) - cpuSaveType = 0; - flashSize = 0x10000; - enableRtc = false; - mirroringEnable = false; + cpuSaveType = settings.cpuSaveType; + flashSize = settings.flashSize; + enableRtc = settings.enableRtc; + mirroringEnable = settings.mirroringEnable; + skipBios = settings.skipBios; + + if(flashSize == 0x10000) + { + flashDeviceID = 0x1b; + flashManufacturerID = 0x32; + } + else + { + flashDeviceID = 0x13; //0x09; + flashManufacturerID = 0x62; //0xc2; + } - if(flashSize == 0x10000 || flashSize == 0x20000) - flashSetSize(flashSize); - if(enableRtc) - rtcEnable(enableRtc); doMirroring(mirroringEnable); CPUInit(biosfile, biosfilelen); @@ -13396,9 +13241,9 @@ EXPORT void Destroy(Gigazoid *g) delete g; } -EXPORT int LoadRom(Gigazoid *g, const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen) +EXPORT int LoadRom(Gigazoid *g, const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings *settings) { - return g->LoadRom(romfile, romfilelen, biosfile, biosfilelen); + return g->LoadRom(romfile, romfilelen, biosfile, biosfilelen, *settings); } EXPORT void Reset(Gigazoid *g) @@ -13412,6 +13257,35 @@ EXPORT int FrameAdvance(Gigazoid *g, int input, u32 *videobuffer, s16 *audiobuff return g->FrameAdvance(input, videobuffer, audiobuffer, numsamp); } +EXPORT int SaveRamSize(Gigazoid *g) +{ + NewStateDummy dummy; + g->SyncBatteryRam(&dummy); + return dummy.GetLength(); +} + +EXPORT int SaveRamSave(Gigazoid *g, char *data, int length) +{ + NewStateExternalBuffer saver(data, length); + g->SyncBatteryRam(&saver); + return !saver.Overflow() && saver.GetLength() == length; +} + +EXPORT int SaveRamLoad(Gigazoid *g, const char *data, int length) +{ + NewStateExternalBuffer loader(const_cast(data), length); + if (g->SyncBatteryRam(&loader)) + { + return !loader.Overflow() && loader.GetLength() == length; + } + else + { + // couldn't find the magic signature at the top, so try a salvage load + g->LoadLegacyBatteryRam(reinterpret_cast(data), length); + return true; + } +} + EXPORT int BinStateSize(Gigazoid *g) { NewStateDummy dummy; diff --git a/vbanext/instance.h b/vbanext/instance.h index b0d58f4419..025f88336b 100644 --- a/vbanext/instance.h +++ b/vbanext/instance.h @@ -1,6 +1,15 @@ #ifndef INSTANCE_H #define INSTANCE_H +struct FrontEndSettings +{ + int cpuSaveType; // [0auto] 1eeprom 2sram 3flash 4eeprom+sensor 5none + int flashSize; // [0x10000] 0x20000 + int enableRtc; // [false] true + int mirroringEnable; // [false] true + int skipBios; // [false] true +}; + #define FLASH_128K_SZ 0x20000 #define EEPROM_IDLE 0