ISO: Add ISO reader code and ISO device

Adds infrastructure to read files/data from ISOs.

Also adds classes extending fs::device_base and fs::file_base in order
to allow reading files through fs namespace functions. This approach
should allow ISO data to be read by the emulator with the least changes
to existing code.
This commit is contained in:
Functionable
2026-01-09 14:40:51 +02:00
committed by Elad
parent ef5a4bf7e4
commit 6c083d6184
5 changed files with 717 additions and 2 deletions
+1 -1
View File
@@ -155,7 +155,7 @@ namespace fs
// Virtual device
struct device_base
{
const std::string fs_prefix;
std::string fs_prefix;
device_base();
virtual ~device_base();
+1
View File
@@ -125,6 +125,7 @@ target_sources(rpcs3_emu PRIVATE
../Loader/PSF.cpp
../Loader/PUP.cpp
../Loader/TAR.cpp
../Loader/ISO.cpp
../Loader/TROPUSR.cpp
../Loader/TRP.cpp
)
File diff suppressed because it is too large Load Diff
+112
View File
@@ -0,0 +1,112 @@
#pragma once
#include "Utilities/File.h"
#include "util/types.hpp"
bool is_file_iso(const std::string& path);
bool is_file_iso(const fs::file& path);
void load_iso(const std::string& path);
struct iso_extent_info
{
u64 start;
u64 size;
};
struct iso_fs_metadata
{
std::string name;
s64 time;
bool is_directory;
bool has_multiple_extents;
std::vector<iso_extent_info> extents;
u64 size() const;
};
struct iso_fs_node
{
iso_fs_metadata metadata;
std::vector<std::unique_ptr<iso_fs_node>> children;
};
class iso_file : public fs::file_base
{
fs::file m_file;
iso_fs_metadata m_meta;
u64 m_pos;
std::pair<u64, iso_extent_info> get_extent_pos(u64 pos) const;
u64 file_offset(u64 pos) const;
u64 local_extent_remaining(u64 pos) const;
u64 local_extent_size(u64 pos) const;
public:
iso_file(fs::file&& iso_handle, const iso_fs_node& node);
fs::stat_t get_stat() override;
bool trunc(u64 length) override;
u64 read(void* buffer, u64 size) override;
u64 read_at(u64 offset, void* buffer, u64 size) override;
u64 write(const void* buffer, u64 size) override;
u64 seek(s64 offset, fs::seek_mode whence) override;
u64 size() override;
void release() override;
};
class iso_dir : public fs::dir_base
{
const iso_fs_node& m_node;
u64 m_pos;
public:
iso_dir(const iso_fs_node& node)
: m_node(node), m_pos(0)
{}
bool read(fs::dir_entry&) override;
void rewind() override;
};
// represents the .iso file itself.
class iso_archive
{
std::string m_path;
iso_fs_node m_root;
fs::file m_file;
public:
iso_archive(const std::string& path);
iso_fs_node* retrieve(const std::string& path);
bool exists(const std::string& path);
bool is_file(const std::string& path);
iso_file open(const std::string& path);
};
class iso_device : public fs::device_base
{
iso_archive m_archive;
std::string iso_path;
public:
inline static std::string virtual_device_name = "/vfsv0_virtual_iso_overlay_fs_dev";
iso_device(const std::string& iso_path, const std::string& device_name = virtual_device_name)
: m_archive(iso_path), iso_path(iso_path)
{
fs_prefix = device_name;
}
~iso_device() override = default;
const std::string& get_loaded_iso() const { return iso_path; }
bool stat(const std::string& path, fs::stat_t& info) override;
bool statfs(const std::string& path, fs::device_stat& info) override;
std::unique_ptr<fs::file_base> open(const std::string& path, bs_t<fs::open_mode> mode) override;
std::unique_ptr<fs::dir_base> open_dir(const std::string& path) override;
};
+3 -1
View File
@@ -540,6 +540,7 @@
<ClCompile Include="Loader\PSF.cpp" />
<ClCompile Include="Loader\PUP.cpp" />
<ClCompile Include="Loader\TAR.cpp" />
<ClCompile Include="Loader\ISO.cpp" />
<ClCompile Include="Loader\mself.cpp" />
<ClCompile Include="Loader\TROPUSR.cpp" />
<ClCompile Include="Loader\TRP.cpp" />
@@ -1021,6 +1022,7 @@
<ClInclude Include="Loader\PSF.h" />
<ClInclude Include="Loader\PUP.h" />
<ClInclude Include="Loader\TAR.h" />
<ClInclude Include="Loader\ISO.h" />
<ClInclude Include="Loader\TROPUSR.h" />
<ClInclude Include="Loader\TRP.h" />
<ClInclude Include="rpcs3_version.h" />
@@ -1096,4 +1098,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>