PSFLoader improved

This commit is contained in:
Nekotekina 2015-04-16 18:33:55 +03:00
parent 37b22ec99d
commit b2111b3c3d
10 changed files with 216 additions and 91 deletions

View File

@ -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;
};
};

View File

@ -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;
}

View File

@ -282,6 +282,8 @@ struct SaveDataEntry
struct SaveDataDialogInstance
{
std::mutex mutex;
SaveDataDialogInstance();
virtual ~SaveDataDialogInstance() = default;
};

View File

@ -0,0 +1,4 @@
#include "stdafx_gui.h"
#include "Emu/Memory/Memory.h"
#include "SaveDataDialog.h"

View File

@ -0,0 +1,9 @@
#pragma once
#include "Emu/SysCalls/Modules/cellSaveData.h"
class SaveDataDialogFrame : public SaveDataDialogInstance
{
public:
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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_);

View File

@ -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" />

View File

@ -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>