added psf file format and correct load to gamelist viewer
This commit is contained in:
parent
2c8cab1f05
commit
7101247fd5
|
@ -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
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
};
|
||||||
|
|
|
@ -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())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue