we can now extract icon0 from pkg (WIP progress in the rest extraction)
This commit is contained in:
parent
711e9e917d
commit
7bd433ffea
|
@ -28,4 +28,39 @@ bool PKG::open(const std::string& filepath) {
|
||||||
file.Close();
|
file.Close();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
bool PKG::extract(const std::string& filepath, const std::string& extractPath, std::string& failreason)
|
||||||
|
{
|
||||||
|
this->extractPath = extractPath;
|
||||||
|
FsFile file;
|
||||||
|
if (!file.Open(filepath, fsRead))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pkgSize = file.getFileSize();
|
||||||
|
PKGHeader pkgheader;
|
||||||
|
file.ReadBE(pkgheader);
|
||||||
|
|
||||||
|
file.Seek(0, fsSeekSet);
|
||||||
|
pkg = (U08*)mmap(pkgSize, file.fileDescr());
|
||||||
|
|
||||||
|
file.Read(pkg, pkgSize);
|
||||||
|
|
||||||
|
U32 offset = pkgheader.pkg_table_entry_offset;
|
||||||
|
U32 n_files = pkgheader.pkg_table_entry_count;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < n_files; i++) {
|
||||||
|
PKGEntry entry = (PKGEntry&)pkg[offset + i * 0x20];
|
||||||
|
ReadBE(entry);
|
||||||
|
if (entry.id == 0x1200)//test code for extracting icon0
|
||||||
|
{
|
||||||
|
FsFile out;
|
||||||
|
out.Open(extractPath + "icon0.png", fsWrite);
|
||||||
|
out.Write(pkg + entry.offset, entry.size);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
munmap(pkg);
|
||||||
|
return true;
|
||||||
}
|
}
|
|
@ -1,17 +1,105 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../../Types.h"
|
#include "../../Types.h"
|
||||||
|
#include <io.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
struct PKGHeader {
|
struct PKGHeader {
|
||||||
/*BE*/U32 magic; // Magic
|
/*BE*/U32 magic;// Magic
|
||||||
|
/*BE*/U32 pkg_type;
|
||||||
|
/*BE*/U32 pkg_0x8; //unknown field
|
||||||
|
/*BE*/U32 pkg_file_count;
|
||||||
|
/*BE*/U32 pkg_table_entry_count;
|
||||||
|
/*BE*/U16 pkg_sc_entry_count;
|
||||||
|
/*BE*/U16 pkg_table_entry_count_2;// same as pkg_entry_count
|
||||||
|
/*BE*/U32 pkg_table_entry_offset;//file table offset
|
||||||
|
/*BE*/U32 pkg_sc_entry_data_size;
|
||||||
|
/*BE*/U64 pkg_body_offset;//offset of PKG entries
|
||||||
|
/*BE*/U64 pkg_body_size;//length of all PKG entries
|
||||||
|
/*BE*/U64 pkg_content_offset;
|
||||||
|
/*BE*/U64 pkg_content_size;
|
||||||
|
U08 pkg_content_id[0x24];//packages' content ID as a 36-byte string
|
||||||
|
U08 pkg_padding[0xC];//padding
|
||||||
|
/*BE*/U32 pkg_drm_type;//DRM type
|
||||||
|
/*BE*/U32 pkg_content_type;//Content type
|
||||||
|
/*BE*/U32 pkg_content_flags;//Content flags
|
||||||
|
/*BE*/U32 pkg_promote_size;
|
||||||
|
/*BE*/U32 pkg_version_date;
|
||||||
|
/*BE*/U32 pkg_version_hash;
|
||||||
|
/*BE*/U32 pkg_0x088;
|
||||||
|
/*BE*/U32 pkg_0x08C;
|
||||||
|
/*BE*/U32 pkg_0x090;
|
||||||
|
/*BE*/U32 pkg_0x094;
|
||||||
|
/*BE*/U32 pkg_iro_tag;
|
||||||
|
/*BE*/U32 pkg_drm_type_version;
|
||||||
|
|
||||||
|
U08 pkg_zeroes_1[0x60];
|
||||||
|
|
||||||
|
/* Digest table */
|
||||||
|
U08 digest_entries1[0x20]; // sha256 digest for main entry 1
|
||||||
|
U08 digest_entries2[0x20]; // sha256 digest for main entry 2
|
||||||
|
U08 digest_table_digest[0x20]; // sha256 digest for digest table
|
||||||
|
U08 digest_body_digest[0x20]; // sha256 digest for main table
|
||||||
|
|
||||||
|
U08 pkg_zeroes_2[0x280];
|
||||||
|
|
||||||
|
U32 pkg_0x400;
|
||||||
|
|
||||||
|
U32 pfs_image_count; // count of PFS images
|
||||||
|
U64 pfs_image_flags; // PFS flags
|
||||||
|
U64 pfs_image_offset; // offset to start of external PFS image
|
||||||
|
U64 pfs_image_size; // size of external PFS image
|
||||||
|
U64 mount_image_offset;
|
||||||
|
U64 mount_image_size;
|
||||||
|
U64 pkg_size;
|
||||||
|
U32 pfs_signed_size;
|
||||||
|
U32 pfs_cache_size;
|
||||||
|
U08 pfs_image_digest[0x20];
|
||||||
|
U08 pfs_signed_digest[0x20];
|
||||||
|
U64 pfs_split_size_nth_0;
|
||||||
|
U64 pfs_split_size_nth_1;
|
||||||
|
|
||||||
|
U08 pkg_zeroes_3[0xB50];
|
||||||
|
|
||||||
|
U08 pkg_digest[0x20];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void ReadBE(PKGHeader& s)
|
||||||
|
{
|
||||||
|
ReadBE(s.magic);
|
||||||
|
ReadBE(s.pkg_table_entry_offset);
|
||||||
|
ReadBE(s.pkg_table_entry_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PKGEntry {
|
||||||
|
U32 id; // File ID, useful for files without a filename entry
|
||||||
|
U32 filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is located
|
||||||
|
U32 flags1; // Flags including encrypted flag, etc
|
||||||
|
U32 flags2; // Flags including encryption key index, etc
|
||||||
|
U32 offset; // Offset into PKG to find the file
|
||||||
|
U32 size; // Size of the file
|
||||||
|
U64 padding; // blank padding
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void ReadBE(PKGEntry& s)
|
||||||
|
{
|
||||||
|
ReadBE(s.id);
|
||||||
|
ReadBE(s.filename_offset);
|
||||||
|
ReadBE(s.flags1);
|
||||||
|
ReadBE(s.flags2);
|
||||||
|
ReadBE(s.offset);
|
||||||
|
ReadBE(s.size);
|
||||||
|
ReadBE(s.padding);
|
||||||
|
}
|
||||||
|
|
||||||
class PKG
|
class PKG
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
U08* pkg;
|
U08* pkg;
|
||||||
U64 pkgSize = 0;
|
U64 pkgSize = 0;
|
||||||
S08 pkgTitleID[9];
|
S08 pkgTitleID[9];
|
||||||
|
std::string extractPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PKG();
|
PKG();
|
||||||
|
@ -23,7 +111,31 @@ public:
|
||||||
}
|
}
|
||||||
std::string getTitleID()
|
std::string getTitleID()
|
||||||
{
|
{
|
||||||
return std::string(pkgTitleID);
|
return std::string(pkgTitleID,9);
|
||||||
|
}
|
||||||
|
bool extract(const std::string& filepath, const std::string& extractPath, std::string& failreason);
|
||||||
|
|
||||||
|
void* mmap(size_t sLength, std::FILE* nFd) {
|
||||||
|
HANDLE hHandle;
|
||||||
|
void* pStart;
|
||||||
|
hHandle = CreateFileMapping(
|
||||||
|
(HANDLE)_get_osfhandle(_fileno((nFd))),
|
||||||
|
NULL, // default security
|
||||||
|
PAGE_WRITECOPY, // read/write access
|
||||||
|
0, // maximum object size (high-order DWORD)
|
||||||
|
0, // maximum object size (low-order DWORD)
|
||||||
|
NULL); // name of mapping object
|
||||||
|
|
||||||
|
if (hHandle != NULL) {
|
||||||
|
pStart = MapViewOfFile(hHandle, FILE_MAP_COPY, 0, 0, sLength);
|
||||||
|
}
|
||||||
|
return pStart;
|
||||||
|
}
|
||||||
|
int munmap(void* pStart) {
|
||||||
|
if (UnmapViewOfFile(pStart) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,23 @@ void shadps4gui::installPKG()
|
||||||
{
|
{
|
||||||
PKG pkg;
|
PKG pkg;
|
||||||
pkg.open(file);
|
pkg.open(file);
|
||||||
|
//if pkg is ok we procced with extraction
|
||||||
|
std::string failreason;
|
||||||
|
QString gamedir = QDir::currentPath() + "/game/" + QString::fromStdString(pkg.getTitleID());
|
||||||
|
QDir dir(gamedir);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkpath(".");
|
||||||
|
}
|
||||||
|
std::string extractpath = QDir::currentPath().toStdString() + "/game/" + pkg.getTitleID() + "/";
|
||||||
|
if (!pkg.extract(file, extractpath, failreason))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "PKG ERROR", QString::fromStdString(failreason), QMessageBox::Ok, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::information(this, "Extraction Finished", "Game successfully installed at " + gamedir, QMessageBox::Ok, 0);
|
||||||
|
game_list->RefreshGameDirectory();//force refreshing since filelistwatcher doesn't work properly
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -56,12 +56,12 @@
|
||||||
<Import Project="$(QtMsBuild)\qt_defaults.props" />
|
<Import Project="$(QtMsBuild)\qt_defaults.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||||
<QtInstall>qt6.4.0</QtInstall>
|
<QtInstall>6.4.0</QtInstall>
|
||||||
<QtModules>core;gui;widgets</QtModules>
|
<QtModules>core;gui;widgets</QtModules>
|
||||||
<QtBuildConfig>debug</QtBuildConfig>
|
<QtBuildConfig>debug</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||||
<QtInstall>qt6.4.0</QtInstall>
|
<QtInstall>6.4.0</QtInstall>
|
||||||
<QtModules>core;gui;widgets</QtModules>
|
<QtModules>core;gui;widgets</QtModules>
|
||||||
<QtBuildConfig>release</QtBuildConfig>
|
<QtBuildConfig>release</QtBuildConfig>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
Loading…
Reference in New Issue