From 37b22ec99dd96ce04f8f5287530254800e9056c6 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 16 Apr 2015 02:17:42 +0300 Subject: [PATCH] PSFLoader improved --- rpcs3/Emu/FS/vfsStream.h | 11 ++ rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 76 ++++----- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 4 - rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 44 +++-- rpcs3/Emu/SysCalls/Modules/cellSaveData.h | 8 +- rpcs3/Emu/System.cpp | 4 +- rpcs3/Gui/GameViewer.cpp | 4 +- rpcs3/Loader/PSF.cpp | 167 +++++++++---------- rpcs3/Loader/PSF.h | 37 ++-- rpcs3/Loader/TRP.h | 3 +- 11 files changed, 174 insertions(+), 186 deletions(-) diff --git a/rpcs3/Emu/FS/vfsStream.h b/rpcs3/Emu/FS/vfsStream.h index cceb80b2ed..b7a640d8c3 100644 --- a/rpcs3/Emu/FS/vfsStream.h +++ b/rpcs3/Emu/FS/vfsStream.h @@ -23,8 +23,19 @@ public: virtual u64 GetSize(); virtual u64 Write(const void* src, u64 size); + + template __forceinline bool Write(const T& data) + { + return Write(&data, sizeof(T)) == sizeof(T); + } + virtual u64 Read(void* dst, u64 size); + template __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(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index dc7c3d85aa..49ec2e06b1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -17,13 +17,16 @@ std::string contentInfo = ""; std::string usrdir = ""; bool path_set = false; -s32 cellHddGameCheck(u32 version, vm::ptr dirName, u32 errDialog, vm::ptr funcStat, u32 container) +s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr 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 param; vm::var result; @@ -37,20 +40,19 @@ s32 cellHddGameCheck(u32 version, vm::ptr 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 dirName, u32 errDialog, vm strcpy_trunc(get->getParam.dataVersion, app_ver); strcpy_trunc(get->getParam.titleId, dir); - for (u32 i = 0; i 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 type, vm::ptr attributes, vm::ptrsysSizeKB = 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 size, vm::ptr 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 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 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 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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index f8c1b9ef0e..1123f9df6c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -18,10 +18,6 @@ MsgDialogInstance::MsgDialogInstance() { } -MsgDialogInstance::~MsgDialogInstance() -{ -} - void MsgDialogInstance::Close() { state = msgDialogClose; diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h index 6b2a3e1527..b1b1e8b880 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h @@ -99,7 +99,7 @@ struct MsgDialogInstance u32 progress_bar_count = 0; MsgDialogInstance(); - virtual ~MsgDialogInstance(); + virtual ~MsgDialogInstance() = default; virtual void Close(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 35ad8b2021..2b05a74fb4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -11,15 +11,21 @@ #include "cellSaveData.h" #ifdef _WIN32 - #include - #undef CreateFile +#include +#undef CreateFile #else - #include - #include +#include +#include #endif extern Module cellSysutil; +std::unique_ptr 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& saveEntries, vm::ptr newData) { SaveDataEntry saveEntry; @@ -158,7 +149,7 @@ void getSaveDataStat(SaveDataEntry entry, vm::ptr 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); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.h b/rpcs3/Emu/SysCalls/Modules/cellSaveData.h index e804ad4dc6..1bf9103637 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.h @@ -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; +}; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 7e3a9b21f2..3bfed22962 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -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()); diff --git a/rpcs3/Gui/GameViewer.cpp b/rpcs3/Gui/GameViewer.cpp index 6a2d9a8fe0..28f0d1df8b 100644 --- a/rpcs3/Gui/GameViewer.cpp +++ b/rpcs3/Gui/GameViewer.cpp @@ -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... diff --git a/rpcs3/Loader/PSF.cpp b/rpcs3/Loader/PSF.cpp index 6bf66f4378..f050301c65 100644 --- a/rpcs3/Loader/PSF.cpp +++ b/rpcs3/Loader/PSF.cpp @@ -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; + } + + 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 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() -{ - 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= sizeof(m_entries[i].name) || c == '\0') - break; - } - } - - return true; -} - -bool PSFLoader::LoadDataTable() -{ - for(u32 i=0; iFormatString(); + } 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(); + } else - return 0; + { + return def; + } } diff --git a/rpcs3/Loader/PSF.h b/rpcs3/Loader/PSF.h index 8fdfa8a532..9c0275d41b 100644 --- a/rpcs3/Loader/PSF.h +++ b/rpcs3/Loader/PSF.h @@ -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 m_psfindxs; std::vector 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); -}; \ No newline at end of file + 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; +}; diff --git a/rpcs3/Loader/TRP.h b/rpcs3/Loader/TRP.h index 64d491d414..006df5f18e 100644 --- a/rpcs3/Loader/TRP.h +++ b/rpcs3/Loader/TRP.h @@ -1,5 +1,4 @@ #pragma once -#include "Loader.h" struct vfsStream; @@ -41,4 +40,4 @@ public: virtual void RenameEntry(const char *oldname, const char *newname); virtual bool Close(); -}; \ No newline at end of file +};