Skip to content

Commit

Permalink
HostFS: Retain File Handles in Save States
Browse files Browse the repository at this point in the history
[SAVEVERSION+]
Save file handle information in save states, and reopen handles when states are loaded.
  • Loading branch information
pips3 authored and F0bes committed Oct 7, 2024
1 parent 68678ac commit bba85dc
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
87 changes: 87 additions & 0 deletions pcsx2/IopBios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,16 @@ namespace R3000A
}
};

struct fileHandle
{
u32 fd_index;
std::string full_path;
s32 flags;
u16 mode;
};

std::vector<fileHandle> handles;

namespace ioman
{
const int firstfd = 0x100;
Expand Down Expand Up @@ -515,6 +525,7 @@ namespace R3000A
if (fds[i])
fds[i].close();
}
handles.clear();
}

bool is_host(const std::string_view path)
Expand Down Expand Up @@ -604,6 +615,13 @@ namespace R3000A
file->close();
}

fileHandle handle;
handle.fd_index = v0 - firstfd;
handle.flags = flags;
handle.full_path = path;
handle.mode = mode;
handles.push_back(handle);

pc = ra;
return 1;
}
Expand All @@ -618,6 +636,16 @@ namespace R3000A
if (getfd<IOManFile>(fd))
{
freefd(fd);

for (size_t i = 0; i < handles.size(); i++)
{
if (handles[i].fd_index == (u32) fd - firstfd)
{
handles.erase(handles.begin() + i);
break;
}
}

v0 = 0;
pc = ra;
return 1;
Expand Down Expand Up @@ -1387,3 +1415,62 @@ namespace R3000A
}

} // end namespace R3000A

bool SaveStateBase::handleFreeze()
{
if (!EmuConfig.HostFs) //if hostfs isn't enabled, skip loading/saving file handles
return IsOkay();

if (IsLoading())
R3000A::ioman::reset();

if (!FreezeTag("hostHandles"))
return false;

const int firstfd = R3000A::ioman::firstfd;
size_t handleCount = R3000A::handles.size();
Freeze(handleCount);

for (size_t i = 0; i < handleCount; i++)
{
if (IsLoading())
{
//load the parameters for opening the file
s32 pos;
Freeze(pos);

R3000A::fileHandle handle;
Freeze(handle.flags);
FreezeString(handle.full_path);
Freeze(handle.mode);
R3000A::handles.push_back(handle);

//reopen the file
IOManFile* file = NULL;
R3000A::HostFile::open(&file, handle.full_path, handle.flags, handle.mode);
if (!file)
{
Console.Warning("Failed to open file: '%s'", handle.full_path.c_str());
continue;
}
R3000A::handles[i].fd_index = R3000A::ioman::allocfd(file) - firstfd;

//seek file to position when saved
file->lseek(pos, SEEK_SET);
}
else
{
//save the current file position
const u32 fd = R3000A::handles[i].fd_index;
IOManFile* file = R3000A::ioman::getfd<IOManFile>(fd + firstfd);
s32 pos = file->lseek(0, SEEK_CUR);
Freeze(pos);

//save the parameters for opening the file
Freeze(R3000A::handles[i].flags);
FreezeString(R3000A::handles[i].full_path);
Freeze(R3000A::handles[i].mode);
}
}
return IsOkay();
}
2 changes: 2 additions & 0 deletions pcsx2/SaveState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ bool SaveStateBase::FreezeInternals(Error* error)

okay = okay && InputRecordingFreeze();

okay = okay && handleFreeze(); //file handles

return okay;
}

Expand Down
3 changes: 2 additions & 1 deletion pcsx2/SaveState.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.

static const u32 g_SaveVersion = (0x9A4F << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A50 << 16) | 0x0000;


// the freezing data between submodules and core
Expand Down Expand Up @@ -211,6 +211,7 @@ class SaveStateBase
bool cdvdFreeze();
bool psxRcntFreeze();
bool deci2Freeze();
bool handleFreeze();

// Save or load PCSX2's global frame counter (g_FrameCount) along with each savestate
//
Expand Down

0 comments on commit bba85dc

Please sign in to comment.