From db77b52caa38142cfe5ccc7897c7f7bb42de678e Mon Sep 17 00:00:00 2001 From: Kentucky Compass Date: Sat, 28 Dec 2013 23:43:02 -0800 Subject: [PATCH] Save/restore local file handles and seek positions --- Core/FileSystems/DirectoryFileSystem.cpp | 59 ++++++++++++++++++++++-- Core/FileSystems/DirectoryFileSystem.h | 4 ++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 02782b3e4e..655c37ff45 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -303,10 +303,16 @@ DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string hAlloc = _hAlloc; } -DirectoryFileSystem::~DirectoryFileSystem() { +void DirectoryFileSystem::CloseAll() { for (auto iter = entries.begin(); iter != entries.end(); ++iter) { iter->second.hFile.Close(); } + + entries.clear(); +} + +DirectoryFileSystem::~DirectoryFileSystem() { + CloseAll(); } std::string DirectoryFileSystem::GetLocalPath(std::string localpath) { @@ -466,6 +472,10 @@ u32 DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const #endif u32 newHandle = hAlloc->GetNewHandle(); + + entry.guestFilename = filename; + entry.access = access; + entries[newHandle] = entry; return newHandle; @@ -672,9 +682,50 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { } void DirectoryFileSystem::DoState(PointerWrap &p) { - if (!entries.empty()) { - p.SetError(p.ERROR_WARNING); - ERROR_LOG(FILESYS, "FIXME: Open files during savestate, could go badly."); + auto s = p.Section("DirectoryFileSystem", 0, 1); + if (!s) + return; + + // Savestate layout: + // u32: number of entries + // per-entry: + // u32: handle number + // std::string filename (in guest's terms, untranslated) + // enum FileAccess file access mode + // u32 seek position + + u32 num = (u32) entries.size(); + p.Do(num); + + if (p.mode == p.MODE_READ) { + CloseAll(); + u32 key; + OpenFileEntry entry; + for (u32 i = 0; i < num; i++) { + p.Do(key); + p.Do(entry.guestFilename); + p.Do(entry.access); + if (! entry.hFile.Open(basePath,entry.guestFilename,entry.access)) { + ERROR_LOG(FILESYS, "Failed to reopen file while loading state: %s", entry.guestFilename.c_str()); + continue; + } + u32 position; + p.Do(position); + if (position != entry.hFile.Seek(position, FILEMOVE_BEGIN)) { + ERROR_LOG(FILESYS, "Failed to restore seek position while loading state: %s", entry.guestFilename.c_str()); + continue; + } + entries[key] = entry; + } + } else { + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { + u32 key = iter->first; + p.Do(key); + p.Do(iter->second.guestFilename); + p.Do(iter->second.access); + u32 position = iter->second.hFile.Seek(0, FILEMOVE_CURRENT); + p.Do(position); + } } } diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 9a669a639d..71e43b1800 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -86,6 +86,8 @@ public: DirectoryFileSystem(IHandleAllocator *_hAlloc, std::string _basePath); ~DirectoryFileSystem(); + void CloseAll(); + void DoState(PointerWrap &p); std::vector GetDirListing(std::string path); u32 OpenFile(std::string filename, FileAccess access, const char *devicename=NULL); @@ -107,6 +109,8 @@ public: private: struct OpenFileEntry { DirectoryFileHandle hFile; + std::string guestFilename; + FileAccess access; }; typedef std::map EntryMap;