mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-21 05:09:46 -06:00
SRAM things (#970)
* Allow SRAMManager to save to/load from a buffer. * Don't delete what doesn't exist. Don't create a thread that will do absolutely nothing. * Update SRAMManager's SecondaryBuffer when loading a savestate.
This commit is contained in:
@ -111,6 +111,10 @@ void DoSavestate(Savestate* file)
|
|||||||
|
|
||||||
file->Var8(&StatusReg);
|
file->Var8(&StatusReg);
|
||||||
file->Var32(&Addr);
|
file->Var32(&Addr);
|
||||||
|
|
||||||
|
// SRAMManager might now have an old buffer (or one from the future or alternate timeline!)
|
||||||
|
if (!file->Saving)
|
||||||
|
NDSCart_SRAMManager::RequestFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadSave(const char* path, u32 type)
|
void LoadSave(const char* path, u32 type)
|
||||||
@ -145,6 +149,7 @@ void LoadSave(const char* path, u32 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SRAMFileDirty = false;
|
||||||
NDSCart_SRAMManager::Setup(path, SRAM, SRAMLength);
|
NDSCart_SRAMManager::Setup(path, SRAM, SRAMLength);
|
||||||
|
|
||||||
switch (SRAMLength)
|
switch (SRAMLength)
|
||||||
|
@ -45,13 +45,9 @@ namespace NDSCart_SRAMManager
|
|||||||
u32 FlushVersion;
|
u32 FlushVersion;
|
||||||
|
|
||||||
void FlushThreadFunc();
|
void FlushThreadFunc();
|
||||||
void FlushSecondaryBufferToFile();
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
FlushThread = Platform::Thread_Create(FlushThreadFunc);
|
|
||||||
FlushThreadRunning = true;
|
|
||||||
|
|
||||||
SecondaryBufferLock = Platform::Mutex_Create();
|
SecondaryBufferLock = Platform::Mutex_Create();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -64,10 +60,11 @@ namespace NDSCart_SRAMManager
|
|||||||
FlushThreadRunning = false;
|
FlushThreadRunning = false;
|
||||||
Platform::Thread_Wait(FlushThread);
|
Platform::Thread_Wait(FlushThread);
|
||||||
Platform::Thread_Free(FlushThread);
|
Platform::Thread_Free(FlushThread);
|
||||||
FlushSecondaryBufferToFile();
|
FlushSecondaryBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete SecondaryBuffer;
|
if (SecondaryBuffer) delete SecondaryBuffer;
|
||||||
|
SecondaryBuffer = NULL;
|
||||||
|
|
||||||
Platform::Mutex_Free(SecondaryBufferLock);
|
Platform::Mutex_Free(SecondaryBufferLock);
|
||||||
}
|
}
|
||||||
@ -75,7 +72,7 @@ namespace NDSCart_SRAMManager
|
|||||||
void Setup(const char* path, u8* buffer, u32 length)
|
void Setup(const char* path, u8* buffer, u32 length)
|
||||||
{
|
{
|
||||||
// Flush SRAM in case there is unflushed data from previous state.
|
// Flush SRAM in case there is unflushed data from previous state.
|
||||||
FlushSecondaryBufferToFile();
|
FlushSecondaryBuffer();
|
||||||
|
|
||||||
Platform::Mutex_Lock(SecondaryBufferLock);
|
Platform::Mutex_Lock(SecondaryBufferLock);
|
||||||
|
|
||||||
@ -85,7 +82,7 @@ namespace NDSCart_SRAMManager
|
|||||||
Buffer = buffer;
|
Buffer = buffer;
|
||||||
Length = length;
|
Length = length;
|
||||||
|
|
||||||
delete SecondaryBuffer; // Delete secondary buffer, there might be previous state.
|
if(SecondaryBuffer) delete SecondaryBuffer; // Delete secondary buffer, there might be previous state.
|
||||||
|
|
||||||
SecondaryBuffer = new u8[length];
|
SecondaryBuffer = new u8[length];
|
||||||
SecondaryBufferLength = length;
|
SecondaryBufferLength = length;
|
||||||
@ -95,6 +92,12 @@ namespace NDSCart_SRAMManager
|
|||||||
TimeAtLastFlushRequest = 0;
|
TimeAtLastFlushRequest = 0;
|
||||||
|
|
||||||
Platform::Mutex_Unlock(SecondaryBufferLock);
|
Platform::Mutex_Unlock(SecondaryBufferLock);
|
||||||
|
|
||||||
|
if (path[0] != '\0')
|
||||||
|
{
|
||||||
|
FlushThread = Platform::Thread_Create(FlushThreadFunc);
|
||||||
|
FlushThreadRunning = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestFlush()
|
void RequestFlush()
|
||||||
@ -121,27 +124,52 @@ namespace NDSCart_SRAMManager
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlushSecondaryBufferToFile();
|
FlushSecondaryBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushSecondaryBufferToFile()
|
void FlushSecondaryBuffer(u8* dst, s32 dstLength)
|
||||||
{
|
{
|
||||||
if (FlushVersion == PreviousFlushVersion)
|
// When flushing to a file, there's no point in re-writing the exact same data.
|
||||||
{
|
if (!dst && !NeedsFlush()) return;
|
||||||
return;
|
// When flushing to memory, we don't know if dst already has any data so we only check that we CAN flush.
|
||||||
}
|
if (dst && dstLength < SecondaryBufferLength) return;
|
||||||
|
|
||||||
Platform::Mutex_Lock(SecondaryBufferLock);
|
Platform::Mutex_Lock(SecondaryBufferLock);
|
||||||
FILE* f = Platform::OpenFile(Path, "wb");
|
if (dst)
|
||||||
if (f)
|
|
||||||
{
|
{
|
||||||
printf("NDS SRAM: Written\n");
|
memcpy(dst, SecondaryBuffer, SecondaryBufferLength);
|
||||||
fwrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
|
}
|
||||||
fclose(f);
|
else
|
||||||
|
{
|
||||||
|
FILE* f = Platform::OpenFile(Path, "wb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
printf("NDS SRAM: Written\n");
|
||||||
|
fwrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PreviousFlushVersion = FlushVersion;
|
PreviousFlushVersion = FlushVersion;
|
||||||
TimeAtLastFlushRequest = 0;
|
TimeAtLastFlushRequest = 0;
|
||||||
Platform::Mutex_Unlock(SecondaryBufferLock);
|
Platform::Mutex_Unlock(SecondaryBufferLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NeedsFlush()
|
||||||
|
{
|
||||||
|
return FlushVersion != PreviousFlushVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateBuffer(u8* src, s32 srcLength)
|
||||||
|
{
|
||||||
|
if (!src || srcLength != Length) return;
|
||||||
|
|
||||||
|
// should we create a lock for the primary buffer? this method is not intended to be called from a secondary thread in the way Flush is
|
||||||
|
memcpy(Buffer, src, srcLength);
|
||||||
|
Platform::Mutex_Lock(SecondaryBufferLock);
|
||||||
|
memcpy(SecondaryBuffer, src, srcLength);
|
||||||
|
Platform::Mutex_Unlock(SecondaryBufferLock);
|
||||||
|
|
||||||
|
PreviousFlushVersion = FlushVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,17 @@
|
|||||||
|
|
||||||
namespace NDSCart_SRAMManager
|
namespace NDSCart_SRAMManager
|
||||||
{
|
{
|
||||||
|
extern u32 SecondaryBufferLength;
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
void Setup(const char* path, u8* buffer, u32 length);
|
void Setup(const char* path, u8* buffer, u32 length);
|
||||||
void RequestFlush();
|
void RequestFlush();
|
||||||
|
|
||||||
|
bool NeedsFlush();
|
||||||
|
void FlushSecondaryBuffer(u8* dst = NULL, s32 dstLength = 0);
|
||||||
|
void UpdateBuffer(u8* src, s32 srcLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NDSCART_SRAMMANAGER_H
|
#endif // NDSCART_SRAMMANAGER_H
|
Reference in New Issue
Block a user