mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
DiscIO: Make all BlobReader implementations use DirectIOFile to make CopyReader functionality thread safe.
This commit is contained in:
parent
b98acb9a37
commit
239330017c
@ -4,14 +4,13 @@
|
|||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
|
||||||
#include <limits>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "DiscIO/CISOBlob.h"
|
#include "DiscIO/CISOBlob.h"
|
||||||
@ -213,9 +212,9 @@ u32 SectorReader::ReadChunk(u8* buffer, u64 chunk_num)
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
||||||
{
|
{
|
||||||
File::IOFile file(filename, "rb");
|
File::DirectIOFile file(filename, File::AccessMode::Read);
|
||||||
u32 magic;
|
u32 magic;
|
||||||
if (!file.ReadArray(&magic, 1))
|
if (!file.Read(Common::AsWritableU8Span(magic)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Conveniently, every supported file format (except for plain disc images and
|
// Conveniently, every supported file format (except for plain disc images and
|
||||||
|
|||||||
@ -4,22 +4,20 @@
|
|||||||
#include "DiscIO/CISOBlob.h"
|
#include "DiscIO/CISOBlob.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
CISOFileReader::CISOFileReader(File::IOFile file) : m_file(std::move(file))
|
CISOFileReader::CISOFileReader(File::DirectIOFile file) : m_file(std::move(file))
|
||||||
{
|
{
|
||||||
m_size = m_file.GetSize();
|
m_size = m_file.GetSize();
|
||||||
|
|
||||||
CISOHeader header;
|
CISOHeader header;
|
||||||
m_file.Seek(0, File::SeekOrigin::Begin);
|
m_file.OffsetRead(0, Common::AsWritableU8Span(header));
|
||||||
m_file.ReadArray(&header, 1);
|
|
||||||
|
|
||||||
m_block_size = header.block_size;
|
m_block_size = header.block_size;
|
||||||
|
|
||||||
@ -28,11 +26,10 @@ CISOFileReader::CISOFileReader(File::IOFile file) : m_file(std::move(file))
|
|||||||
m_ciso_map[idx] = (1 == header.map[idx]) ? count++ : UNUSED_BLOCK_ID;
|
m_ciso_map[idx] = (1 == header.map[idx]) ? count++ : UNUSED_BLOCK_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CISOFileReader> CISOFileReader::Create(File::IOFile file)
|
std::unique_ptr<CISOFileReader> CISOFileReader::Create(File::DirectIOFile file)
|
||||||
{
|
{
|
||||||
CISOHeader header;
|
CISOHeader header;
|
||||||
if (file.Seek(0, File::SeekOrigin::Begin) && file.ReadArray(&header, 1) &&
|
if (file.OffsetRead(0, Common::AsWritableU8Span(header)) && header.magic == CISO_MAGIC)
|
||||||
header.magic == CISO_MAGIC)
|
|
||||||
{
|
{
|
||||||
return std::unique_ptr<CISOFileReader>(new CISOFileReader(std::move(file)));
|
return std::unique_ptr<CISOFileReader>(new CISOFileReader(std::move(file)));
|
||||||
}
|
}
|
||||||
@ -42,7 +39,7 @@ std::unique_ptr<CISOFileReader> CISOFileReader::Create(File::IOFile file)
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> CISOFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> CISOFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
return Create(m_file.Duplicate("rb"));
|
return Create(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CISOFileReader::GetDataSize() const
|
u64 CISOFileReader::GetDataSize() const
|
||||||
@ -71,12 +68,8 @@ bool CISOFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
// calculate the base address
|
// calculate the base address
|
||||||
u64 const file_off = CISO_HEADER_SIZE + m_ciso_map[block] * (u64)m_block_size + data_offset;
|
u64 const file_off = CISO_HEADER_SIZE + m_ciso_map[block] * (u64)m_block_size + data_offset;
|
||||||
|
|
||||||
if (!(m_file.Seek(file_off, File::SeekOrigin::Begin) &&
|
if (!m_file.OffsetRead(file_off, out_ptr, bytes_to_read))
|
||||||
m_file.ReadArray(out_ptr, bytes_to_read)))
|
|
||||||
{
|
|
||||||
m_file.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,12 +3,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -33,7 +32,7 @@ struct CISOHeader
|
|||||||
class CISOFileReader final : public BlobReader
|
class CISOFileReader final : public BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<CISOFileReader> Create(File::IOFile file);
|
static std::unique_ptr<CISOFileReader> Create(File::DirectIOFile file);
|
||||||
|
|
||||||
BlobType GetBlobType() const override { return BlobType::CISO; }
|
BlobType GetBlobType() const override { return BlobType::CISO; }
|
||||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||||
@ -50,12 +49,12 @@ public:
|
|||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CISOFileReader(File::IOFile file);
|
CISOFileReader(File::DirectIOFile file);
|
||||||
|
|
||||||
typedef u16 MapType;
|
typedef u16 MapType;
|
||||||
static constexpr MapType UNUSED_BLOCK_ID = UINT16_MAX;
|
static constexpr MapType UNUSED_BLOCK_ID = UINT16_MAX;
|
||||||
|
|
||||||
File::IOFile m_file;
|
File::DirectIOFile m_file;
|
||||||
u64 m_size;
|
u64 m_size;
|
||||||
u32 m_block_size;
|
u32 m_block_size;
|
||||||
MapType m_ciso_map[CISO_MAP_SIZE];
|
MapType m_ciso_map[CISO_MAP_SIZE];
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
#include "DiscIO/CompressedBlob.h"
|
#include "DiscIO/CompressedBlob.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -19,10 +18,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/Hash.h"
|
#include "Common/Hash.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
@ -32,22 +31,23 @@
|
|||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
bool IsGCZBlob(File::IOFile& file);
|
bool IsGCZBlob(File::DirectIOFile& file);
|
||||||
|
|
||||||
CompressedBlobReader::CompressedBlobReader(File::IOFile file, const std::string& filename)
|
CompressedBlobReader::CompressedBlobReader(File::DirectIOFile file, const std::string& filename)
|
||||||
: m_file(std::move(file)), m_file_name(filename)
|
: m_file(std::move(file)), m_file_name(filename)
|
||||||
{
|
{
|
||||||
m_file_size = m_file.GetSize();
|
m_file_size = m_file.GetSize();
|
||||||
m_file.Seek(0, File::SeekOrigin::Begin);
|
m_file.Seek(0, File::SeekOrigin::Begin);
|
||||||
m_file.ReadArray(&m_header, 1);
|
m_file.Read(Common::AsWritableU8Span(m_header));
|
||||||
|
|
||||||
SetSectorSize(m_header.block_size);
|
SetSectorSize(m_header.block_size);
|
||||||
|
|
||||||
// cache block pointers and hashes
|
// cache block pointers and hashes
|
||||||
m_block_pointers.resize(m_header.num_blocks);
|
m_block_pointers.resize(m_header.num_blocks);
|
||||||
m_file.ReadArray(m_block_pointers.data(), m_header.num_blocks);
|
m_file.Read(Common::AsWritableU8Span(m_block_pointers));
|
||||||
|
|
||||||
m_hashes.resize(m_header.num_blocks);
|
m_hashes.resize(m_header.num_blocks);
|
||||||
m_file.ReadArray(m_hashes.data(), m_header.num_blocks);
|
m_file.Read(Common::AsWritableU8Span(m_hashes));
|
||||||
|
|
||||||
m_data_offset = (sizeof(CompressedBlobHeader)) +
|
m_data_offset = (sizeof(CompressedBlobHeader)) +
|
||||||
(sizeof(u64)) * m_header.num_blocks // skip block pointers
|
(sizeof(u64)) * m_header.num_blocks // skip block pointers
|
||||||
@ -60,7 +60,7 @@ CompressedBlobReader::CompressedBlobReader(File::IOFile file, const std::string&
|
|||||||
m_zlib_buffer.resize(zlib_buffer_size);
|
m_zlib_buffer.resize(zlib_buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CompressedBlobReader> CompressedBlobReader::Create(File::IOFile file,
|
std::unique_ptr<CompressedBlobReader> CompressedBlobReader::Create(File::DirectIOFile file,
|
||||||
const std::string& filename)
|
const std::string& filename)
|
||||||
{
|
{
|
||||||
if (IsGCZBlob(file))
|
if (IsGCZBlob(file))
|
||||||
@ -74,7 +74,7 @@ CompressedBlobReader::~CompressedBlobReader() = default;
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> CompressedBlobReader::CopyReader() const
|
std::unique_ptr<BlobReader> CompressedBlobReader::CopyReader() const
|
||||||
{
|
{
|
||||||
return Create(m_file.Duplicate("rb"), m_file_name);
|
return Create(m_file, m_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function.
|
// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function.
|
||||||
@ -107,12 +107,10 @@ bool CompressedBlobReader::GetBlock(u64 block_num, u8* out_ptr)
|
|||||||
// clear unused part of zlib buffer. maybe this can be deleted when it works fully.
|
// clear unused part of zlib buffer. maybe this can be deleted when it works fully.
|
||||||
memset(&m_zlib_buffer[comp_block_size], 0, m_zlib_buffer.size() - comp_block_size);
|
memset(&m_zlib_buffer[comp_block_size], 0, m_zlib_buffer.size() - comp_block_size);
|
||||||
|
|
||||||
m_file.Seek(offset, File::SeekOrigin::Begin);
|
if (!m_file.OffsetRead(offset, m_zlib_buffer.data(), comp_block_size))
|
||||||
if (!m_file.ReadBytes(m_zlib_buffer.data(), comp_block_size))
|
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(DISCIO, "The disc image \"{}\" is truncated, some of the data is missing.",
|
ERROR_LOG_FMT(DISCIO, "The disc image \"{}\" is truncated, some of the data is missing.",
|
||||||
m_file_name);
|
m_file_name);
|
||||||
m_file.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +239,7 @@ static ConversionResult<OutputParameters> Compress(CompressThreadState* state,
|
|||||||
return std::move(output_parameters);
|
return std::move(output_parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ConversionResultCode Output(OutputParameters parameters, File::IOFile* outfile,
|
static ConversionResultCode Output(OutputParameters parameters, File::DirectIOFile* outfile,
|
||||||
u64* position, std::vector<u64>* offsets, int progress_monitor,
|
u64* position, std::vector<u64>* offsets, int progress_monitor,
|
||||||
u32 num_blocks, const CompressCB& callback)
|
u32 num_blocks, const CompressCB& callback)
|
||||||
{
|
{
|
||||||
@ -252,7 +250,7 @@ static ConversionResultCode Output(OutputParameters parameters, File::IOFile* ou
|
|||||||
|
|
||||||
*position += parameters.data.size();
|
*position += parameters.data.size();
|
||||||
|
|
||||||
if (!outfile->WriteBytes(parameters.data.data(), parameters.data.size()))
|
if (!outfile->Write(parameters.data))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
|
|
||||||
if (parameters.block_number % progress_monitor == 0)
|
if (parameters.block_number % progress_monitor == 0)
|
||||||
@ -278,8 +276,8 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
|
|||||||
{
|
{
|
||||||
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
||||||
|
|
||||||
File::IOFile outfile(outfile_path, "wb");
|
File::DirectIOFile outfile(outfile_path, File::AccessMode::Write);
|
||||||
if (!outfile)
|
if (!outfile.IsOpen())
|
||||||
{
|
{
|
||||||
PanicAlertFmtT(
|
PanicAlertFmtT(
|
||||||
"Failed to open the output file \"{0}\".\n"
|
"Failed to open the output file \"{0}\".\n"
|
||||||
@ -365,9 +363,9 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
|
|||||||
{
|
{
|
||||||
// Okay, go back and fill in headers
|
// Okay, go back and fill in headers
|
||||||
outfile.Seek(0, File::SeekOrigin::Begin);
|
outfile.Seek(0, File::SeekOrigin::Begin);
|
||||||
outfile.WriteArray(&header, 1);
|
outfile.Write(Common::AsU8Span(header));
|
||||||
outfile.WriteArray(offsets.data(), header.num_blocks);
|
outfile.Write(Common::AsU8Span(offsets));
|
||||||
outfile.WriteArray(hashes.data(), header.num_blocks);
|
outfile.Write(Common::AsU8Span(hashes));
|
||||||
|
|
||||||
callback(Common::GetStringT("Done compressing disc image."), 1.0f);
|
callback(Common::GetStringT("Done compressing disc image."), 1.0f);
|
||||||
}
|
}
|
||||||
@ -385,15 +383,10 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path,
|
|||||||
return result == ConversionResultCode::Success;
|
return result == ConversionResultCode::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGCZBlob(File::IOFile& file)
|
bool IsGCZBlob(File::DirectIOFile& file)
|
||||||
{
|
{
|
||||||
const u64 position = file.Tell();
|
|
||||||
if (!file.Seek(0, File::SeekOrigin::Begin))
|
|
||||||
return false;
|
|
||||||
CompressedBlobHeader header;
|
CompressedBlobHeader header;
|
||||||
bool is_gcz = file.ReadArray(&header, 1) && header.magic_cookie == GCZ_MAGIC;
|
return file.OffsetRead(0, Common::AsWritableU8Span(header)) && header.magic_cookie == GCZ_MAGIC;
|
||||||
file.Seek(position, File::SeekOrigin::Begin);
|
|
||||||
return is_gcz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DiscIO
|
} // namespace DiscIO
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -43,7 +43,7 @@ struct CompressedBlobHeader // 32 bytes
|
|||||||
class CompressedBlobReader final : public SectorReader
|
class CompressedBlobReader final : public SectorReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<CompressedBlobReader> Create(File::IOFile file,
|
static std::unique_ptr<CompressedBlobReader> Create(File::DirectIOFile file,
|
||||||
const std::string& filename);
|
const std::string& filename);
|
||||||
~CompressedBlobReader() override;
|
~CompressedBlobReader() override;
|
||||||
|
|
||||||
@ -65,13 +65,13 @@ public:
|
|||||||
bool GetBlock(u64 block_num, u8* out_ptr) override;
|
bool GetBlock(u64 block_num, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CompressedBlobReader(File::IOFile file, const std::string& filename);
|
CompressedBlobReader(File::DirectIOFile file, const std::string& filename);
|
||||||
|
|
||||||
CompressedBlobHeader m_header;
|
CompressedBlobHeader m_header;
|
||||||
std::vector<u64> m_block_pointers;
|
std::vector<u64> m_block_pointers;
|
||||||
std::vector<u32> m_hashes;
|
std::vector<u32> m_hashes;
|
||||||
int m_data_offset;
|
int m_data_offset;
|
||||||
File::IOFile m_file;
|
File::DirectIOFile m_file;
|
||||||
u64 m_file_size;
|
u64 m_file_size;
|
||||||
std::vector<u8> m_zlib_buffer;
|
std::vector<u8> m_zlib_buffer;
|
||||||
std::string m_file_name;
|
std::string m_file_name;
|
||||||
|
|||||||
@ -4,9 +4,7 @@
|
|||||||
#include "DiscIO/DirectoryBlob.h"
|
#include "DiscIO/DirectoryBlob.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <locale>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -17,14 +15,12 @@
|
|||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonPaths.h"
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/DirectIOFile.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
#include "Core/Boot/DolReader.h"
|
|
||||||
#include "Core/IOS/ES/Formats.h"
|
#include "Core/IOS/ES/Formats.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/DiscUtils.h"
|
#include "DiscIO/DiscUtils.h"
|
||||||
@ -97,9 +93,8 @@ bool DiscContent::Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReade
|
|||||||
if (std::holds_alternative<ContentFile>(m_content_source))
|
if (std::holds_alternative<ContentFile>(m_content_source))
|
||||||
{
|
{
|
||||||
const auto& content = std::get<ContentFile>(m_content_source);
|
const auto& content = std::get<ContentFile>(m_content_source);
|
||||||
File::IOFile file(content.m_filename, "rb");
|
File::DirectIOFile file(content.m_filename, File::AccessMode::Read);
|
||||||
if (!file.Seek(content.m_offset + offset_in_content, File::SeekOrigin::Begin) ||
|
if (!file.OffsetRead(content.m_offset + offset_in_content, *buffer, bytes_to_read))
|
||||||
!file.ReadBytes(*buffer, bytes_to_read))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1013,9 +1008,9 @@ void DirectoryBlobPartition::SetBI2(std::vector<u8> bi2)
|
|||||||
|
|
||||||
u64 DirectoryBlobPartition::SetApploaderFromFile(const std::string& path)
|
u64 DirectoryBlobPartition::SetApploaderFromFile(const std::string& path)
|
||||||
{
|
{
|
||||||
File::IOFile file(path, "rb");
|
File::DirectIOFile file(path, File::AccessMode::Read);
|
||||||
std::vector<u8> apploader(file.GetSize());
|
std::vector<u8> apploader(file.GetSize());
|
||||||
file.ReadBytes(apploader.data(), apploader.size());
|
file.Read(apploader);
|
||||||
return SetApploader(std::move(apploader), path);
|
return SetApploader(std::move(apploader), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1256,10 +1251,9 @@ void DirectoryBlobPartition::WriteDirectory(std::vector<u8>* fst_data,
|
|||||||
|
|
||||||
static size_t ReadFileToVector(const std::string& path, std::vector<u8>* vector)
|
static size_t ReadFileToVector(const std::string& path, std::vector<u8>* vector)
|
||||||
{
|
{
|
||||||
File::IOFile file(path, "rb");
|
File::DirectIOFile file(path, File::AccessMode::Read);
|
||||||
size_t bytes_read;
|
file.Read(vector->data(), std::min<u64>(file.GetSize(), vector->size()));
|
||||||
file.ReadArray<u8>(vector->data(), std::min<u64>(file.GetSize(), vector->size()), &bytes_read);
|
return file.Tell();
|
||||||
return bytes_read;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PadToAddress(u64 start_address, u64* address, u64* length, u8** buffer)
|
static void PadToAddress(u64 start_address, u64* address, u64* length, u8** buffer)
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/FileUtil.h"
|
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
#include "DiscIO/WiiEncryptionCache.h"
|
#include "DiscIO/WiiEncryptionCache.h"
|
||||||
@ -23,7 +22,6 @@
|
|||||||
namespace File
|
namespace File
|
||||||
{
|
{
|
||||||
struct FSTEntry;
|
struct FSTEntry;
|
||||||
class IOFile;
|
|
||||||
} // namespace File
|
} // namespace File
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
|
|||||||
@ -15,14 +15,14 @@
|
|||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
PlainFileReader::PlainFileReader(File::IOFile file) : m_file(std::move(file))
|
PlainFileReader::PlainFileReader(File::DirectIOFile file) : m_file(std::move(file))
|
||||||
{
|
{
|
||||||
m_size = m_file.GetSize();
|
m_size = m_file.GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::IOFile file)
|
std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::DirectIOFile file)
|
||||||
{
|
{
|
||||||
if (file)
|
if (file.IsOpen())
|
||||||
return std::unique_ptr<PlainFileReader>(new PlainFileReader(std::move(file)));
|
return std::unique_ptr<PlainFileReader>(new PlainFileReader(std::move(file)));
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -30,20 +30,12 @@ std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::IOFile file)
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> PlainFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> PlainFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
return Create(m_file.Duplicate("rb"));
|
return Create(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
||||||
{
|
{
|
||||||
if (m_file.Seek(offset, File::SeekOrigin::Begin) && m_file.ReadBytes(out_ptr, nbytes))
|
return m_file.OffsetRead(offset, out_ptr, nbytes);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_file.ClearError();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
|
bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
|
||||||
@ -51,8 +43,8 @@ bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
|
|||||||
{
|
{
|
||||||
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
||||||
|
|
||||||
File::IOFile outfile(outfile_path, "wb");
|
File::DirectIOFile outfile(outfile_path, File::AccessMode::Write);
|
||||||
if (!outfile)
|
if (!outfile.IsOpen())
|
||||||
{
|
{
|
||||||
PanicAlertFmtT(
|
PanicAlertFmtT(
|
||||||
"Failed to open the output file \"{0}\".\n"
|
"Failed to open the output file \"{0}\".\n"
|
||||||
@ -99,7 +91,7 @@ bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
|
|||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!outfile.WriteBytes(buffer.data(), sz))
|
if (!outfile.Write(buffer.data(), sz))
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("Failed to write the output file \"{0}\".\n"
|
PanicAlertFmtT("Failed to write the output file \"{0}\".\n"
|
||||||
"Check that you have enough space available on the target drive.",
|
"Check that you have enough space available on the target drive.",
|
||||||
|
|||||||
@ -3,12 +3,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -16,7 +15,7 @@ namespace DiscIO
|
|||||||
class PlainFileReader final : public BlobReader
|
class PlainFileReader final : public BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<PlainFileReader> Create(File::IOFile file);
|
static std::unique_ptr<PlainFileReader> Create(File::DirectIOFile file);
|
||||||
|
|
||||||
BlobType GetBlobType() const override { return BlobType::PLAIN; }
|
BlobType GetBlobType() const override { return BlobType::PLAIN; }
|
||||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||||
@ -33,9 +32,9 @@ public:
|
|||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PlainFileReader(File::IOFile file);
|
PlainFileReader(File::DirectIOFile file);
|
||||||
|
|
||||||
File::IOFile m_file;
|
File::DirectIOFile m_file;
|
||||||
u64 m_size;
|
u64 m_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,9 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Crypto/AES.h"
|
#include "Common/Crypto/AES.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
@ -39,8 +39,8 @@ bool NFSFileReader::ReadKey(const std::string& path, const std::string& director
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::string key_path = parent + "code/htk.bin";
|
const std::string key_path = parent + "code/htk.bin";
|
||||||
File::IOFile key_file(key_path, "rb");
|
File::DirectIOFile key_file(key_path, File::AccessMode::Read);
|
||||||
if (!key_file.ReadBytes(key_out->data(), key_out->size()))
|
if (!key_file.Read(*key_out))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(DISCIO, "Failed to read from {}", key_path);
|
ERROR_LOG_FMT(DISCIO, "Failed to read from {}", key_path);
|
||||||
return false;
|
return false;
|
||||||
@ -67,13 +67,13 @@ std::vector<NFSLBARange> NFSFileReader::GetLBARanges(const NFSHeader& header)
|
|||||||
return lba_ranges;
|
return lba_ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<File::IOFile> NFSFileReader::OpenFiles(const std::string& directory,
|
std::vector<File::DirectIOFile> NFSFileReader::OpenFiles(const std::string& directory,
|
||||||
File::IOFile first_file, u64 expected_raw_size,
|
File::DirectIOFile first_file,
|
||||||
u64* raw_size_out)
|
u64 expected_raw_size, u64* raw_size_out)
|
||||||
{
|
{
|
||||||
const u64 file_count = Common::AlignUp(expected_raw_size, MAX_FILE_SIZE) / MAX_FILE_SIZE;
|
const u64 file_count = Common::AlignUp(expected_raw_size, MAX_FILE_SIZE) / MAX_FILE_SIZE;
|
||||||
|
|
||||||
std::vector<File::IOFile> files;
|
std::vector<File::DirectIOFile> files;
|
||||||
files.reserve(file_count);
|
files.reserve(file_count);
|
||||||
|
|
||||||
*raw_size_out = first_file.GetSize();
|
*raw_size_out = first_file.GetSize();
|
||||||
@ -82,8 +82,8 @@ std::vector<File::IOFile> NFSFileReader::OpenFiles(const std::string& directory,
|
|||||||
for (u64 i = 1; i < file_count; ++i)
|
for (u64 i = 1; i < file_count; ++i)
|
||||||
{
|
{
|
||||||
const std::string child_path = fmt::format("{}hif_{:06}.nfs", directory, i);
|
const std::string child_path = fmt::format("{}hif_{:06}.nfs", directory, i);
|
||||||
File::IOFile child(child_path, "rb");
|
File::DirectIOFile child(child_path, File::AccessMode::Read);
|
||||||
if (!child)
|
if (!child.IsOpen())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(DISCIO, "Failed to open {}", child_path);
|
ERROR_LOG_FMT(DISCIO, "Failed to open {}", child_path);
|
||||||
return {};
|
return {};
|
||||||
@ -123,7 +123,7 @@ u64 NFSFileReader::CalculateExpectedDataSize(const std::vector<NFSLBARange>& lba
|
|||||||
return u64(greatest_block_index) * BLOCK_SIZE;
|
return u64(greatest_block_index) * BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::IOFile first_file,
|
std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::DirectIOFile first_file,
|
||||||
const std::string& path)
|
const std::string& path)
|
||||||
{
|
{
|
||||||
std::string directory, filename, extension;
|
std::string directory, filename, extension;
|
||||||
@ -136,18 +136,15 @@ std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::IOFile first_file,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
NFSHeader header;
|
NFSHeader header;
|
||||||
if (!first_file.Seek(0, File::SeekOrigin::Begin) || !first_file.ReadArray(&header, 1) ||
|
if (!first_file.OffsetRead(0, Common::AsWritableU8Span(header)) || header.magic != NFS_MAGIC)
|
||||||
header.magic != NFS_MAGIC)
|
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<NFSLBARange> lba_ranges = GetLBARanges(header);
|
std::vector<NFSLBARange> lba_ranges = GetLBARanges(header);
|
||||||
|
|
||||||
const u64 expected_raw_size = CalculateExpectedRawSize(lba_ranges);
|
const u64 expected_raw_size = CalculateExpectedRawSize(lba_ranges);
|
||||||
|
|
||||||
u64 raw_size;
|
u64 raw_size;
|
||||||
std::vector<File::IOFile> files =
|
std::vector<File::DirectIOFile> files =
|
||||||
OpenFiles(directory, std::move(first_file), expected_raw_size, &raw_size);
|
OpenFiles(directory, std::move(first_file), expected_raw_size, &raw_size);
|
||||||
|
|
||||||
if (files.empty())
|
if (files.empty())
|
||||||
@ -157,8 +154,8 @@ std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::IOFile first_file,
|
|||||||
new NFSFileReader(std::move(lba_ranges), std::move(files), key, raw_size));
|
new NFSFileReader(std::move(lba_ranges), std::move(files), key, raw_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
NFSFileReader::NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::IOFile> files,
|
NFSFileReader::NFSFileReader(std::vector<NFSLBARange> lba_ranges,
|
||||||
Key key, u64 raw_size)
|
std::vector<File::DirectIOFile> files, Key key, u64 raw_size)
|
||||||
: m_lba_ranges(std::move(lba_ranges)), m_files(std::move(files)),
|
: m_lba_ranges(std::move(lba_ranges)), m_files(std::move(files)),
|
||||||
m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size), m_key(key)
|
m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size), m_key(key)
|
||||||
{
|
{
|
||||||
@ -167,11 +164,7 @@ NFSFileReader::NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<Fi
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> NFSFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> NFSFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
std::vector<File::IOFile> new_files{};
|
return std::unique_ptr<BlobReader>{new NFSFileReader(m_lba_ranges, m_files, m_key, m_raw_size)};
|
||||||
for (const File::IOFile& file : m_files)
|
|
||||||
new_files.push_back(file.Duplicate("rb"));
|
|
||||||
return std::unique_ptr<NFSFileReader>(
|
|
||||||
new NFSFileReader(m_lba_ranges, std::move(new_files), m_key, m_raw_size));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 NFSFileReader::GetDataSize() const
|
u64 NFSFileReader::GetDataSize() const
|
||||||
@ -208,6 +201,7 @@ bool NFSFileReader::ReadEncryptedBlock(u64 physical_block_index)
|
|||||||
|
|
||||||
const u64 file_index = physical_block_index / BLOCKS_PER_FILE;
|
const u64 file_index = physical_block_index / BLOCKS_PER_FILE;
|
||||||
const u64 block_in_file = physical_block_index % BLOCKS_PER_FILE;
|
const u64 block_in_file = physical_block_index % BLOCKS_PER_FILE;
|
||||||
|
const u64 offset_in_file = sizeof(NFSHeader) + block_in_file * BLOCK_SIZE;
|
||||||
|
|
||||||
if (block_in_file == BLOCKS_PER_FILE - 1)
|
if (block_in_file == BLOCKS_PER_FILE - 1)
|
||||||
{
|
{
|
||||||
@ -217,33 +211,23 @@ bool NFSFileReader::ReadEncryptedBlock(u64 physical_block_index)
|
|||||||
constexpr size_t PART_1_SIZE = BLOCK_SIZE - sizeof(NFSHeader);
|
constexpr size_t PART_1_SIZE = BLOCK_SIZE - sizeof(NFSHeader);
|
||||||
constexpr size_t PART_2_SIZE = sizeof(NFSHeader);
|
constexpr size_t PART_2_SIZE = sizeof(NFSHeader);
|
||||||
|
|
||||||
File::IOFile& file_1 = m_files[file_index];
|
File::DirectIOFile& file_1 = m_files[file_index];
|
||||||
File::IOFile& file_2 = m_files[file_index + 1];
|
File::DirectIOFile& file_2 = m_files[file_index + 1];
|
||||||
|
|
||||||
if (!file_1.Seek(sizeof(NFSHeader) + block_in_file * BLOCK_SIZE, File::SeekOrigin::Begin) ||
|
if (!file_1.OffsetRead(offset_in_file, m_current_block_encrypted.data(), PART_1_SIZE))
|
||||||
!file_1.ReadBytes(m_current_block_encrypted.data(), PART_1_SIZE))
|
|
||||||
{
|
|
||||||
file_1.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_2.Seek(0, File::SeekOrigin::Begin) ||
|
if (!file_2.OffsetRead(0, m_current_block_encrypted.data() + PART_1_SIZE, PART_2_SIZE))
|
||||||
!file_2.ReadBytes(m_current_block_encrypted.data() + PART_1_SIZE, PART_2_SIZE))
|
|
||||||
{
|
|
||||||
file_2.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Normal case. The read is offset by 0x200 bytes, but it's all within one file.
|
// Normal case. The read is offset by 0x200 bytes, but it's all within one file.
|
||||||
|
|
||||||
File::IOFile& file = m_files[file_index];
|
File::DirectIOFile& file = m_files[file_index];
|
||||||
|
|
||||||
if (!file.Seek(sizeof(NFSHeader) + block_in_file * BLOCK_SIZE, File::SeekOrigin::Begin) ||
|
if (!file.OffsetRead(offset_in_file, m_current_block_encrypted.data(), BLOCK_SIZE))
|
||||||
!file.ReadBytes(m_current_block_encrypted.data(), BLOCK_SIZE))
|
|
||||||
{
|
{
|
||||||
file.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Crypto/AES.h"
|
#include "Common/Crypto/AES.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
// This is the file format used for Wii games released on the Wii U eShop.
|
// This is the file format used for Wii games released on the Wii U eShop.
|
||||||
@ -41,7 +41,7 @@ static_assert(sizeof(NFSHeader) == 0x200);
|
|||||||
class NFSFileReader final : public BlobReader
|
class NFSFileReader final : public BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<NFSFileReader> Create(File::IOFile first_file,
|
static std::unique_ptr<NFSFileReader> Create(File::DirectIOFile first_file,
|
||||||
const std::string& directory_path);
|
const std::string& directory_path);
|
||||||
|
|
||||||
BlobType GetBlobType() const override { return BlobType::NFS; }
|
BlobType GetBlobType() const override { return BlobType::NFS; }
|
||||||
@ -65,12 +65,13 @@ private:
|
|||||||
|
|
||||||
static bool ReadKey(const std::string& path, const std::string& directory, Key* key_out);
|
static bool ReadKey(const std::string& path, const std::string& directory, Key* key_out);
|
||||||
static std::vector<NFSLBARange> GetLBARanges(const NFSHeader& header);
|
static std::vector<NFSLBARange> GetLBARanges(const NFSHeader& header);
|
||||||
static std::vector<File::IOFile> OpenFiles(const std::string& directory, File::IOFile first_file,
|
static std::vector<File::DirectIOFile> OpenFiles(const std::string& directory,
|
||||||
u64 expected_raw_size, u64* raw_size_out);
|
File::DirectIOFile first_file,
|
||||||
|
u64 expected_raw_size, u64* raw_size_out);
|
||||||
static u64 CalculateExpectedRawSize(const std::vector<NFSLBARange>& lba_ranges);
|
static u64 CalculateExpectedRawSize(const std::vector<NFSLBARange>& lba_ranges);
|
||||||
static u64 CalculateExpectedDataSize(const std::vector<NFSLBARange>& lba_ranges);
|
static u64 CalculateExpectedDataSize(const std::vector<NFSLBARange>& lba_ranges);
|
||||||
|
|
||||||
NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::IOFile> files, Key key,
|
NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::DirectIOFile> files, Key key,
|
||||||
u64 raw_size);
|
u64 raw_size);
|
||||||
|
|
||||||
u64 ToPhysicalBlockIndex(u64 logical_block_index) const;
|
u64 ToPhysicalBlockIndex(u64 logical_block_index) const;
|
||||||
@ -83,7 +84,7 @@ private:
|
|||||||
u64 m_current_logical_block_index = std::numeric_limits<u64>::max();
|
u64 m_current_logical_block_index = std::numeric_limits<u64>::max();
|
||||||
|
|
||||||
std::vector<NFSLBARange> m_lba_ranges;
|
std::vector<NFSLBARange> m_lba_ranges;
|
||||||
std::vector<File::IOFile> m_files;
|
std::vector<File::DirectIOFile> m_files;
|
||||||
std::unique_ptr<Common::AES::Context> m_aes_context;
|
std::unique_ptr<Common::AES::Context> m_aes_context;
|
||||||
u64 m_raw_size;
|
u64 m_raw_size;
|
||||||
u64 m_data_size;
|
u64 m_data_size;
|
||||||
|
|||||||
@ -4,17 +4,11 @@
|
|||||||
#include "DiscIO/SplitFileBlob.h"
|
#include "DiscIO/SplitFileBlob.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
|
||||||
#include "Common/FileUtil.h"
|
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/MsgHandler.h"
|
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
SplitPlainFileReader::SplitPlainFileReader(std::vector<SingleFile> files)
|
SplitPlainFileReader::SplitPlainFileReader(std::vector<SingleFile> files)
|
||||||
@ -38,7 +32,7 @@ std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_v
|
|||||||
u64 offset = 0;
|
u64 offset = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
File::IOFile f(fmt::format("{}.part{}.iso", base_path, index), "rb");
|
File::DirectIOFile f(fmt::format("{}.part{}.iso", base_path, index), File::AccessMode::Read);
|
||||||
if (!f.IsOpen())
|
if (!f.IsOpen())
|
||||||
break;
|
break;
|
||||||
const u64 size = f.GetSize();
|
const u64 size = f.GetSize();
|
||||||
@ -58,13 +52,7 @@ std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_v
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> SplitPlainFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> SplitPlainFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
std::vector<SingleFile> new_files{};
|
return std::unique_ptr<SplitPlainFileReader>{new SplitPlainFileReader(m_files)};
|
||||||
for (const SingleFile& file : m_files)
|
|
||||||
{
|
|
||||||
new_files.push_back(
|
|
||||||
{.file = file.file.Duplicate("rb"), .offset = file.offset, .size = file.size});
|
|
||||||
}
|
|
||||||
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(new_files)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
||||||
@ -80,13 +68,10 @@ bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
if (current_offset >= file.offset && current_offset < file.offset + file.size)
|
if (current_offset >= file.offset && current_offset < file.offset + file.size)
|
||||||
{
|
{
|
||||||
auto& f = file.file;
|
auto& f = file.file;
|
||||||
const u64 seek_offset = current_offset - file.offset;
|
const u64 offset_in_file = current_offset - file.offset;
|
||||||
const u64 current_read = std::min(file.size - seek_offset, rest);
|
const u64 current_read = std::min(file.size - offset_in_file, rest);
|
||||||
if (!f.Seek(seek_offset, File::SeekOrigin::Begin) || !f.ReadBytes(out, current_read))
|
if (!f.OffsetRead(offset_in_file, out, current_read))
|
||||||
{
|
|
||||||
f.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
rest -= current_read;
|
rest -= current_read;
|
||||||
if (rest == 0)
|
if (rest == 0)
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -37,7 +37,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct SingleFile
|
struct SingleFile
|
||||||
{
|
{
|
||||||
File::IOFile file;
|
File::DirectIOFile file;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 size;
|
u64 size;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,12 +5,11 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/IOFile.h"
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -45,11 +44,10 @@ void Replace(u64 offset, u64 size, u8* out_ptr, u64 replace_offset, const T& rep
|
|||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
std::unique_ptr<TGCFileReader> TGCFileReader::Create(File::IOFile file)
|
std::unique_ptr<TGCFileReader> TGCFileReader::Create(File::DirectIOFile file)
|
||||||
{
|
{
|
||||||
TGCHeader header;
|
TGCHeader header;
|
||||||
if (file.Seek(0, File::SeekOrigin::Begin) && file.ReadArray(&header, 1) &&
|
if (file.OffsetRead(0, Common::AsWritableU8Span(header)) && header.magic == TGC_MAGIC)
|
||||||
header.magic == TGC_MAGIC)
|
|
||||||
{
|
{
|
||||||
return std::unique_ptr<TGCFileReader>(new TGCFileReader(std::move(file)));
|
return std::unique_ptr<TGCFileReader>(new TGCFileReader(std::move(file)));
|
||||||
}
|
}
|
||||||
@ -57,18 +55,16 @@ std::unique_ptr<TGCFileReader> TGCFileReader::Create(File::IOFile file)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TGCFileReader::TGCFileReader(File::IOFile file) : m_file(std::move(file))
|
TGCFileReader::TGCFileReader(File::DirectIOFile file) : m_file(std::move(file))
|
||||||
{
|
{
|
||||||
m_file.Seek(0, File::SeekOrigin::Begin);
|
m_file.OffsetRead(0, Common::AsWritableU8Span(m_header));
|
||||||
m_file.ReadArray(&m_header, 1);
|
|
||||||
|
|
||||||
m_size = m_file.GetSize();
|
m_size = m_file.GetSize();
|
||||||
|
|
||||||
const u32 fst_offset = Common::swap32(m_header.fst_real_offset);
|
const u32 fst_offset = Common::swap32(m_header.fst_real_offset);
|
||||||
const u32 fst_size = Common::swap32(m_header.fst_size);
|
const u32 fst_size = Common::swap32(m_header.fst_size);
|
||||||
m_fst.resize(fst_size);
|
m_fst.resize(fst_size);
|
||||||
if (!m_file.Seek(fst_offset, File::SeekOrigin::Begin) ||
|
if (!m_file.OffsetRead(fst_offset, m_fst))
|
||||||
!m_file.ReadBytes(m_fst.data(), m_fst.size()))
|
|
||||||
{
|
{
|
||||||
m_fst.clear();
|
m_fst.clear();
|
||||||
}
|
}
|
||||||
@ -100,7 +96,7 @@ TGCFileReader::TGCFileReader(File::IOFile file) : m_file(std::move(file))
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> TGCFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> TGCFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
return Create(m_file.Duplicate("rb"));
|
return Create(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 TGCFileReader::GetDataSize() const
|
u64 TGCFileReader::GetDataSize() const
|
||||||
@ -112,8 +108,7 @@ bool TGCFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
{
|
{
|
||||||
const u32 tgc_header_size = Common::swap32(m_header.tgc_header_size);
|
const u32 tgc_header_size = Common::swap32(m_header.tgc_header_size);
|
||||||
|
|
||||||
if (m_file.Seek(offset + tgc_header_size, File::SeekOrigin::Begin) &&
|
if (m_file.OffsetRead(offset + tgc_header_size, out_ptr, nbytes))
|
||||||
m_file.ReadBytes(out_ptr, nbytes))
|
|
||||||
{
|
{
|
||||||
const u32 replacement_dol_offset = SubtractBE32(m_header.dol_real_offset, tgc_header_size);
|
const u32 replacement_dol_offset = SubtractBE32(m_header.dol_real_offset, tgc_header_size);
|
||||||
const u32 replacement_fst_offset = SubtractBE32(m_header.fst_real_offset, tgc_header_size);
|
const u32 replacement_fst_offset = SubtractBE32(m_header.fst_real_offset, tgc_header_size);
|
||||||
@ -126,7 +121,6 @@ bool TGCFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -39,7 +38,7 @@ struct TGCHeader
|
|||||||
class TGCFileReader final : public BlobReader
|
class TGCFileReader final : public BlobReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<TGCFileReader> Create(File::IOFile file);
|
static std::unique_ptr<TGCFileReader> Create(File::DirectIOFile file);
|
||||||
|
|
||||||
BlobType GetBlobType() const override { return BlobType::TGC; }
|
BlobType GetBlobType() const override { return BlobType::TGC; }
|
||||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||||
@ -56,9 +55,9 @@ public:
|
|||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TGCFileReader(File::IOFile file);
|
TGCFileReader(File::DirectIOFile file);
|
||||||
|
|
||||||
File::IOFile m_file;
|
File::DirectIOFile m_file;
|
||||||
u64 m_size;
|
u64 m_size;
|
||||||
|
|
||||||
std::vector<u8> m_fst;
|
std::vector<u8> m_fst;
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Crypto/SHA1.h"
|
#include "Common/Crypto/SHA1.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
@ -78,7 +78,7 @@ std::pair<int, int> GetAllowedCompressionLevels(WIARVZCompressionType compressio
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
WIARVZFileReader<RVZ>::WIARVZFileReader(File::IOFile file, const std::string& path)
|
WIARVZFileReader<RVZ>::WIARVZFileReader(File::DirectIOFile file, const std::string& path)
|
||||||
: m_file(std::move(file)), m_path(path), m_encryption_cache(this)
|
: m_file(std::move(file)), m_path(path), m_encryption_cache(this)
|
||||||
{
|
{
|
||||||
m_valid = Initialize(path);
|
m_valid = Initialize(path);
|
||||||
@ -90,8 +90,11 @@ WIARVZFileReader<RVZ>::~WIARVZFileReader() = default;
|
|||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
bool WIARVZFileReader<RVZ>::Initialize(const std::string& path)
|
bool WIARVZFileReader<RVZ>::Initialize(const std::string& path)
|
||||||
{
|
{
|
||||||
if (!m_file.Seek(0, File::SeekOrigin::Begin) || !m_file.ReadArray(&m_header_1, 1))
|
if (!m_file.Seek(0, File::SeekOrigin::Begin) ||
|
||||||
|
!m_file.Read(Common::AsWritableU8Span(m_header_1)))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!RVZ && m_header_1.magic != WIA_MAGIC) || (RVZ && m_header_1.magic != RVZ_MAGIC))
|
if ((!RVZ && m_header_1.magic != WIA_MAGIC) || (RVZ && m_header_1.magic != RVZ_MAGIC))
|
||||||
return false;
|
return false;
|
||||||
@ -126,7 +129,7 @@ bool WIARVZFileReader<RVZ>::Initialize(const std::string& path)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<u8> header_2(header_2_size);
|
std::vector<u8> header_2(header_2_size);
|
||||||
if (!m_file.ReadBytes(header_2.data(), header_2.size()))
|
if (!m_file.Read(header_2))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto header_2_actual_hash = Common::SHA1::CalculateDigest(header_2);
|
const auto header_2_actual_hash = Common::SHA1::CalculateDigest(header_2);
|
||||||
@ -161,10 +164,10 @@ bool WIARVZFileReader<RVZ>::Initialize(const std::string& path)
|
|||||||
const size_t number_of_partition_entries = Common::swap32(m_header_2.number_of_partition_entries);
|
const size_t number_of_partition_entries = Common::swap32(m_header_2.number_of_partition_entries);
|
||||||
const size_t partition_entry_size = Common::swap32(m_header_2.partition_entry_size);
|
const size_t partition_entry_size = Common::swap32(m_header_2.partition_entry_size);
|
||||||
std::vector<u8> partition_entries(partition_entry_size * number_of_partition_entries);
|
std::vector<u8> partition_entries(partition_entry_size * number_of_partition_entries);
|
||||||
if (!m_file.Seek(Common::swap64(m_header_2.partition_entries_offset), File::SeekOrigin::Begin))
|
if (!m_file.OffsetRead(Common::swap64(m_header_2.partition_entries_offset), partition_entries))
|
||||||
return false;
|
{
|
||||||
if (!m_file.ReadBytes(partition_entries.data(), partition_entries.size()))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto partition_entries_actual_hash = Common::SHA1::CalculateDigest(partition_entries);
|
const auto partition_entries_actual_hash = Common::SHA1::CalculateDigest(partition_entries);
|
||||||
if (m_header_2.partition_entries_hash != partition_entries_actual_hash)
|
if (m_header_2.partition_entries_hash != partition_entries_actual_hash)
|
||||||
@ -273,7 +276,7 @@ bool WIARVZFileReader<RVZ>::HasDataOverlap() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
std::unique_ptr<WIARVZFileReader<RVZ>> WIARVZFileReader<RVZ>::Create(File::IOFile file,
|
std::unique_ptr<WIARVZFileReader<RVZ>> WIARVZFileReader<RVZ>::Create(File::DirectIOFile file,
|
||||||
const std::string& path)
|
const std::string& path)
|
||||||
{
|
{
|
||||||
std::unique_ptr<WIARVZFileReader> blob(new WIARVZFileReader(std::move(file), path));
|
std::unique_ptr<WIARVZFileReader> blob(new WIARVZFileReader(std::move(file), path));
|
||||||
@ -289,7 +292,7 @@ BlobType WIARVZFileReader<RVZ>::GetBlobType() const
|
|||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
std::unique_ptr<BlobReader> WIARVZFileReader<RVZ>::CopyReader() const
|
std::unique_ptr<BlobReader> WIARVZFileReader<RVZ>::CopyReader() const
|
||||||
{
|
{
|
||||||
return Create(m_file.Duplicate("rb"), m_path);
|
return Create(m_file, m_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
@ -628,8 +631,8 @@ template <bool RVZ>
|
|||||||
WIARVZFileReader<RVZ>::Chunk::Chunk() = default;
|
WIARVZFileReader<RVZ>::Chunk::Chunk() = default;
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
WIARVZFileReader<RVZ>::Chunk::Chunk(File::IOFile* file, u64 offset_in_file, u64 compressed_size,
|
WIARVZFileReader<RVZ>::Chunk::Chunk(File::DirectIOFile* file, u64 offset_in_file,
|
||||||
u64 decompressed_size, u32 exception_lists,
|
u64 compressed_size, u64 decompressed_size, u32 exception_lists,
|
||||||
bool compressed_exception_lists, u32 rvz_packed_size,
|
bool compressed_exception_lists, u32 rvz_packed_size,
|
||||||
u64 data_offset, std::unique_ptr<Decompressor> decompressor)
|
u64 data_offset, std::unique_ptr<Decompressor> decompressor)
|
||||||
: m_decompressor(std::move(decompressor)), m_file(file), m_offset_in_file(offset_in_file),
|
: m_decompressor(std::move(decompressor)), m_file(file), m_offset_in_file(offset_in_file),
|
||||||
@ -691,9 +694,7 @@ bool WIARVZFileReader<RVZ>::Chunk::Read(u64 offset, u64 size, u8* out_ptr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_file->Seek(m_offset_in_file, File::SeekOrigin::Begin))
|
if (!m_file->OffsetRead(m_offset_in_file, m_in.data.data() + m_in.bytes_written, bytes_to_read))
|
||||||
return false;
|
|
||||||
if (!m_file->ReadBytes(m_in.data.data() + m_in.bytes_written, bytes_to_read))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_offset_in_file += bytes_to_read;
|
m_offset_in_file += bytes_to_read;
|
||||||
@ -881,7 +882,7 @@ bool WIARVZFileReader<RVZ>::ApplyHashExceptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
bool WIARVZFileReader<RVZ>::PadTo4(File::IOFile* file, u64* bytes_written)
|
bool WIARVZFileReader<RVZ>::PadTo4(File::DirectIOFile* file, u64* bytes_written)
|
||||||
{
|
{
|
||||||
constexpr u32 ZEROES = 0;
|
constexpr u32 ZEROES = 0;
|
||||||
const u64 bytes_to_write = Common::AlignUp(*bytes_written, 4) - *bytes_written;
|
const u64 bytes_to_write = Common::AlignUp(*bytes_written, 4) - *bytes_written;
|
||||||
@ -889,7 +890,7 @@ bool WIARVZFileReader<RVZ>::PadTo4(File::IOFile* file, u64* bytes_written)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
*bytes_written += bytes_to_write;
|
*bytes_written += bytes_to_write;
|
||||||
return file->WriteBytes(&ZEROES, bytes_to_write);
|
return file->Write(Common::AsU8Span(ZEROES).first(bytes_to_write));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
@ -1646,7 +1647,7 @@ WIARVZFileReader<RVZ>::ProcessAndCompress(CompressThreadState* state, CompressPa
|
|||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
ConversionResultCode WIARVZFileReader<RVZ>::Output(std::vector<OutputParametersEntry>* entries,
|
ConversionResultCode WIARVZFileReader<RVZ>::Output(std::vector<OutputParametersEntry>* entries,
|
||||||
File::IOFile* outfile,
|
File::DirectIOFile* outfile,
|
||||||
std::map<ReuseID, GroupEntry>* reusable_groups,
|
std::map<ReuseID, GroupEntry>* reusable_groups,
|
||||||
std::mutex* reusable_groups_mutex,
|
std::mutex* reusable_groups_mutex,
|
||||||
GroupEntry* group_entry, u64* bytes_written)
|
GroupEntry* group_entry, u64* bytes_written)
|
||||||
@ -1675,9 +1676,9 @@ ConversionResultCode WIARVZFileReader<RVZ>::Output(std::vector<OutputParametersE
|
|||||||
}
|
}
|
||||||
group_entry->data_size = Common::swap32(data_size);
|
group_entry->data_size = Common::swap32(data_size);
|
||||||
|
|
||||||
if (!outfile->WriteArray(entry.exception_lists.data(), entry.exception_lists.size()))
|
if (!outfile->Write(entry.exception_lists))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
if (!outfile->WriteArray(entry.main_data.data(), entry.main_data.size()))
|
if (!outfile->Write(entry.main_data))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
|
|
||||||
*bytes_written += entry.exception_lists.size() + entry.main_data.size();
|
*bytes_written += entry.exception_lists.size() + entry.main_data.size();
|
||||||
@ -1716,7 +1717,7 @@ ConversionResultCode WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
bool WIARVZFileReader<RVZ>::WriteHeader(File::IOFile* file, const u8* data, size_t size,
|
bool WIARVZFileReader<RVZ>::WriteHeader(File::DirectIOFile* file, const u8* data, size_t size,
|
||||||
u64 upper_bound, u64* bytes_written, u64* offset_out)
|
u64 upper_bound, u64* bytes_written, u64* offset_out)
|
||||||
{
|
{
|
||||||
// The first part of the check is to prevent this from running more than once. If *bytes_written
|
// The first part of the check is to prevent this from running more than once. If *bytes_written
|
||||||
@ -1731,7 +1732,7 @@ bool WIARVZFileReader<RVZ>::WriteHeader(File::IOFile* file, const u8* data, size
|
|||||||
}
|
}
|
||||||
|
|
||||||
*offset_out = *bytes_written;
|
*offset_out = *bytes_written;
|
||||||
if (!file->WriteArray(data, size))
|
if (!file->Write(data, size))
|
||||||
return false;
|
return false;
|
||||||
*bytes_written += size;
|
*bytes_written += size;
|
||||||
return PadTo4(file, bytes_written);
|
return PadTo4(file, bytes_written);
|
||||||
@ -1740,7 +1741,7 @@ bool WIARVZFileReader<RVZ>::WriteHeader(File::IOFile* file, const u8* data, size
|
|||||||
template <bool RVZ>
|
template <bool RVZ>
|
||||||
ConversionResultCode
|
ConversionResultCode
|
||||||
WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volume,
|
WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volume,
|
||||||
File::IOFile* outfile, WIARVZCompressionType compression_type,
|
File::DirectIOFile* outfile, WIARVZCompressionType compression_type,
|
||||||
int compression_level, int chunk_size, CompressCB callback)
|
int compression_level, int chunk_size, CompressCB callback)
|
||||||
{
|
{
|
||||||
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
ASSERT(infile->GetDataSizeType() == DataSizeType::Accurate);
|
||||||
@ -1806,7 +1807,7 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu
|
|||||||
std::vector<u8> buffer;
|
std::vector<u8> buffer;
|
||||||
|
|
||||||
buffer.resize(headers_size_upper_bound);
|
buffer.resize(headers_size_upper_bound);
|
||||||
outfile->WriteBytes(buffer.data(), buffer.size());
|
outfile->Write(buffer);
|
||||||
bytes_written = headers_size_upper_bound;
|
bytes_written = headers_size_upper_bound;
|
||||||
|
|
||||||
if (!infile->Read(0, header_2.disc_header.size(), header_2.disc_header.data()))
|
if (!infile->Read(0, header_2.disc_header.size(), header_2.disc_header.data()))
|
||||||
@ -2029,9 +2030,9 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu
|
|||||||
if (!outfile->Seek(0, File::SeekOrigin::Begin))
|
if (!outfile->Seek(0, File::SeekOrigin::Begin))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
|
|
||||||
if (!outfile->WriteArray(&header_1, 1))
|
if (!outfile->Write(Common::AsU8Span(header_1)))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
if (!outfile->WriteArray(&header_2, 1))
|
if (!outfile->Write(Common::AsU8Span(header_2)))
|
||||||
return ConversionResultCode::WriteFailed;
|
return ConversionResultCode::WriteFailed;
|
||||||
|
|
||||||
return ConversionResultCode::Success;
|
return ConversionResultCode::Success;
|
||||||
@ -2042,8 +2043,8 @@ bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path,
|
|||||||
WIARVZCompressionType compression_type, int compression_level,
|
WIARVZCompressionType compression_type, int compression_level,
|
||||||
int chunk_size, const CompressCB& callback)
|
int chunk_size, const CompressCB& callback)
|
||||||
{
|
{
|
||||||
File::IOFile outfile(outfile_path, "wb");
|
File::DirectIOFile outfile(outfile_path, File::AccessMode::Write);
|
||||||
if (!outfile)
|
if (!outfile.IsOpen())
|
||||||
{
|
{
|
||||||
PanicAlertFmtT(
|
PanicAlertFmtT(
|
||||||
"Failed to open the output file \"{0}\".\n"
|
"Failed to open the output file \"{0}\".\n"
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Crypto/SHA1.h"
|
#include "Common/Crypto/SHA1.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
#include "DiscIO/MultithreadedCompressor.h"
|
#include "DiscIO/MultithreadedCompressor.h"
|
||||||
@ -46,7 +46,7 @@ class WIARVZFileReader final : public BlobReader
|
|||||||
public:
|
public:
|
||||||
~WIARVZFileReader() override;
|
~WIARVZFileReader() override;
|
||||||
|
|
||||||
static std::unique_ptr<WIARVZFileReader> Create(File::IOFile file, const std::string& path);
|
static std::unique_ptr<WIARVZFileReader> Create(File::DirectIOFile file, const std::string& path);
|
||||||
|
|
||||||
BlobType GetBlobType() const override;
|
BlobType GetBlobType() const override;
|
||||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||||
@ -68,8 +68,9 @@ public:
|
|||||||
bool ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, u64 partition_data_offset) override;
|
bool ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, u64 partition_data_offset) override;
|
||||||
|
|
||||||
static ConversionResultCode Convert(BlobReader* infile, const VolumeDisc* infile_volume,
|
static ConversionResultCode Convert(BlobReader* infile, const VolumeDisc* infile_volume,
|
||||||
File::IOFile* outfile, WIARVZCompressionType compression_type,
|
File::DirectIOFile* outfile,
|
||||||
int compression_level, int chunk_size, CompressCB callback);
|
WIARVZCompressionType compression_type, int compression_level,
|
||||||
|
int chunk_size, CompressCB callback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using WiiKey = std::array<u8, 16>;
|
using WiiKey = std::array<u8, 16>;
|
||||||
@ -188,7 +189,7 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Chunk();
|
Chunk();
|
||||||
Chunk(File::IOFile* file, u64 offset_in_file, u64 compressed_size, u64 decompressed_size,
|
Chunk(File::DirectIOFile* file, u64 offset_in_file, u64 compressed_size, u64 decompressed_size,
|
||||||
u32 exception_lists, bool compressed_exception_lists, u32 rvz_packed_size,
|
u32 exception_lists, bool compressed_exception_lists, u32 rvz_packed_size,
|
||||||
u64 data_offset, std::unique_ptr<Decompressor> decompressor);
|
u64 data_offset, std::unique_ptr<Decompressor> decompressor);
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ private:
|
|||||||
size_t m_in_bytes_read = 0;
|
size_t m_in_bytes_read = 0;
|
||||||
|
|
||||||
std::unique_ptr<Decompressor> m_decompressor = nullptr;
|
std::unique_ptr<Decompressor> m_decompressor = nullptr;
|
||||||
File::IOFile* m_file = nullptr;
|
File::DirectIOFile* m_file = nullptr;
|
||||||
u64 m_offset_in_file = 0;
|
u64 m_offset_in_file = 0;
|
||||||
|
|
||||||
size_t m_out_bytes_allocated_for_exceptions = 0;
|
size_t m_out_bytes_allocated_for_exceptions = 0;
|
||||||
@ -228,7 +229,7 @@ private:
|
|||||||
u64 m_data_offset = 0;
|
u64 m_data_offset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit WIARVZFileReader(File::IOFile file, const std::string& path);
|
explicit WIARVZFileReader(File::DirectIOFile file, const std::string& path);
|
||||||
bool Initialize(const std::string& path);
|
bool Initialize(const std::string& path);
|
||||||
bool HasDataOverlap() const;
|
bool HasDataOverlap() const;
|
||||||
|
|
||||||
@ -323,7 +324,7 @@ private:
|
|||||||
size_t group_index = 0;
|
size_t group_index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool PadTo4(File::IOFile* file, u64* bytes_written);
|
static bool PadTo4(File::DirectIOFile* file, u64* bytes_written);
|
||||||
static void AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* total_groups,
|
static void AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* total_groups,
|
||||||
std::vector<RawDataEntry>* raw_data_entries,
|
std::vector<RawDataEntry>* raw_data_entries,
|
||||||
std::vector<DataEntry>* data_entries);
|
std::vector<DataEntry>* data_entries);
|
||||||
@ -337,7 +338,7 @@ private:
|
|||||||
std::vector<DataEntry>* data_entries, std::vector<const FileSystem*>* partition_file_systems);
|
std::vector<DataEntry>* data_entries, std::vector<const FileSystem*>* partition_file_systems);
|
||||||
static std::optional<std::vector<u8>> Compress(Compressor* compressor, const u8* data,
|
static std::optional<std::vector<u8>> Compress(Compressor* compressor, const u8* data,
|
||||||
size_t size);
|
size_t size);
|
||||||
static bool WriteHeader(File::IOFile* file, const u8* data, size_t size, u64 upper_bound,
|
static bool WriteHeader(File::DirectIOFile* file, const u8* data, size_t size, u64 upper_bound,
|
||||||
u64* bytes_written, u64* offset_out);
|
u64* bytes_written, u64* offset_out);
|
||||||
|
|
||||||
static void SetUpCompressor(std::unique_ptr<Compressor>* compressor,
|
static void SetUpCompressor(std::unique_ptr<Compressor>* compressor,
|
||||||
@ -354,7 +355,7 @@ private:
|
|||||||
u64 exception_lists_per_chunk, bool compressed_exception_lists,
|
u64 exception_lists_per_chunk, bool compressed_exception_lists,
|
||||||
bool compression);
|
bool compression);
|
||||||
static ConversionResultCode Output(std::vector<OutputParametersEntry>* entries,
|
static ConversionResultCode Output(std::vector<OutputParametersEntry>* entries,
|
||||||
File::IOFile* outfile,
|
File::DirectIOFile* outfile,
|
||||||
std::map<ReuseID, GroupEntry>* reusable_groups,
|
std::map<ReuseID, GroupEntry>* reusable_groups,
|
||||||
std::mutex* reusable_groups_mutex, GroupEntry* group_entry,
|
std::mutex* reusable_groups_mutex, GroupEntry* group_entry,
|
||||||
u64* bytes_written);
|
u64* bytes_written);
|
||||||
@ -365,7 +366,7 @@ private:
|
|||||||
bool m_valid;
|
bool m_valid;
|
||||||
WIARVZCompressionType m_compression_type;
|
WIARVZCompressionType m_compression_type;
|
||||||
|
|
||||||
File::IOFile m_file;
|
File::DirectIOFile m_file;
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
Chunk m_cached_chunk;
|
Chunk m_cached_chunk;
|
||||||
u64 m_cached_chunk_offset = std::numeric_limits<u64>::max();
|
u64 m_cached_chunk_offset = std::numeric_limits<u64>::max();
|
||||||
|
|||||||
@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/BitUtils.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ static constexpr u64 WII_SECTOR_SIZE = 0x8000;
|
|||||||
static constexpr u64 WII_SECTOR_COUNT = 143432 * 2;
|
static constexpr u64 WII_SECTOR_COUNT = 143432 * 2;
|
||||||
static constexpr u64 WII_DISC_HEADER_SIZE = 256;
|
static constexpr u64 WII_DISC_HEADER_SIZE = 256;
|
||||||
|
|
||||||
WbfsFileReader::WbfsFileReader(File::IOFile file, const std::string& path)
|
WbfsFileReader::WbfsFileReader(File::DirectIOFile file, const std::string& path)
|
||||||
: m_size(0), m_good(false)
|
: m_size(0), m_good(false)
|
||||||
{
|
{
|
||||||
if (!AddFileToList(std::move(file)))
|
if (!AddFileToList(std::move(file)))
|
||||||
@ -39,7 +39,7 @@ WbfsFileReader::WbfsFileReader(File::IOFile file, const std::string& path)
|
|||||||
m_wlba_table.resize(m_blocks_per_disc);
|
m_wlba_table.resize(m_blocks_per_disc);
|
||||||
m_files[0].file.Seek(m_hd_sector_size + WII_DISC_HEADER_SIZE /*+ i * m_disc_info_size*/,
|
m_files[0].file.Seek(m_hd_sector_size + WII_DISC_HEADER_SIZE /*+ i * m_disc_info_size*/,
|
||||||
File::SeekOrigin::Begin);
|
File::SeekOrigin::Begin);
|
||||||
m_files[0].file.ReadBytes(m_wlba_table.data(), m_blocks_per_disc * sizeof(u16));
|
m_files[0].file.Read(Common::AsWritableU8Span(m_wlba_table));
|
||||||
for (size_t i = 0; i < m_blocks_per_disc; i++)
|
for (size_t i = 0; i < m_blocks_per_disc; i++)
|
||||||
m_wlba_table[i] = Common::swap16(m_wlba_table[i]);
|
m_wlba_table[i] = Common::swap16(m_wlba_table[i]);
|
||||||
}
|
}
|
||||||
@ -48,10 +48,9 @@ WbfsFileReader::~WbfsFileReader() = default;
|
|||||||
|
|
||||||
std::unique_ptr<BlobReader> WbfsFileReader::CopyReader() const
|
std::unique_ptr<BlobReader> WbfsFileReader::CopyReader() const
|
||||||
{
|
{
|
||||||
auto retval =
|
auto retval = std::unique_ptr<WbfsFileReader>(new WbfsFileReader(m_files[0].file));
|
||||||
std::unique_ptr<WbfsFileReader>(new WbfsFileReader(m_files[0].file.Duplicate("rb")));
|
|
||||||
for (size_t ix = 1; ix < m_files.size(); ix++)
|
for (size_t ix = 1; ix < m_files.size(); ix++)
|
||||||
retval->AddFileToList(m_files[ix].file.Duplicate("rb"));
|
retval->AddFileToList(m_files[ix].file);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,12 +73,12 @@ void WbfsFileReader::OpenAdditionalFiles(const std::string& path)
|
|||||||
return;
|
return;
|
||||||
std::string current_path = path;
|
std::string current_path = path;
|
||||||
current_path.back() = static_cast<char>('0' + m_files.size());
|
current_path.back() = static_cast<char>('0' + m_files.size());
|
||||||
if (!AddFileToList(File::IOFile(current_path, "rb")))
|
if (!AddFileToList(File::DirectIOFile(current_path, File::AccessMode::Read)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WbfsFileReader::AddFileToList(File::IOFile file)
|
bool WbfsFileReader::AddFileToList(File::DirectIOFile file)
|
||||||
{
|
{
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
return false;
|
return false;
|
||||||
@ -95,7 +94,7 @@ bool WbfsFileReader::ReadHeader()
|
|||||||
{
|
{
|
||||||
// Read hd size info
|
// Read hd size info
|
||||||
m_files[0].file.Seek(0, File::SeekOrigin::Begin);
|
m_files[0].file.Seek(0, File::SeekOrigin::Begin);
|
||||||
m_files[0].file.ReadBytes(&m_header, sizeof(WbfsHeader));
|
m_files[0].file.Read(Common::AsWritableU8Span(m_header));
|
||||||
if (m_header.magic != WBFS_MAGIC)
|
if (m_header.magic != WBFS_MAGIC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -128,14 +127,13 @@ bool WbfsFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
while (nbytes)
|
while (nbytes)
|
||||||
{
|
{
|
||||||
u64 read_size;
|
u64 read_size;
|
||||||
File::IOFile& data_file = SeekToCluster(offset, &read_size);
|
auto& data_file = SeekToCluster(offset, &read_size);
|
||||||
if (read_size == 0)
|
if (read_size == 0)
|
||||||
return false;
|
return false;
|
||||||
read_size = std::min(read_size, nbytes);
|
read_size = std::min(read_size, nbytes);
|
||||||
|
|
||||||
if (!data_file.ReadBytes(out_ptr, read_size))
|
if (!data_file.Read(out_ptr, read_size))
|
||||||
{
|
{
|
||||||
data_file.ClearError();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +145,7 @@ bool WbfsFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
File::IOFile& WbfsFileReader::SeekToCluster(u64 offset, u64* available)
|
File::DirectIOFile& WbfsFileReader::SeekToCluster(u64 offset, u64* available)
|
||||||
{
|
{
|
||||||
u64 base_cluster = (offset >> m_header.wbfs_sector_shift);
|
u64 base_cluster = (offset >> m_header.wbfs_sector_shift);
|
||||||
if (base_cluster < m_blocks_per_disc)
|
if (base_cluster < m_blocks_per_disc)
|
||||||
@ -180,7 +178,8 @@ File::IOFile& WbfsFileReader::SeekToCluster(u64 offset, u64* available)
|
|||||||
return m_files[0].file;
|
return m_files[0].file;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<WbfsFileReader> WbfsFileReader::Create(File::IOFile file, const std::string& path)
|
std::unique_ptr<WbfsFileReader> WbfsFileReader::Create(File::DirectIOFile file,
|
||||||
|
const std::string& path)
|
||||||
{
|
{
|
||||||
auto reader = std::unique_ptr<WbfsFileReader>(new WbfsFileReader(std::move(file), path));
|
auto reader = std::unique_ptr<WbfsFileReader>(new WbfsFileReader(std::move(file), path));
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/DirectIOFile.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
@ -20,7 +20,7 @@ class WbfsFileReader final : public BlobReader
|
|||||||
public:
|
public:
|
||||||
~WbfsFileReader() override;
|
~WbfsFileReader() override;
|
||||||
|
|
||||||
static std::unique_ptr<WbfsFileReader> Create(File::IOFile file, const std::string& path);
|
static std::unique_ptr<WbfsFileReader> Create(File::DirectIOFile file, const std::string& path);
|
||||||
|
|
||||||
BlobType GetBlobType() const override { return BlobType::WBFS; }
|
BlobType GetBlobType() const override { return BlobType::WBFS; }
|
||||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||||
@ -37,22 +37,22 @@ public:
|
|||||||
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
bool Read(u64 offset, u64 nbytes, u8* out_ptr) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WbfsFileReader(File::IOFile file, const std::string& path = "");
|
WbfsFileReader(File::DirectIOFile file, const std::string& path = "");
|
||||||
|
|
||||||
void OpenAdditionalFiles(const std::string& path);
|
void OpenAdditionalFiles(const std::string& path);
|
||||||
bool AddFileToList(File::IOFile file);
|
bool AddFileToList(File::DirectIOFile file);
|
||||||
bool ReadHeader();
|
bool ReadHeader();
|
||||||
|
|
||||||
File::IOFile& SeekToCluster(u64 offset, u64* available);
|
File::DirectIOFile& SeekToCluster(u64 offset, u64* available);
|
||||||
bool IsGood() const { return m_good; }
|
bool IsGood() const { return m_good; }
|
||||||
struct FileEntry
|
struct FileEntry
|
||||||
{
|
{
|
||||||
FileEntry(File::IOFile file_, u64 base_address_, u64 size_)
|
FileEntry(File::DirectIOFile file_, u64 base_address_, u64 size_)
|
||||||
: file(std::move(file_)), base_address(base_address_), size(size_)
|
: file(std::move(file_)), base_address(base_address_), size(size_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
File::IOFile file;
|
File::DirectIOFile file;
|
||||||
u64 base_address;
|
u64 base_address;
|
||||||
u64 size;
|
u64 size;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Common/Config/Config.h"
|
#include "Common/Config/Config.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
#include "Common/Version.h"
|
#include "Common/Version.h"
|
||||||
#include "Common/WindowSystemInfo.h"
|
#include "Common/WindowSystemInfo.h"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user