From a59edfe8cf4c3dd9275058ca1acd88019a3f6abf Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 20 Jun 2017 21:51:40 +0200 Subject: [PATCH] FilesystemPanel: Put partitions in separate folders when extracting all partitions --- Source/Core/DiscIO/DiscExtractor.cpp | 27 +++++++++++++++++++ Source/Core/DiscIO/DiscExtractor.h | 2 ++ Source/Core/DiscIO/Volume.h | 1 + Source/Core/DiscIO/VolumeWii.cpp | 18 +++++++++---- Source/Core/DiscIO/VolumeWii.h | 2 ++ .../ISOProperties/FilesystemPanel.cpp | 14 +++++++--- 6 files changed, 56 insertions(+), 8 deletions(-) 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) { diff --git a/Source/Core/DiscIO/DiscExtractor.h b/Source/Core/DiscIO/DiscExtractor.h index aa4d2ea3c5..b3a1332c4b 100644 --- a/Source/Core/DiscIO/DiscExtractor.h +++ b/Source/Core/DiscIO/DiscExtractor.h @@ -15,6 +15,8 @@ class FileInfo; struct Partition; class Volume; +std::string DirectoryNameForPartitionType(u32 partition_type); + u64 ReadFile(const Volume& volume, const Partition& partition, const FileInfo* file_info, u8* buffer, u64 max_buffer_size, u64 offset_in_file = 0); bool ExportData(const Volume& volume, const Partition& partition, u64 offset, u64 size, diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index bbdffaa618..e0978048ab 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -53,6 +53,7 @@ public: } virtual std::vector GetPartitions() const { return {}; } virtual Partition GetGamePartition() const { return PARTITION_NONE; } + virtual std::optional GetPartitionType(const Partition& partition) const { return {}; } std::optional GetTitleID() const { return GetTitleID(GetGamePartition()); } virtual std::optional GetTitleID(const Partition& partition) const { return {}; } virtual const IOS::ES::TicketReader& GetTicket(const Partition& partition) const diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp index 0379a0c3cd..93c7133036 100644 --- a/Source/Core/DiscIO/VolumeWii.cpp +++ b/Source/Core/DiscIO/VolumeWii.cpp @@ -67,10 +67,11 @@ VolumeWii::VolumeWii(std::unique_ptr reader) continue; const u64 partition_offset = static_cast(*read_buffer) << 2; - // Check if this is the game partition - const bool is_game_partition = - m_game_partition == PARTITION_NONE && - m_pReader->ReadSwapped(partition_table_offset + (i * 8) + 4) == u32(0); + // Read the partition type + const std::optional partition_type = + m_pReader->ReadSwapped(partition_table_offset + (i * 8) + 4); + if (!partition_type) + continue; // Read ticket std::vector ticket_buffer(sizeof(IOS::ES::Ticket)); @@ -106,10 +107,11 @@ VolumeWii::VolumeWii(std::unique_ptr reader) // We've read everything. Time to store it! (The reason we don't store anything // earlier is because we want to be able to skip adding the partition if an error occurs.) const Partition partition(partition_offset); + m_partition_types[partition] = *partition_type; m_partition_keys[partition] = std::move(aes_context); m_partition_tickets[partition] = std::move(ticket); m_partition_tmds[partition] = std::move(tmd); - if (is_game_partition) + if (m_game_partition == PARTITION_NONE && *partition_type == 0) m_game_partition = partition; } } @@ -185,6 +187,12 @@ Partition VolumeWii::GetGamePartition() const return m_game_partition; } +std::optional VolumeWii::GetPartitionType(const Partition& partition) const +{ + auto it = m_partition_types.find(partition); + return it != m_partition_types.end() ? it->second : std::optional(); +} + std::optional VolumeWii::GetTitleID(const Partition& partition) const { const IOS::ES::TicketReader& ticket = GetTicket(partition); diff --git a/Source/Core/DiscIO/VolumeWii.h b/Source/Core/DiscIO/VolumeWii.h index 38dc5c4bc2..780bdb6dd4 100644 --- a/Source/Core/DiscIO/VolumeWii.h +++ b/Source/Core/DiscIO/VolumeWii.h @@ -34,6 +34,7 @@ public: bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, const Partition& partition) const override; std::vector GetPartitions() const override; Partition GetGamePartition() const override; + std::optional GetPartitionType(const Partition& partition) const override; std::optional GetTitleID(const Partition& partition) const override; const IOS::ES::TicketReader& GetTicket(const Partition& partition) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition) const override; @@ -64,6 +65,7 @@ public: private: std::unique_ptr m_pReader; + std::map m_partition_types; std::map> m_partition_keys; std::map m_partition_tickets; std::map m_partition_tmds; diff --git a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp index 4369d2ee3f..9888036d2a 100644 --- a/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp +++ b/Source/Core/DolphinWX/ISOProperties/FilesystemPanel.cpp @@ -277,6 +277,8 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event) if (extract_path.empty()) return; + const std::string std_extract_path = WxStrToStr(extract_path); + const wxTreeItemId selection = m_tree_ctrl->GetSelection(); const bool first_item_selected = m_tree_ctrl->GetFirstVisibleItem() == selection; @@ -290,18 +292,24 @@ void FilesystemPanel::OnExtractAll(wxCommandEvent& event) while (item.IsOk()) { const auto* const partition = static_cast(m_tree_ctrl->GetItemData(item)); - ExtractPartition(WxStrToStr(extract_path), *partition->filesystem); + const std::optional partition_type = + *m_opened_iso->GetPartitionType(partition->filesystem->GetPartition()); + if (partition_type) + { + const std::string partition_name = DiscIO::DirectoryNameForPartitionType(*partition_type); + ExtractPartition(std_extract_path + '/' + partition_name, *partition->filesystem); + } item = m_tree_ctrl->GetNextChild(root, cookie); } } else if (m_has_partitions && !first_item_selected) { const auto* const partition = static_cast(m_tree_ctrl->GetItemData(selection)); - ExtractPartition(WxStrToStr(extract_path), *partition->filesystem); + ExtractPartition(std_extract_path, *partition->filesystem); } else { - ExtractPartition(WxStrToStr(extract_path), *m_filesystem); + ExtractPartition(std_extract_path, *m_filesystem); } }