Merge pull request #5871 from JosJuice/read-swapped-and-shifted
DiscIO: Add a Volume::ReadSwappedAndShifted function
This commit is contained in:
commit
54778303ee
|
@ -160,13 +160,13 @@ bool ExportTMD(const Volume& volume, const Partition& partition, const std::stri
|
||||||
if (volume.GetVolumeType() != Platform::WII_DISC)
|
if (volume.GetVolumeType() != Platform::WII_DISC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::optional<u32> size = volume.ReadSwapped<u32>(partition.offset + 0x2a4, PARTITION_NONE);
|
const std::optional<u32> size = volume.ReadSwapped<u32>(partition.offset + 0x2a4, PARTITION_NONE);
|
||||||
std::optional<u32> offset = volume.ReadSwapped<u32>(partition.offset + 0x2a8, PARTITION_NONE);
|
const std::optional<u64> offset =
|
||||||
|
volume.ReadSwappedAndShifted(partition.offset + 0x2a8, PARTITION_NONE);
|
||||||
if (!size || !offset)
|
if (!size || !offset)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const u64 actual_offset = partition.offset + (static_cast<u64>(*offset) << 2);
|
return ExportData(volume, PARTITION_NONE, *offset, *size, export_filename);
|
||||||
return ExportData(volume, PARTITION_NONE, actual_offset, *size, export_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExportCertificateChain(const Volume& volume, const Partition& partition,
|
bool ExportCertificateChain(const Volume& volume, const Partition& partition,
|
||||||
|
@ -175,13 +175,13 @@ bool ExportCertificateChain(const Volume& volume, const Partition& partition,
|
||||||
if (volume.GetVolumeType() != Platform::WII_DISC)
|
if (volume.GetVolumeType() != Platform::WII_DISC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::optional<u32> size = volume.ReadSwapped<u32>(partition.offset + 0x2ac, PARTITION_NONE);
|
const std::optional<u32> size = volume.ReadSwapped<u32>(partition.offset + 0x2ac, PARTITION_NONE);
|
||||||
std::optional<u32> offset = volume.ReadSwapped<u32>(partition.offset + 0x2b0, PARTITION_NONE);
|
const std::optional<u64> offset =
|
||||||
|
volume.ReadSwappedAndShifted(partition.offset + 0x2b0, PARTITION_NONE);
|
||||||
if (!size || !offset)
|
if (!size || !offset)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const u64 actual_offset = partition.offset + (static_cast<u64>(*offset) << 2);
|
return ExportData(volume, PARTITION_NONE, *offset, *size, export_filename);
|
||||||
return ExportData(volume, PARTITION_NONE, actual_offset, *size, export_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExportH3Hashes(const Volume& volume, const Partition& partition,
|
bool ExportH3Hashes(const Volume& volume, const Partition& partition,
|
||||||
|
@ -190,12 +190,12 @@ bool ExportH3Hashes(const Volume& volume, const Partition& partition,
|
||||||
if (volume.GetVolumeType() != Platform::WII_DISC)
|
if (volume.GetVolumeType() != Platform::WII_DISC)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::optional<u32> offset = volume.ReadSwapped<u32>(partition.offset + 0x2b4, PARTITION_NONE);
|
const std::optional<u64> offset =
|
||||||
|
volume.ReadSwappedAndShifted(partition.offset + 0x2b4, PARTITION_NONE);
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const u64 actual_offset = partition.offset + (static_cast<u64>(*offset) << 2);
|
return ExportData(volume, PARTITION_NONE, *offset, 0x18000, export_filename);
|
||||||
return ExportData(volume, PARTITION_NONE, actual_offset, 0x18000, export_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExportHeader(const Volume& volume, const Partition& partition,
|
bool ExportHeader(const Volume& volume, const Partition& partition,
|
||||||
|
@ -239,9 +239,7 @@ std::optional<u64> GetBootDOLOffset(const Volume& volume, const Partition& parti
|
||||||
if (!IsDisc(volume_type))
|
if (!IsDisc(volume_type))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const std::optional<u32> offset = volume.ReadSwapped<u32>(0x420, partition);
|
return volume.ReadSwappedAndShifted(0x420, partition);
|
||||||
const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0;
|
|
||||||
return offset ? static_cast<u64>(*offset) << offset_shift : std::optional<u64>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> GetBootDOLSize(const Volume& volume, const Partition& partition, u64 dol_offset)
|
std::optional<u32> GetBootDOLSize(const Volume& volume, const Partition& partition, u64 dol_offset)
|
||||||
|
@ -295,9 +293,7 @@ std::optional<u64> GetFSTOffset(const Volume& volume, const Partition& partition
|
||||||
if (!IsDisc(volume_type))
|
if (!IsDisc(volume_type))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const std::optional<u32> offset = volume.ReadSwapped<u32>(0x424, partition);
|
return volume.ReadSwappedAndShifted(0x424, partition);
|
||||||
const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0;
|
|
||||||
return offset ? static_cast<u64>(*offset) << offset_shift : std::optional<u64>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u64> GetFSTSize(const Volume& volume, const Partition& partition)
|
std::optional<u64> GetFSTSize(const Volume& volume, const Partition& partition)
|
||||||
|
@ -306,9 +302,7 @@ std::optional<u64> GetFSTSize(const Volume& volume, const Partition& partition)
|
||||||
if (!IsDisc(volume_type))
|
if (!IsDisc(volume_type))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const std::optional<u32> size = volume.ReadSwapped<u32>(0x428, partition);
|
return volume.ReadSwappedAndShifted(0x428, partition);
|
||||||
const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0;
|
|
||||||
return size ? static_cast<u64>(*size) << offset_shift : std::optional<u64>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExportFST(const Volume& volume, const Partition& partition, const std::string& export_filename)
|
bool ExportFST(const Volume& volume, const Partition& partition, const std::string& export_filename)
|
||||||
|
|
|
@ -136,9 +136,9 @@ bool DiscScrubber::ReadFromVolume(u64 offset, u32& buffer, const Partition& part
|
||||||
|
|
||||||
bool DiscScrubber::ReadFromVolume(u64 offset, u64& buffer, const Partition& partition)
|
bool DiscScrubber::ReadFromVolume(u64 offset, u64& buffer, const Partition& partition)
|
||||||
{
|
{
|
||||||
std::optional<u32> value = m_disc->ReadSwapped<u32>(offset, partition);
|
std::optional<u64> value = m_disc->ReadSwappedAndShifted(offset, partition);
|
||||||
if (value)
|
if (value)
|
||||||
buffer = static_cast<u64>(*value) << 2;
|
buffer = *value;
|
||||||
return value.has_value();
|
return value.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,15 +185,16 @@ bool FileInfoGCWii::IsValid(u64 fst_size, const FileInfoGCWii& parent_directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partition)
|
FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partition)
|
||||||
: FileSystem(volume, partition), m_valid(false), m_offset_shift(0), m_root(nullptr, 0, 0, 0)
|
: FileSystem(volume, partition), m_valid(false), m_root(nullptr, 0, 0, 0)
|
||||||
{
|
{
|
||||||
|
u8 offset_shift;
|
||||||
// Check if this is a GameCube or Wii disc
|
// Check if this is a GameCube or Wii disc
|
||||||
if (m_volume->ReadSwapped<u32>(0x18, m_partition) == u32(0x5D1C9EA3))
|
if (m_volume->ReadSwapped<u32>(0x18, m_partition) == u32(0x5D1C9EA3))
|
||||||
m_offset_shift = 2; // Wii file system
|
offset_shift = 2; // Wii file system
|
||||||
else if (m_volume->ReadSwapped<u32>(0x1c, m_partition) == u32(0xC2339F3D))
|
else if (m_volume->ReadSwapped<u32>(0x1c, m_partition) == u32(0xC2339F3D))
|
||||||
m_offset_shift = 0; // GameCube file system
|
offset_shift = 0; // GameCube file system
|
||||||
else
|
else
|
||||||
return;
|
return; // Invalid partition (maybe someone removed its data but not its partition table entry)
|
||||||
|
|
||||||
const std::optional<u64> fst_offset = GetFSTOffset(*m_volume, m_partition);
|
const std::optional<u64> fst_offset = GetFSTOffset(*m_volume, m_partition);
|
||||||
const std::optional<u64> fst_size = GetFSTSize(*m_volume, m_partition);
|
const std::optional<u64> fst_size = GetFSTSize(*m_volume, m_partition);
|
||||||
|
@ -226,7 +227,7 @@ FileSystemGCWii::FileSystemGCWii(const Volume* volume, const Partition& partitio
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the root object
|
// Create the root object
|
||||||
m_root = FileInfoGCWii(m_file_system_table.data(), m_offset_shift);
|
m_root = FileInfoGCWii(m_file_system_table.data(), offset_shift);
|
||||||
if (!m_root.IsDirectory())
|
if (!m_root.IsDirectory())
|
||||||
{
|
{
|
||||||
ERROR_LOG(DISCIO, "File system root is not a directory");
|
ERROR_LOG(DISCIO, "File system root is not a directory");
|
||||||
|
|
|
@ -95,7 +95,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_valid;
|
bool m_valid;
|
||||||
u32 m_offset_shift;
|
|
||||||
std::vector<u8> m_file_system_table;
|
std::vector<u8> m_file_system_table;
|
||||||
FileInfoGCWii m_root;
|
FileInfoGCWii m_root;
|
||||||
// Maps the end offset of files to FST indexes
|
// Maps the end offset of files to FST indexes
|
||||||
|
|
|
@ -51,6 +51,12 @@ public:
|
||||||
return {};
|
return {};
|
||||||
return Common::FromBigEndian(temp);
|
return Common::FromBigEndian(temp);
|
||||||
}
|
}
|
||||||
|
std::optional<u64> ReadSwappedAndShifted(u64 offset, const Partition& partition) const
|
||||||
|
{
|
||||||
|
const std::optional<u32> temp = ReadSwapped<u32>(offset, partition);
|
||||||
|
return temp ? static_cast<u64>(*temp) << GetOffsetShift() : std::optional<u64>();
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::vector<Partition> GetPartitions() const { return {}; }
|
virtual std::vector<Partition> GetPartitions() const { return {}; }
|
||||||
virtual Partition GetGamePartition() const { return PARTITION_NONE; }
|
virtual Partition GetGamePartition() const { return PARTITION_NONE; }
|
||||||
virtual std::optional<u32> GetPartitionType(const Partition& partition) const { return {}; }
|
virtual std::optional<u32> GetPartitionType(const Partition& partition) const { return {}; }
|
||||||
|
@ -108,6 +114,7 @@ protected:
|
||||||
return CP1252ToUTF8(string);
|
return CP1252ToUTF8(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual u32 GetOffsetShift() const { return 0; }
|
||||||
static std::map<Language, std::string> ReadWiiNames(const std::vector<u8>& data);
|
static std::map<Language, std::string> ReadWiiNames(const std::vector<u8>& data);
|
||||||
|
|
||||||
static const size_t NUMBER_OF_LANGUAGES = 10;
|
static const size_t NUMBER_OF_LANGUAGES = 10;
|
||||||
|
|
|
@ -52,22 +52,22 @@ VolumeWii::VolumeWii(std::unique_ptr<BlobReader> reader)
|
||||||
if (!number_of_partitions)
|
if (!number_of_partitions)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::optional<u32> read_buffer =
|
const std::optional<u64> partition_table_offset =
|
||||||
m_pReader->ReadSwapped<u32>(0x40000 + (partition_group * 8) + 4);
|
ReadSwappedAndShifted(0x40000 + (partition_group * 8) + 4, PARTITION_NONE);
|
||||||
if (!read_buffer)
|
if (!partition_table_offset)
|
||||||
continue;
|
continue;
|
||||||
const u64 partition_table_offset = static_cast<u64>(*read_buffer) << 2;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < number_of_partitions; i++)
|
for (u32 i = 0; i < number_of_partitions; i++)
|
||||||
{
|
{
|
||||||
read_buffer = m_pReader->ReadSwapped<u32>(partition_table_offset + (i * 8));
|
const std::optional<u64> partition_offset =
|
||||||
if (!read_buffer)
|
ReadSwappedAndShifted(*partition_table_offset + (i * 8), PARTITION_NONE);
|
||||||
|
if (!partition_offset)
|
||||||
continue;
|
continue;
|
||||||
const u64 partition_offset = static_cast<u64>(*read_buffer) << 2;
|
|
||||||
const Partition partition(partition_offset);
|
const Partition partition(*partition_offset);
|
||||||
|
|
||||||
const std::optional<u32> partition_type =
|
const std::optional<u32> partition_type =
|
||||||
m_pReader->ReadSwapped<u32>(partition_table_offset + (i * 8) + 4);
|
m_pReader->ReadSwapped<u32>(*partition_table_offset + (i * 8) + 4);
|
||||||
if (!partition_type)
|
if (!partition_type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -84,10 +84,10 @@ VolumeWii::VolumeWii(std::unique_ptr<BlobReader> reader)
|
||||||
|
|
||||||
auto get_tmd = [this, partition]() -> IOS::ES::TMDReader {
|
auto get_tmd = [this, partition]() -> IOS::ES::TMDReader {
|
||||||
const std::optional<u32> tmd_size = m_pReader->ReadSwapped<u32>(partition.offset + 0x2a4);
|
const std::optional<u32> tmd_size = m_pReader->ReadSwapped<u32>(partition.offset + 0x2a4);
|
||||||
std::optional<u32> tmd_address = m_pReader->ReadSwapped<u32>(partition.offset + 0x2a8);
|
const std::optional<u64> tmd_address =
|
||||||
|
ReadSwappedAndShifted(partition.offset + 0x2a8, PARTITION_NONE);
|
||||||
if (!tmd_size || !tmd_address)
|
if (!tmd_size || !tmd_address)
|
||||||
return INVALID_TMD;
|
return INVALID_TMD;
|
||||||
*tmd_address <<= 2;
|
|
||||||
if (!IOS::ES::IsValidTMDSize(*tmd_size))
|
if (!IOS::ES::IsValidTMDSize(*tmd_size))
|
||||||
{
|
{
|
||||||
// This check is normally done by ES in ES_DiVerify, but that would happen too late
|
// This check is normally done by ES in ES_DiVerify, but that would happen too late
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
static constexpr unsigned int BLOCK_DATA_SIZE = 0x7C00;
|
static constexpr unsigned int BLOCK_DATA_SIZE = 0x7C00;
|
||||||
static constexpr unsigned int BLOCK_TOTAL_SIZE = BLOCK_HEADER_SIZE + BLOCK_DATA_SIZE;
|
static constexpr unsigned int BLOCK_TOTAL_SIZE = BLOCK_HEADER_SIZE + BLOCK_DATA_SIZE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 GetOffsetShift() const override { return 2; }
|
||||||
private:
|
private:
|
||||||
struct PartitionDetails
|
struct PartitionDetails
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue