added psf file format and correct load to gamelist viewer

This commit is contained in:
georgemoralis 2022-10-27 17:44:17 +03:00
parent 2c8cab1f05
commit 7101247fd5
6 changed files with 169 additions and 8 deletions

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <immintrin.h>
using S08 = char; using S08 = char;
using S16 = short; using S16 = short;
@ -12,3 +13,34 @@ using U64 = unsigned long long;
using F32 = float; using F32 = float;
using F64 = double; using F64 = double;
template< typename T > T inline LoadBE(T* src) { return *src; };
template< typename T > inline void StoreBE(T* dst, T src) { *dst = src; };
inline S16 LoadBE(S16* src) { return _loadbe_i16(src); };
inline S32 LoadBE(S32* src) { return _loadbe_i32(src); };
inline S64 LoadBE(S64* src) { return _loadbe_i64(src); };
inline U16 LoadBE(U16* src) { return _load_be_u16(src); };
inline U32 LoadBE(U32* src) { return _load_be_u32(src); };
inline U64 LoadBE(U64* src) { return _load_be_u64(src); };
inline void StoreBE(S16* dst, S16 const src) { _storebe_i16(dst, src); };
inline void StoreBE(S32* dst, S32 const src) { _storebe_i32(dst, src); };
inline void StoreBE(S64* dst, S64 const src) { _storebe_i64(dst, src); };
inline void StoreBE(U16* dst, U16 const src) { _store_be_u16(dst, src); };
inline void StoreBE(U32* dst, U32 const src) { _store_be_u32(dst, src); };
inline void StoreBE(U64* dst, U64 const src) { _store_be_u64(dst, src); };
template< typename T > inline void ReadBE(T& val)
{
val = LoadBE(&val); // swap inplace
}
template< typename T > inline void WriteBE(T& val)
{
StoreBE(&val, val); // swap inplace
}

View File

@ -0,0 +1,70 @@
#include "PSF.h"
#include "../../Core/FsFile.h"
#include <iostream>
#include <fstream>
PSF::PSF()
{
}
PSF::~PSF()
{
}
bool PSF::open(const std::string& filepath) {
FsFile file;
if (!file.Open(filepath, fsRead))
{
return false;
}
const U64 psfSize = file.getFileSize();
psf.resize(psfSize);
file.Seek(0, fsSeekSet);
file.Read(&psf[0], psfSize);
// Parse file contents
const auto& header = (PSFHeader&)psf[0];
for (U32 i = 0; i < header.indexTableEntries; i++) {
const U32 offset = sizeof(PSFHeader) + i * sizeof(PSFEntry);
auto& entry = (PSFEntry&)psf[offset];
std::string key = (char*)&psf[header.keyTableOffset + entry.keyOffset];
ReadBE(entry.param_fmt);//param_fmt is big endian convert it (this convert the original entry maybe we should store it elsewhere?)
if (entry.param_fmt == PSFEntry::Fmt::TEXT_RAW ||
entry.param_fmt == PSFEntry::Fmt::TEXT_NORMAL) {
map_strings[key] = (char*)&psf[header.dataTableOffset + entry.dataOffset];
}
if (entry.param_fmt == PSFEntry::Fmt::INTEGER) {
map_integers[key] = (U32&)psf[header.dataTableOffset + entry.dataOffset];
}
}
//debug code print all keys
std::ofstream out;
out.open("psf.txt", std::fstream::out | std::fstream::app);
out << "---------------------------------------------" << "\n";
for (auto stringkey : map_strings)
{
out << " " << stringkey.first << " : " << stringkey.second << "\n";
}
for (auto integerkey : map_integers)
{
out << " " << integerkey.first << " : " << integerkey.second << "\n";
}
out << "---------------------------------------------" << "\n";
return true;
}
std::string PSF::get_string(const std::string& key) {
if (map_strings.find(key) != map_strings.end()) {
return map_strings.at(key);
}
return "";
}
U32 PSF::get_integer(const std::string& key)
{
if (map_integers.find(key) != map_integers.end()) {
return map_integers.at(key); //TODO std::invalid_argument exception if it fails?
}
return 0;
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <unordered_map>
#include <vector>
#include "../../types.h"
struct PSFHeader {
U32 magic; //big endian
U32 version;
U32 keyTableOffset;
U32 dataTableOffset;
U32 indexTableEntries;
};
struct PSFEntry {
enum Fmt : U16 {
TEXT_RAW = 0x0400, // String in UTF-8 format and not NULL terminated
TEXT_NORMAL = 0x0402, // String in UTF-8 format and NULL terminated
INTEGER = 0x0404, // Unsigned 32-bit integer
};
U16 keyOffset;
U16 param_fmt;//big endian
U32 paramLen;
U32 paramMaxLen;
U32 dataOffset;
};
class PSF
{
std::vector<U08> psf;
std::unordered_map<std::string, std::string> map_strings;
std::unordered_map<std::string, U32> map_integers;
public:
PSF();
~PSF();
bool open(const std::string& filepath);
// Access data
std::string get_string(const std::string& key);
U32 get_integer(const std::string& key);
};

View File

@ -6,6 +6,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDirIterator> #include <QDirIterator>
#include <QLineEdit> #include <QLineEdit>
#include "../emulator/fileFormat/PSF.h"
GameListViewer::GameListViewer(QWidget* parent) GameListViewer::GameListViewer(QWidget* parent)
: QWidget(parent) : QWidget(parent)
@ -147,20 +148,20 @@ void GameListWorker::AddEntriesToGameList(const std::string& dir_path) {
QFileInfoList fList = parent_folder.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::DirsFirst); QFileInfoList fList = parent_folder.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::DirsFirst);
foreach(QFileInfo item, fList) foreach(QFileInfo item, fList)
{ {
//TODO PSF psf; PSF psf;
//TODO if (!psf.open(item.absoluteFilePath().toStdString() + "/PARAM.SFO")) if (!psf.open(item.absoluteFilePath().toStdString() + "/PARAM.SFO"))
//TODO continue;//if we can't open param.sfo go to the next entry continue;//if we can't open param.sfo go to the next entry
//TODO std::string test = psf.get_string("TITLE_ID"); //TODO std::string test = psf.get_string("TITLE_ID");
QString iconpath(item.absoluteFilePath() + "/ICON0.PNG"); QString iconpath(item.absoluteFilePath() + "/ICON0.PNG");
emit EntryReady({ emit EntryReady({
new GameIconItem(iconpath), new GameIconItem(iconpath),
new GameListItem("TODO"/*QString::fromStdString(psf.get_string("TITLE"))*/), new GameListItem(QString::fromStdString(psf.get_string("TITLE"))),
new GameListItem("TODO"/*QString::fromStdString(psf.get_string("TITLE_ID"))*/), new GameListItem(QString::fromStdString(psf.get_string("TITLE_ID"))),
new GameListItem("TODO"/*QString::fromStdString(psf.get_string("SYSTEM_VER"))*/), new GameListItem(QString("%1").arg(psf.get_integer("SYSTEM_VER"), 8, 16, QLatin1Char('0'))),
new GameListItem("TODO"/*QString::fromStdString(psf.get_string("APP_VER"))*/), new GameListItem(QString::fromStdString(psf.get_string("APP_VER"))),
new GameListItem("TODO"/*QString::fromStdString(psf.get_string("CATEGORY"))*/), new GameListItem(QString::fromStdString(psf.get_string("CATEGORY"))),
new GameListItem(item.fileName()) new GameListItem(item.fileName())
}); });

View File

@ -12,6 +12,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="core\FsFile.cpp" /> <ClCompile Include="core\FsFile.cpp" />
<ClCompile Include="emulator\fileFormat\PSF.cpp" />
<ClCompile Include="gui\GameListViewer.cpp" /> <ClCompile Include="gui\GameListViewer.cpp" />
<ClCompile Include="gui\shadps4gui.cpp" /> <ClCompile Include="gui\shadps4gui.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
@ -27,6 +28,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="core\FsFile.h" /> <ClInclude Include="core\FsFile.h" />
<ClInclude Include="emulator\fileFormat\PSF.h" />
<ClInclude Include="Types.h" /> <ClInclude Include="Types.h" />
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">

View File

@ -27,6 +27,12 @@
<Filter Include="Core"> <Filter Include="Core">
<UniqueIdentifier>{73d07238-8864-48b5-9987-e455fa73c82f}</UniqueIdentifier> <UniqueIdentifier>{73d07238-8864-48b5-9987-e455fa73c82f}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="emulator">
<UniqueIdentifier>{66864aec-390b-47a8-bddb-b52032630d7a}</UniqueIdentifier>
</Filter>
<Filter Include="emulator\fileFormat">
<UniqueIdentifier>{ed31734c-f010-4590-9f01-18e0b2497ffb}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
@ -41,6 +47,9 @@
<ClCompile Include="core\FsFile.cpp"> <ClCompile Include="core\FsFile.cpp">
<Filter>Core</Filter> <Filter>Core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="emulator\fileFormat\PSF.cpp">
<Filter>emulator\fileFormat</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtUic Include="gui\shadps4gui.ui"> <QtUic Include="gui\shadps4gui.ui">
@ -62,5 +71,8 @@
<ClInclude Include="core\FsFile.h"> <ClInclude Include="core\FsFile.h">
<Filter>Core</Filter> <Filter>Core</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="emulator\fileFormat\PSF.h">
<Filter>emulator\fileFormat</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>