mirror of https://github.com/RPCS3/rpcs3.git
Adds support for multi-files pkg.
This commit is contained in:
parent
d8c449aadf
commit
474bd7beaf
|
@ -3,19 +3,71 @@
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "key_vault.h"
|
#include "key_vault.h"
|
||||||
|
#include "Utilities/StrFmt.h"
|
||||||
#include "unpkg.h"
|
#include "unpkg.h"
|
||||||
|
|
||||||
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync)
|
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync, const std::string& pkg_filepath)
|
||||||
{
|
{
|
||||||
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
|
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
|
||||||
|
std::vector<fs::file> filelist;
|
||||||
|
u32 cur_file=0;
|
||||||
|
|
||||||
|
fs::file original_file(pkg_filepath);
|
||||||
|
original_file.seek(pkg_f.pos());
|
||||||
|
|
||||||
|
filelist.push_back(std::move(original_file));
|
||||||
|
|
||||||
// Save current file offset (probably zero)
|
// Save current file offset (probably zero)
|
||||||
const u64 start_offset = pkg_f.pos();
|
const u64 start_offset = pkg_f.pos();
|
||||||
|
u64 cur_offset = start_offset;
|
||||||
|
u64 cur_file_offset = start_offset;
|
||||||
|
|
||||||
// Get basic PKG information
|
// Get basic PKG information
|
||||||
PKGHeader header;
|
PKGHeader header;
|
||||||
|
|
||||||
if (!pkg_f.read(header))
|
auto archive_seek = [&](const s64 new_offset, const fs::seek_mode damode = fs::seek_set)
|
||||||
|
{
|
||||||
|
if(damode == fs::seek_set) cur_offset = new_offset;
|
||||||
|
else if (damode == fs::seek_cur) cur_offset += new_offset;
|
||||||
|
|
||||||
|
u64 _offset = 0;
|
||||||
|
for (u32 i = 0; i < filelist.size(); i++)
|
||||||
|
{
|
||||||
|
if (cur_offset < (_offset + filelist[i].size()))
|
||||||
|
{
|
||||||
|
cur_file = i;
|
||||||
|
cur_file_offset = cur_offset - _offset;
|
||||||
|
filelist[i].seek(cur_file_offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_offset += filelist[i].size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto archive_read = [&](const void *data_ptr, const u64 num_bytes)
|
||||||
|
{
|
||||||
|
u64 num_bytes_left = filelist[cur_file].size() - cur_file_offset;
|
||||||
|
//check if it continues in another file
|
||||||
|
if (num_bytes > num_bytes_left)
|
||||||
|
{
|
||||||
|
filelist[cur_file].read((u8 *)data_ptr, num_bytes_left);
|
||||||
|
if ((cur_file + 1) < filelist.size()) cur_file++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_offset += num_bytes_left;
|
||||||
|
cur_file_offset = filelist[cur_file].size();
|
||||||
|
return num_bytes_left;
|
||||||
|
}
|
||||||
|
u64 num_read = filelist[cur_file].read((u8 *)data_ptr + num_bytes_left, num_bytes - num_bytes_left);
|
||||||
|
cur_offset += (num_read + num_bytes_left);
|
||||||
|
cur_file_offset = num_bytes - num_bytes_left;
|
||||||
|
return num_read;
|
||||||
|
}
|
||||||
|
return filelist[cur_file].read((u8 *)data_ptr, num_bytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (archive_read(&header, sizeof(header)) != sizeof(header))
|
||||||
{
|
{
|
||||||
LOG_ERROR(LOADER, "PKG file is too short!");
|
LOG_ERROR(LOADER, "PKG file is too short!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,11 +102,32 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.pkg_size > pkg_f.size())
|
if (header.pkg_size > pkg_f.size())
|
||||||
|
{
|
||||||
|
//Check if multi-files pkg
|
||||||
|
if (pkg_filepath.length() < 7 || pkg_filepath.substr(pkg_filepath.length() - 7).compare("_00.pkg") != 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
|
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string name_wo_number = pkg_filepath.substr(0, pkg_filepath.length() - 7);
|
||||||
|
u64 cursize = pkg_f.size();
|
||||||
|
while (cursize != header.pkg_size)
|
||||||
|
{
|
||||||
|
std::string archive_filename = fmt::format("%s_%2d.pkg", name_wo_number, filelist.size());
|
||||||
|
|
||||||
|
fs::file archive_file(archive_filename);
|
||||||
|
if (!archive_file)
|
||||||
|
{
|
||||||
|
LOG_ERROR(LOADER, "Missing part of the multi-files pkg: %s", archive_filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursize += archive_file.size();
|
||||||
|
filelist.push_back(std::move(archive_file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (header.data_size + header.data_offset > header.pkg_size)
|
if (header.data_size + header.data_offset > header.pkg_size)
|
||||||
{
|
{
|
||||||
LOG_ERROR(LOADER, "PKG data size mismatch (data_size=0x%llx, data_offset=0x%llx, file_size=0x%llx)", header.data_size, header.data_offset, header.pkg_size);
|
LOG_ERROR(LOADER, "PKG data size mismatch (data_size=0x%llx, data_offset=0x%llx, file_size=0x%llx)", header.data_size, header.data_offset, header.pkg_size);
|
||||||
|
@ -64,7 +137,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
be_t<u32> drm_type{0};
|
be_t<u32> drm_type{0};
|
||||||
be_t<u32> content_type{0};
|
be_t<u32> content_type{0};
|
||||||
|
|
||||||
pkg_f.seek(header.pkg_info_off);
|
archive_seek(header.pkg_info_off);
|
||||||
|
|
||||||
for (u32 i = 0; i < header.pkg_info_num; i++)
|
for (u32 i = 0; i < header.pkg_info_num; i++)
|
||||||
{
|
{
|
||||||
|
@ -74,7 +147,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
be_t<u32> size;
|
be_t<u32> size;
|
||||||
} packet;
|
} packet;
|
||||||
|
|
||||||
pkg_f.read(packet);
|
archive_read(&packet, sizeof(packet));
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
switch (+packet.id)
|
switch (+packet.id)
|
||||||
|
@ -83,7 +156,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
{
|
{
|
||||||
if (packet.size == sizeof(drm_type))
|
if (packet.size == sizeof(drm_type))
|
||||||
{
|
{
|
||||||
pkg_f.read(drm_type);
|
archive_read(&drm_type, sizeof(drm_type));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +166,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
{
|
{
|
||||||
if (packet.size == sizeof(content_type))
|
if (packet.size == sizeof(content_type))
|
||||||
{
|
{
|
||||||
pkg_f.read(content_type);
|
archive_read(&content_type, sizeof(content_type));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +174,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg_f.seek(packet.size, fs::seek_cur);
|
archive_seek(packet.size, fs::seek_cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate buffer with BUF_SIZE size or more if required
|
// Allocate buffer with BUF_SIZE size or more if required
|
||||||
|
@ -110,10 +183,10 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
||||||
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
||||||
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
|
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
|
||||||
{
|
{
|
||||||
pkg_f.seek(start_offset + header.data_offset + offset);
|
archive_seek(start_offset + header.data_offset + offset);
|
||||||
|
|
||||||
// Read the data and set available size
|
// Read the data and set available size
|
||||||
const u64 read = pkg_f.read(buf.get(), size);
|
const u64 read = archive_read(buf.get(), size);
|
||||||
|
|
||||||
// Get block count
|
// Get block count
|
||||||
const u64 blocks = (read + 15) / 16;
|
const u64 blocks = (read + 15) / 16;
|
||||||
|
|
|
@ -57,4 +57,4 @@ struct PKGEntry
|
||||||
be_t<u32> pad; // Padding (zeros)
|
be_t<u32> pad; // Padding (zeros)
|
||||||
};
|
};
|
||||||
|
|
||||||
bool pkg_install(const class fs::file& pkg_f, const std::string& dir, atomic_t<double>&);
|
bool pkg_install(const class fs::file& pkg_f, const std::string& dir, atomic_t<double>&, const std::string& pkg_filepath);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
@ -395,7 +395,7 @@ void main_window::InstallPkg(const QString& dropPath)
|
||||||
// Run PKG unpacking asynchronously
|
// Run PKG unpacking asynchronously
|
||||||
scope_thread worker("PKG Installer", [&]
|
scope_thread worker("PKG Installer", [&]
|
||||||
{
|
{
|
||||||
if (pkg_install(pkg_f, local_path + '/', progress))
|
if (pkg_install(pkg_f, local_path + '/', progress, path))
|
||||||
{
|
{
|
||||||
progress = 1.;
|
progress = 1.;
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue