mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-03 19:42:45 +01:00
DiscIO: Add support for CleanRip-style split ISOs.
This commit is contained in:
parent
4acdbc0e84
commit
655cc7f75c
@ -19,6 +19,7 @@
|
|||||||
#include "DiscIO/DirectoryBlob.h"
|
#include "DiscIO/DirectoryBlob.h"
|
||||||
#include "DiscIO/FileBlob.h"
|
#include "DiscIO/FileBlob.h"
|
||||||
#include "DiscIO/NFSBlob.h"
|
#include "DiscIO/NFSBlob.h"
|
||||||
|
#include "DiscIO/SplitFileBlob.h"
|
||||||
#include "DiscIO/TGCBlob.h"
|
#include "DiscIO/TGCBlob.h"
|
||||||
#include "DiscIO/WIABlob.h"
|
#include "DiscIO/WIABlob.h"
|
||||||
#include "DiscIO/WbfsBlob.h"
|
#include "DiscIO/WbfsBlob.h"
|
||||||
@ -53,6 +54,8 @@ std::string GetName(BlobType blob_type, bool translate)
|
|||||||
return translate_str("Mod");
|
return translate_str("Mod");
|
||||||
case BlobType::NFS:
|
case BlobType::NFS:
|
||||||
return "NFS";
|
return "NFS";
|
||||||
|
case BlobType::SPLIT_PLAIN:
|
||||||
|
return translate_str("Multi-part ISO");
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -245,6 +248,8 @@ std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
|||||||
default:
|
default:
|
||||||
if (auto directory_blob = DirectoryBlobReader::Create(filename))
|
if (auto directory_blob = DirectoryBlobReader::Create(filename))
|
||||||
return std::move(directory_blob);
|
return std::move(directory_blob);
|
||||||
|
if (auto split_blob = SplitPlainFileReader::Create(filename))
|
||||||
|
return std::move(split_blob);
|
||||||
|
|
||||||
return PlainFileReader::Create(std::move(file));
|
return PlainFileReader::Create(std::move(file));
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ enum class BlobType
|
|||||||
RVZ,
|
RVZ,
|
||||||
MOD_DESCRIPTOR,
|
MOD_DESCRIPTOR,
|
||||||
NFS,
|
NFS,
|
||||||
|
SPLIT_PLAIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
// If you convert an ISO file to another format and then call GetDataSize on it, what is the result?
|
// If you convert an ISO file to another format and then call GetDataSize on it, what is the result?
|
||||||
|
@ -36,6 +36,8 @@ add_library(discio
|
|||||||
RiivolutionPatcher.h
|
RiivolutionPatcher.h
|
||||||
ScrubbedBlob.cpp
|
ScrubbedBlob.cpp
|
||||||
ScrubbedBlob.h
|
ScrubbedBlob.h
|
||||||
|
SplitFileBlob.cpp
|
||||||
|
SplitFileBlob.h
|
||||||
TGCBlob.cpp
|
TGCBlob.cpp
|
||||||
TGCBlob.h
|
TGCBlob.h
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
|
90
Source/Core/DiscIO/SplitFileBlob.cpp
Normal file
90
Source/Core/DiscIO/SplitFileBlob.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "DiscIO/SplitFileBlob.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
|
namespace DiscIO
|
||||||
|
{
|
||||||
|
SplitPlainFileReader::SplitPlainFileReader(std::vector<SingleFile> files)
|
||||||
|
: m_files(std::move(files))
|
||||||
|
{
|
||||||
|
m_size = 0;
|
||||||
|
for (const auto& f : m_files)
|
||||||
|
m_size += f.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_view first_file_path)
|
||||||
|
{
|
||||||
|
constexpr std::string_view part0_iso = ".part0.iso";
|
||||||
|
if (!first_file_path.ends_with(part0_iso))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const std::string_view base_path =
|
||||||
|
first_file_path.substr(0, first_file_path.size() - part0_iso.size());
|
||||||
|
std::vector<SingleFile> files;
|
||||||
|
size_t index = 0;
|
||||||
|
u64 offset = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
File::IOFile f(fmt::format("{}.part{}.iso", base_path, index), "rb");
|
||||||
|
if (!f.IsOpen())
|
||||||
|
break;
|
||||||
|
const u64 size = f.GetSize();
|
||||||
|
if (size == 0)
|
||||||
|
return nullptr;
|
||||||
|
files.emplace_back(SingleFile{std::move(f), offset, size});
|
||||||
|
offset += size;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files.size() < 2)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
files.shrink_to_fit();
|
||||||
|
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(files)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
||||||
|
{
|
||||||
|
if (offset >= m_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u64 current_offset = offset;
|
||||||
|
u64 rest = nbytes;
|
||||||
|
u8* out = out_ptr;
|
||||||
|
for (auto& file : m_files)
|
||||||
|
{
|
||||||
|
if (current_offset >= file.offset && current_offset < file.offset + file.size)
|
||||||
|
{
|
||||||
|
auto& f = file.file;
|
||||||
|
const u64 seek_offset = current_offset - file.offset;
|
||||||
|
const u64 current_read = std::min(file.size - seek_offset, rest);
|
||||||
|
if (!f.Seek(seek_offset, File::SeekOrigin::Begin) || !f.ReadBytes(out, current_read))
|
||||||
|
{
|
||||||
|
f.ClearError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rest -= current_read;
|
||||||
|
if (rest == 0)
|
||||||
|
return true;
|
||||||
|
current_offset += current_read;
|
||||||
|
out += current_read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rest == 0;
|
||||||
|
}
|
||||||
|
} // namespace DiscIO
|
50
Source/Core/DiscIO/SplitFileBlob.h
Normal file
50
Source/Core/DiscIO/SplitFileBlob.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2023 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
|
namespace DiscIO
|
||||||
|
{
|
||||||
|
class SplitPlainFileReader final : public BlobReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<SplitPlainFileReader> Create(std::string_view first_file_path);
|
||||||
|
|
||||||
|
BlobType GetBlobType() const override { return BlobType::SPLIT_PLAIN; }
|
||||||
|
|
||||||
|
u64 GetRawSize() const override { return m_size; }
|
||||||
|
u64 GetDataSize() const override { return m_size; }
|
||||||
|
DataSizeType GetDataSizeType() const override { return DataSizeType::Accurate; }
|
||||||
|
|
||||||
|
u64 GetBlockSize() const override { return 0; }
|
||||||
|
bool HasFastRandomAccessInBlock() const override { return true; }
|
||||||
|
std::string GetCompressionMethod() const override { return {}; }
|
||||||
|
std::optional<int> GetCompressionLevel() const override { return std::nullopt; }
|
||||||
|
|
||||||
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SingleFile
|
||||||
|
{
|
||||||
|
File::IOFile file;
|
||||||
|
u64 offset;
|
||||||
|
u64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
SplitPlainFileReader(std::vector<SingleFile> m_files);
|
||||||
|
|
||||||
|
std::vector<SingleFile> m_files;
|
||||||
|
u64 m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace DiscIO
|
@ -453,6 +453,7 @@
|
|||||||
<ClInclude Include="DiscIO\RiivolutionParser.h" />
|
<ClInclude Include="DiscIO\RiivolutionParser.h" />
|
||||||
<ClInclude Include="DiscIO\RiivolutionPatcher.h" />
|
<ClInclude Include="DiscIO\RiivolutionPatcher.h" />
|
||||||
<ClInclude Include="DiscIO\ScrubbedBlob.h" />
|
<ClInclude Include="DiscIO\ScrubbedBlob.h" />
|
||||||
|
<ClInclude Include="DiscIO\SplitFileBlob.h" />
|
||||||
<ClInclude Include="DiscIO\TGCBlob.h" />
|
<ClInclude Include="DiscIO\TGCBlob.h" />
|
||||||
<ClInclude Include="DiscIO\Volume.h" />
|
<ClInclude Include="DiscIO\Volume.h" />
|
||||||
<ClInclude Include="DiscIO\VolumeDisc.h" />
|
<ClInclude Include="DiscIO\VolumeDisc.h" />
|
||||||
@ -1078,6 +1079,7 @@
|
|||||||
<ClCompile Include="DiscIO\RiivolutionParser.cpp" />
|
<ClCompile Include="DiscIO\RiivolutionParser.cpp" />
|
||||||
<ClCompile Include="DiscIO\RiivolutionPatcher.cpp" />
|
<ClCompile Include="DiscIO\RiivolutionPatcher.cpp" />
|
||||||
<ClCompile Include="DiscIO\ScrubbedBlob.cpp" />
|
<ClCompile Include="DiscIO\ScrubbedBlob.cpp" />
|
||||||
|
<ClCompile Include="DiscIO\SplitFileBlob.cpp" />
|
||||||
<ClCompile Include="DiscIO\TGCBlob.cpp" />
|
<ClCompile Include="DiscIO\TGCBlob.cpp" />
|
||||||
<ClCompile Include="DiscIO\Volume.cpp" />
|
<ClCompile Include="DiscIO\Volume.cpp" />
|
||||||
<ClCompile Include="DiscIO\VolumeDisc.cpp" />
|
<ClCompile Include="DiscIO\VolumeDisc.cpp" />
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
namespace UICommon
|
namespace UICommon
|
||||||
{
|
{
|
||||||
static constexpr u32 CACHE_REVISION = 23; // Last changed in PR 10932
|
static constexpr u32 CACHE_REVISION = 24; // Last changed in PR 11557
|
||||||
|
|
||||||
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
|
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
|
||||||
bool recursive_scan)
|
bool recursive_scan)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user