From 1778e148723a7c7abcebe668164b5097c9334578 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 30 Mar 2026 16:22:57 +0200 Subject: [PATCH 1/6] Fix some warnings --- rpcs3/Emu/RSX/NV47/FW/draw_call.hpp | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp index 0fe726d417..7b2591f544 100644 --- a/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp +++ b/rpcs3/Emu/RSX/NV47/FW/draw_call.hpp @@ -33,7 +33,7 @@ namespace rsx u32 draw_command_barrier_mask = 0; // Draw-time iterator to the draw_command_barriers struct - mutable rsx::simple_array::iterator current_barrier_it; + mutable rsx::simple_array::iterator current_barrier_it {}; // Subranges memory cache mutable rsx::simple_array subranges_store; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index a7338cbf56..33fd4a662b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2970,7 +2970,7 @@ namespace rsx auto& cfg = g_fxo->get(); - std::unique_lock hle_lock; + std::optional> hle_lock; for (u32 i = 0; i < std::size(unmap_status); i++) { @@ -3011,7 +3011,7 @@ namespace rsx if (hle_lock) { - hle_lock.unlock(); + hle_lock->unlock(); } // Pause RSX thread momentarily to handle unmapping From fa75dd0d382b0c890d58bddf3327de1a04661756 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 4 Apr 2026 15:23:26 +0200 Subject: [PATCH 2/6] iso: batch file reads --- rpcs3/Loader/ISO.cpp | 51 ++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index 0ddc3e39d9..cf05342541 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "Utilities/Timer.h" LOG_CHANNEL(sys_log, "SYS"); @@ -37,19 +38,19 @@ bool is_file_iso(const fs::file& file) const int ISO_BLOCK_SIZE = 2048; template -inline T read_both_endian_int(fs::file& file) +inline T retrieve_endian_int(const u8* buf) { - T out; + T out {}; - if (std::endian::little == std::endian::native) + if constexpr (std::endian::little == std::endian::native) { - out = file.read(); - file.seek(sizeof(T), fs::seek_cur); + // first half = little-endian copy + std::memcpy(&out, buf, sizeof(T)); } else { - file.seek(sizeof(T), fs::seek_cur); - out = file.read(); + // second half = big-endian copy + std::memcpy(&out, buf + sizeof(T), sizeof(T)); } return out; @@ -63,31 +64,36 @@ std::optional iso_read_directory_entry(fs::file& file, bool nam if (entry_length == 0) return std::nullopt; - file.seek(1, fs::seek_cur); - const u32 start_sector = read_both_endian_int(file); - const u32 file_size = read_both_endian_int(file); + // Batch this set of file reads. This reduces overall time spent in iso_read_directory_entry by ~38% + constexpr usz read_size = 1 + 4 * sizeof(u32) + 8 + 6 + 1; + const std::array data = file.read>(); + u32 pos = 1; + + const u32 start_sector = retrieve_endian_int(&data[pos]); + pos += 2 * sizeof(u32); + + const u32 file_size = retrieve_endian_int(&data[pos]); + pos += 2 * sizeof(u32); std::tm file_date = {}; - file_date.tm_year = file.read(); - file_date.tm_mon = file.read() - 1; - file_date.tm_mday = file.read(); - file_date.tm_hour = file.read(); - file_date.tm_min = file.read(); - file_date.tm_sec = file.read(); - const s16 timezone_value = file.read(); + file_date.tm_year = ::at32(data, pos++); + file_date.tm_mon = ::at32(data, pos++) - 1; + file_date.tm_mday = ::at32(data, pos++); + file_date.tm_hour = ::at32(data, pos++); + file_date.tm_min = ::at32(data, pos++); + file_date.tm_sec = ::at32(data, pos++); + const s16 timezone_value = ::at32(data, pos++); const s16 timezone_offset = (timezone_value - 50) * 15 * 60; const std::time_t date_time = std::mktime(&file_date) + timezone_offset; - const u8 flags = file.read(); + const u8 flags = ::at32(data, pos++); // 2nd flag bit indicates whether a given fs node is a directory const bool is_directory = flags & 0b00000010; const bool has_more_extents = flags & 0b10000000; - file.seek(6, fs::seek_cur); - - const u8 file_name_length = file.read(); + const u8 file_name_length = data.back(); std::string file_name; file.read(file_name, file_name_length); @@ -180,6 +186,7 @@ void iso_form_hierarchy(fs::file& file, iso_fs_node& node, bool use_ucs2_decodin selected_node->metadata.extents.push_back(entry->extents[0]); extent_added = true; + break; } } @@ -254,7 +261,9 @@ iso_archive::iso_archive(const std::string& path) } while (descriptor_type != 255); + Timer timer {}; iso_form_hierarchy(m_file, m_root, use_ucs2_decoding); + sys_log.error("iso_form_hierarchy: %.2f (%s)", timer.GetElapsedTimeInMilliSec(), path); } iso_fs_node* iso_archive::retrieve(const std::string& passed_path) From 131f4aaf30c1427c9996a8295ab3a27d8e031234 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 4 Apr 2026 17:32:05 +0200 Subject: [PATCH 3/6] iso: batch file reads (test) # Conflicts: # rpcs3/Loader/ISO.cpp --- rpcs3/Loader/ISO.cpp | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index cf05342541..fb74b14f74 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -38,65 +38,65 @@ bool is_file_iso(const fs::file& file) const int ISO_BLOCK_SIZE = 2048; template -inline T retrieve_endian_int(const u8* buf) +inline T read_both_endian_int(fs::file& file) { - T out {}; + T out; - if constexpr (std::endian::little == std::endian::native) + if (std::endian::little == std::endian::native) { - // first half = little-endian copy - std::memcpy(&out, buf, sizeof(T)); + out = file.read(); + file.seek(sizeof(T), fs::seek_cur); } else { - // second half = big-endian copy - std::memcpy(&out, buf + sizeof(T), sizeof(T)); + file.seek(sizeof(T), fs::seek_cur); + out = file.read(); } return out; } // assumed that directory_entry is at file head -std::optional iso_read_directory_entry(fs::file& file, bool names_in_ucs2 = false) +static std::optional iso_read_directory_entry(fs::file& entry, bool names_in_ucs2 = false) { - const auto start_pos = file.pos(); - const u8 entry_length = file.read(); + const auto start_pos = entry.pos(); + const u8 entry_length = entry.read(); if (entry_length == 0) return std::nullopt; // Batch this set of file reads. This reduces overall time spent in iso_read_directory_entry by ~38% constexpr usz read_size = 1 + 4 * sizeof(u32) + 8 + 6 + 1; - const std::array data = file.read>(); - u32 pos = 1; + const std::array data = entry.read>(); + fs::file file(data.data(), data.size()); - const u32 start_sector = retrieve_endian_int(&data[pos]); - pos += 2 * sizeof(u32); - - const u32 file_size = retrieve_endian_int(&data[pos]); - pos += 2 * sizeof(u32); + file.seek(1, fs::seek_cur); + const u32 start_sector = read_both_endian_int(file); + const u32 file_size = read_both_endian_int(file); std::tm file_date = {}; - file_date.tm_year = ::at32(data, pos++); - file_date.tm_mon = ::at32(data, pos++) - 1; - file_date.tm_mday = ::at32(data, pos++); - file_date.tm_hour = ::at32(data, pos++); - file_date.tm_min = ::at32(data, pos++); - file_date.tm_sec = ::at32(data, pos++); - const s16 timezone_value = ::at32(data, pos++); + file_date.tm_year = file.read(); + file_date.tm_mon = file.read() - 1; + file_date.tm_mday = file.read(); + file_date.tm_hour = file.read(); + file_date.tm_min = file.read(); + file_date.tm_sec = file.read(); + const s16 timezone_value = file.read(); const s16 timezone_offset = (timezone_value - 50) * 15 * 60; const std::time_t date_time = std::mktime(&file_date) + timezone_offset; - const u8 flags = ::at32(data, pos++); + const u8 flags = file.read(); // 2nd flag bit indicates whether a given fs node is a directory const bool is_directory = flags & 0b00000010; const bool has_more_extents = flags & 0b10000000; - const u8 file_name_length = data.back(); + file.seek(6, fs::seek_cur); + + const u8 file_name_length = file.read(); std::string file_name; - file.read(file_name, file_name_length); + entry.read(file_name, file_name_length); if (file_name_length == 1 && file_name[0] == 0) { @@ -132,7 +132,7 @@ std::optional iso_read_directory_entry(fs::file& file, bool nam } // skip the rest of the entry. - file.seek(entry_length + start_pos); + entry.seek(entry_length + start_pos); return iso_fs_metadata { From 0c90556b7521e6204f851271cd881cb7c3b5fcea Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 4 Apr 2026 18:35:05 +0200 Subject: [PATCH 4/6] iso: batch file reads (test 2) --- rpcs3/Loader/ISO.cpp | 76 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index fb74b14f74..12d03f0273 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -38,19 +38,19 @@ bool is_file_iso(const fs::file& file) const int ISO_BLOCK_SIZE = 2048; template -inline T read_both_endian_int(fs::file& file) +inline T retrieve_endian_int(const u8* buf) { - T out; + T out {}; - if (std::endian::little == std::endian::native) + if constexpr (std::endian::little == std::endian::native) { - out = file.read(); - file.seek(sizeof(T), fs::seek_cur); + // first half = little-endian copy + std::memcpy(&out, buf, sizeof(T)); } else { - file.seek(sizeof(T), fs::seek_cur); - out = file.read(); + // second half = big-endian copy + std::memcpy(&out, buf + sizeof(T), sizeof(T)); } return out; @@ -64,41 +64,51 @@ static std::optional iso_read_directory_entry(fs::file& entry, if (entry_length == 0) return std::nullopt; - // Batch this set of file reads. This reduces overall time spent in iso_read_directory_entry by ~38% - constexpr usz read_size = 1 + 4 * sizeof(u32) + 8 + 6 + 1; - const std::array data = entry.read>(); - fs::file file(data.data(), data.size()); + // Batch this set of file reads. This reduces overall time spent in iso_read_directory_entry by ~41% +#pragma pack(push, 1) + struct entry_header + { + u8 padding; + std::array start_sector; + std::array file_size; + u8 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; + u8 timezone_value; + u8 flags; + std::array padding2; + u8 file_name_length; + }; +#pragma pack(pop) - file.seek(1, fs::seek_cur); - const u32 start_sector = read_both_endian_int(file); - const u32 file_size = read_both_endian_int(file); + const entry_header header = entry.read(); + + const u32 start_sector = retrieve_endian_int(header.start_sector.data()); + const u32 file_size = retrieve_endian_int(header.file_size.data()); std::tm file_date = {}; - file_date.tm_year = file.read(); - file_date.tm_mon = file.read() - 1; - file_date.tm_mday = file.read(); - file_date.tm_hour = file.read(); - file_date.tm_min = file.read(); - file_date.tm_sec = file.read(); - const s16 timezone_value = file.read(); + file_date.tm_year = header.year; + file_date.tm_mon = header.month - 1; + file_date.tm_mday = header.day; + file_date.tm_hour = header.hour; + file_date.tm_min = header.minute; + file_date.tm_sec = header.second; + const s16 timezone_value = header.timezone_value; const s16 timezone_offset = (timezone_value - 50) * 15 * 60; const std::time_t date_time = std::mktime(&file_date) + timezone_offset; - const u8 flags = file.read(); - // 2nd flag bit indicates whether a given fs node is a directory - const bool is_directory = flags & 0b00000010; - const bool has_more_extents = flags & 0b10000000; - - file.seek(6, fs::seek_cur); - - const u8 file_name_length = file.read(); + const bool is_directory = header.flags & 0b00000010; + const bool has_more_extents = header.flags & 0b10000000; std::string file_name; - entry.read(file_name, file_name_length); + entry.read(file_name, header.file_name_length); - if (file_name_length == 1 && file_name[0] == 0) + if (header.file_name_length == 1 && file_name[0] == 0) { file_name = "."; } @@ -110,7 +120,7 @@ static std::optional iso_read_directory_entry(fs::file& entry, { // characters are stored in big endian format. std::u16string utf16; - utf16.resize(file_name_length / 2); + utf16.resize(header.file_name_length / 2); const u16* raw = reinterpret_cast(file_name.data()); for (size_t i = 0; i < utf16.size(); ++i, raw++) @@ -126,7 +136,7 @@ static std::optional iso_read_directory_entry(fs::file& entry, file_name.erase(file_name.end() - 2, file_name.end()); } - if (file_name_length > 1 && file_name.ends_with(".")) + if (header.file_name_length > 1 && file_name.ends_with(".")) { file_name.pop_back(); } From 65d1a112ee3ef03021ad77a46c97050cc08f4e90 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 4 Apr 2026 20:49:15 +0200 Subject: [PATCH 5/6] ISO: remove timer --- rpcs3/Loader/ISO.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index 12d03f0273..9955e64f02 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -8,7 +8,6 @@ #include #include #include -#include "Utilities/Timer.h" LOG_CHANNEL(sys_log, "SYS"); @@ -271,9 +270,7 @@ iso_archive::iso_archive(const std::string& path) } while (descriptor_type != 255); - Timer timer {}; iso_form_hierarchy(m_file, m_root, use_ucs2_decoding); - sys_log.error("iso_form_hierarchy: %.2f (%s)", timer.GetElapsedTimeInMilliSec(), path); } iso_fs_node* iso_archive::retrieve(const std::string& passed_path) From 112804f90e14ec5c046d7675475a9657396c0ba1 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 4 Apr 2026 21:03:50 +0200 Subject: [PATCH 6/6] ISO: clarify some more fields --- rpcs3/Loader/ISO.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rpcs3/Loader/ISO.cpp b/rpcs3/Loader/ISO.cpp index 9955e64f02..71af44f7ce 100644 --- a/rpcs3/Loader/ISO.cpp +++ b/rpcs3/Loader/ISO.cpp @@ -65,9 +65,10 @@ static std::optional iso_read_directory_entry(fs::file& entry, // Batch this set of file reads. This reduces overall time spent in iso_read_directory_entry by ~41% #pragma pack(push, 1) - struct entry_header + struct iso_entry_header { - u8 padding; + //u8 entry_length; // Handled separately + u8 extended_attribute_length; std::array start_sector; std::array file_size; u8 year; @@ -78,12 +79,15 @@ static std::optional iso_read_directory_entry(fs::file& entry, u8 second; u8 timezone_value; u8 flags; - std::array padding2; + u8 file_unit_size; + u8 interleave; + std::array volume_sequence_number; u8 file_name_length; + //u8 file_name[file_name_length]; // Handled separately }; #pragma pack(pop) - const entry_header header = entry.read(); + const iso_entry_header header = entry.read(); const u32 start_sector = retrieve_endian_int(header.start_sector.data()); const u32 file_size = retrieve_endian_int(header.file_size.data());