mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 00:11:24 +12:00
PSFLoader improved
This commit is contained in:
parent
00205bfa58
commit
37b22ec99d
11 changed files with 174 additions and 186 deletions
|
@ -23,8 +23,19 @@ public:
|
||||||
virtual u64 GetSize();
|
virtual u64 GetSize();
|
||||||
|
|
||||||
virtual u64 Write(const void* src, u64 size);
|
virtual u64 Write(const void* src, u64 size);
|
||||||
|
|
||||||
|
template<typename T> __forceinline bool Write(const T& data)
|
||||||
|
{
|
||||||
|
return Write(&data, sizeof(T)) == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
virtual u64 Read(void* dst, u64 size);
|
virtual u64 Read(void* dst, u64 size);
|
||||||
|
|
||||||
|
template<typename T> __forceinline bool Read(T& data)
|
||||||
|
{
|
||||||
|
return Read(&data, sizeof(T)) == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet);
|
virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet);
|
||||||
virtual u64 Tell() const;
|
virtual u64 Tell() const;
|
||||||
virtual bool Eof();
|
virtual bool Eof();
|
||||||
|
|
|
@ -17,13 +17,16 @@ std::string contentInfo = "";
|
||||||
std::string usrdir = "";
|
std::string usrdir = "";
|
||||||
bool path_set = false;
|
bool path_set = false;
|
||||||
|
|
||||||
s32 cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
|
s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::ptr<const char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
|
||||||
{
|
{
|
||||||
cellGame.Warning("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
cellGame.Warning("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
||||||
|
|
||||||
std::string dir = dirName.get_ptr();
|
std::string dir = dirName.get_ptr();
|
||||||
|
|
||||||
if (dir.size() != 9)
|
if (dir.size() != 9)
|
||||||
|
{
|
||||||
return CELL_HDDGAME_ERROR_PARAM;
|
return CELL_HDDGAME_ERROR_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
vm::var<CellHddGameSystemFileParam> param;
|
vm::var<CellHddGameSystemFileParam> param;
|
||||||
vm::var<CellHddGameCBResult> result;
|
vm::var<CellHddGameCBResult> result;
|
||||||
|
@ -37,20 +40,19 @@ s32 cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm
|
||||||
get->ctime = 0; // TODO
|
get->ctime = 0; // TODO
|
||||||
get->mtime = 0; // TODO
|
get->mtime = 0; // TODO
|
||||||
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
|
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
|
||||||
memcpy(get->contentInfoPath, ("/dev_hdd0/game/" + dir).c_str(), CELL_HDDGAME_PATH_MAX);
|
strcpy_trunc(get->contentInfoPath, "/dev_hdd0/game/" + dir);
|
||||||
memcpy(get->hddGamePath, ("/dev_hdd0/game/" + dir + "/USRDIR").c_str(), CELL_HDDGAME_PATH_MAX);
|
strcpy_trunc(get->hddGamePath, "/dev_hdd0/game/" + dir + "/USRDIR");
|
||||||
|
|
||||||
if (!Emu.GetVFS().ExistsDir(("/dev_hdd0/game/" + dir).c_str()))
|
if (!Emu.GetVFS().ExistsDir("/dev_hdd0/game/" + dir))
|
||||||
{
|
{
|
||||||
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
|
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
|
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
|
||||||
|
const PSFLoader psf(vfsFile("/dev_hdd0/game/" + dir + "/PARAM.SFO"));
|
||||||
vfsFile f(("/dev_hdd0/game/" + dir + "/PARAM.SFO").c_str());
|
if (!psf)
|
||||||
PSFLoader psf(f);
|
{
|
||||||
if (!psf.Load(false)) {
|
|
||||||
return CELL_HDDGAME_ERROR_BROKEN;
|
return CELL_HDDGAME_ERROR_BROKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +66,8 @@ s32 cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm
|
||||||
strcpy_trunc(get->getParam.dataVersion, app_ver);
|
strcpy_trunc(get->getParam.dataVersion, app_ver);
|
||||||
strcpy_trunc(get->getParam.titleId, dir);
|
strcpy_trunc(get->getParam.titleId, dir);
|
||||||
|
|
||||||
for (u32 i = 0; i<CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) {
|
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
|
||||||
|
{
|
||||||
char key[16];
|
char key[16];
|
||||||
sprintf(key, "TITLE_%02d", i);
|
sprintf(key, "TITLE_%02d", i);
|
||||||
title = psf.GetString(key);
|
title = psf.GetString(key);
|
||||||
|
@ -76,10 +79,10 @@ s32 cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm
|
||||||
|
|
||||||
//funcStat(result, get, set);
|
//funcStat(result, get, set);
|
||||||
|
|
||||||
if (result->result != CELL_HDDGAME_CBRESULT_OK &&
|
//if (result->result != CELL_HDDGAME_CBRESULT_OK && result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
|
||||||
result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL) {
|
//{
|
||||||
return CELL_HDDGAME_ERROR_CBRESULT;
|
// return CELL_HDDGAME_ERROR_CBRESULT;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// TODO ?
|
// TODO ?
|
||||||
|
|
||||||
|
@ -100,15 +103,8 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
|
||||||
size->sysSizeKB = 0;
|
size->sysSizeKB = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfsFile f("/app_home/../PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
if (!f.IsOpened())
|
if (!psf)
|
||||||
{
|
|
||||||
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
|
|
||||||
return CELL_GAME_ERROR_ACCESS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSFLoader psf(f);
|
|
||||||
if (!psf.Load(false))
|
|
||||||
{
|
{
|
||||||
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
|
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
|
||||||
return CELL_GAME_ERROR_ACCESS_ERROR;
|
return CELL_GAME_ERROR_ACCESS_ERROR;
|
||||||
|
@ -167,15 +163,8 @@ s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved
|
||||||
size->sysSizeKB = 0;
|
size->sysSizeKB = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfsFile f("/app_home/../PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
if (!f.IsOpened())
|
if (!psf)
|
||||||
{
|
|
||||||
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot open PARAM.SFO)");
|
|
||||||
return CELL_GAME_ERROR_ACCESS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSFLoader psf(f);
|
|
||||||
if (!psf.Load(false))
|
|
||||||
{
|
{
|
||||||
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
|
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
|
||||||
return CELL_GAME_ERROR_ACCESS_ERROR;
|
return CELL_GAME_ERROR_ACCESS_ERROR;
|
||||||
|
@ -301,15 +290,8 @@ s32 cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr<const char> di
|
||||||
return CELL_GAMEDATA_RET_OK;
|
return CELL_GAMEDATA_RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfsFile f(dir + "/PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
if (!f.IsOpened())
|
if (!psf)
|
||||||
{
|
|
||||||
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot open PARAM.SFO)");
|
|
||||||
return CELL_GAMEDATA_ERROR_BROKEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSFLoader psf(f);
|
|
||||||
if (!psf.Load(false))
|
|
||||||
{
|
{
|
||||||
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
|
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
|
||||||
return CELL_GAMEDATA_ERROR_BROKEN;
|
return CELL_GAMEDATA_ERROR_BROKEN;
|
||||||
|
@ -437,10 +419,11 @@ s32 cellGameGetParamInt(u32 id, vm::ptr<u32> value)
|
||||||
cellGame.Warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value);
|
cellGame.Warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value);
|
||||||
|
|
||||||
// TODO: Access through cellGame***Check functions
|
// TODO: Access through cellGame***Check functions
|
||||||
vfsFile f("/app_home/../PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
PSFLoader psf(f);
|
if (!psf)
|
||||||
if(!psf.Load(false))
|
{
|
||||||
return CELL_GAME_ERROR_FAILURE;
|
return CELL_GAME_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
|
@ -460,10 +443,11 @@ s32 cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
|
||||||
cellGame.Warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
|
cellGame.Warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
|
||||||
|
|
||||||
// TODO: Access through cellGame***Check functions
|
// TODO: Access through cellGame***Check functions
|
||||||
vfsFile f("/app_home/../PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
PSFLoader psf(f);
|
if (!psf)
|
||||||
if(!psf.Load(false))
|
{
|
||||||
return CELL_GAME_ERROR_FAILURE;
|
return CELL_GAME_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
std::string data;
|
std::string data;
|
||||||
switch(id)
|
switch(id)
|
||||||
|
|
|
@ -18,10 +18,6 @@ MsgDialogInstance::MsgDialogInstance()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgDialogInstance::~MsgDialogInstance()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MsgDialogInstance::Close()
|
void MsgDialogInstance::Close()
|
||||||
{
|
{
|
||||||
state = msgDialogClose;
|
state = msgDialogClose;
|
||||||
|
|
|
@ -99,7 +99,7 @@ struct MsgDialogInstance
|
||||||
u32 progress_bar_count = 0;
|
u32 progress_bar_count = 0;
|
||||||
|
|
||||||
MsgDialogInstance();
|
MsgDialogInstance();
|
||||||
virtual ~MsgDialogInstance();
|
virtual ~MsgDialogInstance() = default;
|
||||||
|
|
||||||
virtual void Close();
|
virtual void Close();
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
|
|
||||||
extern Module cellSysutil;
|
extern Module cellSysutil;
|
||||||
|
|
||||||
|
std::unique_ptr<SaveDataDialogInstance> g_savedata_dialog;
|
||||||
|
|
||||||
|
SaveDataDialogInstance::SaveDataDialogInstance()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Auxiliary Classes
|
// Auxiliary Classes
|
||||||
class SortSaveDataEntry
|
class SortSaveDataEntry
|
||||||
{
|
{
|
||||||
|
@ -66,21 +72,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auxiliary Functions
|
// Auxiliary Functions
|
||||||
u64 get_save_data_size(const std::string& dir)
|
|
||||||
{
|
|
||||||
u64 result = 0;
|
|
||||||
|
|
||||||
for (const auto entry : vfsDir(dir))
|
|
||||||
{
|
|
||||||
if ((entry->flags & DirEntry_TypeMask) == DirEntry_TypeFile)
|
|
||||||
{
|
|
||||||
result += entry->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addNewSaveDataEntry(std::vector<SaveDataEntry>& saveEntries, vm::ptr<CellSaveDataListNewData> newData)
|
void addNewSaveDataEntry(std::vector<SaveDataEntry>& saveEntries, vm::ptr<CellSaveDataListNewData> newData)
|
||||||
{
|
{
|
||||||
SaveDataEntry saveEntry;
|
SaveDataEntry saveEntry;
|
||||||
|
@ -158,7 +149,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr<CellSaveDataStatGet> statGet)
|
||||||
statGet->isNewData = CELL_SAVEDATA_ISNEWDATA_NO;
|
statGet->isNewData = CELL_SAVEDATA_ISNEWDATA_NO;
|
||||||
|
|
||||||
statGet->bind = 0; // TODO ?
|
statGet->bind = 0; // TODO ?
|
||||||
statGet->sizeKB = entry.sizeKB;
|
statGet->sizeKB = entry.size / 1024;
|
||||||
statGet->hddFreeSizeKB = 40000000; // 40 GB. TODO ?
|
statGet->hddFreeSizeKB = 40000000; // 40 GB. TODO ?
|
||||||
statGet->sysSizeKB = 0; // TODO: This is the size of PARAM.SFO + PARAM.PDF
|
statGet->sysSizeKB = 0; // TODO: This is the size of PARAM.SFO + PARAM.PDF
|
||||||
statGet->dir.st_atime_ = 0; // TODO ?
|
statGet->dir.st_atime_ = 0; // TODO ?
|
||||||
|
@ -358,9 +349,8 @@ __noinline s32 savedata_op(
|
||||||
listGet->dirNum++;
|
listGet->dirNum++;
|
||||||
|
|
||||||
// PSF parameters
|
// PSF parameters
|
||||||
vfsFile f(base_dir + entry->name + "/PARAM.SFO");
|
const PSFLoader psf(vfsFile(base_dir + entry->name + "/PARAM.SFO"));
|
||||||
PSFLoader psf(f);
|
if (!psf)
|
||||||
if (!psf.Load(false))
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +361,7 @@ __noinline s32 savedata_op(
|
||||||
save_entry.title = psf.GetString("TITLE");
|
save_entry.title = psf.GetString("TITLE");
|
||||||
save_entry.subtitle = psf.GetString("SUB_TITLE");
|
save_entry.subtitle = psf.GetString("SUB_TITLE");
|
||||||
save_entry.details = psf.GetString("DETAIL");
|
save_entry.details = psf.GetString("DETAIL");
|
||||||
save_entry.sizeKB = get_save_data_size(base_dir + entry->name) / 1024;
|
|
||||||
save_entry.atime = entry->access_time;
|
save_entry.atime = entry->access_time;
|
||||||
save_entry.mtime = entry->modify_time;
|
save_entry.mtime = entry->modify_time;
|
||||||
save_entry.ctime = entry->create_time;
|
save_entry.ctime = entry->create_time;
|
||||||
|
@ -379,6 +369,12 @@ __noinline s32 savedata_op(
|
||||||
//save_entry.iconBufSize = 0; // TODO: Size of the PNG file
|
//save_entry.iconBufSize = 0; // TODO: Size of the PNG file
|
||||||
save_entry.isNew = false;
|
save_entry.isNew = false;
|
||||||
|
|
||||||
|
save_entry.size = 0;
|
||||||
|
for (const auto& entry2 : vfsDir(base_dir + entry->name))
|
||||||
|
{
|
||||||
|
save_entry.size += entry2->size;
|
||||||
|
}
|
||||||
|
|
||||||
save_entries.push_back(save_entry);
|
save_entries.push_back(save_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -271,7 +271,7 @@ struct SaveDataEntry
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string subtitle;
|
std::string subtitle;
|
||||||
std::string details;
|
std::string details;
|
||||||
u64 sizeKB;
|
u64 size;
|
||||||
s64 atime;
|
s64 atime;
|
||||||
s64 mtime;
|
s64 mtime;
|
||||||
s64 ctime;
|
s64 ctime;
|
||||||
|
@ -279,3 +279,9 @@ struct SaveDataEntry
|
||||||
//u32 iconBufSize;
|
//u32 iconBufSize;
|
||||||
bool isNew;
|
bool isNew;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SaveDataDialogInstance
|
||||||
|
{
|
||||||
|
SaveDataDialogInstance();
|
||||||
|
virtual ~SaveDataDialogInstance() = default;
|
||||||
|
};
|
||||||
|
|
|
@ -212,9 +212,7 @@ void Emulator::Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_NOTICE(LOADER, " "); //used to be skip_line
|
LOG_NOTICE(LOADER, " "); //used to be skip_line
|
||||||
vfsFile sfo("/app_home/../PARAM.SFO");
|
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
|
||||||
PSFLoader psf(sfo);
|
|
||||||
psf.Load(false);
|
|
||||||
std::string title = psf.GetString("TITLE");
|
std::string title = psf.GetString("TITLE");
|
||||||
std::string title_id = psf.GetString("TITLE_ID");
|
std::string title_id = psf.GetString("TITLE_ID");
|
||||||
LOG_NOTICE(LOADER, "Title: %s", title.c_str());
|
LOG_NOTICE(LOADER, "Title: %s", title.c_str());
|
||||||
|
|
|
@ -144,8 +144,8 @@ void GameViewer::LoadPSF()
|
||||||
if(!f.Open(sfo))
|
if(!f.Open(sfo))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PSFLoader psf(f);
|
const PSFLoader psf(f);
|
||||||
if(!psf.Load(false))
|
if(!psf)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// get local path from VFS...
|
// get local path from VFS...
|
||||||
|
|
|
@ -3,111 +3,104 @@
|
||||||
#include "Emu/FS/vfsStream.h"
|
#include "Emu/FS/vfsStream.h"
|
||||||
#include "PSF.h"
|
#include "PSF.h"
|
||||||
|
|
||||||
PSFLoader::PSFLoader(vfsStream& f) : psf_f(f)
|
bool PSFLoader::Load(vfsStream& stream)
|
||||||
{
|
{
|
||||||
|
Close();
|
||||||
|
|
||||||
|
// Load Header
|
||||||
|
if (stream.Read(&m_header, sizeof(PSFHeader)) != sizeof(PSFHeader) || !m_header.CheckMagic())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PSFEntry* PSFLoader::SearchEntry(const std::string& key)
|
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)
|
||||||
|
{
|
||||||
|
if (!stream.Read(m_psfindxs[i]))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entries[i].fmt = m_psfindxs[i].psf_param_fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
int c_pos = 0;
|
||||||
|
|
||||||
|
while (c_pos < sizeof(m_entries[i].name) - 1)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (!stream.Read(c) || !c)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entries[i].name[c_pos++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
m_loaded = false;
|
||||||
|
m_header = {};
|
||||||
|
m_psfindxs.clear();
|
||||||
|
m_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const PSFEntry* PSFLoader::SearchEntry(const std::string& key) const
|
||||||
{
|
{
|
||||||
for (auto& entry : m_entries)
|
for (auto& entry : m_entries)
|
||||||
{
|
{
|
||||||
if(entry.name == key)
|
if (key == entry.name)
|
||||||
|
{
|
||||||
return &entry;
|
return &entry;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PSFLoader::Load(bool show)
|
std::string PSFLoader::GetString(const std::string& key, std::string def) const
|
||||||
{
|
{
|
||||||
if(!psf_f.IsOpened()) return false;
|
if (const auto entry = SearchEntry(key))
|
||||||
|
|
||||||
m_show_log = show;
|
|
||||||
|
|
||||||
if(!LoadHeader()) return false;
|
|
||||||
if(!LoadKeyTable()) return false;
|
|
||||||
if(!LoadDataTable()) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PSFLoader::Close()
|
|
||||||
{
|
{
|
||||||
return psf_f.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PSFLoader::LoadHeader()
|
|
||||||
{
|
|
||||||
if(psf_f.Read(&m_header, sizeof(PSFHeader)) != sizeof(PSFHeader))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!m_header.CheckMagic())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(m_show_log) LOG_NOTICE(LOADER, "PSF version: 0x%x", m_header.psf_version);
|
|
||||||
|
|
||||||
m_psfindxs.clear();
|
|
||||||
m_entries.clear();
|
|
||||||
m_psfindxs.resize(m_header.psf_entries_num);
|
|
||||||
m_entries.resize(m_header.psf_entries_num);
|
|
||||||
|
|
||||||
for(u32 i=0; i<m_header.psf_entries_num; ++i)
|
|
||||||
{
|
|
||||||
if(psf_f.Read(&m_psfindxs[i], sizeof(PSFDefTbl)) != sizeof(PSFDefTbl))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_entries[i].fmt = m_psfindxs[i].psf_param_fmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PSFLoader::LoadKeyTable()
|
|
||||||
{
|
|
||||||
for(u32 i=0; i<m_header.psf_entries_num; ++i)
|
|
||||||
{
|
|
||||||
psf_f.Seek(m_header.psf_offset_key_table + m_psfindxs[i].psf_key_table_offset);
|
|
||||||
|
|
||||||
int c_pos = 0;
|
|
||||||
|
|
||||||
while(!psf_f.Eof())
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
psf_f.Read(&c, 1);
|
|
||||||
m_entries[i].name[c_pos++] = c;
|
|
||||||
|
|
||||||
if(c_pos >= sizeof(m_entries[i].name) || c == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PSFLoader::LoadDataTable()
|
|
||||||
{
|
|
||||||
for(u32 i=0; i<m_header.psf_entries_num; ++i)
|
|
||||||
{
|
|
||||||
psf_f.Seek(m_header.psf_offset_data_table + m_psfindxs[i].psf_data_tbl_offset);
|
|
||||||
psf_f.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 true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PSFLoader::GetString(const std::string& key)
|
|
||||||
{
|
|
||||||
if(PSFEntry* entry = SearchEntry(key))
|
|
||||||
return entry->FormatString();
|
return entry->FormatString();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return "";
|
{
|
||||||
|
return def;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 PSFLoader::GetInteger(const std::string& key)
|
u32 PSFLoader::GetInteger(const std::string& key, u32 def) const
|
||||||
|
{
|
||||||
|
if (const auto entry = SearchEntry(key))
|
||||||
{
|
{
|
||||||
if(PSFEntry* entry = SearchEntry(key))
|
|
||||||
return entry->FormatInteger();
|
return entry->FormatInteger();
|
||||||
else
|
}
|
||||||
return 0;
|
else
|
||||||
|
{
|
||||||
|
return def;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Loader.h"
|
|
||||||
|
|
||||||
struct vfsStream;
|
struct vfsStream;
|
||||||
|
|
||||||
|
@ -50,23 +49,29 @@ struct PSFEntry
|
||||||
|
|
||||||
class PSFLoader
|
class PSFLoader
|
||||||
{
|
{
|
||||||
vfsStream& psf_f;
|
bool m_loaded = false;
|
||||||
|
PSFHeader m_header = {};
|
||||||
PSFHeader m_header;
|
|
||||||
std::vector<PSFDefTbl> m_psfindxs;
|
std::vector<PSFDefTbl> m_psfindxs;
|
||||||
std::vector<PSFEntry> m_entries;
|
std::vector<PSFEntry> m_entries;
|
||||||
bool m_show_log;
|
|
||||||
|
|
||||||
bool LoadHeader();
|
|
||||||
bool LoadKeyTable();
|
|
||||||
bool LoadDataTable();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PSFLoader(vfsStream& f);
|
PSFLoader(vfsStream& stream)
|
||||||
virtual bool Load(bool show = true);
|
{
|
||||||
virtual bool Close();
|
Load(stream);
|
||||||
|
}
|
||||||
|
|
||||||
PSFEntry* SearchEntry(const std::string& key);
|
virtual ~PSFLoader() = default;
|
||||||
std::string GetString(const std::string& key);
|
|
||||||
u32 GetInteger(const std::string& key);
|
bool Load(vfsStream& stream);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return m_loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PSFEntry* SearchEntry(const std::string& key) const;
|
||||||
|
std::string GetString(const std::string& key, std::string def = "") const;
|
||||||
|
u32 GetInteger(const std::string& key, u32 def = 0) const;
|
||||||
};
|
};
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Loader.h"
|
|
||||||
|
|
||||||
struct vfsStream;
|
struct vfsStream;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue