iso stuff

This commit is contained in:
Megamouse 2026-04-13 08:50:51 +02:00
parent 9e3e01d8f6
commit b10c742f10
4 changed files with 48 additions and 40 deletions

View File

@ -11,6 +11,7 @@
#include <stack>
LOG_CHANNEL(sys_log, "SYS");
LOG_CHANNEL(iso_log, "ISO");
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
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;
}
@ -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)
{
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;
}
@ -142,7 +143,7 @@ static bool decrypt_data(aes_context& aes, u64 offset, unsigned char* buffer, u6
// 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)
{
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;
}
@ -164,8 +165,6 @@ bool iso_file_decryption::init(const std::string& path)
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)
//
@ -174,19 +173,21 @@ bool iso_file_decryption::init(const std::string& path)
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;
}
std::array<u8, ISO_SECTOR_SIZE * 2> sec0_sec1 {};
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;
}
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;
}
@ -195,12 +196,12 @@ bool iso_file_decryption::init(const std::string& path)
// 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
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
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;
}
@ -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
{
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
{
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
{
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)
@ -323,16 +324,16 @@ bool iso_file_decryption::init(const std::string& path)
switch (m_enc_type)
{
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;
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;
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;
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;
}
@ -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,
offset,
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);
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);
}
@ -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_view path_sv = path;
size_t start = 0;
size_t end = path_sv.find_first_of(fs::delim);
usz start = 0;
usz end = path_sv.find_first_of(fs::delim);
std::stack<iso_fs_node*> search_stack;
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)
{
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);
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)
{
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);
return 0;

View File

@ -91,6 +91,8 @@ namespace iso_cache
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 dir = get_cache_dir();
const std::string yml_path = dir + stem + ".yml";

View File

@ -29,4 +29,4 @@ namespace iso_cache
// Remove cache entries for ISOs that are no longer in the scanned set.
void cleanup(const std::unordered_set<std::string>& valid_iso_paths);
}
}

View File

@ -566,11 +566,7 @@ void game_list_frame::OnParsingFinished()
// Load PSF: from archive on cache miss, rehydrate from cached SFO bytes on hit.
psf::registry psf{};
if (archive)
{
psf = archive->open_psf(sfo_path);
}
else if (!cache_entry.psf_data.empty())
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);
// 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();
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);
psf = archive->open_psf(sfo_path);
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", "");
@ -676,17 +681,17 @@ void game_list_frame::OnParsingFinished()
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))
{
game.info.movie_path = std::move(movie_path);
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))
{
game.info.movie_path = std::move(movie_path);
@ -701,13 +706,13 @@ void game_list_frame::OnParsingFinished()
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.
game.info.audio_path = cache_entry.audio_path;
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.has_audio_file = true;