From d06b532150bbf969476f73ea93213c65e203558c Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Jun 2017 12:37:30 +0200 Subject: DiscIO: Move parts of Filesystem to the new file DiscExtractor --- Source/Core/DiscIO/DiscExtractor.cpp | 174 +++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 Source/Core/DiscIO/DiscExtractor.cpp (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp new file mode 100644 index 0000000000..403e6f6d0a --- /dev/null +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -0,0 +1,174 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DiscIO/DiscExtractor.h" + +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "DiscIO/Enums.h" +#include "DiscIO/Filesystem.h" +#include "DiscIO/Volume.h" + +namespace DiscIO +{ +u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, + u8* buffer, u64 max_buffer_size, u64 offset_in_file) +{ + if (!file_info || file_info->IsDirectory()) + return 0; + + if (offset_in_file >= file_info->GetSize()) + return 0; + + u64 read_length = std::min(max_buffer_size, file_info->GetSize() - offset_in_file); + + DEBUG_LOG(DISCIO, "Reading %" PRIx64 " bytes at %" PRIx64 " from file %s. Offset: %" PRIx64 + " Size: %" PRIx32, + read_length, offset_in_file, file_info->GetPath().c_str(), file_info->GetOffset(), + file_info->GetSize()); + + volume.Read(file_info->GetOffset() + offset_in_file, read_length, buffer, partition); + + return read_length; +} + +bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, + const std::string& export_filename) +{ + if (!file_info || file_info->IsDirectory()) + return false; + + u64 remaining_size = file_info->GetSize(); + u64 file_offset = file_info->GetOffset(); + + File::IOFile f(export_filename, "wb"); + if (!f) + return false; + + bool result = true; + + while (remaining_size) + { + // Limit read size to 128 MB + size_t read_size = (size_t)std::min(remaining_size, (u64)0x08000000); + + std::vector buffer(read_size); + + result = volume.Read(file_offset, read_size, &buffer[0], partition); + + if (!result) + break; + + f.WriteBytes(&buffer[0], read_size); + + remaining_size -= read_size; + file_offset += read_size; + } + + return result; +} + +bool ExportApploader(const Volume& volume, const Partition& partition, + const std::string& export_folder) +{ + if (!IsDisc(volume.GetVolumeType())) + return false; + + std::optional apploader_size = volume.ReadSwapped(0x2440 + 0x14, partition); + const std::optional trailer_size = volume.ReadSwapped(0x2440 + 0x18, partition); + constexpr u32 header_size = 0x20; + if (!apploader_size || !trailer_size) + return false; + *apploader_size += *trailer_size + header_size; + DEBUG_LOG(DISCIO, "Apploader size -> %x", *apploader_size); + + std::vector buffer(*apploader_size); + if (volume.Read(0x2440, *apploader_size, buffer.data(), partition)) + { + std::string export_name(export_folder + "/apploader.img"); + + File::IOFile apploader_file(export_name, "wb"); + if (apploader_file) + { + apploader_file.WriteBytes(buffer.data(), *apploader_size); + return true; + } + } + + return false; +} + +std::optional GetBootDOLOffset(const Volume& volume, const Partition& partition) +{ + const Platform volume_type = volume.GetVolumeType(); + if (!IsDisc(volume_type)) + return {}; + + std::optional offset = volume.ReadSwapped(0x420, partition); + const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0; + return offset ? static_cast(*offset) << offset_shift : std::optional(); +} + +std::optional GetBootDOLSize(const Volume& volume, const Partition& partition, u64 dol_offset) +{ + if (!IsDisc(volume.GetVolumeType())) + return {}; + + u32 dol_size = 0; + + // Iterate through the 7 code segments + for (u8 i = 0; i < 7; i++) + { + const std::optional offset = volume.ReadSwapped(dol_offset + 0x00 + i * 4, partition); + const std::optional size = volume.ReadSwapped(dol_offset + 0x90 + i * 4, partition); + if (!offset || !size) + return {}; + dol_size = std::max(*offset + *size, dol_size); + } + + // Iterate through the 11 data segments + for (u8 i = 0; i < 11; i++) + { + const std::optional offset = volume.ReadSwapped(dol_offset + 0x1c + i * 4, partition); + const std::optional size = volume.ReadSwapped(dol_offset + 0xac + i * 4, partition); + if (!offset || !size) + return {}; + dol_size = std::max(*offset + *size, dol_size); + } + + return dol_size; +} + +bool ExportDOL(const Volume& volume, const Partition& partition, const std::string& export_folder) +{ + if (!IsDisc(volume.GetVolumeType())) + return false; + + std::optional dol_offset = GetBootDOLOffset(volume, partition); + if (!dol_offset) + return false; + std::optional dol_size = GetBootDOLSize(volume, partition, *dol_offset); + if (!dol_size) + return false; + + std::vector buffer(*dol_size); + if (volume.Read(*dol_offset, *dol_size, buffer.data(), partition)) + { + std::string export_name(export_folder + "/boot.dol"); + + File::IOFile dol_file(export_name, "wb"); + if (dol_file) + { + dol_file.WriteBytes(&buffer[0], *dol_size); + return true; + } + } + + return false; +} + +} // namespace DiscIO -- cgit v1.2.3 From a17272c1467a5e655c309a619e839c00e1538acd Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Jun 2017 13:26:04 +0200 Subject: DiscExtractor: Minor cleanup --- Source/Core/DiscIO/DiscExtractor.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 403e6f6d0a..e8ef494f4d 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -18,13 +18,10 @@ namespace DiscIO u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, u8* buffer, u64 max_buffer_size, u64 offset_in_file) { - if (!file_info || file_info->IsDirectory()) - return 0; - - if (offset_in_file >= file_info->GetSize()) + if (!file_info || file_info->IsDirectory() || offset_in_file >= file_info->GetSize()) return 0; - u64 read_length = std::min(max_buffer_size, file_info->GetSize() - offset_in_file); + const u64 read_length = std::min(max_buffer_size, file_info->GetSize() - offset_in_file); DEBUG_LOG(DISCIO, "Reading %" PRIx64 " bytes at %" PRIx64 " from file %s. Offset: %" PRIx64 " Size: %" PRIx32, @@ -49,27 +46,23 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo if (!f) return false; - bool result = true; - while (remaining_size) { // Limit read size to 128 MB - size_t read_size = (size_t)std::min(remaining_size, (u64)0x08000000); + const size_t read_size = static_cast(std::min(remaining_size, 0x08000000)); std::vector buffer(read_size); - result = volume.Read(file_offset, read_size, &buffer[0], partition); - - if (!result) - break; + if (!volume.Read(file_offset, read_size, buffer.data(), partition)) + return false; - f.WriteBytes(&buffer[0], read_size); + f.WriteBytes(buffer.data(), read_size); remaining_size -= read_size; file_offset += read_size; } - return result; + return true; } bool ExportApploader(const Volume& volume, const Partition& partition, @@ -89,7 +82,7 @@ bool ExportApploader(const Volume& volume, const Partition& partition, std::vector buffer(*apploader_size); if (volume.Read(0x2440, *apploader_size, buffer.data(), partition)) { - std::string export_name(export_folder + "/apploader.img"); + const std::string export_name(export_folder + "/apploader.img"); File::IOFile apploader_file(export_name, "wb"); if (apploader_file) @@ -108,7 +101,7 @@ std::optional GetBootDOLOffset(const Volume& volume, const Partition& parti if (!IsDisc(volume_type)) return {}; - std::optional offset = volume.ReadSwapped(0x420, partition); + const std::optional offset = volume.ReadSwapped(0x420, partition); const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0; return offset ? static_cast(*offset) << offset_shift : std::optional(); } @@ -148,22 +141,22 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri if (!IsDisc(volume.GetVolumeType())) return false; - std::optional dol_offset = GetBootDOLOffset(volume, partition); + const std::optional dol_offset = GetBootDOLOffset(volume, partition); if (!dol_offset) return false; - std::optional dol_size = GetBootDOLSize(volume, partition, *dol_offset); + const std::optional dol_size = GetBootDOLSize(volume, partition, *dol_offset); if (!dol_size) return false; std::vector buffer(*dol_size); if (volume.Read(*dol_offset, *dol_size, buffer.data(), partition)) { - std::string export_name(export_folder + "/boot.dol"); + const std::string export_name(export_folder + "/boot.dol"); File::IOFile dol_file(export_name, "wb"); if (dol_file) { - dol_file.WriteBytes(&buffer[0], *dol_size); + dol_file.WriteBytes(buffer.data(), *dol_size); return true; } } -- cgit v1.2.3 From 1f31390b54f17f7dd5bd8f17f1842d76b9a4697d Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Jun 2017 13:28:14 +0200 Subject: DiscExtractor: Improve error handling --- Source/Core/DiscIO/DiscExtractor.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index e8ef494f4d..430ab7f55f 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -28,7 +28,8 @@ u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* f read_length, offset_in_file, file_info->GetPath().c_str(), file_info->GetOffset(), file_info->GetSize()); - volume.Read(file_info->GetOffset() + offset_in_file, read_length, buffer, partition); + if (!volume.Read(file_info->GetOffset() + offset_in_file, read_length, buffer, partition)) + return 0; return read_length; } @@ -56,7 +57,8 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo if (!volume.Read(file_offset, read_size, buffer.data(), partition)) return false; - f.WriteBytes(buffer.data(), read_size); + if (!f.WriteBytes(buffer.data(), read_size)) + return false; remaining_size -= read_size; file_offset += read_size; @@ -85,11 +87,8 @@ bool ExportApploader(const Volume& volume, const Partition& partition, const std::string export_name(export_folder + "/apploader.img"); File::IOFile apploader_file(export_name, "wb"); - if (apploader_file) - { - apploader_file.WriteBytes(buffer.data(), *apploader_size); + if (apploader_file.WriteBytes(buffer.data(), *apploader_size)) return true; - } } return false; @@ -154,11 +153,8 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri const std::string export_name(export_folder + "/boot.dol"); File::IOFile dol_file(export_name, "wb"); - if (dol_file) - { - dol_file.WriteBytes(buffer.data(), *dol_size); + if (dol_file.WriteBytes(buffer.data(), *dol_size)) return true; - } } return false; -- cgit v1.2.3 From 89c901780edb286df7cfbdce8cb1b38a6cb529e2 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Jun 2017 13:37:33 +0200 Subject: DiscScrubber: Deduplicate code for writing to file --- Source/Core/DiscIO/DiscExtractor.cpp | 52 +++++++++++++----------------------- 1 file changed, 18 insertions(+), 34 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 430ab7f55f..8adbcf02fe 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -34,39 +34,43 @@ u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* f return read_length; } -bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, +bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size, const std::string& export_filename) { - if (!file_info || file_info->IsDirectory()) - return false; - - u64 remaining_size = file_info->GetSize(); - u64 file_offset = file_info->GetOffset(); - File::IOFile f(export_filename, "wb"); if (!f) return false; - while (remaining_size) + while (size) { // Limit read size to 128 MB - const size_t read_size = static_cast(std::min(remaining_size, 0x08000000)); + const size_t read_size = static_cast(std::min(size, 0x08000000)); std::vector buffer(read_size); - if (!volume.Read(file_offset, read_size, buffer.data(), partition)) + if (!volume.Read(offset, read_size, buffer.data(), partition)) return false; if (!f.WriteBytes(buffer.data(), read_size)) return false; - remaining_size -= read_size; - file_offset += read_size; + size -= read_size; + offset += read_size; } return true; } +bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, + const std::string& export_filename) +{ + if (!file_info || file_info->IsDirectory()) + return false; + + return ExportData(volume, partition, file_info->GetOffset(), file_info->GetSize(), + export_filename); +} + bool ExportApploader(const Volume& volume, const Partition& partition, const std::string& export_folder) { @@ -81,17 +85,7 @@ bool ExportApploader(const Volume& volume, const Partition& partition, *apploader_size += *trailer_size + header_size; DEBUG_LOG(DISCIO, "Apploader size -> %x", *apploader_size); - std::vector buffer(*apploader_size); - if (volume.Read(0x2440, *apploader_size, buffer.data(), partition)) - { - const std::string export_name(export_folder + "/apploader.img"); - - File::IOFile apploader_file(export_name, "wb"); - if (apploader_file.WriteBytes(buffer.data(), *apploader_size)) - return true; - } - - return false; + return ExportData(volume, partition, 0x2440, *apploader_size, export_folder + "/apploader.img"); } std::optional GetBootDOLOffset(const Volume& volume, const Partition& partition) @@ -147,17 +141,7 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri if (!dol_size) return false; - std::vector buffer(*dol_size); - if (volume.Read(*dol_offset, *dol_size, buffer.data(), partition)) - { - const std::string export_name(export_folder + "/boot.dol"); - - File::IOFile dol_file(export_name, "wb"); - if (dol_file.WriteBytes(buffer.data(), *dol_size)) - return true; - } - - return false; + return ExportData(volume, partition, *dol_offset, *dol_size, export_folder + "/boot.dol"); } } // namespace DiscIO -- cgit v1.2.3 From baf3a3b188cb996a9994c18960e914f292b43841 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 17 Jun 2017 16:53:55 +0200 Subject: DiscExtractor: Don't hardcode names in ExportApploader and ExportDOL --- Source/Core/DiscIO/DiscExtractor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 8adbcf02fe..323fe706f2 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -72,7 +72,7 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo } bool ExportApploader(const Volume& volume, const Partition& partition, - const std::string& export_folder) + const std::string& export_filename) { if (!IsDisc(volume.GetVolumeType())) return false; @@ -85,7 +85,7 @@ bool ExportApploader(const Volume& volume, const Partition& partition, *apploader_size += *trailer_size + header_size; DEBUG_LOG(DISCIO, "Apploader size -> %x", *apploader_size); - return ExportData(volume, partition, 0x2440, *apploader_size, export_folder + "/apploader.img"); + return ExportData(volume, partition, 0x2440, *apploader_size, export_filename); } std::optional GetBootDOLOffset(const Volume& volume, const Partition& partition) @@ -129,7 +129,7 @@ std::optional GetBootDOLSize(const Volume& volume, const Partition& partiti return dol_size; } -bool ExportDOL(const Volume& volume, const Partition& partition, const std::string& export_folder) +bool ExportDOL(const Volume& volume, const Partition& partition, const std::string& export_filename) { if (!IsDisc(volume.GetVolumeType())) return false; @@ -141,7 +141,7 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri if (!dol_size) return false; - return ExportData(volume, partition, *dol_offset, *dol_size, export_folder + "/boot.dol"); + return ExportData(volume, partition, *dol_offset, *dol_size, export_filename); } } // namespace DiscIO -- cgit v1.2.3 From 6d5199264895f007b9714d448519f5fafec00fa6 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 18 Jun 2017 13:20:54 +0200 Subject: Move ExtractDir from FilesystemPanel to DiscExtractor --- Source/Core/DiscIO/DiscExtractor.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 323fe706f2..dbd5a7a821 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -71,6 +71,38 @@ bool ExportFile(const Volume& volume, const Partition& partition, const FileInfo export_filename); } +void ExportDirectory(const Volume& volume, const Partition partition, const FileInfo& directory, + bool recursive, const std::string& filesystem_path, + const std::string& export_folder, + const std::function& update_progress) +{ + for (const FileInfo& file_info : directory) + { + const std::string path = + filesystem_path + file_info.GetName() + (file_info.IsDirectory() ? "/" : ""); + const std::string export_path = export_folder + '/' + path; + + if (update_progress(path)) + return; + + DEBUG_LOG(DISCIO, "%s", export_path.c_str()); + + if (!file_info.IsDirectory()) + { + if (File::Exists(export_path)) + NOTICE_LOG(DISCIO, "%s already exists", export_path.c_str()); + else if (!ExportFile(volume, partition, &file_info, export_path)) + ERROR_LOG(DISCIO, "Could not export %s", export_path.c_str()); + } + else if (recursive) + { + File::CreateFullPath(export_path); + ExportDirectory(volume, partition, file_info, recursive, path, export_folder, + update_progress); + } + } +} + bool ExportApploader(const Volume& volume, const Partition& partition, const std::string& export_filename) { -- cgit v1.2.3 From 39ff203c1e60cae0f31fc881cd88fa68a203b79f Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 18 Jun 2017 14:17:33 +0200 Subject: DiscExtractor: Don't create extra folders when extracting a folder Before, if you extracted a directory like /map/Final/Release/, Dolphin would create the nested folders map, Final and Release in the output directory and put the files in Release instead of just putting the files directly in the output directory. --- Source/Core/DiscIO/DiscExtractor.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index dbd5a7a821..9a2dd16487 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -76,11 +76,13 @@ void ExportDirectory(const Volume& volume, const Partition partition, const File const std::string& export_folder, const std::function& update_progress) { + File::CreateFullPath(export_folder + '/'); + for (const FileInfo& file_info : directory) { - const std::string path = - filesystem_path + file_info.GetName() + (file_info.IsDirectory() ? "/" : ""); - const std::string export_path = export_folder + '/' + path; + const std::string name = file_info.GetName() + (file_info.IsDirectory() ? "/" : ""); + const std::string path = filesystem_path + name; + const std::string export_path = export_folder + '/' + name; if (update_progress(path)) return; @@ -96,9 +98,7 @@ void ExportDirectory(const Volume& volume, const Partition partition, const File } else if (recursive) { - File::CreateFullPath(export_path); - ExportDirectory(volume, partition, file_info, recursive, path, export_folder, - update_progress); + ExportDirectory(volume, partition, file_info, recursive, path, export_path, update_progress); } } } -- cgit v1.2.3 From 0b068d84d58e4e6584672c5e1a632df8ad67df5c Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 20 Jun 2017 15:41:17 +0200 Subject: FilesystemPanel: Overhaul the right-click menu --- Source/Core/DiscIO/DiscExtractor.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index 9a2dd16487..d0d7500897 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -176,4 +176,13 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri return ExportData(volume, partition, *dol_offset, *dol_size, export_filename); } +bool ExportSystemData(const Volume& volume, const Partition& partition, + const std::string& export_folder) +{ + bool success = true; + success &= ExportApploader(volume, partition, export_folder + "/apploader.img"); + success &= ExportDOL(volume, partition, export_folder + "/boot.dol"); + return success; +} + } // namespace DiscIO -- cgit v1.2.3 From 1b6506f4e8efb75ad075903a1f28581091a5806b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 20 Jun 2017 17:31:50 +0200 Subject: DiscExtractor: Add support for more things to extract --- Source/Core/DiscIO/DiscExtractor.cpp | 143 ++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index d0d7500897..f5dd28d9a5 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -103,6 +103,92 @@ void ExportDirectory(const Volume& volume, const Partition partition, const File } } +bool ExportWiiUnencryptedHeader(const Volume& volume, const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + return ExportData(volume, PARTITION_NONE, 0, 0x100, export_filename); +} + +bool ExportWiiRegionData(const Volume& volume, const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + return ExportData(volume, PARTITION_NONE, 0x4E000, 0x20, export_filename); +} + +bool ExportTicket(const Volume& volume, const Partition& partition, + const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + return ExportData(volume, PARTITION_NONE, partition.offset, 0x2a4, export_filename); +} + +bool ExportTMD(const Volume& volume, const Partition& partition, const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + std::optional size = volume.ReadSwapped(partition.offset + 0x2a4, PARTITION_NONE); + std::optional offset = volume.ReadSwapped(partition.offset + 0x2a8, PARTITION_NONE); + if (!size || !offset) + return false; + + const u64 actual_offset = partition.offset + (static_cast(*offset) << 2); + return ExportData(volume, PARTITION_NONE, actual_offset, *size, export_filename); +} + +bool ExportCertificateChain(const Volume& volume, const Partition& partition, + const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + std::optional size = volume.ReadSwapped(partition.offset + 0x2ac, PARTITION_NONE); + std::optional offset = volume.ReadSwapped(partition.offset + 0x2b0, PARTITION_NONE); + if (!size || !offset) + return false; + + const u64 actual_offset = partition.offset + (static_cast(*offset) << 2); + return ExportData(volume, PARTITION_NONE, actual_offset, *size, export_filename); +} + +bool ExportH3Hashes(const Volume& volume, const Partition& partition, + const std::string& export_filename) +{ + if (volume.GetVolumeType() != Platform::WII_DISC) + return false; + + std::optional offset = volume.ReadSwapped(partition.offset + 0x2b4, PARTITION_NONE); + if (!offset) + return false; + + const u64 actual_offset = partition.offset + (static_cast(*offset) << 2); + return ExportData(volume, PARTITION_NONE, actual_offset, 0x18000, export_filename); +} + +bool ExportHeader(const Volume& volume, const Partition& partition, + const std::string& export_filename) +{ + if (!IsDisc(volume.GetVolumeType())) + return false; + + return ExportData(volume, partition, 0, 0x440, export_filename); +} + +bool ExportBI2Data(const Volume& volume, const Partition& partition, + const std::string& export_filename) +{ + if (!IsDisc(volume.GetVolumeType())) + return false; + + return ExportData(volume, partition, 0x440, 0x2000, export_filename); +} + bool ExportApploader(const Volume& volume, const Partition& partition, const std::string& export_filename) { @@ -176,12 +262,65 @@ bool ExportDOL(const Volume& volume, const Partition& partition, const std::stri return ExportData(volume, partition, *dol_offset, *dol_size, export_filename); } +std::optional GetFSTOffset(const Volume& volume, const Partition& partition) +{ + const Platform volume_type = volume.GetVolumeType(); + if (!IsDisc(volume_type)) + return {}; + + const std::optional offset = volume.ReadSwapped(0x424, partition); + const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0; + return offset ? static_cast(*offset) << offset_shift : std::optional(); +} + +std::optional GetFSTSize(const Volume& volume, const Partition& partition) +{ + const Platform volume_type = volume.GetVolumeType(); + if (!IsDisc(volume_type)) + return {}; + + const std::optional size = volume.ReadSwapped(0x428, partition); + const u8 offset_shift = volume_type == Platform::WII_DISC ? 2 : 0; + return size ? static_cast(*size) << offset_shift : std::optional(); +} + +bool ExportFST(const Volume& volume, const Partition& partition, const std::string& export_filename) +{ + if (!IsDisc(volume.GetVolumeType())) + return false; + + const std::optional fst_offset = GetFSTOffset(volume, partition); + const std::optional fst_size = GetFSTSize(volume, partition); + if (!fst_offset || !fst_size) + return false; + + return ExportData(volume, partition, *fst_offset, *fst_size, export_filename); +} + bool ExportSystemData(const Volume& volume, const Partition& partition, const std::string& export_folder) { bool success = true; - success &= ExportApploader(volume, partition, export_folder + "/apploader.img"); - success &= ExportDOL(volume, partition, export_folder + "/boot.dol"); + + File::CreateFullPath(export_folder + "/sys/"); + success &= ExportHeader(volume, partition, export_folder + "/sys/boot.bin"); + success &= ExportBI2Data(volume, partition, export_folder + "/sys/bi2.bin"); + success &= ExportApploader(volume, partition, export_folder + "/sys/apploader.img"); + success &= ExportDOL(volume, partition, export_folder + "/sys/main.dol"); + success &= ExportFST(volume, partition, export_folder + "/sys/fst.bin"); + + if (volume.GetVolumeType() == Platform::WII_DISC) + { + File::CreateFullPath(export_folder + "/disc/"); + success &= ExportWiiUnencryptedHeader(volume, export_folder + "/disc/header.bin"); + success &= ExportWiiRegionData(volume, export_folder + "/disc/region.bin"); + + success &= ExportTicket(volume, partition, export_folder + "/ticket.bin"); + success &= ExportTMD(volume, partition, export_folder + "/tmd.bin"); + success &= ExportCertificateChain(volume, partition, export_folder + "/cert.bin"); + success &= ExportH3Hashes(volume, partition, export_folder + "/h3.bin"); + } + return success; } -- cgit v1.2.3 From a59edfe8cf4c3dd9275058ca1acd88019a3f6abf Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 20 Jun 2017 21:51:40 +0200 Subject: FilesystemPanel: Put partitions in separate folders when extracting all partitions --- Source/Core/DiscIO/DiscExtractor.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'Source/Core/DiscIO/DiscExtractor.cpp') diff --git a/Source/Core/DiscIO/DiscExtractor.cpp b/Source/Core/DiscIO/DiscExtractor.cpp index f5dd28d9a5..b56f120a67 100644 --- a/Source/Core/DiscIO/DiscExtractor.cpp +++ b/Source/Core/DiscIO/DiscExtractor.cpp @@ -6,15 +6,42 @@ #include #include +#include #include #include "Common/CommonTypes.h" +#include "Common/StringUtil.h" #include "DiscIO/Enums.h" #include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" namespace DiscIO { +std::string DirectoryNameForPartitionType(u32 partition_type) +{ + switch (partition_type) + { + case 0: + return "DATA"; + case 1: + return "UPDATE"; + case 2: + return "CHANNEL"; + default: + const std::string type_as_game_id{static_cast((partition_type >> 24) & 0xFF), + static_cast((partition_type >> 16) & 0xFF), + static_cast((partition_type >> 8) & 0xFF), + static_cast(partition_type & 0xFF)}; + if (std::all_of(type_as_game_id.cbegin(), type_as_game_id.cend(), + [](char c) { return std::isprint(c, std::locale::classic()); })) + { + return "P-" + type_as_game_id; + } + + return StringFromFormat("P%u", partition_type); + } +} + u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, u8* buffer, u64 max_buffer_size, u64 offset_in_file) { -- cgit v1.2.3