Closed skarab closed 5 months ago
I'm not the author of this sub module but i do believe that Blastem doesn't support flash saving, afaik no emulator support that feature still it's probably reasonable to ask the original author (@doragasu)
Ok. I just tested with Sonic 3 and the save slots works on Blastem. Will try to contact him.
I just wrote on it on Spritesmind, closing it here.
This is different from the sonic 3 save with is just f-ram but using the classic SRAM mapper, here it uses the flash EPROM to save game into it.
Oh ok, i misanderstood, so it's completly different of this https://huguesjohnson.com/programming/genesis/save-load/ ? Maybe I may try to use this.
Maybe I could just use your sram.h helper
Maybe I could just use your sram.h helper
Yeah, that's the API to use classic SRAM :)
Awesome it works fine with Blastem :)
Made helpers to load / save structs (32bits aligned) with a "checksum" test :
` bool smeSRAM_Load(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enableRO();
u32 checksum = SRAM_readLong(offset);
if (checksum == CHECKSUM)
{
for (i = 0; i < count; ++i)
{
dat[i] = SRAM_readLong(offset + 4 + (i << 2));
}
}
SRAM_disable();
SYS_enableInts();
return checksum == CHECKSUM;
}
void smeSRAM_Save(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enable();
SRAM_writeLong(offset, CHECKSUM);
for (i = 0; i < count; ++i)
{
SRAM_writeLong(offset + 4 + (i << 2), dat[i]);
}
SRAM_disable();
SYS_enableInts();
}`
will add real checksum at the end i think, but having header number is cool to detect if slot is free or not fastly.
`
bool smeSRAM_Load(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enableRO();
u32 magic_number = SRAM_readLong(offset);
u32 checksum = 0;
if (magic_number == MAGIC_NUMBER)
{
for (i = 0; i < count; ++i)
{
dat[i] = SRAM_readLong(offset + 4 + (i << 2));
checksum += dat[i];
}
}
u32 stored_checksum = SRAM_readLong(offset + 4 + (count << 2));
SRAM_disable();
SYS_enableInts();
return magic_number == MAGIC_NUMBER && stored_checksum == checksum;
}
void smeSRAM_Save(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enable();
SRAM_writeLong(offset, MAGIC_NUMBER);
u32 checksum = 0;
for (i = 0; i < count; ++i)
{
SRAM_writeLong(offset + 4 + (i << 2), dat[i]);
checksum += dat[i];
}
SRAM_writeLong(offset + 4 + (count << 2), checksum);
SRAM_disable();
SYS_enableInts();
}
bool smeSRAM_IsValid(u32 offset) { SYS_disableInts(); SRAM_enableRO(); u32 magic_number = SRAM_readLong(offset); SRAM_disable(); SYS_enableInts(); return magic_number == MAGIC_NUMBER; } `
then instead of offset, could be cool to have some api like the saveman, u32 slotId = AddSlot(u32 size), and base all this code on slots ids
A bit row but it seams to work :)
`
bool smeSRAM_Load(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 remaining = count >> 2 - length; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enableRO();
u32 magic_number = SRAM_readLong(offset);
u32 checksum = 0;
if (magic_number == MAGIC_NUMBER)
{
for (i = 0; i < count; ++i)
{
dat[i] = SRAM_readLong(offset + 4 + (i << 2));
checksum += dat[i];
}
}
u32 stored_checksum = SRAM_readLong(offset + 4 + (count << 2));
SRAM_disable();
SYS_enableInts();
return magic_number == MAGIC_NUMBER && stored_checksum == checksum;
}
void smeSRAM_Save(u32 offset, void data, u32 length) { u32 i; u32 count = length >> 2; u32 dat = (u32*)data;
SYS_disableInts();
SRAM_enable();
SRAM_writeLong(offset, MAGIC_NUMBER);
u32 checksum = 0;
for (i = 0; i < count; ++i)
{
SRAM_writeLong(offset + 4 + (i << 2), dat[i]);
checksum += dat[i];
}
SRAM_writeLong(offset + 4 + (count << 2), checksum);
SRAM_disable();
SYS_enableInts();
}
bool smeSRAM_IsValid(u32 offset) { SYS_disableInts(); SRAM_enableRO(); u32 magic_number = SRAM_readLong(offset); SRAM_disable(); SYS_enableInts(); return magic_number == MAGIC_NUMBER; }
void smeSRAM_Erase(u32 offset) { SYS_disableInts(); SRAM_enable(); SRAM_writeLong(offset, 0); SRAM_disable(); SYS_enableInts(); }
typedef struct { u32 offset; u32 size; } smeSRAMSlot;
smeSRAMSlot SRAMSlots[MAXIMUM_SLOT_COUNT]; u8 SRAMSlotCount = 0;
void smeSRAM_SLOTS_Initialize() { SRAMSlotCount = 0; }
u8 smeSRAM_SLOTS_Add(u32 size) { SRAMSlots[SRAMSlotCount].offset = SRAMSlotCount == 0 ? 0 : SRAMSlots[SRAMSlotCount - 1].offset + SRAMSlots[SRAMSlotCount - 1].size + 8; SRAMSlots[SRAMSlotCount].size = size; ++SRAMSlotCount; }
bool smeSRAM_SLOTS_Load(u8 slotId, void* data) { return smeSRAM_Load(SRAMSlots[slotId].offset, data, SRAMSlots[slotId].size); }
void smeSRAM_SLOTS_Save(u8 slotId, void* data) { smeSRAM_Save(SRAMSlots[slotId].offset, data, SRAMSlots[slotId].size); }
bool smeSRAM_SLOTS_IsValid(u8 slotId) { return smeSRAM_IsValid(SRAMSlots[slotId].offset); }
void smeSRAM_SLOTS_Erase(u8 slotId) { smeSRAM_Erase(SRAMSlots[slotId].offset); }
`
Hi, it looks like for you the issue is worked around by using SRAM save, but I will add a bit here for completeness.
The Flash save module uses a completely different mechanism to save data, taking advantage of the flash chips used in most carts released nowadays. Unfortunately AFAIK no emulator supports this as of today. For this to work on emulators, emulator devs need to emulate the flash chip commands. So this issue should be better reported to BlastEm! author.
Hi Doragasu, ok I understand now, should work well with recent flash cards. I added a msg on the SpritesMind forum. Anyway I'll stick on SRAM I think, will contact dragonbox later on (free digital game but would like to have cool box later). But... it looks an API supporting both may be created in SGDK :) Cheers
That could be great, Kusfo did something similar for his game Gotris on SEGA Master System, the game tries to initialize the Flash, and if it fails, falls back to SRAM (so it can save data on my flash-based FrugalMapper carts, but also on emulators).
Ok, I'll do this then. Awesome idea, and opens future doors.
Hello, as the title say the sample doesnt work with Blastem, I tried switching Blastem options but it does not work, am I missing something ? Regards