Merge pull request #4494 from lioncash/isoproperties
ISOProperties: Separate the filesystem tab out into its own class
This commit is contained in:
commit
b042377393
|
@ -34,6 +34,7 @@ set(GUI_SRCS
|
|||
Debugger/RegisterWindow.cpp
|
||||
Debugger/WatchView.cpp
|
||||
Debugger/WatchWindow.cpp
|
||||
ISOProperties/FilesystemPanel.cpp
|
||||
ISOProperties/InfoPanel.cpp
|
||||
ISOProperties/ISOProperties.cpp
|
||||
NetPlay/ChangeGameDialog.cpp
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
<ClCompile Include="Debugger\WatchView.cpp" />
|
||||
<ClCompile Include="Debugger\WatchWindow.cpp" />
|
||||
<ClCompile Include="DolphinSlider.cpp" />
|
||||
<ClCompile Include="ISOProperties\FilesystemPanel.cpp" />
|
||||
<ClCompile Include="ISOProperties\InfoPanel.cpp" />
|
||||
<ClCompile Include="ISOProperties\ISOProperties.cpp" />
|
||||
<ClCompile Include="NetPlay\ChangeGameDialog.cpp" />
|
||||
|
@ -146,6 +147,7 @@
|
|||
<ClInclude Include="Config\PathConfigPane.h" />
|
||||
<ClInclude Include="Config\WiiConfigPane.h" />
|
||||
<ClInclude Include="DolphinSlider.h" />
|
||||
<ClInclude Include="ISOProperties\FilesystemPanel.h" />
|
||||
<ClInclude Include="ISOProperties\InfoPanel.h" />
|
||||
<ClInclude Include="ISOProperties\ISOProperties.h" />
|
||||
<ClInclude Include="NetPlay\ChangeGameDialog.h" />
|
||||
|
|
|
@ -224,6 +224,9 @@
|
|||
<ClCompile Include="Config\AdvancedConfigPane.cpp">
|
||||
<Filter>GUI\Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ISOProperties\FilesystemPanel.cpp">
|
||||
<Filter>GUI\ISOProperties</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ISOProperties\InfoPanel.cpp">
|
||||
<Filter>GUI\ISOProperties</Filter>
|
||||
</ClCompile>
|
||||
|
@ -437,6 +440,9 @@
|
|||
<ClInclude Include="Config\AdvancedConfigPane.h">
|
||||
<Filter>GUI\Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ISOProperties\FilesystemPanel.h">
|
||||
<Filter>GUI\ISOProperties</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ISOProperties\InfoPanel.h">
|
||||
<Filter>GUI\ISOProperties</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -0,0 +1,641 @@
|
|||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinWX/ISOProperties/FilesystemPanel.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/imaglist.h>
|
||||
#include <wx/menu.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/treectrl.h>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Filesystem.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
#include "DolphinWX/ISOFile.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class WiiPartition final : public wxTreeItemData
|
||||
{
|
||||
public:
|
||||
WiiPartition(std::unique_ptr<DiscIO::IVolume> volume_,
|
||||
std::unique_ptr<DiscIO::IFileSystem> filesystem_)
|
||||
: volume{std::move(volume_)}, filesystem{std::move(filesystem_)}
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<DiscIO::IVolume> volume;
|
||||
std::unique_ptr<DiscIO::IFileSystem> filesystem;
|
||||
};
|
||||
|
||||
class IntegrityCheckThread final : public wxThread
|
||||
{
|
||||
public:
|
||||
explicit IntegrityCheckThread(const WiiPartition& partition)
|
||||
: wxThread{wxTHREAD_JOINABLE}, m_partition{partition}
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
ExitCode Entry() override
|
||||
{
|
||||
return reinterpret_cast<ExitCode>(m_partition.volume->CheckIntegrity());
|
||||
}
|
||||
|
||||
private:
|
||||
const WiiPartition& m_partition;
|
||||
};
|
||||
|
||||
enum : int
|
||||
{
|
||||
ICON_DISC,
|
||||
ICON_FOLDER,
|
||||
ICON_FILE
|
||||
};
|
||||
|
||||
wxImageList* LoadIconBitmaps(const wxWindow* context)
|
||||
{
|
||||
static constexpr std::array<const char*, 3> icon_names{
|
||||
{"isoproperties_disc", "isoproperties_folder", "isoproperties_file"}};
|
||||
|
||||
const wxSize icon_size = context->FromDIP(wxSize(16, 16));
|
||||
auto* const icon_list = new wxImageList(icon_size.GetWidth(), icon_size.GetHeight());
|
||||
|
||||
for (const auto& name : icon_names)
|
||||
{
|
||||
icon_list->Add(
|
||||
WxUtils::LoadScaledResourceBitmap(name, context, icon_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER));
|
||||
}
|
||||
|
||||
return icon_list;
|
||||
}
|
||||
|
||||
size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
|
||||
const std::vector<DiscIO::SFileInfo>& file_infos,
|
||||
const size_t first_index, const size_t last_index)
|
||||
{
|
||||
size_t current_index = first_index;
|
||||
|
||||
while (current_index < last_index)
|
||||
{
|
||||
const DiscIO::SFileInfo& file_info = file_infos[current_index];
|
||||
std::string file_path = file_info.m_FullPath;
|
||||
|
||||
// Trim the trailing '/' if it exists.
|
||||
if (file_path.back() == DIR_SEP_CHR)
|
||||
{
|
||||
file_path.pop_back();
|
||||
}
|
||||
|
||||
// Cut off the path up to the actual filename or folder.
|
||||
// Say we have "/music/stream/stream1.strm", the result will be "stream1.strm".
|
||||
const size_t dir_sep_index = file_path.rfind(DIR_SEP_CHR);
|
||||
if (dir_sep_index != std::string::npos)
|
||||
{
|
||||
file_path = file_path.substr(dir_sep_index + 1);
|
||||
}
|
||||
|
||||
// check next index
|
||||
if (file_info.IsDirectory())
|
||||
{
|
||||
const wxTreeItemId item = tree_ctrl->AppendItem(parent, StrToWxStr(file_path), ICON_FOLDER);
|
||||
current_index = CreateDirectoryTree(tree_ctrl, item, file_infos, current_index + 1,
|
||||
static_cast<size_t>(file_info.m_FileSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
tree_ctrl->AppendItem(parent, StrToWxStr(file_path), ICON_FILE);
|
||||
current_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return current_index;
|
||||
}
|
||||
|
||||
size_t CreateDirectoryTree(wxTreeCtrl* tree_ctrl, wxTreeItemId parent,
|
||||
const std::vector<DiscIO::SFileInfo>& file_infos)
|
||||
{
|
||||
if (file_infos.empty())
|
||||
return 0;
|
||||
|
||||
return CreateDirectoryTree(tree_ctrl, parent, file_infos, 1, file_infos.at(0).m_FileSize);
|
||||
}
|
||||
|
||||
WiiPartition* FindWiiPartition(wxTreeCtrl* tree_ctrl, const wxString& label)
|
||||
{
|
||||
wxTreeItemIdValue cookie;
|
||||
auto partition = tree_ctrl->GetFirstChild(tree_ctrl->GetRootItem(), cookie);
|
||||
|
||||
while (partition.IsOk())
|
||||
{
|
||||
const wxString partition_label = tree_ctrl->GetItemText(partition);
|
||||
|
||||
if (partition_label == label)
|
||||
return static_cast<WiiPartition*>(tree_ctrl->GetItemData(partition));
|
||||
|
||||
partition = tree_ctrl->GetNextSibling(partition);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
FilesystemPanel::FilesystemPanel(wxWindow* parent, wxWindowID id, const GameListItem& item,
|
||||
const std::unique_ptr<DiscIO::IVolume>& opened_iso)
|
||||
: wxPanel{parent, id}, m_game_list_item{item}, m_opened_iso{opened_iso}
|
||||
{
|
||||
CreateGUI();
|
||||
BindEvents();
|
||||
PopulateFileSystemTree();
|
||||
|
||||
m_tree_ctrl->Expand(m_tree_ctrl->GetRootItem());
|
||||
}
|
||||
|
||||
FilesystemPanel::~FilesystemPanel() = default;
|
||||
|
||||
void FilesystemPanel::BindEvents()
|
||||
{
|
||||
m_tree_ctrl->Bind(wxEVT_TREE_ITEM_RIGHT_CLICK, &FilesystemPanel::OnRightClickTree, this);
|
||||
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnExtractFile, this, ID_EXTRACT_FILE);
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnExtractDirectories, this, ID_EXTRACT_ALL);
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnExtractDirectories, this, ID_EXTRACT_DIR);
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnExtractHeaderData, this, ID_EXTRACT_APPLOADER);
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnExtractHeaderData, this, ID_EXTRACT_DOL);
|
||||
Bind(wxEVT_MENU, &FilesystemPanel::OnCheckPartitionIntegrity, this, ID_CHECK_INTEGRITY);
|
||||
}
|
||||
|
||||
void FilesystemPanel::CreateGUI()
|
||||
{
|
||||
m_tree_ctrl = new wxTreeCtrl(this);
|
||||
m_tree_ctrl->AssignImageList(LoadIconBitmaps(this));
|
||||
m_tree_ctrl->AddRoot(_("Disc"), ICON_DISC);
|
||||
|
||||
const auto space_5 = FromDIP(5);
|
||||
auto* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->AddSpacer(space_5);
|
||||
main_sizer->Add(m_tree_ctrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space_5);
|
||||
main_sizer->AddSpacer(space_5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
||||
void FilesystemPanel::PopulateFileSystemTree()
|
||||
{
|
||||
switch (m_opened_iso->GetVolumeType())
|
||||
{
|
||||
case DiscIO::Platform::GAMECUBE_DISC:
|
||||
PopulateFileSystemTreeGC();
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::WII_DISC:
|
||||
PopulateFileSystemTreeWii();
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::ELF_DOL:
|
||||
case DiscIO::Platform::NUMBER_OF_PLATFORMS:
|
||||
case DiscIO::Platform::WII_WAD:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::PopulateFileSystemTreeGC()
|
||||
{
|
||||
m_filesystem = DiscIO::CreateFileSystem(m_opened_iso.get());
|
||||
if (!m_filesystem)
|
||||
return;
|
||||
|
||||
CreateDirectoryTree(m_tree_ctrl, m_tree_ctrl->GetRootItem(), m_filesystem->GetFileList());
|
||||
}
|
||||
|
||||
void FilesystemPanel::PopulateFileSystemTreeWii() const
|
||||
{
|
||||
u32 partition_count = 0;
|
||||
|
||||
for (u32 group = 0; group < 4; group++)
|
||||
{
|
||||
// yes, technically there can be OVER NINE THOUSAND partitions...
|
||||
for (u32 i = 0; i < 0xFFFFFFFF; i++)
|
||||
{
|
||||
auto volume = DiscIO::CreateVolumeFromFilename(m_game_list_item.GetFileName(), group, i);
|
||||
if (volume == nullptr)
|
||||
break;
|
||||
|
||||
auto file_system = DiscIO::CreateFileSystem(volume.get());
|
||||
if (file_system != nullptr)
|
||||
{
|
||||
auto* const partition = new WiiPartition(std::move(volume), std::move(file_system));
|
||||
|
||||
const wxTreeItemId partition_root = m_tree_ctrl->AppendItem(
|
||||
m_tree_ctrl->GetRootItem(), wxString::Format(_("Partition %u"), partition_count),
|
||||
ICON_DISC);
|
||||
|
||||
m_tree_ctrl->SetItemData(partition_root, partition);
|
||||
CreateDirectoryTree(m_tree_ctrl, partition_root, partition->filesystem->GetFileList());
|
||||
|
||||
if (partition_count == 1)
|
||||
m_tree_ctrl->Expand(partition_root);
|
||||
|
||||
partition_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::OnRightClickTree(wxTreeEvent& event)
|
||||
{
|
||||
m_tree_ctrl->SelectItem(event.GetItem());
|
||||
|
||||
wxMenu menu;
|
||||
|
||||
const auto selection = m_tree_ctrl->GetSelection();
|
||||
const auto first_visible_item = m_tree_ctrl->GetFirstVisibleItem();
|
||||
const int image_type = m_tree_ctrl->GetItemImage(selection);
|
||||
|
||||
if (image_type == ICON_DISC && first_visible_item != selection)
|
||||
{
|
||||
menu.Append(ID_EXTRACT_DIR, _("Extract Partition..."));
|
||||
}
|
||||
else if (image_type == ICON_FOLDER)
|
||||
{
|
||||
menu.Append(ID_EXTRACT_DIR, _("Extract Directory..."));
|
||||
}
|
||||
else if (image_type == ICON_FILE)
|
||||
{
|
||||
menu.Append(ID_EXTRACT_FILE, _("Extract File..."));
|
||||
}
|
||||
|
||||
menu.Append(ID_EXTRACT_ALL, _("Extract All Files..."));
|
||||
|
||||
if (m_opened_iso->GetVolumeType() != DiscIO::Platform::WII_DISC ||
|
||||
(image_type == ICON_DISC && first_visible_item != selection))
|
||||
{
|
||||
menu.AppendSeparator();
|
||||
menu.Append(ID_EXTRACT_APPLOADER, _("Extract Apploader..."));
|
||||
menu.Append(ID_EXTRACT_DOL, _("Extract DOL..."));
|
||||
}
|
||||
|
||||
if (image_type == ICON_DISC && first_visible_item != selection)
|
||||
{
|
||||
menu.AppendSeparator();
|
||||
menu.Append(ID_CHECK_INTEGRITY, _("Check Partition Integrity"));
|
||||
}
|
||||
|
||||
PopupMenu(&menu);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void FilesystemPanel::OnExtractFile(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
const wxString selection_label = m_tree_ctrl->GetItemText(m_tree_ctrl->GetSelection());
|
||||
|
||||
const wxString output_file_path =
|
||||
wxFileSelector(_("Extract File"), wxEmptyString, selection_label, wxEmptyString,
|
||||
wxGetTranslation(wxALL_FILES), wxFD_SAVE, this);
|
||||
|
||||
if (output_file_path.empty() || selection_label.empty())
|
||||
return;
|
||||
|
||||
ExtractSingleFile(output_file_path);
|
||||
}
|
||||
|
||||
void FilesystemPanel::OnExtractDirectories(wxCommandEvent& event)
|
||||
{
|
||||
const wxString selected_directory_label = m_tree_ctrl->GetItemText(m_tree_ctrl->GetSelection());
|
||||
const wxString extract_path = wxDirSelector(_("Choose the folder to extract to"));
|
||||
|
||||
if (extract_path.empty() || selected_directory_label.empty())
|
||||
return;
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
case ID_EXTRACT_ALL:
|
||||
ExtractAllFiles(extract_path);
|
||||
break;
|
||||
case ID_EXTRACT_DIR:
|
||||
ExtractSingleDirectory(extract_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::OnExtractHeaderData(wxCommandEvent& event)
|
||||
{
|
||||
DiscIO::IFileSystem* file_system = nullptr;
|
||||
const wxString path = wxDirSelector(_("Choose the folder to extract to"));
|
||||
|
||||
if (path.empty())
|
||||
return;
|
||||
|
||||
if (m_opened_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
const auto* const selection_data = m_tree_ctrl->GetItemData(m_tree_ctrl->GetSelection());
|
||||
const auto* const partition = static_cast<const WiiPartition*>(selection_data);
|
||||
|
||||
file_system = partition->filesystem.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
file_system = m_filesystem.get();
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
if (event.GetId() == ID_EXTRACT_APPLOADER)
|
||||
{
|
||||
ret = file_system->ExportApploader(WxStrToStr(path));
|
||||
}
|
||||
else if (event.GetId() == ID_EXTRACT_DOL)
|
||||
{
|
||||
ret = file_system->ExportDOL(WxStrToStr(path));
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
WxUtils::ShowErrorDialog(
|
||||
wxString::Format(_("Failed to extract to %s!"), WxStrToStr(path).c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::OnCheckPartitionIntegrity(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
// Normally we can't enter this function if we aren't analyzing a Wii disc
|
||||
// anyway, but let's still check to be sure.
|
||||
if (m_opened_iso->GetVolumeType() != DiscIO::Platform::WII_DISC)
|
||||
return;
|
||||
|
||||
wxProgressDialog dialog(_("Checking integrity..."), _("Working..."), 1000, this,
|
||||
wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_SMOOTH);
|
||||
|
||||
const auto selection = m_tree_ctrl->GetSelection();
|
||||
|
||||
IntegrityCheckThread thread(*static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(selection)));
|
||||
thread.Run();
|
||||
|
||||
while (thread.IsAlive())
|
||||
{
|
||||
dialog.Pulse();
|
||||
wxThread::Sleep(50);
|
||||
}
|
||||
|
||||
dialog.Destroy();
|
||||
|
||||
if (thread.Wait())
|
||||
{
|
||||
wxMessageBox(_("Integrity check completed. No errors have been found."),
|
||||
_("Integrity check completed"), wxOK | wxICON_INFORMATION, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMessageBox(wxString::Format(_("Integrity check for %s failed. The disc image is most "
|
||||
"likely corrupted or has been patched incorrectly."),
|
||||
m_tree_ctrl->GetItemText(selection)),
|
||||
_("Integrity Check Error"), wxOK | wxICON_ERROR, this);
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractAllFiles(const wxString& output_folder)
|
||||
{
|
||||
switch (m_opened_iso->GetVolumeType())
|
||||
{
|
||||
case DiscIO::Platform::GAMECUBE_DISC:
|
||||
ExtractAllFilesGC(output_folder);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::WII_DISC:
|
||||
ExtractAllFilesWii(output_folder);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::ELF_DOL:
|
||||
case DiscIO::Platform::NUMBER_OF_PLATFORMS:
|
||||
case DiscIO::Platform::WII_WAD:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractAllFilesGC(const wxString& output_folder)
|
||||
{
|
||||
ExtractDirectories("", WxStrToStr(output_folder), m_filesystem.get());
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractAllFilesWii(const wxString& output_folder)
|
||||
{
|
||||
const wxTreeItemId root = m_tree_ctrl->GetRootItem();
|
||||
|
||||
wxTreeItemIdValue cookie;
|
||||
wxTreeItemId item = m_tree_ctrl->GetFirstChild(root, cookie);
|
||||
|
||||
while (item.IsOk())
|
||||
{
|
||||
const auto* const partition = static_cast<WiiPartition*>(m_tree_ctrl->GetItemData(item));
|
||||
ExtractDirectories("", WxStrToStr(output_folder), partition->filesystem.get());
|
||||
item = m_tree_ctrl->GetNextChild(root, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleFile(const wxString& output_file_path) const
|
||||
{
|
||||
const auto selection_file_path = BuildFilePathFromSelection();
|
||||
|
||||
switch (m_opened_iso->GetVolumeType())
|
||||
{
|
||||
case DiscIO::Platform::GAMECUBE_DISC:
|
||||
ExtractSingleFileGC(selection_file_path, output_file_path);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::WII_DISC:
|
||||
ExtractSingleFileWii(selection_file_path, output_file_path);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::ELF_DOL:
|
||||
case DiscIO::Platform::NUMBER_OF_PLATFORMS:
|
||||
case DiscIO::Platform::WII_WAD:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleFileGC(const wxString& file_path,
|
||||
const wxString& output_file_path) const
|
||||
{
|
||||
m_filesystem->ExportFile(WxStrToStr(file_path), WxStrToStr(output_file_path));
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleFileWii(wxString file_path,
|
||||
const wxString& output_file_path) const
|
||||
{
|
||||
const size_t slash_index = file_path.find('/');
|
||||
const wxString partition_label = file_path.substr(0, slash_index);
|
||||
const auto* const partition = FindWiiPartition(m_tree_ctrl, partition_label);
|
||||
|
||||
// Remove "Partition x/"
|
||||
file_path.erase(0, slash_index + 1);
|
||||
|
||||
partition->filesystem->ExportFile(WxStrToStr(file_path), WxStrToStr(output_file_path));
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleDirectory(const wxString& output_folder)
|
||||
{
|
||||
const wxString directory_path = BuildDirectoryPathFromSelection();
|
||||
|
||||
switch (m_opened_iso->GetVolumeType())
|
||||
{
|
||||
case DiscIO::Platform::GAMECUBE_DISC:
|
||||
ExtractSingleDirectoryGC(directory_path, output_folder);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::WII_DISC:
|
||||
ExtractSingleDirectoryWii(directory_path, output_folder);
|
||||
break;
|
||||
|
||||
case DiscIO::Platform::ELF_DOL:
|
||||
case DiscIO::Platform::NUMBER_OF_PLATFORMS:
|
||||
case DiscIO::Platform::WII_WAD:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleDirectoryGC(const wxString& directory_path,
|
||||
const wxString& output_folder)
|
||||
{
|
||||
ExtractDirectories(WxStrToStr(directory_path), WxStrToStr(output_folder), m_filesystem.get());
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractSingleDirectoryWii(wxString directory_path,
|
||||
const wxString& output_folder)
|
||||
{
|
||||
const size_t slash_index = directory_path.find('/');
|
||||
const wxString partition_label = directory_path.substr(0, slash_index);
|
||||
const auto* const partition = FindWiiPartition(m_tree_ctrl, partition_label);
|
||||
|
||||
// Remove "Partition x/"
|
||||
directory_path.erase(0, slash_index + 1);
|
||||
|
||||
ExtractDirectories(WxStrToStr(directory_path), WxStrToStr(output_folder),
|
||||
partition->filesystem.get());
|
||||
}
|
||||
|
||||
void FilesystemPanel::ExtractDirectories(const std::string& full_path,
|
||||
const std::string& output_folder,
|
||||
DiscIO::IFileSystem* filesystem)
|
||||
{
|
||||
const std::vector<DiscIO::SFileInfo>& fst = filesystem->GetFileList();
|
||||
|
||||
u32 index = 0;
|
||||
u32 size = 0;
|
||||
|
||||
// Extract all
|
||||
if (full_path.empty())
|
||||
{
|
||||
size = static_cast<u32>(fst.size());
|
||||
|
||||
filesystem->ExportApploader(output_folder);
|
||||
if (m_opened_iso->GetVolumeType() == DiscIO::Platform::GAMECUBE_DISC)
|
||||
filesystem->ExportDOL(output_folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for the dir we are going to extract
|
||||
for (index = 0; index < fst.size(); ++index)
|
||||
{
|
||||
if (fst[index].m_FullPath == full_path)
|
||||
{
|
||||
INFO_LOG(DISCIO, "Found the directory at %u", index);
|
||||
size = static_cast<u32>(fst[index].m_FileSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(DISCIO, "Directory found from %u to %u\nextracting to: %s", index, size,
|
||||
output_folder.c_str());
|
||||
}
|
||||
|
||||
const auto dialog_title = (index != 0) ? _("Extracting Directory") : _("Extracting All Files");
|
||||
wxProgressDialog dialog(dialog_title, _("Extracting..."), static_cast<int>(size - 1), this,
|
||||
wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME |
|
||||
wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
|
||||
|
||||
// Extraction
|
||||
for (u32 i = index; i < size; i++)
|
||||
{
|
||||
dialog.SetTitle(wxString::Format(
|
||||
"%s : %u%%", dialog_title.c_str(),
|
||||
static_cast<u32>((static_cast<float>(i - index) / static_cast<float>(size - index)) *
|
||||
100)));
|
||||
|
||||
dialog.Update(i, wxString::Format(_("Extracting %s"), StrToWxStr(fst[i].m_FullPath)));
|
||||
|
||||
if (dialog.WasCancelled())
|
||||
break;
|
||||
|
||||
if (fst[i].IsDirectory())
|
||||
{
|
||||
const std::string export_name =
|
||||
StringFromFormat("%s/%s/", output_folder.c_str(), fst[i].m_FullPath.c_str());
|
||||
INFO_LOG(DISCIO, "%s", export_name.c_str());
|
||||
|
||||
if (!File::Exists(export_name) && !File::CreateFullPath(export_name))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Could not create the path %s", export_name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File::IsDirectory(export_name))
|
||||
ERROR_LOG(DISCIO, "%s already exists and is not a directory", export_name.c_str());
|
||||
|
||||
ERROR_LOG(DISCIO, "Folder %s already exists", export_name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string export_name =
|
||||
StringFromFormat("%s/%s", output_folder.c_str(), fst[i].m_FullPath.c_str());
|
||||
INFO_LOG(DISCIO, "%s", export_name.c_str());
|
||||
|
||||
if (!File::Exists(export_name) && !filesystem->ExportFile(fst[i].m_FullPath, export_name))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Could not export %s", export_name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(DISCIO, "%s already exists", export_name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString FilesystemPanel::BuildFilePathFromSelection() const
|
||||
{
|
||||
wxString file_path = m_tree_ctrl->GetItemText(m_tree_ctrl->GetSelection());
|
||||
|
||||
const auto root_node = m_tree_ctrl->GetRootItem();
|
||||
auto node = m_tree_ctrl->GetItemParent(m_tree_ctrl->GetSelection());
|
||||
|
||||
while (node != root_node)
|
||||
{
|
||||
file_path = m_tree_ctrl->GetItemText(node) + DIR_SEP_CHR + file_path;
|
||||
node = m_tree_ctrl->GetItemParent(node);
|
||||
}
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
wxString FilesystemPanel::BuildDirectoryPathFromSelection() const
|
||||
{
|
||||
wxString directory_path = BuildFilePathFromSelection();
|
||||
directory_path += DIR_SEP_CHR;
|
||||
return directory_path;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <wx/panel.h>
|
||||
|
||||
class GameListItem;
|
||||
class wxTreeCtrl;
|
||||
class wxTreeEvent;
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
class IFileSystem;
|
||||
class IVolume;
|
||||
}
|
||||
|
||||
class FilesystemPanel final : public wxPanel
|
||||
{
|
||||
public:
|
||||
explicit FilesystemPanel(wxWindow* parent, wxWindowID id, const GameListItem& item,
|
||||
const std::unique_ptr<DiscIO::IVolume>& opened_iso);
|
||||
~FilesystemPanel();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
ID_EXTRACT_DIR = 20000,
|
||||
ID_EXTRACT_ALL,
|
||||
ID_EXTRACT_FILE,
|
||||
ID_EXTRACT_APPLOADER,
|
||||
ID_EXTRACT_DOL,
|
||||
ID_CHECK_INTEGRITY,
|
||||
};
|
||||
|
||||
void CreateGUI();
|
||||
void BindEvents();
|
||||
|
||||
void PopulateFileSystemTree();
|
||||
void PopulateFileSystemTreeGC();
|
||||
void PopulateFileSystemTreeWii() const;
|
||||
|
||||
void OnRightClickTree(wxTreeEvent&);
|
||||
void OnExtractFile(wxCommandEvent&);
|
||||
void OnExtractDirectories(wxCommandEvent&);
|
||||
void OnExtractHeaderData(wxCommandEvent&);
|
||||
void OnCheckPartitionIntegrity(wxCommandEvent&);
|
||||
|
||||
void ExtractAllFiles(const wxString& output_folder);
|
||||
void ExtractAllFilesGC(const wxString& output_folder);
|
||||
void ExtractAllFilesWii(const wxString& output_folder);
|
||||
|
||||
void ExtractSingleFile(const wxString& output_file_path) const;
|
||||
void ExtractSingleFileGC(const wxString& file_path, const wxString& output_file_path) const;
|
||||
void ExtractSingleFileWii(wxString file_path, const wxString& output_file_path) const;
|
||||
|
||||
void ExtractSingleDirectory(const wxString& output_folder);
|
||||
void ExtractSingleDirectoryGC(const wxString& directory_path, const wxString& output_folder);
|
||||
void ExtractSingleDirectoryWii(wxString directory_path, const wxString& output_folder);
|
||||
|
||||
void ExtractDirectories(const std::string& full_path, const std::string& output_folder,
|
||||
DiscIO::IFileSystem* filesystem);
|
||||
|
||||
wxString BuildFilePathFromSelection() const;
|
||||
wxString BuildDirectoryPathFromSelection() const;
|
||||
|
||||
wxTreeCtrl* m_tree_ctrl;
|
||||
|
||||
const GameListItem& m_game_list_item;
|
||||
const std::unique_ptr<DiscIO::IVolume>& m_opened_iso;
|
||||
|
||||
std::unique_ptr<DiscIO::IFileSystem> m_filesystem;
|
||||
};
|
|
@ -4,13 +4,11 @@
|
|||
|
||||
#include "DolphinWX/ISOProperties/ISOProperties.h"
|
||||
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
@ -22,25 +20,18 @@
|
|||
#include <wx/checklst.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dirdlg.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/imaglist.h>
|
||||
#include <wx/itemid.h>
|
||||
#include <wx/menu.h>
|
||||
#include <wx/mimetype.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/thread.h>
|
||||
#include <wx/treebase.h>
|
||||
#include <wx/treectrl.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
|
@ -48,14 +39,12 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/SysConf.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/GeckoCodeConfig.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Filesystem.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
|
||||
|
@ -65,6 +54,7 @@
|
|||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/ISOFile.h"
|
||||
#include "DolphinWX/ISOProperties/FilesystemPanel.h"
|
||||
#include "DolphinWX/ISOProperties/InfoPanel.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/PatchAddEdit.h"
|
||||
|
@ -197,13 +187,6 @@ EVT_LISTBOX(ID_PATCHES_LIST, CISOProperties::PatchListSelectionChanged)
|
|||
EVT_BUTTON(ID_EDITPATCH, CISOProperties::PatchButtonClicked)
|
||||
EVT_BUTTON(ID_ADDPATCH, CISOProperties::PatchButtonClicked)
|
||||
EVT_BUTTON(ID_REMOVEPATCH, CISOProperties::PatchButtonClicked)
|
||||
EVT_TREE_ITEM_RIGHT_CLICK(ID_TREECTRL, CISOProperties::OnRightClickOnTree)
|
||||
EVT_MENU(IDM_EXTRACTFILE, CISOProperties::OnExtractFile)
|
||||
EVT_MENU(IDM_EXTRACTDIR, CISOProperties::OnExtractDir)
|
||||
EVT_MENU(IDM_EXTRACTALL, CISOProperties::OnExtractDir)
|
||||
EVT_MENU(IDM_EXTRACTAPPLOADER, CISOProperties::OnExtractDataFromHeader)
|
||||
EVT_MENU(IDM_EXTRACTDOL, CISOProperties::OnExtractDataFromHeader)
|
||||
EVT_MENU(IDM_CHECKINTEGRITY, CISOProperties::CheckPartitionIntegrity)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* parent, wxWindowID id,
|
||||
|
@ -227,58 +210,6 @@ CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* par
|
|||
CreateGUIControls();
|
||||
LoadGameConfig();
|
||||
|
||||
// Filesystem browser/dumper
|
||||
// TODO : Should we add a way to browse the wad file ?
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_WAD)
|
||||
{
|
||||
if (m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
int partition_count = 0;
|
||||
for (int group = 0; group < 4; group++)
|
||||
{
|
||||
for (u32 i = 0; i < 0xFFFFFFFF;
|
||||
i++) // yes, technically there can be OVER NINE THOUSAND partitions...
|
||||
{
|
||||
std::unique_ptr<DiscIO::IVolume> volume(
|
||||
DiscIO::CreateVolumeFromFilename(OpenGameListItem.GetFileName(), group, i));
|
||||
if (volume != nullptr)
|
||||
{
|
||||
std::unique_ptr<DiscIO::IFileSystem> file_system(
|
||||
DiscIO::CreateFileSystem(volume.get()));
|
||||
if (file_system != nullptr)
|
||||
{
|
||||
WiiPartition* const partition =
|
||||
new WiiPartition(std::move(volume), std::move(file_system));
|
||||
|
||||
wxTreeItemId PartitionRoot = m_Treectrl->AppendItem(
|
||||
RootId, wxString::Format(_("Partition %i"), partition_count), 0, 0);
|
||||
|
||||
m_Treectrl->SetItemData(PartitionRoot, partition);
|
||||
CreateDirectoryTree(PartitionRoot, partition->FileSystem->GetFileList());
|
||||
|
||||
if (partition_count == 1)
|
||||
m_Treectrl->Expand(PartitionRoot);
|
||||
|
||||
partition_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filesystem = DiscIO::CreateFileSystem(m_open_iso.get());
|
||||
if (m_filesystem)
|
||||
CreateDirectoryTree(RootId, m_filesystem->GetFileList());
|
||||
}
|
||||
|
||||
m_Treectrl->Expand(RootId);
|
||||
}
|
||||
|
||||
wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &CISOProperties::OnLocalIniModified, this);
|
||||
}
|
||||
|
||||
|
@ -286,57 +217,6 @@ CISOProperties::~CISOProperties()
|
|||
{
|
||||
}
|
||||
|
||||
size_t CISOProperties::CreateDirectoryTree(wxTreeItemId& parent,
|
||||
const std::vector<DiscIO::SFileInfo>& fileInfos)
|
||||
{
|
||||
if (fileInfos.empty())
|
||||
return 0;
|
||||
else
|
||||
return CreateDirectoryTree(parent, fileInfos, 1, fileInfos.at(0).m_FileSize);
|
||||
}
|
||||
|
||||
size_t CISOProperties::CreateDirectoryTree(wxTreeItemId& parent,
|
||||
const std::vector<DiscIO::SFileInfo>& fileInfos,
|
||||
const size_t _FirstIndex, const size_t _LastIndex)
|
||||
{
|
||||
size_t CurrentIndex = _FirstIndex;
|
||||
|
||||
while (CurrentIndex < _LastIndex)
|
||||
{
|
||||
const DiscIO::SFileInfo rFileInfo = fileInfos[CurrentIndex];
|
||||
std::string filePath = rFileInfo.m_FullPath;
|
||||
|
||||
// Trim the trailing '/' if it exists.
|
||||
if (filePath[filePath.length() - 1] == DIR_SEP_CHR)
|
||||
{
|
||||
filePath.pop_back();
|
||||
}
|
||||
|
||||
// Cut off the path up to the actual filename or folder.
|
||||
// Say we have "/music/stream/stream1.strm", the result will be "stream1.strm".
|
||||
size_t dirSepIndex = filePath.find_last_of(DIR_SEP_CHR);
|
||||
if (dirSepIndex != std::string::npos)
|
||||
{
|
||||
filePath = filePath.substr(dirSepIndex + 1);
|
||||
}
|
||||
|
||||
// check next index
|
||||
if (rFileInfo.IsDirectory())
|
||||
{
|
||||
wxTreeItemId item = m_Treectrl->AppendItem(parent, StrToWxStr(filePath), 1, 1);
|
||||
CurrentIndex =
|
||||
CreateDirectoryTree(item, fileInfos, CurrentIndex + 1, (size_t)rFileInfo.m_FileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Treectrl->AppendItem(parent, StrToWxStr(filePath), 2, 2);
|
||||
CurrentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return CurrentIndex;
|
||||
}
|
||||
|
||||
long CISOProperties::GetElementStyle(const char* section, const char* key)
|
||||
{
|
||||
// Disable 3rd state if default gameini overrides the setting
|
||||
|
@ -554,29 +434,9 @@ void CISOProperties::CreateGUIControls()
|
|||
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_WAD)
|
||||
{
|
||||
wxPanel* const filesystem_panel = new wxPanel(m_Notebook, ID_FILESYSTEM);
|
||||
m_Notebook->AddPage(filesystem_panel, _("Filesystem"));
|
||||
|
||||
// Filesystem icons
|
||||
wxSize icon_size = FromDIP(wxSize(16, 16));
|
||||
wxImageList* const m_iconList = new wxImageList(icon_size.GetWidth(), icon_size.GetHeight());
|
||||
static const std::array<const char* const, 3> s_icon_names{
|
||||
{"isoproperties_disc", "isoproperties_folder", "isoproperties_file"}};
|
||||
for (const auto& name : s_icon_names)
|
||||
m_iconList->Add(
|
||||
WxUtils::LoadScaledResourceBitmap(name, this, icon_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER));
|
||||
|
||||
// Filesystem tree
|
||||
m_Treectrl = new wxTreeCtrl(filesystem_panel, ID_TREECTRL);
|
||||
m_Treectrl->AssignImageList(m_iconList);
|
||||
RootId = m_Treectrl->AddRoot(_("Disc"), 0, 0, nullptr);
|
||||
|
||||
wxBoxSizer* sTreePage = new wxBoxSizer(wxVERTICAL);
|
||||
sTreePage->AddSpacer(space5);
|
||||
sTreePage->Add(m_Treectrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sTreePage->AddSpacer(space5);
|
||||
filesystem_panel->SetSizer(sTreePage);
|
||||
m_Notebook->AddPage(
|
||||
new FilesystemPanel(m_Notebook, ID_FILESYSTEM, OpenGameListItem, m_open_iso),
|
||||
_("Filesystem"));
|
||||
}
|
||||
|
||||
wxStdDialogButtonSizer* sButtons = CreateStdDialogButtonSizer(wxOK | wxNO_DEFAULT);
|
||||
|
@ -626,313 +486,6 @@ void CISOProperties::OnCloseClick(wxCommandEvent& WXUNUSED(event))
|
|||
Close();
|
||||
}
|
||||
|
||||
void CISOProperties::OnRightClickOnTree(wxTreeEvent& event)
|
||||
{
|
||||
m_Treectrl->SelectItem(event.GetItem());
|
||||
|
||||
wxMenu popupMenu;
|
||||
|
||||
if (m_Treectrl->GetItemImage(m_Treectrl->GetSelection()) == 0 &&
|
||||
m_Treectrl->GetFirstVisibleItem() != m_Treectrl->GetSelection())
|
||||
{
|
||||
popupMenu.Append(IDM_EXTRACTDIR, _("Extract Partition..."));
|
||||
}
|
||||
else if (m_Treectrl->GetItemImage(m_Treectrl->GetSelection()) == 1)
|
||||
{
|
||||
popupMenu.Append(IDM_EXTRACTDIR, _("Extract Directory..."));
|
||||
}
|
||||
else if (m_Treectrl->GetItemImage(m_Treectrl->GetSelection()) == 2)
|
||||
{
|
||||
popupMenu.Append(IDM_EXTRACTFILE, _("Extract File..."));
|
||||
}
|
||||
|
||||
popupMenu.Append(IDM_EXTRACTALL, _("Extract All Files..."));
|
||||
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_DISC ||
|
||||
(m_Treectrl->GetItemImage(m_Treectrl->GetSelection()) == 0 &&
|
||||
m_Treectrl->GetFirstVisibleItem() != m_Treectrl->GetSelection()))
|
||||
{
|
||||
popupMenu.AppendSeparator();
|
||||
popupMenu.Append(IDM_EXTRACTAPPLOADER, _("Extract Apploader..."));
|
||||
popupMenu.Append(IDM_EXTRACTDOL, _("Extract DOL..."));
|
||||
}
|
||||
|
||||
if (m_Treectrl->GetItemImage(m_Treectrl->GetSelection()) == 0 &&
|
||||
m_Treectrl->GetFirstVisibleItem() != m_Treectrl->GetSelection())
|
||||
{
|
||||
popupMenu.AppendSeparator();
|
||||
popupMenu.Append(IDM_CHECKINTEGRITY, _("Check Partition Integrity"));
|
||||
}
|
||||
|
||||
PopupMenu(&popupMenu);
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void CISOProperties::OnExtractFile(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxString File = m_Treectrl->GetItemText(m_Treectrl->GetSelection());
|
||||
|
||||
wxString Path = wxFileSelector(_("Export File"), wxEmptyString, File, wxEmptyString,
|
||||
wxGetTranslation(wxALL_FILES), wxFD_SAVE, this);
|
||||
|
||||
if (!Path || !File)
|
||||
return;
|
||||
|
||||
while (m_Treectrl->GetItemParent(m_Treectrl->GetSelection()) != m_Treectrl->GetRootItem())
|
||||
{
|
||||
wxString temp = m_Treectrl->GetItemText(m_Treectrl->GetItemParent(m_Treectrl->GetSelection()));
|
||||
File = temp + DIR_SEP_CHR + File;
|
||||
|
||||
m_Treectrl->SelectItem(m_Treectrl->GetItemParent(m_Treectrl->GetSelection()));
|
||||
}
|
||||
|
||||
if (m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
const wxTreeItemId tree_selection = m_Treectrl->GetSelection();
|
||||
WiiPartition* partition =
|
||||
reinterpret_cast<WiiPartition*>(m_Treectrl->GetItemData(tree_selection));
|
||||
File.erase(0, m_Treectrl->GetItemText(tree_selection).length() + 1); // Remove "Partition x/"
|
||||
|
||||
partition->FileSystem->ExportFile(WxStrToStr(File), WxStrToStr(Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filesystem->ExportFile(WxStrToStr(File), WxStrToStr(Path));
|
||||
}
|
||||
}
|
||||
|
||||
void CISOProperties::ExportDir(const std::string& _rFullPath, const std::string& _rExportFolder,
|
||||
const WiiPartition* partition)
|
||||
{
|
||||
bool is_wii = m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC;
|
||||
DiscIO::IFileSystem* const fs = is_wii ? partition->FileSystem.get() : m_filesystem.get();
|
||||
|
||||
const std::vector<DiscIO::SFileInfo>& fst = fs->GetFileList();
|
||||
|
||||
u32 index = 0;
|
||||
u32 size = 0;
|
||||
|
||||
// Extract all
|
||||
if (_rFullPath.empty())
|
||||
{
|
||||
index = 0;
|
||||
size = (u32)fst.size();
|
||||
|
||||
fs->ExportApploader(_rExportFolder);
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_DISC)
|
||||
fs->ExportDOL(_rExportFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for the dir we are going to extract
|
||||
for (index = 0; index != fst.size(); ++index)
|
||||
{
|
||||
if (fst[index].m_FullPath == _rFullPath)
|
||||
{
|
||||
INFO_LOG(DISCIO, "Found the directory at %u", index);
|
||||
size = (u32)fst[index].m_FileSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(DISCIO, "Directory found from %u to %u\nextracting to: %s", index, size,
|
||||
_rExportFolder.c_str());
|
||||
}
|
||||
|
||||
wxString dialogTitle = (index != 0) ? _("Extracting Directory") : _("Extracting All Files");
|
||||
wxProgressDialog dialog(dialogTitle, _("Extracting..."), size - 1, this,
|
||||
wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME |
|
||||
wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_SMOOTH);
|
||||
|
||||
// Extraction
|
||||
for (u32 i = index; i < size; i++)
|
||||
{
|
||||
dialog.SetTitle(wxString::Format("%s : %d%%", dialogTitle.c_str(),
|
||||
(u32)(((float)(i - index) / (float)(size - index)) * 100)));
|
||||
|
||||
dialog.Update(i, wxString::Format(_("Extracting %s"), StrToWxStr(fst[i].m_FullPath)));
|
||||
|
||||
if (dialog.WasCancelled())
|
||||
break;
|
||||
|
||||
if (fst[i].IsDirectory())
|
||||
{
|
||||
const std::string exportName =
|
||||
StringFromFormat("%s/%s/", _rExportFolder.c_str(), fst[i].m_FullPath.c_str());
|
||||
INFO_LOG(DISCIO, "%s", exportName.c_str());
|
||||
|
||||
if (!File::Exists(exportName) && !File::CreateFullPath(exportName))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Could not create the path %s", exportName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File::IsDirectory(exportName))
|
||||
ERROR_LOG(DISCIO, "%s already exists and is not a directory", exportName.c_str());
|
||||
|
||||
ERROR_LOG(DISCIO, "Folder %s already exists", exportName.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string exportName =
|
||||
StringFromFormat("%s/%s", _rExportFolder.c_str(), fst[i].m_FullPath.c_str());
|
||||
INFO_LOG(DISCIO, "%s", exportName.c_str());
|
||||
|
||||
if (!File::Exists(exportName) && !fs->ExportFile(fst[i].m_FullPath, exportName))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Could not export %s", exportName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(DISCIO, "%s already exists", exportName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CISOProperties::OnExtractDir(wxCommandEvent& event)
|
||||
{
|
||||
wxString Directory = m_Treectrl->GetItemText(m_Treectrl->GetSelection());
|
||||
wxString Path = wxDirSelector(_("Choose the folder to extract to"));
|
||||
|
||||
if (!Path || !Directory)
|
||||
return;
|
||||
|
||||
if (event.GetId() == IDM_EXTRACTALL)
|
||||
{
|
||||
if (m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
wxTreeItemIdValue cookie;
|
||||
wxTreeItemId root = m_Treectrl->GetRootItem();
|
||||
wxTreeItemId item = m_Treectrl->GetFirstChild(root, cookie);
|
||||
while (item.IsOk())
|
||||
{
|
||||
ExportDir("", WxStrToStr(Path),
|
||||
reinterpret_cast<WiiPartition*>(m_Treectrl->GetItemData(item)));
|
||||
item = m_Treectrl->GetNextChild(root, cookie);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExportDir("", WxStrToStr(Path));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (m_Treectrl->GetItemParent(m_Treectrl->GetSelection()) != m_Treectrl->GetRootItem())
|
||||
{
|
||||
wxString temp = m_Treectrl->GetItemText(m_Treectrl->GetItemParent(m_Treectrl->GetSelection()));
|
||||
Directory = temp + DIR_SEP_CHR + Directory;
|
||||
|
||||
m_Treectrl->SelectItem(m_Treectrl->GetItemParent(m_Treectrl->GetSelection()));
|
||||
}
|
||||
|
||||
Directory += DIR_SEP_CHR;
|
||||
|
||||
if (m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
const wxTreeItemId tree_selection = m_Treectrl->GetSelection();
|
||||
WiiPartition* partition =
|
||||
reinterpret_cast<WiiPartition*>(m_Treectrl->GetItemData(tree_selection));
|
||||
Directory.erase(0,
|
||||
m_Treectrl->GetItemText(tree_selection).length() + 1); // Remove "Partition x/"
|
||||
|
||||
ExportDir(WxStrToStr(Directory), WxStrToStr(Path), partition);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExportDir(WxStrToStr(Directory), WxStrToStr(Path));
|
||||
}
|
||||
}
|
||||
|
||||
void CISOProperties::OnExtractDataFromHeader(wxCommandEvent& event)
|
||||
{
|
||||
DiscIO::IFileSystem* FS = nullptr;
|
||||
wxString Path = wxDirSelector(_("Choose the folder to extract to"));
|
||||
|
||||
if (Path.empty())
|
||||
return;
|
||||
|
||||
if (m_open_iso->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
WiiPartition* partition =
|
||||
reinterpret_cast<WiiPartition*>(m_Treectrl->GetItemData(m_Treectrl->GetSelection()));
|
||||
FS = partition->FileSystem.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
FS = m_filesystem.get();
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
if (event.GetId() == IDM_EXTRACTAPPLOADER)
|
||||
{
|
||||
ret = FS->ExportApploader(WxStrToStr(Path));
|
||||
}
|
||||
else if (event.GetId() == IDM_EXTRACTDOL)
|
||||
{
|
||||
ret = FS->ExportDOL(WxStrToStr(Path));
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
WxUtils::ShowErrorDialog(
|
||||
wxString::Format(_("Failed to extract to %s!"), WxStrToStr(Path).c_str()));
|
||||
}
|
||||
|
||||
class IntegrityCheckThread : public wxThread
|
||||
{
|
||||
public:
|
||||
IntegrityCheckThread(const WiiPartition& Partition)
|
||||
: wxThread(wxTHREAD_JOINABLE), m_Partition(Partition)
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
ExitCode Entry() override { return (ExitCode)m_Partition.Partition->CheckIntegrity(); }
|
||||
private:
|
||||
const WiiPartition& m_Partition;
|
||||
};
|
||||
|
||||
void CISOProperties::CheckPartitionIntegrity(wxCommandEvent& event)
|
||||
{
|
||||
// Normally we can't enter this function if we aren't analyzing a Wii disc
|
||||
// anyway, but let's still check to be sure.
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_DISC)
|
||||
return;
|
||||
|
||||
wxProgressDialog dialog(_("Checking integrity..."), _("Working..."), 1000, this,
|
||||
wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_SMOOTH);
|
||||
|
||||
WiiPartition* partition =
|
||||
reinterpret_cast<WiiPartition*>(m_Treectrl->GetItemData(m_Treectrl->GetSelection()));
|
||||
IntegrityCheckThread thread(*partition);
|
||||
thread.Run();
|
||||
|
||||
while (thread.IsAlive())
|
||||
{
|
||||
dialog.Pulse();
|
||||
wxThread::Sleep(50);
|
||||
}
|
||||
|
||||
dialog.Destroy();
|
||||
|
||||
if (!thread.Wait())
|
||||
{
|
||||
wxMessageBox(wxString::Format(_("Integrity check for %s failed. The disc image is most "
|
||||
"likely corrupted or has been patched incorrectly."),
|
||||
m_Treectrl->GetItemText(m_Treectrl->GetSelection())),
|
||||
_("Integrity Check Error"), wxOK | wxICON_ERROR, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMessageBox(_("Integrity check completed. No errors have been found."),
|
||||
_("Integrity check completed"), wxOK | wxICON_INFORMATION, this);
|
||||
}
|
||||
}
|
||||
|
||||
void CISOProperties::OnEmustateChanged(wxCommandEvent& event)
|
||||
{
|
||||
EmuIssues->Enable(event.GetSelection() != 0);
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include <wx/treebase.h>
|
||||
|
||||
#include "Common/IniFile.h"
|
||||
#include "DiscIO/Filesystem.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DolphinWX/ISOFile.h"
|
||||
#include "DolphinWX/PatchAddEdit.h"
|
||||
|
||||
class ActionReplayCodesPanel;
|
||||
class CheatWarningMessage;
|
||||
class DolphinSlider;
|
||||
class wxButton;
|
||||
class wxCheckBox;
|
||||
|
@ -27,32 +27,16 @@ class wxChoice;
|
|||
class wxSpinCtrl;
|
||||
class wxStaticBitmap;
|
||||
class wxTextCtrl;
|
||||
class wxTreeCtrl;
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class Language;
|
||||
class IVolume;
|
||||
}
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
class CodeConfigPanel;
|
||||
}
|
||||
class ActionReplayCodesPanel;
|
||||
class CheatWarningMessage;
|
||||
class GameListItem;
|
||||
|
||||
class WiiPartition final : public wxTreeItemData
|
||||
{
|
||||
public:
|
||||
WiiPartition(std::unique_ptr<DiscIO::IVolume> partition,
|
||||
std::unique_ptr<DiscIO::IFileSystem> file_system)
|
||||
: Partition(std::move(partition)), FileSystem(std::move(file_system))
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<DiscIO::IVolume> Partition;
|
||||
std::unique_ptr<DiscIO::IFileSystem> FileSystem;
|
||||
};
|
||||
|
||||
struct PHackData
|
||||
{
|
||||
|
@ -77,7 +61,6 @@ private:
|
|||
DECLARE_EVENT_TABLE();
|
||||
|
||||
std::unique_ptr<DiscIO::IVolume> m_open_iso;
|
||||
std::unique_ptr<DiscIO::IFileSystem> m_filesystem;
|
||||
|
||||
std::vector<PatchEngine::Patch> onFrame;
|
||||
PHackData m_PHack_Data;
|
||||
|
@ -104,9 +87,6 @@ private:
|
|||
wxButton* EditPatch;
|
||||
wxButton* RemovePatch;
|
||||
|
||||
wxTreeCtrl* m_Treectrl;
|
||||
wxTreeItemId RootId;
|
||||
|
||||
ActionReplayCodesPanel* m_ar_code_panel;
|
||||
Gecko::CodeConfigPanel* m_geckocode_panel;
|
||||
|
||||
|
@ -115,9 +95,7 @@ private:
|
|||
|
||||
enum
|
||||
{
|
||||
ID_TREECTRL = 1000,
|
||||
|
||||
ID_NOTEBOOK,
|
||||
ID_NOTEBOOK = 1000,
|
||||
ID_GAMECONFIG,
|
||||
ID_PATCH_PAGE,
|
||||
ID_ARCODE_PAGE,
|
||||
|
@ -147,13 +125,6 @@ private:
|
|||
ID_DEPTHPERCENTAGE,
|
||||
ID_CONVERGENCE,
|
||||
ID_MONODEPTH,
|
||||
|
||||
IDM_EXTRACTDIR,
|
||||
IDM_EXTRACTALL,
|
||||
IDM_EXTRACTFILE,
|
||||
IDM_EXTRACTAPPLOADER,
|
||||
IDM_EXTRACTDOL,
|
||||
IDM_CHECKINTEGRITY,
|
||||
};
|
||||
|
||||
void LaunchExternalEditor(const std::string& filename, bool wait_until_closed);
|
||||
|
@ -165,23 +136,12 @@ private:
|
|||
void OnShowDefaultConfig(wxCommandEvent& event);
|
||||
void PatchListSelectionChanged(wxCommandEvent& event);
|
||||
void PatchButtonClicked(wxCommandEvent& event);
|
||||
void OnRightClickOnTree(wxTreeEvent& event);
|
||||
void OnExtractFile(wxCommandEvent& event);
|
||||
void OnExtractDir(wxCommandEvent& event);
|
||||
void OnExtractDataFromHeader(wxCommandEvent& event);
|
||||
void CheckPartitionIntegrity(wxCommandEvent& event);
|
||||
void OnEmustateChanged(wxCommandEvent& event);
|
||||
void OnCheatCodeToggled(wxCommandEvent& event);
|
||||
void OnChangeTitle(wxCommandEvent& event);
|
||||
|
||||
const GameListItem OpenGameListItem;
|
||||
|
||||
size_t CreateDirectoryTree(wxTreeItemId& parent, const std::vector<DiscIO::SFileInfo>& fileInfos);
|
||||
size_t CreateDirectoryTree(wxTreeItemId& parent, const std::vector<DiscIO::SFileInfo>& fileInfos,
|
||||
const size_t _FirstIndex, const size_t _LastIndex);
|
||||
void ExportDir(const std::string& _rFullPath, const std::string& _rExportFilename,
|
||||
const WiiPartition* partition = nullptr);
|
||||
|
||||
IniFile GameIniDefault;
|
||||
IniFile GameIniLocal;
|
||||
std::string GameIniFileLocal;
|
||||
|
|
Loading…
Reference in New Issue