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:
SuuperW 2021-02-22 19:46:02 -06:00 committed by GitHub
parent 58dd1ec580
commit 94dcc9523e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 19 deletions

View File

@ -111,6 +111,10 @@ void DoSavestate(Savestate* file)
file->Var8(&StatusReg);
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)
@ -145,6 +149,7 @@ void LoadSave(const char* path, u32 type)
}
}
SRAMFileDirty = false;
NDSCart_SRAMManager::Setup(path, SRAM, SRAMLength);
switch (SRAMLength)

View File

@ -45,13 +45,9 @@ namespace NDSCart_SRAMManager
u32 FlushVersion;
void FlushThreadFunc();
void FlushSecondaryBufferToFile();
bool Init()
{
FlushThread = Platform::Thread_Create(FlushThreadFunc);
FlushThreadRunning = true;
SecondaryBufferLock = Platform::Mutex_Create();
return true;
@ -64,10 +60,11 @@ namespace NDSCart_SRAMManager
FlushThreadRunning = false;
Platform::Thread_Wait(FlushThread);
Platform::Thread_Free(FlushThread);
FlushSecondaryBufferToFile();
FlushSecondaryBuffer();
}
delete SecondaryBuffer;
if (SecondaryBuffer) delete SecondaryBuffer;
SecondaryBuffer = NULL;
Platform::Mutex_Free(SecondaryBufferLock);
}
@ -75,7 +72,7 @@ namespace NDSCart_SRAMManager
void Setup(const char* path, u8* buffer, u32 length)
{
// Flush SRAM in case there is unflushed data from previous state.
FlushSecondaryBufferToFile();
FlushSecondaryBuffer();
Platform::Mutex_Lock(SecondaryBufferLock);
@ -85,7 +82,7 @@ namespace NDSCart_SRAMManager
Buffer = buffer;
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];
SecondaryBufferLength = length;
@ -95,6 +92,12 @@ namespace NDSCart_SRAMManager
TimeAtLastFlushRequest = 0;
Platform::Mutex_Unlock(SecondaryBufferLock);
if (path[0] != '\0')
{
FlushThread = Platform::Thread_Create(FlushThreadFunc);
FlushThreadRunning = true;
}
}
void RequestFlush()
@ -121,27 +124,52 @@ namespace NDSCart_SRAMManager
continue;
}
FlushSecondaryBufferToFile();
FlushSecondaryBuffer();
}
}
void FlushSecondaryBufferToFile()
void FlushSecondaryBuffer(u8* dst, s32 dstLength)
{
if (FlushVersion == PreviousFlushVersion)
{
return;
}
// When flushing to a file, there's no point in re-writing the exact same data.
if (!dst && !NeedsFlush()) 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);
FILE* f = Platform::OpenFile(Path, "wb");
if (f)
if (dst)
{
printf("NDS SRAM: Written\n");
fwrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
fclose(f);
memcpy(dst, SecondaryBuffer, SecondaryBufferLength);
}
else
{
FILE* f = Platform::OpenFile(Path, "wb");
if (f)
{
printf("NDS SRAM: Written\n");
fwrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
fclose(f);
}
}
PreviousFlushVersion = FlushVersion;
TimeAtLastFlushRequest = 0;
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;
}
}

View File

@ -23,11 +23,17 @@
namespace NDSCart_SRAMManager
{
extern u32 SecondaryBufferLength;
bool Init();
void DeInit();
void Setup(const char* path, u8* buffer, u32 length);
void RequestFlush();
bool NeedsFlush();
void FlushSecondaryBuffer(u8* dst = NULL, s32 dstLength = 0);
void UpdateBuffer(u8* src, s32 srcLength);
}
#endif // NDSCART_SRAMMANAGER_H