Qt: ISO clean up

Should fix some potential Qt bugs as well
This commit is contained in:
Megamouse
2025-12-16 21:08:08 +01:00
parent be77083a2b
commit 19129eddd7
14 changed files with 191 additions and 196 deletions
+12 -11
View File
@@ -1296,6 +1296,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
m_path_old = m_path; m_path_old = m_path;
resolve_path_as_vfs_path = true; resolve_path_as_vfs_path = true;
if (launching_from_disc_archive) if (launching_from_disc_archive)
{ {
load_iso(disc_info); load_iso(disc_info);
@@ -1636,13 +1637,13 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
} }
// ISO PKG INSTALL HACK! // ISO PKG INSTALL HACK!
if (fs::is_dir(m_path) && launching_from_disc_archive) if (launching_from_disc_archive && fs::is_dir(m_path))
{ {
bdvd_dir = m_path; bdvd_dir = m_path;
} }
// Special boot mode (directory scan) // Special boot mode (directory scan)
if (fs::is_dir(m_path) && !launching_from_disc_archive) if (!launching_from_disc_archive && fs::is_dir(m_path))
{ {
m_state = system_state::ready; m_state = system_state::ready;
GetCallbacks().on_ready(); GetCallbacks().on_ready();
@@ -2142,7 +2143,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
// ISO has no USRDIR/EBOOT.BIN, and we've examined its PKGDIR and extras. // ISO has no USRDIR/EBOOT.BIN, and we've examined its PKGDIR and extras.
// time to wrap up // time to wrap up
if (fs::is_dir(m_path) && launching_from_disc_archive) if (launching_from_disc_archive && fs::is_dir(m_path))
{ {
return game_boot_result::nothing_to_boot; return game_boot_result::nothing_to_boot;
} }
@@ -2255,8 +2256,8 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
// Check game updates // Check game updates
if (const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN"; !m_ar if (const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN"; !m_ar
&& recursion_count == 0 && disc.empty() && !bdvd_dir.empty() && !m_title_id.empty() && recursion_count == 0 && disc.empty() && !bdvd_dir.empty() && !m_title_id.empty()
&& (resolved_path == GetCallbacks().resolve_path(vfs::get("/dev_bdvd/PS3_GAME/USRDIR/EBOOT.BIN")) && (launching_from_disc_archive ||
|| launching_from_disc_archive) resolved_path == GetCallbacks().resolve_path(vfs::get("/dev_bdvd/PS3_GAME/USRDIR/EBOOT.BIN")))
&& resolved_path != GetCallbacks().resolve_path(hdd0_boot) && fs::is_file(hdd0_boot) && resolved_path != GetCallbacks().resolve_path(hdd0_boot) && fs::is_file(hdd0_boot)
&& ppu_exec == elf_error::ok) && ppu_exec == elf_error::ok)
{ {
@@ -2367,7 +2368,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch,
else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir)) else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
{ {
// Disc games are on /dev_bdvd/ // Disc games are on /dev_bdvd/
std::string disc_path = !launching_from_disc_archive ? resolved_path : m_path; const std::string& disc_path = !launching_from_disc_archive ? resolved_path : m_path;
const usz pos = disc_path.rfind(m_game_dir); const usz pos = disc_path.rfind(m_game_dir);
argv[0] = "/dev_bdvd/PS3_GAME/" + unescape(disc_path.substr(pos + m_game_dir.size() + 1)); argv[0] = "/dev_bdvd/PS3_GAME/" + unescape(disc_path.substr(pos + m_game_dir.size() + 1));
m_dir = "/dev_bdvd/PS3_GAME/"; m_dir = "/dev_bdvd/PS3_GAME/";
@@ -3622,13 +3623,13 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
// Game mounted from archive // Game mounted from archive
if (m_path.starts_with(iso_device::virtual_device_name + "/")) if (m_path.starts_with(iso_device::virtual_device_name + "/"))
{ {
auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/"); const auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/");
ensure(device); ensure(device);
auto iso_device = dynamic_cast<class iso_device*>(device.get()); const auto iso_dev = dynamic_cast<const iso_device*>(device.get());
ar(m_path.substr(iso_device::virtual_device_name.size() + 1)); ar(m_path.substr(iso_device::virtual_device_name.size() + 1));
ar(iso_device->get_loaded_iso()); ar(iso_dev->get_loaded_iso());
} }
else if (auto dir = vfs::get("/dev_bdvd/PS3_GAME"); fs::is_dir(dir) && !fs::is_file(fs::get_parent_dir(dir) + "/PS3_DISC.SFB")) else if (auto dir = vfs::get("/dev_bdvd/PS3_GAME"); fs::is_dir(dir) && !fs::is_file(fs::get_parent_dir(dir) + "/PS3_DISC.SFB"))
{ {
@@ -4245,9 +4246,9 @@ game_boot_result Emulator::AddGameToYml(const std::string& path)
// Load PARAM.SFO // Load PARAM.SFO
const std::string elf_dir = fs::get_parent_dir(path); const std::string elf_dir = fs::get_parent_dir(path);
std::string sfo_dir = !archive ? rpcs3::utils::get_sfo_dir_from_game_path(fs::get_parent_dir(elf_dir)) : "PS3_GAME"; std::string sfo_dir = archive ? "PS3_GAME" : rpcs3::utils::get_sfo_dir_from_game_path(fs::get_parent_dir(elf_dir));
const std::string sfo_path = sfo_dir + "/PARAM.SFO"; const std::string sfo_path = sfo_dir + "/PARAM.SFO";
const psf::registry _psf = !archive ? psf::load_object(sfo_path) : archive->open_psf(sfo_path); const psf::registry _psf = archive ? archive->open_psf(sfo_path) : psf::load_object(sfo_path);
const std::string title_id = std::string(psf::get_string(_psf, "TITLE_ID")); const std::string title_id = std::string(psf::get_string(_psf, "TITLE_ID"));
const std::string cat = std::string(psf::get_string(_psf, "CATEGORY")); const std::string cat = std::string(psf::get_string(_psf, "CATEGORY"));
+3 -3
View File
@@ -48,11 +48,11 @@ games_config::result games_config::add_game(const std::string& key, const std::s
{ {
if (path == iso_device::virtual_device_name + "/") if (path == iso_device::virtual_device_name + "/")
{ {
auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/"); const auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/");
if (!device) return result::failure; if (!device) return result::failure;
auto iso_device = dynamic_cast<class iso_device*>(device.get()); const auto iso_dev = dynamic_cast<const iso_device*>(device.get());
return add_game(key, iso_device->get_loaded_iso()); return add_game(key, iso_dev->get_loaded_iso());
} }
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
+60 -71
View File
@@ -11,6 +11,7 @@
bool is_file_iso(const std::string& path) bool is_file_iso(const std::string& path)
{ {
if (path.empty()) return false;
if (fs::is_dir(path)) return false; if (fs::is_dir(path)) return false;
return is_file_iso(fs::file(path)); return is_file_iso(fs::file(path));
@@ -55,14 +56,14 @@ inline T read_both_endian_int(fs::file& file)
// assumed that directory_entry is at file head // assumed that directory_entry is at file head
std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool names_in_ucs2 = false) std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool names_in_ucs2 = false)
{ {
auto start_pos = file.pos(); const auto start_pos = file.pos();
u8 entry_length = file.read<u8>(); const u8 entry_length = file.read<u8>();
if (entry_length == 0) return std::nullopt; if (entry_length == 0) return std::nullopt;
file.seek(1, fs::seek_cur); file.seek(1, fs::seek_cur);
u32 start_sector = read_both_endian_int<u32>(file); const u32 start_sector = read_both_endian_int<u32>(file);
u32 file_size = read_both_endian_int<u32>(file); const u32 file_size = read_both_endian_int<u32>(file);
std::tm file_date = {}; std::tm file_date = {};
file_date.tm_year = file.read<u8>(); file_date.tm_year = file.read<u8>();
@@ -71,20 +72,20 @@ std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool nam
file_date.tm_hour = file.read<u8>(); file_date.tm_hour = file.read<u8>();
file_date.tm_min = file.read<u8>(); file_date.tm_min = file.read<u8>();
file_date.tm_sec = file.read<u8>(); file_date.tm_sec = file.read<u8>();
s16 timezone_value = file.read<u8>(); const s16 timezone_value = file.read<u8>();
s16 timezone_offset = (timezone_value - 50) * 15 * 60; const s16 timezone_offset = (timezone_value - 50) * 15 * 60;
std::time_t date_time = std::mktime(&file_date) + timezone_offset; const std::time_t date_time = std::mktime(&file_date) + timezone_offset;
u8 flags = file.read<u8>(); const u8 flags = file.read<u8>();
// 2nd flag bit indicates whether a given fs node is a directory // 2nd flag bit indicates whether a given fs node is a directory
bool is_directory = flags & 0b00000010; const bool is_directory = flags & 0b00000010;
bool has_more_extents = flags & 0b10000000; const bool has_more_extents = flags & 0b10000000;
file.seek(6, fs::seek_cur); file.seek(6, fs::seek_cur);
u8 file_name_length = file.read<u8>(); const u8 file_name_length = file.read<u8>();
std::string file_name; std::string file_name;
file.read(file_name, file_name_length); file.read(file_name, file_name_length);
@@ -99,7 +100,7 @@ std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool nam
} }
else if (names_in_ucs2) // for strings in joliet descriptor else if (names_in_ucs2) // for strings in joliet descriptor
{ {
std::string new_file_name = ""; std::string new_file_name;
int read = 0; int read = 0;
const u8* raw_str = reinterpret_cast<const u8*>(file_name.c_str()); const u8* raw_str = reinterpret_cast<const u8*>(file_name.c_str());
while (read < file_name_length) while (read < file_name_length)
@@ -134,7 +135,7 @@ std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool nam
return iso_fs_metadata return iso_fs_metadata
{ {
.name = file_name, .name = std::move(file_name),
.time = date_time, .time = date_time,
.is_directory = is_directory, .is_directory = is_directory,
.has_multiple_extents = has_more_extents, .has_multiple_extents = has_more_extents,
@@ -149,26 +150,25 @@ std::optional<iso_fs_metadata> iso_read_directory_entry(fs::file& file, bool nam
}; };
} }
void iso_form_hierarchy(fs::file& file, iso_fs_node& node, void iso_form_hierarchy(fs::file& file, iso_fs_node& node, bool use_ucs2_decoding = false, const std::string& parent_path = "")
bool use_ucs2_decoding = false, std::string parent_path = "")
{ {
if (!node.metadata.is_directory) return; if (!node.metadata.is_directory) return;
std::vector<int> multi_extent_node_indices; std::vector<usz> multi_extent_node_indices;
// assuming the directory spans a single extent // assuming the directory spans a single extent
const auto& directory_extent = node.metadata.extents[0]; const auto& directory_extent = node.metadata.extents[0];
file.seek(directory_extent.start * ISO_BLOCK_SIZE); file.seek(directory_extent.start * ISO_BLOCK_SIZE);
u64 end_pos = directory_extent.size + (directory_extent.start * ISO_BLOCK_SIZE); const u64 end_pos = directory_extent.size + (directory_extent.start * ISO_BLOCK_SIZE);
while(file.pos() < end_pos) while(file.pos() < end_pos)
{ {
auto entry = iso_read_directory_entry(file, use_ucs2_decoding); auto entry = iso_read_directory_entry(file, use_ucs2_decoding);
if (!entry) if (!entry)
{ {
u64 new_sector = (file.pos() / ISO_BLOCK_SIZE) + 1; const u64 new_sector = (file.pos() / ISO_BLOCK_SIZE) + 1;
file.seek(new_sector * ISO_BLOCK_SIZE); file.seek(new_sector * ISO_BLOCK_SIZE);
continue; continue;
} }
@@ -176,10 +176,10 @@ void iso_form_hierarchy(fs::file& file, iso_fs_node& node,
bool extent_added = false; bool extent_added = false;
// find previous extent and merge into it, otherwise we push this node's index // find previous extent and merge into it, otherwise we push this node's index
for (int index : multi_extent_node_indices) for (usz index : multi_extent_node_indices)
{ {
auto& selected_node = node.children.at(index); auto& selected_node = ::at32(node.children, index);
if (selected_node->metadata.name.compare(entry->name) == 0) if (selected_node->metadata.name == entry->name)
{ {
// merge into selected_node // merge into selected_node
selected_node->metadata.extents.push_back(entry->extents[0]); selected_node->metadata.extents.push_back(entry->extents[0]);
@@ -197,7 +197,7 @@ void iso_form_hierarchy(fs::file& file, iso_fs_node& node,
} }
node.children.push_back(std::make_unique<iso_fs_node>(iso_fs_node{ node.children.push_back(std::make_unique<iso_fs_node>(iso_fs_node{
.metadata = *entry .metadata = std::move(*entry)
})); }));
} }
@@ -237,7 +237,7 @@ iso_archive::iso_archive(const std::string& path)
do do
{ {
auto descriptor_start = m_file.pos(); const auto descriptor_start = m_file.pos();
descriptor_type = m_file.read<u8>(); descriptor_type = m_file.read<u8>();
@@ -266,7 +266,7 @@ iso_fs_node* iso_archive::retrieve(const std::string& passed_path)
{ {
if (passed_path.empty()) return nullptr; if (passed_path.empty()) return nullptr;
std::string path = std::filesystem::path(passed_path).string(); const std::string path = std::filesystem::path(passed_path).string();
size_t start = 0; size_t start = 0;
size_t end = path.find_first_of(fs::delim); size_t end = path.find_first_of(fs::delim);
@@ -277,14 +277,14 @@ iso_fs_node* iso_archive::retrieve(const std::string& passed_path)
do do
{ {
if (search_stack.empty()) return nullptr; if (search_stack.empty()) return nullptr;
auto* top_entry = search_stack.top(); const auto* top_entry = search_stack.top();
if (end == std::string::npos) if (end == umax)
{ {
end = path.size(); end = path.size();
} }
auto path_component = path.substr(start, end-start); const auto path_component = path.substr(start, end-start);
bool found = false; bool found = false;
@@ -301,7 +301,7 @@ iso_fs_node* iso_archive::retrieve(const std::string& passed_path)
{ {
for (const auto& entry : top_entry->children) for (const auto& entry : top_entry->children)
{ {
if (entry->metadata.name.compare(path_component) == 0) if (entry->metadata.name == path_component)
{ {
search_stack.push(entry.get()); search_stack.push(entry.get());
@@ -330,7 +330,7 @@ bool iso_archive::exists(const std::string& path)
bool iso_archive::is_file(const std::string& path) bool iso_archive::is_file(const std::string& path)
{ {
auto file_node = retrieve(path); const auto file_node = retrieve(path);
if (!file_node) return false; if (!file_node) return false;
return !file_node->metadata.is_directory; return !file_node->metadata.is_directory;
@@ -338,7 +338,7 @@ bool iso_archive::is_file(const std::string& path)
iso_file iso_archive::open(const std::string& path) iso_file iso_archive::open(const std::string& path)
{ {
return iso_file(fs::file(m_path), *retrieve(path)); return iso_file(fs::file(m_path), *ensure(retrieve(path)));
} }
psf::registry iso_archive::open_psf(const std::string& path) psf::registry iso_archive::open_psf(const std::string& path)
@@ -355,7 +355,7 @@ psf::registry iso_archive::open_psf(const std::string& path)
} }
iso_file::iso_file(fs::file&& iso_handle, const iso_fs_node& node) iso_file::iso_file(fs::file&& iso_handle, const iso_fs_node& node)
: m_file(std::move(iso_handle)), m_meta(node.metadata), m_pos(0) : m_file(std::move(iso_handle)), m_meta(node.metadata)
{ {
m_file.seek(ISO_BLOCK_SIZE * node.metadata.extents[0].start); m_file.seek(ISO_BLOCK_SIZE * node.metadata.extents[0].start);
} }
@@ -374,7 +374,7 @@ fs::stat_t iso_file::get_stat()
}; };
} }
bool iso_file::trunc(u64) bool iso_file::trunc(u64 /*length*/)
{ {
fs::g_tls_error = fs::error::readonly; fs::g_tls_error = fs::error::readonly;
return false; return false;
@@ -382,6 +382,8 @@ bool iso_file::trunc(u64)
std::pair<u64, iso_extent_info> iso_file::get_extent_pos(u64 pos) const std::pair<u64, iso_extent_info> iso_file::get_extent_pos(u64 pos) const
{ {
ensure(!m_meta.extents.empty());
auto it = m_meta.extents.begin(); auto it = m_meta.extents.begin();
while (pos >= it->size && it != m_meta.extents.end() - 1) while (pos >= it->size && it != m_meta.extents.end() - 1)
@@ -397,14 +399,14 @@ std::pair<u64, iso_extent_info> iso_file::get_extent_pos(u64 pos) const
// assumed valid and in bounds. // assumed valid and in bounds.
u64 iso_file::file_offset(u64 pos) const u64 iso_file::file_offset(u64 pos) const
{ {
auto [local_pos, extent] = get_extent_pos(pos); const auto [local_pos, extent] = get_extent_pos(pos);
return (extent.start * ISO_BLOCK_SIZE) + local_pos; return (extent.start * ISO_BLOCK_SIZE) + local_pos;
} }
u64 iso_file::local_extent_remaining(u64 pos) const u64 iso_file::local_extent_remaining(u64 pos) const
{ {
auto [local_pos, extent] = get_extent_pos(pos); const auto [local_pos, extent] = get_extent_pos(pos);
return extent.size - local_pos; return extent.size - local_pos;
} }
@@ -416,25 +418,22 @@ u64 iso_file::local_extent_size(u64 pos) const
u64 iso_file::read(void* buffer, u64 size) u64 iso_file::read(void* buffer, u64 size)
{ {
auto r = read_at(m_pos, buffer, size); const auto r = read_at(m_pos, buffer, size);
m_pos += r; m_pos += r;
return r; return r;
} }
u64 iso_file::read_at(u64 offset, void* buffer, u64 size) u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
{ {
u64 local_remaining = local_extent_remaining(offset); const u64 local_remaining = local_extent_remaining(offset);
u64 total_read = m_file.read_at(file_offset(offset), buffer, std::min(size, local_remaining)); const u64 total_read = m_file.read_at(file_offset(offset), buffer, std::min(size, local_remaining));
auto total_size = this->size(); const auto total_size = this->size();
if (size > total_read && (offset + total_read) < total_size) if (size > total_read && (offset + total_read) < total_size)
{ {
u64 second_total_read = read_at(offset + total_read, const u64 second_total_read = read_at(offset + total_read, reinterpret_cast<u8*>(buffer) + total_read, size - total_read);
reinterpret_cast<u8*>(buffer) + total_read,
size - total_read
);
return total_read + second_total_read; return total_read + second_total_read;
} }
@@ -442,7 +441,7 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
return total_read; return total_read;
} }
u64 iso_file::write(const void*, u64) u64 iso_file::write(const void* /*buffer*/, u64 /*size*/)
{ {
fs::g_tls_error = fs::error::readonly; fs::g_tls_error = fs::error::readonly;
return 0; return 0;
@@ -462,10 +461,8 @@ u64 iso_file::seek(s64 offset, fs::seek_mode whence)
return -1; return -1;
} }
const u64 bad_res = -1; const u64 result = m_file.seek(file_offset(m_pos));
if (result == umax) return umax;
u64 result = m_file.seek(file_offset(m_pos));
if (result == bad_res) return -1;
m_pos = new_pos; m_pos = new_pos;
return m_pos; return m_pos;
@@ -491,8 +488,7 @@ bool iso_dir::read(fs::dir_entry& entry)
{ {
if (m_pos < m_node.children.size()) if (m_pos < m_node.children.size())
{ {
auto& selected = m_node.children[m_pos].get()->metadata; const auto& selected = m_node.children[m_pos].get()->metadata;
u64 size = selected.size();
entry.name = selected.name; entry.name = selected.name;
entry.atime = selected.time; entry.atime = selected.time;
@@ -501,7 +497,7 @@ bool iso_dir::read(fs::dir_entry& entry)
entry.is_directory = selected.is_directory; entry.is_directory = selected.is_directory;
entry.is_symlink = false; entry.is_symlink = false;
entry.is_writable = false; entry.is_writable = false;
entry.size = size; entry.size = selected.size();
m_pos++; m_pos++;
@@ -513,25 +509,23 @@ bool iso_dir::read(fs::dir_entry& entry)
bool iso_device::stat(const std::string& path, fs::stat_t& info) bool iso_device::stat(const std::string& path, fs::stat_t& info)
{ {
auto relative_path = std::filesystem::relative(std::filesystem::path(path), const auto relative_path = std::filesystem::relative(std::filesystem::path(path), std::filesystem::path(fs_prefix)).string();
std::filesystem::path(fs_prefix)).string();
auto node = m_archive.retrieve(relative_path); const auto node = m_archive.retrieve(relative_path);
if (!node) if (!node)
{ {
fs::g_tls_error = fs::error::noent; fs::g_tls_error = fs::error::noent;
return false; return false;
} }
auto& meta = node->metadata; const auto& meta = node->metadata;
u64 size = meta.size();
info = fs::stat_t info = fs::stat_t
{ {
.is_directory = meta.is_directory, .is_directory = meta.is_directory,
.is_symlink = false, .is_symlink = false,
.is_writable = false, .is_writable = false,
.size = size, .size = meta.size(),
.atime = meta.time, .atime = meta.time,
.mtime = meta.time, .mtime = meta.time,
.ctime = meta.time .ctime = meta.time
@@ -542,18 +536,17 @@ bool iso_device::stat(const std::string& path, fs::stat_t& info)
bool iso_device::statfs(const std::string& path, fs::device_stat& info) bool iso_device::statfs(const std::string& path, fs::device_stat& info)
{ {
auto relative_path = std::filesystem::relative(std::filesystem::path(path), const auto relative_path = std::filesystem::relative(std::filesystem::path(path), std::filesystem::path(fs_prefix)).string();
std::filesystem::path(fs_prefix)).string();
auto node = m_archive.retrieve(relative_path); const auto node = m_archive.retrieve(relative_path);
if (!node) if (!node)
{ {
fs::g_tls_error = fs::error::noent; fs::g_tls_error = fs::error::noent;
return false; return false;
} }
auto& meta = node->metadata; const auto& meta = node->metadata;
u64 size = meta.size(); const u64 size = meta.size();
info = fs::device_stat info = fs::device_stat
{ {
@@ -568,10 +561,9 @@ bool iso_device::statfs(const std::string& path, fs::device_stat& info)
std::unique_ptr<fs::file_base> iso_device::open(const std::string& path, bs_t<fs::open_mode> mode) std::unique_ptr<fs::file_base> iso_device::open(const std::string& path, bs_t<fs::open_mode> mode)
{ {
auto relative_path = std::filesystem::relative(std::filesystem::path(path), const auto relative_path = std::filesystem::relative(std::filesystem::path(path), std::filesystem::path(fs_prefix)).string();
std::filesystem::path(fs_prefix)).string();
auto node = m_archive.retrieve(relative_path); const auto node = m_archive.retrieve(relative_path);
if (!node) if (!node)
{ {
fs::g_tls_error = fs::error::noent; fs::g_tls_error = fs::error::noent;
@@ -589,10 +581,9 @@ std::unique_ptr<fs::file_base> iso_device::open(const std::string& path, bs_t<fs
std::unique_ptr<fs::dir_base> iso_device::open_dir(const std::string& path) std::unique_ptr<fs::dir_base> iso_device::open_dir(const std::string& path)
{ {
auto relative_path = std::filesystem::relative(std::filesystem::path(path), const auto relative_path = std::filesystem::relative(std::filesystem::path(path), std::filesystem::path(fs_prefix)).string();
std::filesystem::path(fs_prefix)).string();
auto node = m_archive.retrieve(relative_path); const auto node = m_archive.retrieve(relative_path);
if (!node) if (!node)
{ {
fs::g_tls_error = fs::error::noent; fs::g_tls_error = fs::error::noent;
@@ -618,14 +609,12 @@ void iso_dir::rewind()
void load_iso(const std::string& path) void load_iso(const std::string& path)
{ {
fs::set_virtual_device("iso_overlay_fs_dev", fs::set_virtual_device("iso_overlay_fs_dev", stx::make_shared<iso_device>(path));
stx::make_shared<iso_device>(path));
vfs::mount("/dev_bdvd/"sv, iso_device::virtual_device_name + "/"); vfs::mount("/dev_bdvd/"sv, iso_device::virtual_device_name + "/");
} }
void unload_iso() void unload_iso()
{ {
fs::set_virtual_device("iso_overlay_fs_dev", fs::set_virtual_device("iso_overlay_fs_dev", stx::shared_ptr<iso_device>());
stx::shared_ptr<iso_device>());
} }
+7 -3
View File
@@ -36,9 +36,10 @@ struct iso_fs_node
class iso_file : public fs::file_base class iso_file : public fs::file_base
{ {
private:
fs::file m_file; fs::file m_file;
iso_fs_metadata m_meta; iso_fs_metadata m_meta;
u64 m_pos; u64 m_pos = 0;
std::pair<u64, iso_extent_info> get_extent_pos(u64 pos) const; std::pair<u64, iso_extent_info> get_extent_pos(u64 pos) const;
u64 file_offset(u64 pos) const; u64 file_offset(u64 pos) const;
@@ -61,12 +62,13 @@ class iso_file : public fs::file_base
class iso_dir : public fs::dir_base class iso_dir : public fs::dir_base
{ {
private:
const iso_fs_node& m_node; const iso_fs_node& m_node;
u64 m_pos; u64 m_pos = 0;
public: public:
iso_dir(const iso_fs_node& node) iso_dir(const iso_fs_node& node)
: m_node(node), m_pos(0) : m_node(node)
{} {}
bool read(fs::dir_entry&) override; bool read(fs::dir_entry&) override;
@@ -76,6 +78,7 @@ class iso_dir : public fs::dir_base
// represents the .iso file itself. // represents the .iso file itself.
class iso_archive class iso_archive
{ {
private:
std::string m_path; std::string m_path;
iso_fs_node m_root; iso_fs_node m_root;
fs::file m_file; fs::file m_file;
@@ -94,6 +97,7 @@ class iso_archive
class iso_device : public fs::device_base class iso_device : public fs::device_base
{ {
private:
iso_archive m_archive; iso_archive m_archive;
std::string iso_path; std::string iso_path;
+2 -7
View File
@@ -49,14 +49,9 @@ void game_list_base::IconLoadFunction(game_info game, qreal device_pixel_ratio,
static std::unordered_set<std::string> warn_once_list; static std::unordered_set<std::string> warn_once_list;
static shared_mutex s_mtx; static shared_mutex s_mtx;
if (game->icon.isNull() && (game->info.icon_path.empty() || !game->icon.load(QString::fromStdString(game->info.icon_path)))) if (game->icon.isNull() && !gui::utils::load_icon(game->icon, game->info.icon_path, game->icon_in_archive ? game->info.path : ""))
{ {
if (game->icon_in_archive) if (game_list_log.warning)
{
game->icon_in_archive = gui::utils::load_icon(game->icon, game->info.icon_path, game->info.path);
}
if (!game->icon_in_archive && game_list_log.warning)
{ {
bool logged = false; bool logged = false;
{ {
+3 -4
View File
@@ -531,8 +531,7 @@ void game_list_frame::OnParsingFinished()
const auto file_exists = [&archive](const std::string& path) const auto file_exists = [&archive](const std::string& path)
{ {
if (!archive) return fs::is_file(path); return archive ? archive->is_file(path) : fs::is_file(path);
return archive->is_file(path);
}; };
gui_game_info game{}; gui_game_info game{};
@@ -540,10 +539,10 @@ void game_list_frame::OnParsingFinished()
const Localized thread_localized; const Localized thread_localized;
const std::string sfo_dir = !archive ? rpcs3::utils::get_sfo_dir_from_game_path(dir_or_elf) : "PS3_GAME"; const std::string sfo_dir = archive ? "PS3_GAME" : rpcs3::utils::get_sfo_dir_from_game_path(dir_or_elf);
const std::string sfo_path = sfo_dir + "/PARAM.SFO"; const std::string sfo_path = sfo_dir + "/PARAM.SFO";
const psf::registry psf = !archive ? psf::load_object(sfo_path) : archive->open_psf(sfo_path); const psf::registry psf = archive ? archive->open_psf(sfo_path) : 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", "");
if (title_id.empty()) if (title_id.empty())
+7
View File
@@ -4,6 +4,8 @@
#include "gui_settings.h" #include "gui_settings.h"
#include "qt_utils.h" #include "qt_utils.h"
#include "Loader/ISO.h"
#include <QApplication> #include <QApplication>
game_list_grid::game_list_grid() game_list_grid::game_list_grid()
@@ -110,6 +112,11 @@ void game_list_grid::populate(
if (play_hover_movies && (game->has_hover_gif || game->has_hover_pam)) if (play_hover_movies && (game->has_hover_gif || game->has_hover_pam))
{ {
item->set_video_path(game->info.movie_path); item->set_video_path(game->info.movie_path);
if (!fs::exists(game->info.movie_path) && is_file_iso(game->info.path))
{
item->set_iso_path(game->info.path);
}
} }
if (selected_item_ids.contains(game->info.path + game->info.icon_path)) if (selected_item_ids.contains(game->info.path + game->info.icon_path))
+5 -6
View File
@@ -244,12 +244,6 @@ void game_list_table::populate(
custom_table_widget_item* icon_item = new custom_table_widget_item; custom_table_widget_item* icon_item = new custom_table_widget_item;
game->item = icon_item; game->item = icon_item;
if (is_file_iso(game->info.path) && !game->info.movie_path.empty()
&& !fs::exists(game->info.movie_path))
{
icon_item->set_source_path(game->info.path);
}
icon_item->set_image_change_callback([this, icon_item, game](const QVideoFrame& frame) icon_item->set_image_change_callback([this, icon_item, game](const QVideoFrame& frame)
{ {
if (!icon_item || !game) if (!icon_item || !game)
@@ -308,6 +302,11 @@ void game_list_table::populate(
if (play_hover_movies && (game->has_hover_gif || game->has_hover_pam)) if (play_hover_movies && (game->has_hover_gif || game->has_hover_pam))
{ {
icon_item->set_video_path(game->info.movie_path); icon_item->set_video_path(game->info.movie_path);
if (!fs::exists(game->info.movie_path) && is_file_iso(game->info.path))
{
icon_item->set_iso_path(game->info.path);
}
} }
icon_item->setData(Qt::UserRole, index, true); icon_item->setData(Qt::UserRole, index, true);
+3 -3
View File
@@ -546,9 +546,9 @@ void main_window::Boot(const std::string& path, const std::string& title_id, boo
std::string game_path = Emu.GetBoot(); std::string game_path = Emu.GetBoot();
if (game_path.starts_with(iso_device::virtual_device_name)) if (game_path.starts_with(iso_device::virtual_device_name))
{ {
auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/"); const auto device = fs::get_virtual_device(iso_device::virtual_device_name + "/");
auto iso_device = dynamic_cast<class iso_device*>(device.get()); const auto iso_dev = ensure(dynamic_cast<const iso_device*>(device.get()));
game_path = iso_device->get_loaded_iso(); game_path = iso_dev->get_loaded_iso();
} }
gui_log.success("Boot successful."); gui_log.success("Boot successful.");
+11 -10
View File
@@ -683,27 +683,28 @@ namespace gui
return QString("%1 days ago %2").arg(current_date - exctrated_date).arg(date.toString(fmt_relative)); return QString("%1 days ago %2").arg(current_date - exctrated_date).arg(date.toString(fmt_relative));
} }
bool load_icon(QPixmap& icon, const std::string& icon_path, bool load_icon(QPixmap& icon, const std::string& icon_path, const std::string& archive_path)
const std::string& archive_path)
{ {
if (icon_path.empty()) return false;
if (archive_path.empty())
{
return icon.load(QString::fromStdString(icon_path));
}
if (!is_file_iso(archive_path)) return false; if (!is_file_iso(archive_path)) return false;
iso_archive archive(archive_path); iso_archive archive(archive_path);
if (!archive.exists(icon_path)) return false; if (!archive.exists(icon_path)) return false;
auto icon_file = archive.open(icon_path); auto icon_file = archive.open(icon_path);
auto icon_size = icon_file.size(); const auto icon_size = icon_file.size();
if (icon_size == 0) return false;
QByteArray data(icon_size, 0); QByteArray data(icon_size, 0);
icon_file.read(data.data(), icon_size); icon_file.read(data.data(), icon_size);
QImage iconImage;
if (iconImage.loadFromData(data)) return icon.loadFromData(data);
{
icon = QPixmap::fromImage(iconImage);
}
return true;
} }
QString format_timestamp(s64 time, const QString& fmt) QString format_timestamp(s64 time, const QString& fmt)
+26 -21
View File
@@ -21,9 +21,9 @@ void qt_video_source::set_video_path(const std::string& video_path)
m_video_path = QString::fromStdString(video_path); m_video_path = QString::fromStdString(video_path);
} }
void qt_video_source::set_source_path(const std::string& source_path) void qt_video_source::set_iso_path(const std::string& iso_path)
{ {
m_source_path = QString::fromStdString(source_path); m_iso_path = iso_path;
} }
void qt_video_source::set_active(bool active) void qt_video_source::set_active(bool active)
@@ -62,7 +62,7 @@ void qt_video_source::init_movie()
return; return;
} }
if (!m_image_change_callback || m_video_path.isEmpty() || (!QFile::exists(m_video_path) && m_source_path.isEmpty())) if (!m_image_change_callback || m_video_path.isEmpty() || (m_iso_path.empty() && !QFile::exists(m_video_path)))
{ {
m_video_path.clear(); m_video_path.clear();
return; return;
@@ -72,24 +72,24 @@ void qt_video_source::init_movie()
if (lower.endsWith(".gif")) if (lower.endsWith(".gif"))
{ {
if (m_source_path.isEmpty()) if (m_iso_path.empty())
{ {
m_movie = std::make_unique<QMovie>(m_video_path); m_movie = std::make_unique<QMovie>(m_video_path);
m_video_path.clear();
} }
else else
{ {
iso_archive archive(m_source_path.toStdString()); iso_archive archive(m_iso_path);
auto movie_file = archive.open(m_video_path.toStdString()); auto movie_file = archive.open(m_video_path.toStdString());
auto movie_size = movie_file.size(); const auto movie_size = movie_file.size();
if (movie_size == 0) return;
m_video_data = QByteArray(movie_size, 0); m_video_data = QByteArray(movie_size, 0);
movie_file.read(m_video_data.data(), movie_size); movie_file.read(m_video_data.data(), movie_size);
QBuffer buffer(&m_video_data); m_video_buffer = std::make_unique<QBuffer>(&m_video_data);
buffer.open(QIODevice::ReadOnly); m_video_buffer->open(QIODevice::ReadOnly);
m_movie = std::make_unique<QMovie>(&buffer); m_movie = std::make_unique<QMovie>(m_video_buffer.get());
m_video_path.clear();
} }
if (!m_movie->isValid()) if (!m_movie->isValid())
@@ -109,7 +109,7 @@ void qt_video_source::init_movie()
if (lower.endsWith(".pam")) if (lower.endsWith(".pam"))
{ {
// We can't set PAM files as source of the video player, so we have to feed them as raw data. // We can't set PAM files as source of the video player, so we have to feed them as raw data.
if (m_source_path.isEmpty()) if (m_iso_path.empty())
{ {
QFile file(m_video_path); QFile file(m_video_path);
if (!file.open(QFile::OpenModeFlag::ReadOnly)) if (!file.open(QFile::OpenModeFlag::ReadOnly))
@@ -119,22 +119,26 @@ void qt_video_source::init_movie()
// TODO: Decode the pam properly before pushing it to the player // TODO: Decode the pam properly before pushing it to the player
m_video_data = file.readAll(); m_video_data = file.readAll();
if (m_video_data.isEmpty())
{
return;
}
} }
else else
{ {
auto source_path = m_source_path.toStdString(); iso_archive archive(m_iso_path);
auto video_path = m_video_path.toStdString(); auto movie_file = archive.open(m_video_path.toStdString());
iso_archive archive(source_path.c_str()); const auto movie_size = movie_file.size();
auto movie_file = archive.open(video_path); if (movie_size == 0)
auto movie_size = movie_file.size(); {
return;
}
m_video_data = QByteArray(movie_size, 0); m_video_data = QByteArray(movie_size, 0);
movie_file.read(m_video_data.data(), movie_size); movie_file.read(m_video_data.data(), movie_size);
} }
if (m_video_data.isEmpty())
{
return;
}
m_video_buffer = std::make_unique<QBuffer>(&m_video_data); m_video_buffer = std::make_unique<QBuffer>(&m_video_data);
m_video_buffer->open(QIODevice::ReadOnly); m_video_buffer->open(QIODevice::ReadOnly);
} }
@@ -185,6 +189,7 @@ void qt_video_source::stop_movie()
if (m_movie) if (m_movie)
{ {
m_movie->stop(); m_movie->stop();
m_movie.reset();
} }
m_video_sink.reset(); m_video_sink.reset();
+2 -2
View File
@@ -17,7 +17,7 @@ public:
qt_video_source(); qt_video_source();
virtual ~qt_video_source(); virtual ~qt_video_source();
void set_source_path(const std::string& source_path); void set_iso_path(const std::string& iso_path);
void set_video_path(const std::string& video_path) override; void set_video_path(const std::string& video_path) override;
const QString& video_path() const { return m_video_path; } const QString& video_path() const { return m_video_path; }
@@ -44,7 +44,7 @@ protected:
atomic_t<bool> m_has_new = false; atomic_t<bool> m_has_new = false;
QString m_video_path; QString m_video_path;
QString m_source_path; // path of the source archive std::string m_iso_path; // path of the source archive
QByteArray m_video_data{}; QByteArray m_video_data{};
QImage m_image{}; QImage m_image{};
std::vector<u8> m_image_path; std::vector<u8> m_image_path;
+4 -9
View File
@@ -418,10 +418,10 @@ void savestate_manager_dialog::ResizeGameIcons()
{ {
const qreal dpr = devicePixelRatioF(); const qreal dpr = devicePixelRatioF();
const int savestate_index = item->data(GameUserRole::GameIndex).toInt(); const int savestate_index = item->data(GameUserRole::GameIndex).toInt();
const std::string icon_path = m_savestate_db[savestate_index]->game_icon_path; std::string game_icon_path = m_savestate_db[savestate_index]->game_icon_path;
const std::string archive_path = m_savestate_db[savestate_index]->archive_path; std::string game_archive_path = m_savestate_db[savestate_index]->archive_path;
item->set_icon_load_func([this, icon_path, archive_path, savestate_index, cancel = item->icon_loading_aborted(), dpr](int index) item->set_icon_load_func([this, icon_path = std::move(game_icon_path), archive_path = std::move(game_archive_path), savestate_index, cancel = item->icon_loading_aborted(), dpr](int index)
{ {
if (cancel && cancel->load()) if (cancel && cancel->load())
{ {
@@ -434,13 +434,8 @@ void savestate_manager_dialog::ResizeGameIcons()
{ {
if (!item->data(GameUserRole::GamePixmapLoaded).toBool()) if (!item->data(GameUserRole::GamePixmapLoaded).toBool())
{ {
if (!archive_path.empty())
{
gui::utils::load_icon(icon, icon_path, archive_path);
}
// Load game icon // Load game icon
if (!icon.load(QString::fromStdString(icon_path))) if (!gui::utils::load_icon(icon, icon_path, archive_path))
{ {
gui_log.warning("Could not load savestate game icon from path %s", icon_path); gui_log.warning("Could not load savestate game icon from path %s", icon_path);
} }
+2 -2
View File
@@ -649,9 +649,9 @@ void trophy_manager_dialog::ResizeGameIcons()
{ {
const qreal dpr = devicePixelRatioF(); const qreal dpr = devicePixelRatioF();
const int trophy_index = item->data(GameUserRole::GameIndex).toInt(); const int trophy_index = item->data(GameUserRole::GameIndex).toInt();
const QString icon_path = QString::fromStdString(m_trophies_db[trophy_index]->path); QString trophy_icon_path = QString::fromStdString(m_trophies_db[trophy_index]->path);
item->set_icon_load_func([this, icon_path, localized_icon, trophy_index, cancel = item->icon_loading_aborted(), dpr](int index) item->set_icon_load_func([this, icon_path = std::move(trophy_icon_path), localized_icon, trophy_index, cancel = item->icon_loading_aborted(), dpr](int index)
{ {
if (cancel && cancel->load()) if (cancel && cancel->load())
{ {