From c4ba7e51e5160d06d8ce7f6c06da28ce64e1a1ed Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Mon, 29 Dec 2014 15:11:24 -0800 Subject: [PATCH] GCI folder: flush 1 second after last block is written --- Source/Core/Core/HW/GCMemcardDirectory.cpp | 68 ++++++++++++++++++---- Source/Core/Core/HW/GCMemcardDirectory.h | 8 ++- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/HW/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcardDirectory.cpp index a01f70bad1..7415ea3e3e 100644 --- a/Source/Core/Core/HW/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcardDirectory.cpp @@ -2,9 +2,10 @@ // Licensed under GPLv2 // Refer to the license.txt file included. #include - #include "Common/CommonTypes.h" #include "Common/FileSearch.h" +#include "Common/StdMakeUnique.h" +#include "Common/Thread.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/HW/GCMemcardDirectory.h" @@ -132,13 +133,14 @@ int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::IVolume::EC } GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u16 sizeMb, bool ascii, DiscIO::IVolume::ECountry card_region, int gameId) -: MemoryCardBase(slot, sizeMb) -, m_GameId(gameId) -, m_LastBlock(-1) -, m_hdr(slot, sizeMb, ascii) -, m_bat1(sizeMb) -, m_saves(0) -, m_SaveDirectory(directory) + : MemoryCardBase(slot, sizeMb) + , m_GameId(gameId) + , m_LastBlock(-1) + , m_hdr(slot, sizeMb, ascii) + , m_bat1(sizeMb) + , m_saves(0) + , m_SaveDirectory(directory) + , m_exiting(false) { // Use existing header data if available if (File::Exists(m_SaveDirectory + MC_HDR)) @@ -186,10 +188,51 @@ GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u m_dir1.fixChecksums(); m_dir2 = m_dir1; m_bat2 = m_bat1; + + m_flush_thread = std::thread(&GCMemcardDirectory::FlushThread, this); +} + +void GCMemcardDirectory::FlushThread() +{ + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableMemcardSaving) + { + return; + } + + + Common::SetCurrentThreadName( + StringFromFormat("Memcard%x-Flush", card_index).c_str()); + + while (true) + { + // no-op until signalled + m_flush_trigger.Wait(); + + if (m_exiting) + { + m_exiting = false; + return; + } + // no-op as long as signalled within flush_interval + while (m_flush_trigger.WaitFor(flush_interval)) + { + if (m_exiting) + { + m_exiting = false; + return; + } + } + + FlushToFile(); + } } GCMemcardDirectory::~GCMemcardDirectory() { + m_exiting = true; + m_flush_trigger.Set(); + m_flush_thread.join(); + FlushToFile(); } @@ -253,6 +296,7 @@ s32 GCMemcardDirectory::Read(u32 address, s32 length, u8 *destaddress) s32 GCMemcardDirectory::Write(u32 destaddress, s32 length, u8 *srcaddress) { + std::unique_lock l(m_write_mutex); if (length != 0x80) INFO_LOG(EXPANSIONINTERFACE, "WRITING TO %x, len %x", destaddress, length); s32 block = destaddress / BLOCK_SIZE; @@ -266,9 +310,8 @@ s32 GCMemcardDirectory::Write(u32 destaddress, s32 length, u8 *srcaddress) // verify that we haven't calculated a length beyond BLOCK_SIZE _dbg_assert_msg_(EXPANSIONINTERFACE, (destaddress + length) % BLOCK_SIZE == 0, - "Memcard directory Write Logic Error"); + "Memcard directory Write Logic Error"); } - if (m_LastBlock != block) { switch (block) @@ -310,8 +353,11 @@ s32 GCMemcardDirectory::Write(u32 destaddress, s32 length, u8 *srcaddress) memcpy(m_LastBlockAddress + offset, srcaddress, length); + l.unlock(); if (extra) extra = Write(destaddress + length, extra, srcaddress + length); + if (offset + length == BLOCK_SIZE) + m_flush_trigger.Set(); return length + extra; } @@ -506,6 +552,7 @@ bool GCMemcardDirectory::SetUsedBlocks(int saveIndex) void GCMemcardDirectory::FlushToFile() { + std::unique_lock l(m_write_mutex); int errors = 0; DEntry invalid; for (u16 i = 0; i < m_saves.size(); ++i) @@ -585,6 +632,7 @@ void GCMemcardDirectory::FlushToFile() void GCMemcardDirectory::DoState(PointerWrap &p) { + std::unique_lock l(m_write_mutex); m_LastBlock = -1; m_LastBlockAddress = nullptr; p.Do(m_SaveDirectory); diff --git a/Source/Core/Core/HW/GCMemcardDirectory.h b/Source/Core/Core/HW/GCMemcardDirectory.h index 3d0425e1b1..1273ffbd4e 100644 --- a/Source/Core/Core/HW/GCMemcardDirectory.h +++ b/Source/Core/Core/HW/GCMemcardDirectory.h @@ -4,6 +4,7 @@ #pragma once +#include "Common/Event.h" #include "Core/HW/GCMemcard.h" #include "DiscIO/Volume.h" @@ -18,7 +19,7 @@ public: DiscIO::IVolume::ECountry card_region = DiscIO::IVolume::COUNTRY_EUROPE, int gameId = 0); ~GCMemcardDirectory(); void FlushToFile(); - + void FlushThread(); s32 Read(u32 address, s32 length, u8 *destaddress) override; s32 Write(u32 destaddress, s32 length, u8 *srcaddress) override; void ClearBlock(u32 address) override; @@ -44,4 +45,9 @@ private: std::vector m_loaded_saves; std::string m_SaveDirectory; + const std::chrono::seconds flush_interval = std::chrono::seconds(1); + Common::Event m_flush_trigger; + std::mutex m_write_mutex; + std::atomic m_exiting; + std::thread m_flush_thread; };