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