mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-06 06:55:09 +00:00
PKG installer update for DLC
Also: 1) Don't ask for overwriting. It's outdated feature. 2) Limit cancellation capabilities.
This commit is contained in:
parent
ddbcbd0f1c
commit
5fffef74a2
3 changed files with 77 additions and 98 deletions
|
|
@ -4,27 +4,19 @@
|
|||
#include "sha1.h"
|
||||
#include "key_vault.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/VFS.h"
|
||||
#include "unpkg.h"
|
||||
|
||||
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync, const std::string& pkg_filepath)
|
||||
bool pkg_install(const std::string& path, atomic_t<double>& sync)
|
||||
{
|
||||
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)
|
||||
const u64 start_offset = pkg_f.pos();
|
||||
u64 cur_offset = start_offset;
|
||||
u64 cur_file_offset = start_offset;
|
||||
|
||||
// Get basic PKG information
|
||||
PKGHeader header;
|
||||
filelist.emplace_back(fs::file{path});
|
||||
u32 cur_file = 0;
|
||||
u64 cur_offset = 0;
|
||||
u64 cur_file_offset = 0;
|
||||
|
||||
auto archive_seek = [&](const s64 new_offset, const fs::seek_mode damode = fs::seek_set)
|
||||
{
|
||||
|
|
@ -73,6 +65,8 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
return num_read;
|
||||
};
|
||||
|
||||
// Get basic PKG information
|
||||
PKGHeader header;
|
||||
|
||||
if (archive_read(&header, sizeof(header)) != sizeof(header))
|
||||
{
|
||||
|
|
@ -108,18 +102,18 @@ 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 > filelist[0].size())
|
||||
{
|
||||
//Check if multi-files pkg
|
||||
if (pkg_filepath.length() < 7 || pkg_filepath.substr(pkg_filepath.length() - 7).compare("_00.pkg") != 0)
|
||||
// Check if multi-files pkg
|
||||
if (path.size() < 7 || path.compare(path.size() - 7, 7, "_00.pkg", 7) != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
|
||||
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 name_wo_number = path.substr(0, path.size() - 7);
|
||||
u64 cursize = filelist[0].size();
|
||||
while (cursize < header.pkg_size)
|
||||
{
|
||||
std::string archive_filename = fmt::format("%s_%02d.pkg", name_wo_number, filelist.size());
|
||||
|
||||
|
|
@ -131,7 +125,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
}
|
||||
|
||||
cursize += archive_file.size();
|
||||
filelist.push_back(std::move(archive_file));
|
||||
filelist.emplace_back(std::move(archive_file));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +137,12 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
|
||||
be_t<u32> drm_type{0};
|
||||
be_t<u32> content_type{0};
|
||||
std::string install_id;
|
||||
|
||||
// Read title ID and use it as an installation directory
|
||||
install_id.resize(9);
|
||||
archive_seek(55);
|
||||
archive_read(&install_id.front(), install_id.size());
|
||||
|
||||
archive_seek(header.pkg_info_off);
|
||||
|
||||
|
|
@ -179,18 +179,50 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
|
||||
break;
|
||||
}
|
||||
case 0xA:
|
||||
{
|
||||
if (packet.size > 8)
|
||||
{
|
||||
// Read an actual installation directory (DLC)
|
||||
install_id.resize(packet.size);
|
||||
archive_read(&install_id.front(), packet.size);
|
||||
install_id = install_id.c_str() + 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
archive_seek(packet.size, fs::seek_cur);
|
||||
}
|
||||
|
||||
// If false, an existing directory is being overwritten: cannot cancel the operation
|
||||
bool was_null = true;
|
||||
|
||||
// Get full path and create the directory
|
||||
const std::string dir = Emu.GetHddDir() + "game/" + install_id + '/';
|
||||
|
||||
if (!fs::create_dir(dir))
|
||||
{
|
||||
if (fs::g_tls_error == fs::error::exist)
|
||||
{
|
||||
was_null = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG: Could not create the installation directory %s", dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate buffer with BUF_SIZE size or more if required
|
||||
const std::unique_ptr<u128[]> buf(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count) / sizeof(u128)]);
|
||||
|
||||
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
||||
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
|
||||
{
|
||||
archive_seek(start_offset + header.data_offset + offset);
|
||||
archive_seek(header.data_offset + offset);
|
||||
|
||||
// Read the data and set available size
|
||||
const u64 read = archive_read(buf.get(), size);
|
||||
|
|
@ -334,8 +366,16 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
|
||||
if (sync.fetch_add((block_size + 0.0) / header.data_size) < 0.)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Package installation cancelled: %s", dir);
|
||||
return false;
|
||||
if (was_null)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Package installation cancelled: %s", dir);
|
||||
out.close();
|
||||
fs::remove_all(dir, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot cancel the installation
|
||||
sync += 1.;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue