PSFLoader improved

This commit is contained in:
Nekotekina 2015-04-16 02:17:42 +03:00
parent 00205bfa58
commit 37b22ec99d
11 changed files with 174 additions and 186 deletions

View file

@ -23,8 +23,19 @@ public:
virtual u64 GetSize();
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);
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 Tell() const;
virtual bool Eof();

View file

@ -17,13 +17,16 @@ std::string contentInfo = "";
std::string usrdir = "";
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);
std::string dir = dirName.get_ptr();
if (dir.size() != 9)
{
return CELL_HDDGAME_ERROR_PARAM;
}
vm::var<CellHddGameSystemFileParam> param;
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->mtime = 0; // TODO
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
memcpy(get->contentInfoPath, ("/dev_hdd0/game/" + dir).c_str(), CELL_HDDGAME_PATH_MAX);
memcpy(get->hddGamePath, ("/dev_hdd0/game/" + dir + "/USRDIR").c_str(), CELL_HDDGAME_PATH_MAX);
strcpy_trunc(get->contentInfoPath, "/dev_hdd0/game/" + dir);
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;
}
else
{
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
vfsFile f(("/dev_hdd0/game/" + dir + "/PARAM.SFO").c_str());
PSFLoader psf(f);
if (!psf.Load(false)) {
const PSFLoader psf(vfsFile("/dev_hdd0/game/" + dir + "/PARAM.SFO"));
if (!psf)
{
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.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];
sprintf(key, "TITLE_%02d", i);
title = psf.GetString(key);
@ -76,10 +79,10 @@ s32 cellHddGameCheck(u32 version, vm::ptr<const char> dirName, u32 errDialog, vm
//funcStat(result, get, set);
if (result->result != CELL_HDDGAME_CBRESULT_OK &&
result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL) {
return CELL_HDDGAME_ERROR_CBRESULT;
}
//if (result->result != CELL_HDDGAME_CBRESULT_OK && result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
//{
// return CELL_HDDGAME_ERROR_CBRESULT;
//}
// TODO ?
@ -100,15 +103,8 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
size->sysSizeKB = 0;
}
vfsFile f("/app_home/../PARAM.SFO");
if (!f.IsOpened())
{
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))
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
if (!psf)
{
cellGame.Error("cellGameBootCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
@ -167,15 +163,8 @@ s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved
size->sysSizeKB = 0;
}
vfsFile f("/app_home/../PARAM.SFO");
if (!f.IsOpened())
{
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))
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
if (!psf)
{
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
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;
}
vfsFile f(dir + "/PARAM.SFO");
if (!f.IsOpened())
{
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot open PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN;
}
PSFLoader psf(f);
if (!psf.Load(false))
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
if (!psf)
{
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
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);
// TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO");
PSFLoader psf(f);
if(!psf.Load(false))
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
if (!psf)
{
return CELL_GAME_ERROR_FAILURE;
}
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);
// TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO");
PSFLoader psf(f);
if(!psf.Load(false))
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
if (!psf)
{
return CELL_GAME_ERROR_FAILURE;
}
std::string data;
switch(id)

View file

@ -18,10 +18,6 @@ MsgDialogInstance::MsgDialogInstance()
{
}
MsgDialogInstance::~MsgDialogInstance()
{
}
void MsgDialogInstance::Close()
{
state = msgDialogClose;

View file

@ -99,7 +99,7 @@ struct MsgDialogInstance
u32 progress_bar_count = 0;
MsgDialogInstance();
virtual ~MsgDialogInstance();
virtual ~MsgDialogInstance() = default;
virtual void Close();

View file

@ -20,6 +20,12 @@
extern Module cellSysutil;
std::unique_ptr<SaveDataDialogInstance> g_savedata_dialog;
SaveDataDialogInstance::SaveDataDialogInstance()
{
}
// Auxiliary Classes
class SortSaveDataEntry
{
@ -66,21 +72,6 @@ public:
};
// 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)
{
SaveDataEntry saveEntry;
@ -158,7 +149,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr<CellSaveDataStatGet> statGet)
statGet->isNewData = CELL_SAVEDATA_ISNEWDATA_NO;
statGet->bind = 0; // TODO ?
statGet->sizeKB = entry.sizeKB;
statGet->sizeKB = entry.size / 1024;
statGet->hddFreeSizeKB = 40000000; // 40 GB. TODO ?
statGet->sysSizeKB = 0; // TODO: This is the size of PARAM.SFO + PARAM.PDF
statGet->dir.st_atime_ = 0; // TODO ?
@ -358,9 +349,8 @@ __noinline s32 savedata_op(
listGet->dirNum++;
// PSF parameters
vfsFile f(base_dir + entry->name + "/PARAM.SFO");
PSFLoader psf(f);
if (!psf.Load(false))
const PSFLoader psf(vfsFile(base_dir + entry->name + "/PARAM.SFO"));
if (!psf)
{
break;
}
@ -371,7 +361,7 @@ __noinline s32 savedata_op(
save_entry.title = psf.GetString("TITLE");
save_entry.subtitle = psf.GetString("SUB_TITLE");
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.mtime = entry->modify_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.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);
}

View file

@ -271,7 +271,7 @@ struct SaveDataEntry
std::string title;
std::string subtitle;
std::string details;
u64 sizeKB;
u64 size;
s64 atime;
s64 mtime;
s64 ctime;
@ -279,3 +279,9 @@ struct SaveDataEntry
//u32 iconBufSize;
bool isNew;
};
struct SaveDataDialogInstance
{
SaveDataDialogInstance();
virtual ~SaveDataDialogInstance() = default;
};

View file

@ -212,9 +212,7 @@ void Emulator::Load()
}
LOG_NOTICE(LOADER, " "); //used to be skip_line
vfsFile sfo("/app_home/../PARAM.SFO");
PSFLoader psf(sfo);
psf.Load(false);
const PSFLoader psf(vfsFile("/app_home/../PARAM.SFO"));
std::string title = psf.GetString("TITLE");
std::string title_id = psf.GetString("TITLE_ID");
LOG_NOTICE(LOADER, "Title: %s", title.c_str());

View file

@ -144,8 +144,8 @@ void GameViewer::LoadPSF()
if(!f.Open(sfo))
continue;
PSFLoader psf(f);
if(!psf.Load(false))
const PSFLoader psf(f);
if(!psf)
continue;
// get local path from VFS...

View file

@ -3,111 +3,104 @@
#include "Emu/FS/vfsStream.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)
{
if(entry.name == key)
if (key == entry.name)
{
return &entry;
}
}
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;
m_show_log = show;
if(!LoadHeader()) return false;
if(!LoadKeyTable()) return false;
if(!LoadDataTable()) return false;
return true;
}
bool PSFLoader::Close()
if (const auto entry = SearchEntry(key))
{
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();
}
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();
else
return 0;
}
else
{
return def;
}
}

View file

@ -1,5 +1,4 @@
#pragma once
#include "Loader.h"
struct vfsStream;
@ -50,23 +49,29 @@ struct PSFEntry
class PSFLoader
{
vfsStream& psf_f;
PSFHeader m_header;
bool m_loaded = false;
PSFHeader m_header = {};
std::vector<PSFDefTbl> m_psfindxs;
std::vector<PSFEntry> m_entries;
bool m_show_log;
bool LoadHeader();
bool LoadKeyTable();
bool LoadDataTable();
public:
PSFLoader(vfsStream& f);
virtual bool Load(bool show = true);
virtual bool Close();
PSFLoader(vfsStream& stream)
{
Load(stream);
}
PSFEntry* SearchEntry(const std::string& key);
std::string GetString(const std::string& key);
u32 GetInteger(const std::string& key);
virtual ~PSFLoader() = default;
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;
};

View file

@ -1,5 +1,4 @@
#pragma once
#include "Loader.h"
struct vfsStream;