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 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();

View file

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

View file

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

View file

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

View file

@ -11,15 +11,21 @@
#include "cellSaveData.h" #include "cellSaveData.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#undef CreateFile #undef CreateFile
#else #else
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
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);
} }

View file

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

View file

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

View file

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

View file

@ -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;
}
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);
} }
PSFEntry* PSFLoader::SearchEntry(const std::string& key) void PSFLoader::Close()
{ {
for(auto& entry : m_entries) 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 &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(PSFEntry* entry = SearchEntry(key)) if (const auto entry = SearchEntry(key))
{
return entry->FormatInteger(); return entry->FormatInteger();
}
else else
return 0; {
return def;
}
} }

View file

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

View file

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