mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-06-09 08:35:03 -06:00
iso stuff
This commit is contained in:
parent
9e3e01d8f6
commit
b10c742f10
@ -11,6 +11,7 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
LOG_CHANNEL(sys_log, "SYS");
|
LOG_CHANNEL(sys_log, "SYS");
|
||||||
|
LOG_CHANNEL(iso_log, "ISO");
|
||||||
|
|
||||||
constexpr u64 ISO_SECTOR_SIZE = 2048;
|
constexpr u64 ISO_SECTOR_SIZE = 2048;
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ static bool decrypt_data(aes_context& aes, u64 offset, unsigned char* buffer, u6
|
|||||||
// Partial (or even full) first sector
|
// Partial (or even full) first sector
|
||||||
if (aes_crypt_cbc(&aes, AES_DECRYPT, cur_size, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
if (aes_crypt_cbc(&aes, AES_DECRYPT, cur_size, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
||||||
{
|
{
|
||||||
sys_log.error("decrypt_data(): Error decrypting data on first sector read");
|
iso_log.error("decrypt_data: Error decrypting data on first sector read");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ static bool decrypt_data(aes_context& aes, u64 offset, unsigned char* buffer, u6
|
|||||||
|
|
||||||
if (aes_crypt_cbc(&aes, AES_DECRYPT, ISO_SECTOR_SIZE, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
if (aes_crypt_cbc(&aes, AES_DECRYPT, ISO_SECTOR_SIZE, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
||||||
{
|
{
|
||||||
sys_log.error("decrypt_data(): Error decrypting data on inner sector(s) read");
|
iso_log.error("decrypt_data: Error decrypting data on inner sector(s) read");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ static bool decrypt_data(aes_context& aes, u64 offset, unsigned char* buffer, u6
|
|||||||
// Partial (or even full) last sector
|
// Partial (or even full) last sector
|
||||||
if (aes_crypt_cbc(&aes, AES_DECRYPT, size - cur_offset, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
if (aes_crypt_cbc(&aes, AES_DECRYPT, size - cur_offset, iv.data(), &buffer[cur_offset], &buffer[cur_offset]) != 0)
|
||||||
{
|
{
|
||||||
sys_log.error("decrypt_data(): Error decrypting data on last sector read");
|
iso_log.error("decrypt_data: Error decrypting data on last sector read");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,8 +165,6 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, ISO_SECTOR_SIZE * 2> sec0_sec1 {};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Store the ISO region information (needed by both the "Redump" type (only on "decrypt()" method) and "3k3y" type)
|
// Store the ISO region information (needed by both the "Redump" type (only on "decrypt()" method) and "3k3y" type)
|
||||||
//
|
//
|
||||||
@ -174,19 +173,21 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
|
|
||||||
if (!iso_file)
|
if (!iso_file)
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Failed to open file: %s", path);
|
iso_log.error("init: Failed to open file: %s", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<u8, ISO_SECTOR_SIZE * 2> sec0_sec1 {};
|
||||||
|
|
||||||
if (iso_file.size() < sec0_sec1.size())
|
if (iso_file.size() < sec0_sec1.size())
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Found only %ull sector(s) (minimum required is 2): %s", iso_file.size(), path);
|
iso_log.error("init: Found only %ull sector(s) (minimum required is 2): %s", iso_file.size(), path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iso_file.read(sec0_sec1.data(), sec0_sec1.size()) != sec0_sec1.size())
|
if (iso_file.read(sec0_sec1.data(), sec0_sec1.size()) != sec0_sec1.size())
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Failed to read file: %s", path);
|
iso_log.error("init: Failed to read file: %s", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,12 +196,12 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
// Following checks and assigned values are based on PS3 ISO specification.
|
// Following checks and assigned values are based on PS3 ISO specification.
|
||||||
// E.g. all even regions (0, 2, 4 etc.) are always unencrypted while the odd ones are encrypted
|
// E.g. all even regions (0, 2, 4 etc.) are always unencrypted while the odd ones are encrypted
|
||||||
|
|
||||||
size_t region_count = char_arr_BE_to_uint(sec0_sec1.data());
|
const u32 region_count = char_arr_BE_to_uint(sec0_sec1.data());
|
||||||
|
|
||||||
// Ensure the region count is a proper value
|
// Ensure the region count is a proper value
|
||||||
if (region_count < 1 || region_count > 31) // It's non-PS3ISO
|
if (region_count < 1 || region_count > 31) // It's non-PS3ISO
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Failed to read region information: %s", path);
|
iso_log.error("init: Failed to read region information: '%s' (region_count=%d)", path, region_count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,12 +265,12 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
|
|
||||||
if (m_enc_type == iso_encryption_type::NONE) // If encryption type was not set to REDUMP for any reason
|
if (m_enc_type == iso_encryption_type::NONE) // If encryption type was not set to REDUMP for any reason
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Failed to process key file: %s", key_path);
|
iso_log.error("init: Failed to process key file: %s", key_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sys_log.warning("init(): Failed to open, or missing, key file: %s", key_path);
|
iso_log.warning("init: Failed to open, or missing, key file: %s", key_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -311,7 +312,7 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
|
|
||||||
if (m_enc_type == iso_encryption_type::NONE) // If encryption type was not set to ENC_3K3Y for any reason
|
if (m_enc_type == iso_encryption_type::NONE) // If encryption type was not set to ENC_3K3Y for any reason
|
||||||
{
|
{
|
||||||
sys_log.error("init(): Failed to set encryption type to ENC_3K3Y: %s", path);
|
iso_log.error("init: Failed to set encryption type to ENC_3K3Y: %s", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (memcmp(&k3k3y_dec_watermark[0], &sec0_sec1[0xF70], sizeof(k3k3y_dec_watermark)) == 0)
|
else if (memcmp(&k3k3y_dec_watermark[0], &sec0_sec1[0xF70], sizeof(k3k3y_dec_watermark)) == 0)
|
||||||
@ -323,16 +324,16 @@ bool iso_file_decryption::init(const std::string& path)
|
|||||||
switch (m_enc_type)
|
switch (m_enc_type)
|
||||||
{
|
{
|
||||||
case iso_encryption_type::REDUMP:
|
case iso_encryption_type::REDUMP:
|
||||||
sys_log.warning("init(): Set 'enc type': REDUMP, 'reg count': %u: %s", m_region_info.size(), path);
|
iso_log.warning("init: Set 'enc type': REDUMP, 'reg count': %u: %s", m_region_info.size(), path);
|
||||||
break;
|
break;
|
||||||
case iso_encryption_type::ENC_3K3Y:
|
case iso_encryption_type::ENC_3K3Y:
|
||||||
sys_log.warning("init(): Set 'enc type': ENC_3K3Y, 'reg count': %u: %s", m_region_info.size(), path);
|
iso_log.warning("init: Set 'enc type': ENC_3K3Y, 'reg count': %u: %s", m_region_info.size(), path);
|
||||||
break;
|
break;
|
||||||
case iso_encryption_type::DEC_3K3Y:
|
case iso_encryption_type::DEC_3K3Y:
|
||||||
sys_log.warning("init(): Set 'enc type': DEC_3K3Y, 'reg count': %u: %s", m_region_info.size(), path);
|
iso_log.warning("init: Set 'enc type': DEC_3K3Y, 'reg count': %u: %s", m_region_info.size(), path);
|
||||||
break;
|
break;
|
||||||
case iso_encryption_type::NONE: // If encryption type was not set for any reason
|
case iso_encryption_type::NONE: // If encryption type was not set for any reason
|
||||||
sys_log.warning("init(): Set 'enc type': NONE, 'reg count': %u: %s", m_region_info.size(), path);
|
iso_log.warning("init: Set 'enc type': NONE, 'reg count': %u: %s", m_region_info.size(), path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +385,7 @@ bool iso_file_decryption::decrypt(u64 offset, void* buffer, u64 size, const std:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_log.error("decrypt(): %s: LBA request wasn't in the 'm_region_info' for an encrypted ISO? - RP: 0x%lx, RC: 0x%lx, LR: (0x%016lx - 0x%016lx)",
|
iso_log.error("decrypt: %s: LBA request wasn't in the 'm_region_info' for an encrypted ISO? - RP: 0x%lx, RC: 0x%lx, LR: (0x%016lx - 0x%016lx)",
|
||||||
name,
|
name,
|
||||||
offset,
|
offset,
|
||||||
static_cast<unsigned long int>(m_region_info.size()),
|
static_cast<unsigned long int>(m_region_info.size()),
|
||||||
@ -492,7 +493,7 @@ static std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& entry,
|
|||||||
|
|
||||||
utf16.resize(header.file_name_length / 2);
|
utf16.resize(header.file_name_length / 2);
|
||||||
|
|
||||||
for (size_t i = 0; i < utf16.size(); ++i, raw++)
|
for (usz i = 0; i < utf16.size(); ++i, raw++)
|
||||||
{
|
{
|
||||||
utf16[i] = *reinterpret_cast<const be_t<u16>*>(raw);
|
utf16[i] = *reinterpret_cast<const be_t<u16>*>(raw);
|
||||||
}
|
}
|
||||||
@ -664,8 +665,8 @@ iso_fs_node* iso_archive::retrieve(const std::string& passed_path)
|
|||||||
const std::string path = std::filesystem::path(passed_path).string();
|
const std::string path = std::filesystem::path(passed_path).string();
|
||||||
const std::string_view path_sv = path;
|
const std::string_view path_sv = path;
|
||||||
|
|
||||||
size_t start = 0;
|
usz start = 0;
|
||||||
size_t end = path_sv.find_first_of(fs::delim);
|
usz end = path_sv.find_first_of(fs::delim);
|
||||||
|
|
||||||
std::stack<iso_fs_node*> search_stack;
|
std::stack<iso_fs_node*> search_stack;
|
||||||
search_stack.push(&m_root);
|
search_stack.push(&m_root);
|
||||||
@ -907,7 +908,7 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
|
|||||||
{
|
{
|
||||||
if (total_read != first_sec.size_aligned)
|
if (total_read != first_sec.size_aligned)
|
||||||
{
|
{
|
||||||
sys_log.error("read_at(): %s: Error reading from file", m_meta.name);
|
iso_log.error("read_at: %s: Error reading from file", m_meta.name);
|
||||||
|
|
||||||
seek(m_pos, fs::seek_set);
|
seek(m_pos, fs::seek_set);
|
||||||
return 0;
|
return 0;
|
||||||
@ -949,7 +950,7 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
|
|||||||
|
|
||||||
if (total_read != first_sec.size_aligned + last_sec.size_aligned + expected_inner_sector_read)
|
if (total_read != first_sec.size_aligned + last_sec.size_aligned + expected_inner_sector_read)
|
||||||
{
|
{
|
||||||
sys_log.error("read_at(): %s: Error reading from file", m_meta.name);
|
iso_log.error("read_at: %s: Error reading from file", m_meta.name);
|
||||||
|
|
||||||
seek(m_pos, fs::seek_set);
|
seek(m_pos, fs::seek_set);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -91,6 +91,8 @@ namespace iso_cache
|
|||||||
|
|
||||||
void save(const std::string& iso_path, const iso_metadata_cache_entry& entry)
|
void save(const std::string& iso_path, const iso_metadata_cache_entry& entry)
|
||||||
{
|
{
|
||||||
|
iso_cache_log.notice("Saving cache for '%s'", iso_path);
|
||||||
|
|
||||||
const std::string stem = get_cache_stem(iso_path);
|
const std::string stem = get_cache_stem(iso_path);
|
||||||
const std::string dir = get_cache_dir();
|
const std::string dir = get_cache_dir();
|
||||||
const std::string yml_path = dir + stem + ".yml";
|
const std::string yml_path = dir + stem + ".yml";
|
||||||
|
|||||||
@ -29,4 +29,4 @@ namespace iso_cache
|
|||||||
|
|
||||||
// Remove cache entries for ISOs that are no longer in the scanned set.
|
// Remove cache entries for ISOs that are no longer in the scanned set.
|
||||||
void cleanup(const std::unordered_set<std::string>& valid_iso_paths);
|
void cleanup(const std::unordered_set<std::string>& valid_iso_paths);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -566,11 +566,7 @@ void game_list_frame::OnParsingFinished()
|
|||||||
|
|
||||||
// Load PSF: from archive on cache miss, rehydrate from cached SFO bytes on hit.
|
// Load PSF: from archive on cache miss, rehydrate from cached SFO bytes on hit.
|
||||||
psf::registry psf{};
|
psf::registry psf{};
|
||||||
if (archive)
|
if (!cache_entry.psf_data.empty())
|
||||||
{
|
|
||||||
psf = archive->open_psf(sfo_path);
|
|
||||||
}
|
|
||||||
else if (!cache_entry.psf_data.empty())
|
|
||||||
{
|
{
|
||||||
psf = psf::load_object(fs::make_stream<std::vector<u8>>(std::vector<u8>(cache_entry.psf_data)), sfo_path);
|
psf = psf::load_object(fs::make_stream<std::vector<u8>>(std::vector<u8>(cache_entry.psf_data)), sfo_path);
|
||||||
// Fallback to archive scan if cached PSF is corrupted or missing critical fields.
|
// Fallback to archive scan if cached PSF is corrupted or missing critical fields.
|
||||||
@ -579,14 +575,23 @@ void game_list_frame::OnParsingFinished()
|
|||||||
&& !psf::get_string(psf, "CATEGORY", "").empty();
|
&& !psf::get_string(psf, "CATEGORY", "").empty();
|
||||||
if (!psf_valid)
|
if (!psf_valid)
|
||||||
{
|
{
|
||||||
|
game_list_log.warning("Cached psf for iso not valid: '%s'", game.info.path);
|
||||||
archive = std::make_unique<iso_archive>(dir_or_elf);
|
archive = std::make_unique<iso_archive>(dir_or_elf);
|
||||||
psf = archive->open_psf(sfo_path);
|
|
||||||
cache_entry = {}; // Reset so the cache gets rewritten after scan.
|
cache_entry = {}; // Reset so the cache gets rewritten after scan.
|
||||||
|
psf = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (psf.empty())
|
||||||
{
|
{
|
||||||
psf = psf::load_object(sfo_path);
|
if (archive)
|
||||||
|
{
|
||||||
|
psf = archive->open_psf(sfo_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psf = psf::load_object(sfo_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string_view title_id = psf::get_string(psf, "TITLE_ID", "");
|
const std::string_view title_id = psf::get_string(psf, "TITLE_ID", "");
|
||||||
@ -676,17 +681,17 @@ void game_list_frame::OnParsingFinished()
|
|||||||
|
|
||||||
if (play_hover_movies)
|
if (play_hover_movies)
|
||||||
{
|
{
|
||||||
if (!cache_entry.movie_path.empty() && !archive)
|
|
||||||
{
|
|
||||||
// Cache hit — restore previously resolved movie path.
|
|
||||||
game.info.movie_path = cache_entry.movie_path;
|
|
||||||
game.has_hover_pam = true;
|
|
||||||
}
|
|
||||||
if (std::string movie_path = game_icon_path + game.info.serial + "/hover.gif"; file_exists(movie_path))
|
if (std::string movie_path = game_icon_path + game.info.serial + "/hover.gif"; file_exists(movie_path))
|
||||||
{
|
{
|
||||||
game.info.movie_path = std::move(movie_path);
|
game.info.movie_path = std::move(movie_path);
|
||||||
game.has_hover_gif = true;
|
game.has_hover_gif = true;
|
||||||
}
|
}
|
||||||
|
else if (!cache_entry.movie_path.empty() && !archive)
|
||||||
|
{
|
||||||
|
// Cache hit — restore previously resolved movie path.
|
||||||
|
game.info.movie_path = cache_entry.movie_path;
|
||||||
|
game.has_hover_pam = true;
|
||||||
|
}
|
||||||
else if (std::string movie_path = sfo_dir + "/" + localized_movie; file_exists(movie_path))
|
else if (std::string movie_path = sfo_dir + "/" + localized_movie; file_exists(movie_path))
|
||||||
{
|
{
|
||||||
game.info.movie_path = std::move(movie_path);
|
game.info.movie_path = std::move(movie_path);
|
||||||
@ -701,13 +706,13 @@ void game_list_frame::OnParsingFinished()
|
|||||||
|
|
||||||
if (play_hover_music)
|
if (play_hover_music)
|
||||||
{
|
{
|
||||||
if(!cache_entry.audio_path.empty() && !archive)
|
if (!cache_entry.audio_path.empty() && !archive)
|
||||||
{
|
{
|
||||||
// Cache hit — restore previously resolved audio path.
|
// Cache hit — restore previously resolved audio path.
|
||||||
game.info.audio_path = cache_entry.audio_path;
|
game.info.audio_path = cache_entry.audio_path;
|
||||||
game.has_audio_file = true;
|
game.has_audio_file = true;
|
||||||
}
|
}
|
||||||
if (std::string audio_path = sfo_dir + "/SND0.AT3"; file_exists(audio_path))
|
else if (std::string audio_path = sfo_dir + "/SND0.AT3"; file_exists(audio_path))
|
||||||
{
|
{
|
||||||
game.info.audio_path = std::move(audio_path);
|
game.info.audio_path = std::move(audio_path);
|
||||||
game.has_audio_file = true;
|
game.has_audio_file = true;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user