mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-13 06:03:16 +00:00
- Added trophy decryption when extracting a fpkg. trp icons and xmls are dumped to game_data/<title> (can be restored if deleted by accident by opening the trophy viewer)
- Added a trophy viewer (right click on game ==> trophy viewer) - Enabled Run button. - Switched gui settings to toml. - Added recent files (6 max) - Applied @raphaelthegreat suggestions and corrections (Thanks a lot). - Fixed several bugs and crashes. - Full screen should disabled by default. - Added region in list mode. - Added a simple temp elf list widget. - Added messages when extracting pkg (ex: installing a patch before the game...etc)
This commit is contained in:
parent
71dda8c776
commit
0f27e0edf2
49 changed files with 1616 additions and 891 deletions
|
@ -5,14 +5,16 @@
|
|||
#include <QWidget>
|
||||
#include "pkg_viewer.h"
|
||||
|
||||
PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get,
|
||||
std::shared_ptr<GuiSettings> m_gui_settings,
|
||||
std::function<void(std::string, int, int)> InstallDragDropPkg)
|
||||
: QMainWindow() {
|
||||
PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent,
|
||||
std::function<void(std::filesystem::path, int, int)> InstallDragDropPkg)
|
||||
: QMainWindow(), m_game_info(game_info_get) {
|
||||
this->resize(1280, 720);
|
||||
m_gui_settings_ = m_gui_settings;
|
||||
m_game_info = game_info_get;
|
||||
dir_list = m_gui_settings->GetValue(gui::m_pkg_viewer).toStringList();
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dir_list_std = Config::getPkgViewer();
|
||||
dir_list.clear();
|
||||
for (const auto& str : dir_list_std) {
|
||||
dir_list.append(QString::fromStdString(str));
|
||||
}
|
||||
statusBar = new QStatusBar(treeWidget);
|
||||
this->setStatusBar(statusBar);
|
||||
treeWidget = new QTreeWidget(this);
|
||||
|
@ -20,8 +22,8 @@ PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get,
|
|||
QStringList headers;
|
||||
headers << "Name"
|
||||
<< "Serial"
|
||||
<< "Size"
|
||||
<< "Installed"
|
||||
<< "Size"
|
||||
<< "Category"
|
||||
<< "Type"
|
||||
<< "App Ver"
|
||||
|
@ -50,6 +52,8 @@ PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get,
|
|||
m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget,
|
||||
InstallDragDropPkg);
|
||||
});
|
||||
|
||||
connect(parent, &QWidget::destroyed, this, [parent, this]() { this->deleteLater(); });
|
||||
}
|
||||
|
||||
PKGViewer::~PKGViewer() {}
|
||||
|
@ -59,18 +63,21 @@ void PKGViewer::OpenPKGFolder() {
|
|||
QFileDialog::getExistingDirectory(this, tr("Open Folder"), QDir::homePath());
|
||||
if (!dir_list.contains(folderPath)) {
|
||||
dir_list.append(folderPath);
|
||||
if (!folderPath.isEmpty()) {
|
||||
for (const auto& dir : std::filesystem::directory_iterator(folderPath.toStdString())) {
|
||||
QString file_ext =
|
||||
QString::fromStdString(dir.path().extension().string()).toLower();
|
||||
if (std::filesystem::is_regular_file(dir.path()) && file_ext == ".pkg") {
|
||||
m_pkg_list.append(QString::fromStdString(dir.path().string()));
|
||||
}
|
||||
QDir directory(folderPath);
|
||||
QFileInfoList fileInfoList = directory.entryInfoList(QDir::Files);
|
||||
for (const QFileInfo& fileInfo : fileInfoList) {
|
||||
QString file_ext = fileInfo.suffix();
|
||||
if (fileInfo.isFile() && file_ext == "pkg") {
|
||||
m_pkg_list.append(fileInfo.absoluteFilePath());
|
||||
}
|
||||
std::sort(m_pkg_list.begin(), m_pkg_list.end());
|
||||
ProcessPKGInfo();
|
||||
m_gui_settings_->SetValue(gui::m_pkg_viewer, dir_list);
|
||||
}
|
||||
std::sort(m_pkg_list.begin(), m_pkg_list.end());
|
||||
ProcessPKGInfo();
|
||||
dir_list_std.clear();
|
||||
for (auto dir : dir_list) {
|
||||
dir_list_std.push_back(dir.toStdString());
|
||||
}
|
||||
Config::setPkgViewer(dir_list_std);
|
||||
} else {
|
||||
// qDebug() << "Folder selection canceled.";
|
||||
}
|
||||
|
@ -78,11 +85,13 @@ void PKGViewer::OpenPKGFolder() {
|
|||
|
||||
void PKGViewer::CheckPKGFolders() { // Check for new PKG file additions.
|
||||
m_pkg_list.clear();
|
||||
for (const QString& paths : dir_list) {
|
||||
for (const auto& dir : std::filesystem::directory_iterator(paths.toStdString())) {
|
||||
QString file_ext = QString::fromStdString(dir.path().extension().string()).toLower();
|
||||
if (std::filesystem::is_regular_file(dir.path()) && file_ext == ".pkg") {
|
||||
m_pkg_list.append(QString::fromStdString(dir.path().string()));
|
||||
for (const QString& dir : dir_list) {
|
||||
QDir directory(dir);
|
||||
QFileInfoList fileInfoList = directory.entryInfoList(QDir::Files);
|
||||
for (const QFileInfo& fileInfo : fileInfoList) {
|
||||
QString file_ext = fileInfo.suffix();
|
||||
if (fileInfo.isFile() && file_ext == "pkg") {
|
||||
m_pkg_list.append(fileInfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,87 +106,46 @@ void PKGViewer::ProcessPKGInfo() {
|
|||
m_pkg_patch_list.clear();
|
||||
m_full_pkg_list.clear();
|
||||
for (int i = 0; i < m_pkg_list.size(); i++) {
|
||||
Common::FS::IOFile file(m_pkg_list[i].toStdString(), Common::FS::FileAccessMode::Read);
|
||||
if (!file.IsOpen()) {
|
||||
// return false;
|
||||
}
|
||||
|
||||
file.ReadRaw<u8>(&pkgheader, sizeof(PKGHeader));
|
||||
file.Seek(0);
|
||||
pkgSize = file.GetSize();
|
||||
pkg.resize(pkgheader.pkg_promote_size);
|
||||
file.Read(pkg);
|
||||
|
||||
u32 offset = pkgheader.pkg_table_entry_offset;
|
||||
u32 n_files = pkgheader.pkg_table_entry_count;
|
||||
|
||||
for (int i = 0; i < n_files; i++) {
|
||||
std::memcpy(&entry, &pkg[offset + i * 0x20], sizeof(entry));
|
||||
const auto name = GetEntryNameByType(entry.id);
|
||||
if (name == "param.sfo") {
|
||||
psf.resize(entry.size);
|
||||
int seek = entry.offset;
|
||||
file.Seek(seek);
|
||||
file.Read(psf);
|
||||
std::memcpy(&header, psf.data(), sizeof(header));
|
||||
auto future = std::async(std::launch::async, [&]() {
|
||||
for (u32 i = 0; i < header.index_table_entries; i++) {
|
||||
PSFEntry psfentry;
|
||||
std::memcpy(&psfentry, &psf[sizeof(PSFHeader) + i * sizeof(PSFEntry)],
|
||||
sizeof(psfentry));
|
||||
const std::string key =
|
||||
(char*)&psf[header.key_table_offset + psfentry.key_offset];
|
||||
if (psfentry.param_fmt == PSFEntry::Fmt::TextRaw ||
|
||||
psfentry.param_fmt == PSFEntry::Fmt::TextNormal) {
|
||||
map_strings[key] =
|
||||
(char*)&psf[header.data_table_offset + psfentry.data_offset];
|
||||
}
|
||||
if (psfentry.param_fmt == PSFEntry::Fmt::Integer) {
|
||||
u32 value;
|
||||
std::memcpy(&value,
|
||||
&psf[header.data_table_offset + psfentry.data_offset],
|
||||
sizeof(value));
|
||||
map_integers[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
future.wait();
|
||||
}
|
||||
}
|
||||
QString title_name = GetString("TITLE");
|
||||
QString title_id = GetString("TITLE_ID");
|
||||
QString app_type = GetAppType(GetInteger("APP_TYPE"));
|
||||
QString app_version = GetString("APP_VER");
|
||||
QString title_category = GetString("CATEGORY");
|
||||
QString pkg_size = game_list_util.FormatSize(pkgheader.pkg_size);
|
||||
pkg_content_flag = pkgheader.pkg_content_flags;
|
||||
std::filesystem::path path(m_pkg_list[i].toStdString());
|
||||
#ifdef _WIN32
|
||||
path = std::filesystem::path(m_pkg_list[i].toStdWString());
|
||||
#endif
|
||||
package.Open(path);
|
||||
psf.open("", package.sfo);
|
||||
QString title_name = QString::fromStdString(psf.GetString("TITLE"));
|
||||
QString title_id = QString::fromStdString(psf.GetString("TITLE_ID"));
|
||||
QString app_type = game_list_util.GetAppType(psf.GetInteger("APP_TYPE"));
|
||||
QString app_version = QString::fromStdString(psf.GetString("APP_VER"));
|
||||
QString title_category = QString::fromStdString(psf.GetString("CATEGORY"));
|
||||
QString pkg_size = game_list_util.FormatSize(package.GetPkgHeader().pkg_size);
|
||||
pkg_content_flag = package.GetPkgHeader().pkg_content_flags;
|
||||
QString flagss = "";
|
||||
for (const auto& flag : flagNames) {
|
||||
if (isFlagSet(pkg_content_flag, flag.first)) {
|
||||
for (const auto& flag : package.flagNames) {
|
||||
if (package.isFlagSet(pkg_content_flag, flag.first)) {
|
||||
if (!flagss.isEmpty())
|
||||
flagss.append(", ");
|
||||
flagss.append(QString::fromStdString(flag.second));
|
||||
flagss += (", ");
|
||||
flagss += QString::fromStdString(flag.second.data());
|
||||
}
|
||||
}
|
||||
|
||||
u32 fw_int = GetInteger("SYSTEM_VER");
|
||||
u32 fw_int = psf.GetInteger("SYSTEM_VER");
|
||||
QString fw = QString::number(fw_int, 16);
|
||||
QString fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.')
|
||||
: fw.left(3).insert(1, '.');
|
||||
fw_ = (fw_int == 0) ? "0.00" : fw_;
|
||||
char region = pkgheader.pkg_content_id[0];
|
||||
char region = package.GetPkgHeader().pkg_content_id[0];
|
||||
QString pkg_info = "";
|
||||
if (title_category == "gd") {
|
||||
if (title_category == "gd" && !flagss.contains("PATCH")) {
|
||||
title_category = "App";
|
||||
pkg_info = title_name + ";;" + title_id + ";;" + pkg_size + ";;" + title_category +
|
||||
";;" + app_type + ";;" + app_version + ";;" + fw_ + ";;" +
|
||||
GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
||||
game_list_util.GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
||||
m_pkg_app_list.append(pkg_info);
|
||||
} else {
|
||||
title_category = "Patch";
|
||||
pkg_info = title_name + ";;" + title_id + ";;" + pkg_size + ";;" + title_category +
|
||||
";;" + app_type + ";;" + app_version + ";;" + fw_ + ";;" +
|
||||
GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
||||
game_list_util.GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
||||
m_pkg_patch_list.append(pkg_info);
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +172,7 @@ void PKGViewer::ProcessPKGInfo() {
|
|||
treeItem->setText(9, pkg_app_[8]);
|
||||
treeItem->setText(10, pkg_app_[9]);
|
||||
for (const GameInfo& info : m_game_info->m_games) { // Check if game is installed.
|
||||
if (info.name == pkg_app_[0].toStdString()) {
|
||||
if (info.serial == pkg_app_[1].toStdString()) {
|
||||
treeItem->setText(2, QChar(0x2713));
|
||||
treeItem->setTextAlignment(2, Qt::AlignCenter);
|
||||
}
|
||||
|
@ -233,7 +201,6 @@ void PKGViewer::ProcessPKGInfo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
std::sort(m_full_pkg_list.begin(), m_full_pkg_list.end());
|
||||
|
||||
for (int column = 0; column < treeWidget->columnCount() - 2; ++column) {
|
||||
// Resize the column to fit its contents
|
||||
|
@ -244,18 +211,4 @@ void PKGViewer::ProcessPKGInfo() {
|
|||
int numPkgs = m_pkg_list.size();
|
||||
QString statusMessage = QString::number(numPkgs) + " Package.";
|
||||
statusBar->showMessage(statusMessage);
|
||||
}
|
||||
|
||||
QString PKGViewer::GetString(const std::string& key) {
|
||||
if (map_strings.find(key) != map_strings.end()) {
|
||||
return QString::fromStdString(map_strings.at(key));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
u32 PKGViewer::GetInteger(const std::string& key) {
|
||||
if (map_integers.find(key) != map_integers.end()) {
|
||||
return map_integers.at(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue