mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
PSFLoader improved
This commit is contained in:
parent
37b22ec99d
commit
b2111b3c3d
@ -24,16 +24,16 @@ public:
|
||||
|
||||
virtual u64 Write(const void* src, u64 size);
|
||||
|
||||
template<typename T> __forceinline bool Write(const T& data)
|
||||
template<typename T> __forceinline bool SWrite(const T& data, u64 size = sizeof(T))
|
||||
{
|
||||
return Write(&data, sizeof(T)) == sizeof(T);
|
||||
return Write(&data, size) == size;
|
||||
}
|
||||
|
||||
virtual u64 Read(void* dst, u64 size);
|
||||
|
||||
template<typename T> __forceinline bool Read(T& data)
|
||||
template<typename T> __forceinline bool SRead(T& data, u64 size = sizeof(T))
|
||||
{
|
||||
return Read(&data, sizeof(T)) == sizeof(T);
|
||||
return Read(&data, size) == size;
|
||||
}
|
||||
|
||||
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet);
|
||||
@ -41,4 +41,4 @@ public:
|
||||
virtual bool Eof();
|
||||
|
||||
virtual bool IsOpened() const;
|
||||
};
|
||||
};
|
||||
|
@ -311,6 +311,16 @@ __noinline s32 savedata_op(
|
||||
u32 userId,
|
||||
vm::ptr<CellSaveDataDoneCallback> funcDone)
|
||||
{
|
||||
// TODO: check arguments
|
||||
|
||||
// try to lock the mutex (not sure how it originally works; std::try_to_lock makes it non-blocking)
|
||||
std::unique_lock<std::mutex> lock(g_savedata_dialog->mutex, std::try_to_lock);
|
||||
|
||||
if (!lock)
|
||||
{
|
||||
return CELL_SAVEDATA_ERROR_BUSY;
|
||||
}
|
||||
|
||||
static const std::string base_dir = "/dev_hdd0/home/00000001/savedata/"; // TODO: Get the path of the current or specified user
|
||||
|
||||
vm::stackvar<CellSaveDataCBResult> result(CPU);
|
||||
@ -370,7 +380,7 @@ __noinline s32 savedata_op(
|
||||
save_entry.isNew = false;
|
||||
|
||||
save_entry.size = 0;
|
||||
for (const auto& entry2 : vfsDir(base_dir + entry->name))
|
||||
for (const auto entry2 : vfsDir(base_dir + entry->name))
|
||||
{
|
||||
save_entry.size += entry2->size;
|
||||
}
|
||||
|
@ -282,6 +282,8 @@ struct SaveDataEntry
|
||||
|
||||
struct SaveDataDialogInstance
|
||||
{
|
||||
std::mutex mutex;
|
||||
|
||||
SaveDataDialogInstance();
|
||||
virtual ~SaveDataDialogInstance() = default;
|
||||
};
|
||||
|
4
rpcs3/Gui/SaveDataDialog.cpp
Normal file
4
rpcs3/Gui/SaveDataDialog.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "stdafx_gui.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
||||
#include "SaveDataDialog.h"
|
9
rpcs3/Gui/SaveDataDialog.h
Normal file
9
rpcs3/Gui/SaveDataDialog.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/SysCalls/Modules/cellSaveData.h"
|
||||
|
||||
class SaveDataDialogFrame : public SaveDataDialogInstance
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
@ -5,66 +5,126 @@
|
||||
|
||||
bool PSFLoader::Load(vfsStream& stream)
|
||||
{
|
||||
Close();
|
||||
Clear();
|
||||
|
||||
// Load Header
|
||||
if (stream.Read(&m_header, sizeof(PSFHeader)) != sizeof(PSFHeader) || !m_header.CheckMagic())
|
||||
// load header
|
||||
if (!stream.SRead(m_header))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_psfindxs.resize(m_header.psf_entries_num);
|
||||
m_entries.resize(m_header.psf_entries_num);
|
||||
|
||||
// Load Indices
|
||||
for (u32 i = 0; i < m_header.psf_entries_num; ++i)
|
||||
// check magic
|
||||
if (m_header.magic != *(u32*)"\0PSF")
|
||||
{
|
||||
if (!stream.Read(m_psfindxs[i]))
|
||||
LOG_ERROR(LOADER, "PSFLoader::Load() failed: unknown magic (0x%x)", m_header.magic);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check version
|
||||
if (m_header.version != 0x101)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PSFLoader::Load() failed: unknown version (0x%x)", m_header.version);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load indices
|
||||
std::vector<PSFDefTable> indices;
|
||||
|
||||
indices.resize(m_header.entries_num);
|
||||
|
||||
if (!stream.SRead(indices[0], sizeof(PSFDefTable) * m_header.entries_num))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// load key table
|
||||
if (m_header.off_key_table > m_header.off_data_table)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PSFLoader::Load() failed: off_key_table=0x%x, off_data_table=0x%x", m_header.off_key_table, m_header.off_data_table);
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 key_table_size = m_header.off_data_table - m_header.off_key_table;
|
||||
|
||||
std::unique_ptr<char> keys(new char[key_table_size + 1]);
|
||||
|
||||
stream.Seek(m_header.off_key_table);
|
||||
|
||||
if (stream.Read(keys.get(), key_table_size) != key_table_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
keys.get()[key_table_size] = 0;
|
||||
|
||||
// fill entries
|
||||
m_entries.resize(m_header.entries_num);
|
||||
|
||||
for (u32 i = 0; i < m_header.entries_num; ++i)
|
||||
{
|
||||
m_entries[i].fmt = indices[i].param_fmt;
|
||||
|
||||
if (indices[i].key_off >= key_table_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_entries[i].fmt = m_psfindxs[i].psf_param_fmt;
|
||||
}
|
||||
m_entries[i].name = keys.get() + indices[i].key_off;
|
||||
|
||||
// Load Key Table
|
||||
for (u32 i = 0; i < m_header.psf_entries_num; ++i)
|
||||
{
|
||||
stream.Seek(m_header.psf_offset_key_table + m_psfindxs[i].psf_key_table_offset);
|
||||
// load data
|
||||
stream.Seek(m_header.off_data_table + indices[i].data_off);
|
||||
|
||||
int c_pos = 0;
|
||||
|
||||
while (c_pos < sizeof(m_entries[i].name) - 1)
|
||||
if (indices[i].param_fmt == PSF_PARAM_INT && indices[i].param_len == 4 && indices[i].param_max == 4)
|
||||
{
|
||||
char c;
|
||||
// load int data
|
||||
|
||||
if (!stream.Read(c) || !c)
|
||||
if (!stream.SRead(m_entries[i].vint))
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (indices[i].param_fmt == PSF_PARAM_STR && indices[i].param_max >= indices[i].param_len)
|
||||
{
|
||||
// load str data
|
||||
|
||||
const u32 size = indices[i].param_len;
|
||||
|
||||
std::unique_ptr<char> str(new char[size + 1]);
|
||||
|
||||
if (stream.Read(str.get(), size) != size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_entries[i].name[c_pos++] = c;
|
||||
str.get()[size] = 0;
|
||||
|
||||
m_entries[i].vstr = str.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "PSFLoader::Load() failed: (i=%d) fmt=0x%x, len=0x%x, max=0x%x", i, indices[i].param_fmt, indices[i].param_len, indices[i].param_max);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_entries[i].name[c_pos] = 0;
|
||||
}
|
||||
|
||||
// Load Data Table
|
||||
for (u32 i = 0; i < m_header.psf_entries_num; ++i)
|
||||
{
|
||||
stream.Seek(m_header.psf_offset_data_table + m_psfindxs[i].psf_data_tbl_offset);
|
||||
stream.Read(m_entries[i].param, m_psfindxs[i].psf_param_len);
|
||||
memset(m_entries[i].param + m_psfindxs[i].psf_param_len, 0, m_psfindxs[i].psf_param_max_len - m_psfindxs[i].psf_param_len);
|
||||
}
|
||||
|
||||
return (m_loaded = true);
|
||||
}
|
||||
|
||||
void PSFLoader::Close()
|
||||
bool PSFLoader::Save(vfsStream& stream)
|
||||
{
|
||||
// TODO: Construct m_header
|
||||
|
||||
m_loaded = true;
|
||||
|
||||
// TODO: Save data
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PSFLoader::Clear()
|
||||
{
|
||||
m_loaded = false;
|
||||
m_header = {};
|
||||
m_psfindxs.clear();
|
||||
m_entries.clear();
|
||||
}
|
||||
|
||||
@ -81,26 +141,61 @@ const PSFEntry* PSFLoader::SearchEntry(const std::string& key) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PSFEntry& PSFLoader::AddEntry(const std::string& key, u16 fmt)
|
||||
{
|
||||
for (auto& entry : m_entries)
|
||||
{
|
||||
if (key == entry.name)
|
||||
{
|
||||
entry.fmt = fmt;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
PSFEntry new_entry = {};
|
||||
new_entry.fmt = fmt;
|
||||
new_entry.name = key;
|
||||
m_entries.push_back(new_entry);
|
||||
|
||||
return m_entries.back();
|
||||
}
|
||||
|
||||
std::string PSFLoader::GetString(const std::string& key, std::string def) const
|
||||
{
|
||||
if (const auto entry = SearchEntry(key))
|
||||
{
|
||||
return entry->FormatString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return def;
|
||||
if (entry->fmt == PSF_PARAM_STR)
|
||||
{
|
||||
return entry->vstr;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
u32 PSFLoader::GetInteger(const std::string& key, u32 def) const
|
||||
s32 PSFLoader::GetInteger(const std::string& key, s32 def) const
|
||||
{
|
||||
if (const auto entry = SearchEntry(key))
|
||||
{
|
||||
return entry->FormatInteger();
|
||||
}
|
||||
else
|
||||
{
|
||||
return def;
|
||||
if (entry->fmt == PSF_PARAM_INT)
|
||||
{
|
||||
return entry->vint;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
void PSFLoader::SetString(const std::string& key, std::string value)
|
||||
{
|
||||
auto& entry = AddEntry(key, PSF_PARAM_STR);
|
||||
|
||||
entry.vstr = value;
|
||||
}
|
||||
|
||||
void PSFLoader::SetInteger(const std::string& key, s32 value)
|
||||
{
|
||||
auto& entry = AddEntry(key, PSF_PARAM_INT);
|
||||
|
||||
entry.vint = value;
|
||||
}
|
||||
|
@ -4,54 +4,42 @@ struct vfsStream;
|
||||
|
||||
struct PSFHeader
|
||||
{
|
||||
u32 psf_magic;
|
||||
u32 psf_version;
|
||||
u32 psf_offset_key_table;
|
||||
u32 psf_offset_data_table;
|
||||
u32 psf_entries_num;
|
||||
|
||||
bool CheckMagic() const { return psf_magic == *(u32*)"\0PSF"; }
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 off_key_table;
|
||||
u32 off_data_table;
|
||||
u32 entries_num;
|
||||
};
|
||||
|
||||
struct PSFDefTbl
|
||||
struct PSFDefTable
|
||||
{
|
||||
u16 psf_key_table_offset;
|
||||
u16 psf_param_fmt;
|
||||
u32 psf_param_len;
|
||||
u32 psf_param_max_len;
|
||||
u32 psf_data_tbl_offset;
|
||||
u16 key_off;
|
||||
u16 param_fmt;
|
||||
u32 param_len;
|
||||
u32 param_max;
|
||||
u32 data_off;
|
||||
};
|
||||
|
||||
enum : u16
|
||||
{
|
||||
PSF_PARAM_UNK = 0x0004,
|
||||
PSF_PARAM_STR = 0x0204,
|
||||
PSF_PARAM_INT = 0x0404,
|
||||
};
|
||||
|
||||
struct PSFEntry
|
||||
{
|
||||
char name[128];
|
||||
u16 fmt;
|
||||
char param[4096];
|
||||
std::string name;
|
||||
|
||||
std::string FormatString() const
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
default:
|
||||
case 0x0400:
|
||||
case 0x0402:
|
||||
return std::string(param);
|
||||
case 0x0404:
|
||||
return fmt::Format("0x%x", FormatInteger());
|
||||
}
|
||||
}
|
||||
|
||||
u32 FormatInteger() const
|
||||
{
|
||||
return *(u32*)param;
|
||||
}
|
||||
s32 vint;
|
||||
std::string vstr;
|
||||
};
|
||||
|
||||
class PSFLoader
|
||||
{
|
||||
bool m_loaded = false;
|
||||
PSFHeader m_header = {};
|
||||
std::vector<PSFDefTbl> m_psfindxs;
|
||||
std::vector<PSFEntry> m_entries;
|
||||
|
||||
public:
|
||||
@ -64,7 +52,9 @@ public:
|
||||
|
||||
bool Load(vfsStream& stream);
|
||||
|
||||
void Close();
|
||||
bool Save(vfsStream& stream);
|
||||
|
||||
void Clear();
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
@ -72,6 +62,14 @@ public:
|
||||
}
|
||||
|
||||
const PSFEntry* SearchEntry(const std::string& key) const;
|
||||
|
||||
PSFEntry& PSFLoader::AddEntry(const std::string& key, u16 type);
|
||||
|
||||
std::string GetString(const std::string& key, std::string def = "") const;
|
||||
u32 GetInteger(const std::string& key, u32 def = 0) const;
|
||||
|
||||
s32 GetInteger(const std::string& key, s32 def = 0) const;
|
||||
|
||||
void SetString(const std::string& key, std::string value);
|
||||
|
||||
void SetInteger(const std::string& key, s32 value);
|
||||
};
|
||||
|
@ -22,8 +22,8 @@
|
||||
#include "Emu/Io/XInput/XInputPadHandler.h"
|
||||
#endif
|
||||
|
||||
#include "Emu/SysCalls/Modules/cellMsgDialog.h"
|
||||
#include "Gui/MsgDialog.h"
|
||||
#include "Gui/SaveDataDialog.h"
|
||||
|
||||
#include "Gui/GLGSFrame.h"
|
||||
#include <wx/stdpaths.h>
|
||||
@ -41,9 +41,10 @@ wxDEFINE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent);
|
||||
IMPLEMENT_APP(Rpcs3App)
|
||||
Rpcs3App* TheApp;
|
||||
|
||||
std::string simplify_path(const std::string& path, bool is_dir);
|
||||
extern std::string simplify_path(const std::string& path, bool is_dir);
|
||||
|
||||
extern std::unique_ptr<MsgDialogInstance> g_msg_dialog;
|
||||
extern std::unique_ptr<SaveDataDialogInstance> g_savedata_dialog;
|
||||
|
||||
bool Rpcs3App::OnInit()
|
||||
{
|
||||
@ -137,6 +138,7 @@ bool Rpcs3App::OnInit()
|
||||
});
|
||||
|
||||
g_msg_dialog.reset(new MsgDialogFrame);
|
||||
g_savedata_dialog.reset(new SaveDataDialogFrame);
|
||||
|
||||
TheApp = this;
|
||||
SetAppName(_PRGNAME_);
|
||||
|
@ -183,6 +183,7 @@
|
||||
<ClCompile Include="Gui\MsgDialog.cpp" />
|
||||
<ClCompile Include="Gui\PADManager.cpp" />
|
||||
<ClCompile Include="Gui\RSXDebugger.cpp" />
|
||||
<ClCompile Include="Gui\SaveDataDialog.cpp" />
|
||||
<ClCompile Include="Gui\SaveDataUtility.cpp" />
|
||||
<ClCompile Include="Gui\TextInputDialog.cpp" />
|
||||
<ClCompile Include="Gui\VFSManager.cpp" />
|
||||
@ -224,6 +225,7 @@
|
||||
<ClInclude Include="Gui\MsgDialog.h" />
|
||||
<ClInclude Include="Gui\RegisterEditor.h" />
|
||||
<ClInclude Include="Gui\RSXDebugger.h" />
|
||||
<ClInclude Include="Gui\SaveDataDialog.h" />
|
||||
<ClInclude Include="Gui\SaveDataUtility.h" />
|
||||
<ClInclude Include="Gui\TextInputDialog.h" />
|
||||
<ClInclude Include="Gui\VFSManager.h" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Gui">
|
||||
@ -99,6 +99,9 @@
|
||||
<ClCompile Include="Gui\CgDisasm.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Gui\SaveDataDialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
@ -200,8 +203,8 @@
|
||||
<ClInclude Include="Gui\CgDisasm.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="git-version.h">
|
||||
<ClInclude Include="Gui\SaveDataDialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user