mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
[ci skip] Add GameCardImageDumpOptionsFrame class
This commit turns DumpOptionsFrame into a non-polymorphic, non-instantiable class with an overloaded constructor, and moves most of the generic logic from its header file into a proper C++ module. GameCardImageDumpOptionsFrame is an inherited class of DumpOptionsFrame, which adds the extra option items it needs on its own.
This commit is contained in:
parent
4af144486a
commit
17ec42d812
6 changed files with 437 additions and 331 deletions
|
@ -26,14 +26,7 @@
|
||||||
|
|
||||||
#include <borealis.hpp>
|
#include <borealis.hpp>
|
||||||
|
|
||||||
|
#include "root_view.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace brls::i18n::literals;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace nxdt::views
|
namespace nxdt::views
|
||||||
{
|
{
|
||||||
|
@ -41,333 +34,44 @@ namespace nxdt::views
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
RootView *root_view = nullptr;
|
RootView *root_view = nullptr;
|
||||||
nxdt::tasks::UmsEvent::Subscription ums_task_sub;
|
std::string raw_filename{}, extension{};
|
||||||
|
|
||||||
std::string raw_filename = "";
|
|
||||||
std::string extension = "";
|
|
||||||
|
|
||||||
brls::List *list = nullptr;
|
brls::List *list = nullptr;
|
||||||
brls::InputListItem *filename_item = nullptr;
|
brls::InputListItem *filename = nullptr;
|
||||||
brls::SelectListItem *output_storage_item = nullptr;
|
brls::SelectListItem *output_storage = nullptr;
|
||||||
brls::ToggleListItem *prepend_key_area_item = nullptr;
|
brls::GenericEvent *button_click_event = nullptr;
|
||||||
brls::ToggleListItem *keep_certificate_item = nullptr;
|
|
||||||
brls::ToggleListItem *trim_dump_item = nullptr;
|
|
||||||
brls::ToggleListItem *calculate_checksum_item = nullptr;
|
|
||||||
brls::SelectListItem *checksum_lookup_method_item = nullptr;
|
|
||||||
|
|
||||||
std::string SanitizeFileName(void)
|
nxdt::tasks::UmsEvent::Subscription ums_task_sub;
|
||||||
{
|
|
||||||
char *raw_filename_dup = nullptr;
|
|
||||||
|
|
||||||
if (raw_filename.empty() || !(raw_filename_dup = strdup(this->raw_filename.c_str()))) return "dummy";
|
bool finalized = false;
|
||||||
|
|
||||||
u8 selected = static_cast<u8>(this->output_storage_item ? this->output_storage_item->getSelectedValue() : configGetInteger("output_storage"));
|
void Initialize(std::string& title, brls::Image *icon);
|
||||||
utilsReplaceIllegalCharacters(raw_filename_dup, selected == ConfigOutputStorage_SdCard);
|
|
||||||
|
|
||||||
std::string output = std::string(raw_filename_dup);
|
std::string SanitizeUserFileName(void);
|
||||||
free(raw_filename_dup);
|
|
||||||
|
|
||||||
return output;
|
void UpdateOutputStorages(const nxdt::tasks::UmsDeviceVector& ums_devices);
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateStorages(const nxdt::tasks::UmsDeviceVector& ums_devices)
|
|
||||||
{
|
|
||||||
if (!this->output_storage_item) return;
|
|
||||||
|
|
||||||
std::vector<std::string> storages{};
|
|
||||||
|
|
||||||
size_t elem_count = (ConfigOutputStorage_Count + ums_devices.size());
|
|
||||||
u32 selected = this->output_storage_item->getSelectedValue();
|
|
||||||
|
|
||||||
/* Fill storages vector. */
|
|
||||||
for(size_t i = 0; i < elem_count; i++)
|
|
||||||
{
|
|
||||||
if (i == 1)
|
|
||||||
{
|
|
||||||
storages.push_back("dump_options/output_storage/value_01"_i18n);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 total_sz = 0, free_sz = 0;
|
|
||||||
char total_sz_str[64] = {0}, free_sz_str[64] = {0};
|
|
||||||
|
|
||||||
const nxdt::tasks::UmsDeviceVectorEntry *ums_device_entry = (i >= ConfigOutputStorage_Count ? &(ums_devices.at(i - ConfigOutputStorage_Count)) : nullptr);
|
|
||||||
const UsbHsFsDevice *cur_ums_device = (ums_device_entry ? ums_device_entry->first : nullptr);
|
|
||||||
|
|
||||||
sprintf(total_sz_str, "%s/", cur_ums_device ? cur_ums_device->name : DEVOPTAB_SDMC_DEVICE);
|
|
||||||
utilsGetFileSystemStatsByPath(total_sz_str, &total_sz, &free_sz);
|
|
||||||
utilsGenerateFormattedSizeString(total_sz, total_sz_str, sizeof(total_sz_str));
|
|
||||||
utilsGenerateFormattedSizeString(free_sz, free_sz_str, sizeof(free_sz_str));
|
|
||||||
|
|
||||||
if (cur_ums_device)
|
|
||||||
{
|
|
||||||
storages.push_back(brls::i18n::getStr("dump_options/output_storage/value_02", ums_device_entry->second, free_sz_str, total_sz_str));
|
|
||||||
} else {
|
|
||||||
storages.push_back(brls::i18n::getStr("dump_options/output_storage/value_00", free_sz_str, total_sz_str));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update SelectListItem values. */
|
|
||||||
/* If the dropdown menu currently is being displayed, it'll be reloaded. */
|
|
||||||
this->output_storage_item->updateValues(storages);
|
|
||||||
|
|
||||||
if (selected > ConfigOutputStorage_UsbHost)
|
|
||||||
{
|
|
||||||
/* Set the SD card as the current output storage. */
|
|
||||||
this->output_storage_item->setSelectedValue(ConfigOutputStorage_SdCard);
|
|
||||||
|
|
||||||
/* Manually trigger selection event. */
|
|
||||||
/* This will take care of both updating the JSON configuration and saniziting the filename provided by the user. */
|
|
||||||
this->output_storage_item->getValueSelectedEvent()->fire(ConfigOutputStorage_SdCard);
|
|
||||||
} else {
|
|
||||||
/* Set the current output storage once more. This will make sure the selected device string gets updated. */
|
|
||||||
this->output_storage_item->setSelectedValue(selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onCancel(void) override
|
DumpOptionsFrame(RootView *root_view, std::string& title, std::string& raw_filename, std::string extension);
|
||||||
{
|
DumpOptionsFrame(RootView *root_view, std::string& title, brls::Image *icon, std::string& raw_filename, std::string extension);
|
||||||
/* Pop view. */
|
~DumpOptionsFrame();
|
||||||
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
|
|
||||||
|
|
||||||
return true;
|
bool onCancel(void) override final;
|
||||||
|
|
||||||
|
void addView(brls::View *view, bool fill = false);
|
||||||
|
|
||||||
|
std::string GetFileName(void);
|
||||||
|
|
||||||
|
std::string GetOutputStoragePrefix(void);
|
||||||
|
|
||||||
|
ALWAYS_INLINE brls::GenericEvent::Subscription RegisterButtonListener(brls::GenericEvent::Callback cb)
|
||||||
|
{
|
||||||
|
return this->button_click_event->subscribe(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
ALWAYS_INLINE void UnregisterButtonListener(brls::GenericEvent::Subscription subscription)
|
||||||
DumpOptionsFrame(RootView *root_view, std::string title, brls::Image *icon, std::string raw_filename, std::string extension) : brls::ThumbnailFrame(), root_view(root_view), raw_filename(raw_filename), extension(extension)
|
|
||||||
{
|
{
|
||||||
/* Set UI properties. */
|
this->button_click_event->unsubscribe(subscription);
|
||||||
this->setTitle(title);
|
|
||||||
this->setIcon(icon);
|
|
||||||
|
|
||||||
this->list = new brls::List();
|
|
||||||
this->list->setSpacing(this->list->getSpacing() / 2);
|
|
||||||
this->list->setMarginBottom(20);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->filename_item = new brls::InputListItem("dump_options/filename/label"_i18n, this->SanitizeFileName(), "", "dump_options/filename/description"_i18n, FS_MAX_FILENAME_LENGTH);
|
|
||||||
|
|
||||||
this->filename_item->getClickEvent()->subscribe([this](brls::View *view) {
|
|
||||||
this->raw_filename = this->filename_item->getValue();
|
|
||||||
this->filename_item->setValue(this->SanitizeFileName());
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->filename_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->output_storage_item = new brls::SelectListItem("dump_options/output_storage/label"_i18n, { "dummy0", "dummy1" }, configGetInteger("output_storage"),
|
|
||||||
brls::i18n::getStr("dump_options/output_storage/description", GITHUB_REPOSITORY_URL));
|
|
||||||
|
|
||||||
/* Subscribe to SelectListItem's value selected event. */
|
|
||||||
this->output_storage_item->getValueSelectedEvent()->subscribe([this](int selected) {
|
|
||||||
/* Make sure the current value isn't out of bounds. */
|
|
||||||
if (selected < ConfigOutputStorage_SdCard || selected >= static_cast<int>(this->root_view->GetUmsDevices().size() + ConfigOutputStorage_Count)) return;
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
if (selected == ConfigOutputStorage_SdCard || selected == ConfigOutputStorage_UsbHost) configSetInteger("output_storage", selected);
|
|
||||||
|
|
||||||
/* Sanitize output filename for the selected storage. */
|
|
||||||
this->filename_item->setValue(this->SanitizeFileName());
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Manually update output storages vector. */
|
|
||||||
this->UpdateStorages(this->root_view->GetUmsDevices());
|
|
||||||
|
|
||||||
this->list->addView(this->output_storage_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Subscribe to the UMS device event. */
|
|
||||||
this->ums_task_sub = this->root_view->RegisterUmsTaskListener([this](const nxdt::tasks::UmsDeviceVector& ums_devices) {
|
|
||||||
/* Update output storages vector. */
|
|
||||||
this->UpdateStorages(ums_devices);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->prepend_key_area_item = new brls::ToggleListItem("dump_options/prepend_key_area/label"_i18n, configGetBoolean("gamecard/prepend_key_area"),
|
|
||||||
"dump_options/prepend_key_area/description"_i18n, "generic/value_enabled"_i18n,
|
|
||||||
"generic/value_disabled"_i18n);
|
|
||||||
|
|
||||||
this->prepend_key_area_item->getClickEvent()->subscribe([](brls::View* view) {
|
|
||||||
/* Get current value. */
|
|
||||||
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
|
||||||
bool value = item->getToggleState();
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
configSetBoolean("gamecard/prepend_key_area", value);
|
|
||||||
|
|
||||||
LOG_MSG_DEBUG("Prepend Key Area setting changed by user.");
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->prepend_key_area_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->keep_certificate_item = new brls::ToggleListItem("dump_options/keep_certificate/label"_i18n, configGetBoolean("gamecard/keep_certificate"),
|
|
||||||
"dump_options/keep_certificate/description"_i18n, "generic/value_enabled"_i18n,
|
|
||||||
"generic/value_disabled"_i18n);
|
|
||||||
|
|
||||||
this->keep_certificate_item->getClickEvent()->subscribe([](brls::View* view) {
|
|
||||||
/* Get current value. */
|
|
||||||
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
|
||||||
bool value = item->getToggleState();
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
configSetBoolean("gamecard/keep_certificate", value);
|
|
||||||
|
|
||||||
LOG_MSG_DEBUG("Keep certificate setting changed by user.");
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->keep_certificate_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->trim_dump_item = new brls::ToggleListItem("dump_options/trim_dump/label"_i18n, configGetBoolean("gamecard/trim_dump"),
|
|
||||||
"dump_options/trim_dump/description"_i18n, "generic/value_enabled"_i18n,
|
|
||||||
"generic/value_disabled"_i18n);
|
|
||||||
|
|
||||||
this->trim_dump_item->getClickEvent()->subscribe([](brls::View* view) {
|
|
||||||
/* Get current value. */
|
|
||||||
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
|
||||||
bool value = item->getToggleState();
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
configSetBoolean("gamecard/trim_dump", value);
|
|
||||||
|
|
||||||
LOG_MSG_DEBUG("Trim dump setting changed by user.");
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->trim_dump_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->calculate_checksum_item = new brls::ToggleListItem("dump_options/calculate_checksum/label"_i18n, configGetBoolean("gamecard/calculate_checksum"),
|
|
||||||
"dump_options/calculate_checksum/description"_i18n, "generic/value_enabled"_i18n,
|
|
||||||
"generic/value_disabled"_i18n);
|
|
||||||
|
|
||||||
this->calculate_checksum_item->getClickEvent()->subscribe([](brls::View* view) {
|
|
||||||
/* Get current value. */
|
|
||||||
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
|
||||||
bool value = item->getToggleState();
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
configSetBoolean("gamecard/calculate_checksum", value);
|
|
||||||
|
|
||||||
LOG_MSG_DEBUG("Calculate checksum setting changed by user.");
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->calculate_checksum_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->checksum_lookup_method_item = new brls::SelectListItem("dump_options/checksum_lookup_method/label"_i18n, {
|
|
||||||
"dump_options/checksum_lookup_method/value_00"_i18n,
|
|
||||||
"NSWDB",
|
|
||||||
"No-Intro"
|
|
||||||
}, configGetInteger("gamecard/checksum_lookup_method"),
|
|
||||||
brls::i18n::getStr("dump_options/checksum_lookup_method/description",
|
|
||||||
"dump_options/calculate_checksum/label"_i18n, "NSWDB", NSWDB_XML_NAME, "No-Intro"));
|
|
||||||
|
|
||||||
/* Subscribe to SelectListItem's value selected event. */
|
|
||||||
this->checksum_lookup_method_item->getValueSelectedEvent()->subscribe([this](int selected) {
|
|
||||||
/* Make sure the current value isn't out of bounds. */
|
|
||||||
if (selected < ConfigChecksumLookupMethod_None || selected >= ConfigChecksumLookupMethod_Count) return;
|
|
||||||
|
|
||||||
/* Update configuration. */
|
|
||||||
configSetInteger("gamecard/checksum_lookup_method", selected);
|
|
||||||
});
|
|
||||||
|
|
||||||
this->list->addView(this->checksum_lookup_method_item);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
brls::Button *button = this->getSidebar()->getButton();
|
|
||||||
button->setLabel("dump_options/start_dump"_i18n);
|
|
||||||
button->getClickEvent()->subscribe([this](brls::View *view) {
|
|
||||||
/* Retrieve configuration values set by the user. */
|
|
||||||
//bool prepend_key_area = this->prepend_key_area_item->getToggleState();
|
|
||||||
//bool keep_certificate = this->keep_certificate_item->getToggleState();
|
|
||||||
bool trim_dump = this->trim_dump_item->getToggleState();
|
|
||||||
//bool calculate_checksum = this->calculate_checksum_item->getToggleState();
|
|
||||||
|
|
||||||
/* Get gamecard size. */
|
|
||||||
u64 gc_size = 0;
|
|
||||||
if ((!trim_dump && !gamecardGetTotalSize(&gc_size)) || (trim_dump && !gamecardGetTrimmedSize(&gc_size)) || !gc_size)
|
|
||||||
{
|
|
||||||
brls::Application::notify("fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Display update frame. */
|
|
||||||
//brls::Application::pushView(new OptionsTabUpdateApplicationFrame(), brls::ViewAnimation::SLIDE_LEFT, false);
|
|
||||||
brls::Application::notify(fmt::format("0x{:X}", gc_size));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this->setContentView(this->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
~DumpOptionsFrame()
|
|
||||||
{
|
|
||||||
/* Unregister task listener. */
|
|
||||||
this->root_view->UnregisterUmsTaskListener(this->ums_task_sub);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
45
include/gamecard_image_dump_options_frame.hpp
Normal file
45
include/gamecard_image_dump_options_frame.hpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* gamecard_image_dump_options_frame.hpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2024, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||||
|
*
|
||||||
|
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
|
||||||
|
*
|
||||||
|
* nxdumptool is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* nxdumptool is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef __GAMECARD_IMAGE_DUMP_OPTIONS_FRAME_HPP__
|
||||||
|
#define __GAMECARD_IMAGE_DUMP_OPTIONS_FRAME_HPP__
|
||||||
|
|
||||||
|
#include "dump_options_frame.hpp"
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
class GameCardImageDumpOptionsFrame: public DumpOptionsFrame
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
brls::ToggleListItem *prepend_key_area = nullptr;
|
||||||
|
brls::ToggleListItem *keep_certificate = nullptr;
|
||||||
|
brls::ToggleListItem *trim_dump = nullptr;
|
||||||
|
brls::ToggleListItem *calculate_checksum = nullptr;
|
||||||
|
brls::SelectListItem *checksum_lookup_method = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GameCardImageDumpOptionsFrame(RootView *root_view, std::string title, std::string raw_filename);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __GAMECARD_IMAGE_DUMP_OPTIONS_FRAME_HPP__ */
|
|
@ -20,12 +20,12 @@
|
||||||
|
|
||||||
"update_nswdb_xml": {
|
"update_nswdb_xml": {
|
||||||
"label": "Update NSWDB XML",
|
"label": "Update NSWDB XML",
|
||||||
"description": "Retrieves the latest NSWDB XML, which can be optionally used to validate checksums from gamecard dumps. Requires Internet connectivity."
|
"description": "Retrieves the latest NSWDB XML, which can be optionally used to validate checksums from gamecard dumps. Requires an Internet connection."
|
||||||
},
|
},
|
||||||
|
|
||||||
"update_app": {
|
"update_app": {
|
||||||
"label": "Update application",
|
"label": "Update application",
|
||||||
"description": "Checks if an update is available in nxdumptool's GitHub repository. Requires Internet connectivity.",
|
"description": "Checks if an update is available in nxdumptool's GitHub repository. Requires an Internet connection.",
|
||||||
"frame": {
|
"frame": {
|
||||||
"please_wait": "Please wait…",
|
"please_wait": "Please wait…",
|
||||||
"release_details": "Commit hash: {0:.7}\nRelease date: {1} UTC+0",
|
"release_details": "Commit hash: {0:.7}\nRelease date: {1} UTC+0",
|
||||||
|
|
224
source/dump_options_frame.cpp
Normal file
224
source/dump_options_frame.cpp
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
/*
|
||||||
|
* dump_options_frame.cpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2024, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||||
|
*
|
||||||
|
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
|
||||||
|
*
|
||||||
|
* nxdumptool is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* nxdumptool is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dump_options_frame.hpp>
|
||||||
|
|
||||||
|
namespace i18n = brls::i18n; /* For getStr(). */
|
||||||
|
using namespace i18n::literals; /* For _i18n. */
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
DumpOptionsFrame::DumpOptionsFrame(RootView *root_view, std::string& title, std::string& raw_filename, std::string extension) : brls::ThumbnailFrame(), root_view(root_view), raw_filename(raw_filename), extension(extension)
|
||||||
|
{
|
||||||
|
/* Generate icon using the default image. */
|
||||||
|
brls::Image *icon = new brls::Image();
|
||||||
|
icon->setImage(BOREALIS_ASSET("icon/" APP_TITLE ".jpg"));
|
||||||
|
icon->setScaleType(brls::ImageScaleType::SCALE);
|
||||||
|
|
||||||
|
/* Initialize the rest of the elements. */
|
||||||
|
this->Initialize(title, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
DumpOptionsFrame::DumpOptionsFrame(RootView *root_view, std::string& title, brls::Image *icon, std::string& raw_filename, std::string extension) : brls::ThumbnailFrame(), root_view(root_view), raw_filename(raw_filename), extension(extension)
|
||||||
|
{
|
||||||
|
/* Initialize the rest of the elements. */
|
||||||
|
this->Initialize(title, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
DumpOptionsFrame::~DumpOptionsFrame()
|
||||||
|
{
|
||||||
|
/* Unregister all button click event listeners. */
|
||||||
|
this->button_click_event->unsubscribeAll();
|
||||||
|
|
||||||
|
/* Unregister task listener. */
|
||||||
|
this->root_view->UnregisterUmsTaskListener(this->ums_task_sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpOptionsFrame::Initialize(std::string& title, brls::Image *icon)
|
||||||
|
{
|
||||||
|
/* Set UI properties. */
|
||||||
|
this->setTitle(title);
|
||||||
|
this->setIcon(icon);
|
||||||
|
|
||||||
|
/* Generate List view. */
|
||||||
|
this->list = new brls::List();
|
||||||
|
this->list->setSpacing(this->list->getSpacing() / 2);
|
||||||
|
this->list->setMarginBottom(20);
|
||||||
|
|
||||||
|
/* Filename. */
|
||||||
|
this->filename = new brls::InputListItem("dump_options/filename/label"_i18n, this->SanitizeUserFileName(), "", "dump_options/filename/description"_i18n, FS_MAX_FILENAME_LENGTH);
|
||||||
|
|
||||||
|
this->filename->getClickEvent()->subscribe([this](brls::View *view) {
|
||||||
|
/* Sanitize the string entered by the user. */
|
||||||
|
this->raw_filename = this->filename->getValue();
|
||||||
|
this->filename->setValue(this->SanitizeUserFileName());
|
||||||
|
});
|
||||||
|
|
||||||
|
this->list->addView(this->filename);
|
||||||
|
|
||||||
|
/* Output storage. */
|
||||||
|
this->output_storage = new brls::SelectListItem("dump_options/output_storage/label"_i18n, { "dummy0", "dummy1" }, configGetInteger("output_storage"), brls::i18n::getStr("dump_options/output_storage/description", GITHUB_REPOSITORY_URL));
|
||||||
|
|
||||||
|
this->output_storage->getValueSelectedEvent()->subscribe([this](int selected) {
|
||||||
|
/* Make sure the current value isn't out of bounds. */
|
||||||
|
if (selected < ConfigOutputStorage_SdCard || selected >= static_cast<int>(this->root_view->GetUmsDevices().size() + ConfigOutputStorage_Count)) return;
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
if (selected == ConfigOutputStorage_SdCard || selected == ConfigOutputStorage_UsbHost) configSetInteger("output_storage", selected);
|
||||||
|
|
||||||
|
/* Sanitize output filename for the selected storage. */
|
||||||
|
this->filename->setValue(this->SanitizeUserFileName());
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Manually update output storages vector. */
|
||||||
|
this->UpdateOutputStorages(this->root_view->GetUmsDevices());
|
||||||
|
|
||||||
|
this->list->addView(this->output_storage);
|
||||||
|
|
||||||
|
/* Subscribe to the UMS device event. */
|
||||||
|
this->ums_task_sub = this->root_view->RegisterUmsTaskListener([this](const nxdt::tasks::UmsDeviceVector& ums_devices) {
|
||||||
|
/* Update output storages vector. */
|
||||||
|
this->UpdateOutputStorages(ums_devices);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Start dump button. */
|
||||||
|
brls::Button *button = this->getSidebar()->getButton();
|
||||||
|
button->setLabel("dump_options/start_dump"_i18n);
|
||||||
|
|
||||||
|
/* Retrieve button event pointer. */
|
||||||
|
this->button_click_event = button->getClickEvent();
|
||||||
|
|
||||||
|
/* Set content view. */
|
||||||
|
this->setContentView(this->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DumpOptionsFrame::SanitizeUserFileName(void)
|
||||||
|
{
|
||||||
|
char *raw_filename_dup = nullptr;
|
||||||
|
|
||||||
|
if (this->raw_filename.empty() || !(raw_filename_dup = strdup(this->raw_filename.c_str()))) return "dummy";
|
||||||
|
|
||||||
|
u8 selected = static_cast<u8>(this->output_storage ? this->output_storage->getSelectedValue() : configGetInteger("output_storage"));
|
||||||
|
utilsReplaceIllegalCharacters(raw_filename_dup, selected == ConfigOutputStorage_SdCard);
|
||||||
|
|
||||||
|
std::string output = std::string(raw_filename_dup);
|
||||||
|
free(raw_filename_dup);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpOptionsFrame::UpdateOutputStorages(const nxdt::tasks::UmsDeviceVector& ums_devices)
|
||||||
|
{
|
||||||
|
if (!this->output_storage) return;
|
||||||
|
|
||||||
|
std::vector<std::string> storages{};
|
||||||
|
|
||||||
|
size_t elem_count = (ConfigOutputStorage_Count + ums_devices.size());
|
||||||
|
u32 selected = this->output_storage->getSelectedValue();
|
||||||
|
|
||||||
|
/* Fill storages vector. */
|
||||||
|
for(size_t i = 0; i < elem_count; i++)
|
||||||
|
{
|
||||||
|
if (i == 1)
|
||||||
|
{
|
||||||
|
storages.push_back("dump_options/output_storage/value_01"_i18n);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 total_sz = 0, free_sz = 0;
|
||||||
|
char total_sz_str[64] = {0}, free_sz_str[64] = {0};
|
||||||
|
|
||||||
|
const nxdt::tasks::UmsDeviceVectorEntry *ums_device_entry = (i >= ConfigOutputStorage_Count ? &(ums_devices.at(i - ConfigOutputStorage_Count)) : nullptr);
|
||||||
|
const UsbHsFsDevice *cur_ums_device = (ums_device_entry ? ums_device_entry->first : nullptr);
|
||||||
|
|
||||||
|
sprintf(total_sz_str, "%s/", cur_ums_device ? cur_ums_device->name : DEVOPTAB_SDMC_DEVICE);
|
||||||
|
utilsGetFileSystemStatsByPath(total_sz_str, &total_sz, &free_sz);
|
||||||
|
utilsGenerateFormattedSizeString(total_sz, total_sz_str, sizeof(total_sz_str));
|
||||||
|
utilsGenerateFormattedSizeString(free_sz, free_sz_str, sizeof(free_sz_str));
|
||||||
|
|
||||||
|
if (cur_ums_device)
|
||||||
|
{
|
||||||
|
storages.push_back(brls::i18n::getStr("dump_options/output_storage/value_02", ums_device_entry->second, free_sz_str, total_sz_str));
|
||||||
|
} else {
|
||||||
|
storages.push_back(brls::i18n::getStr("dump_options/output_storage/value_00", free_sz_str, total_sz_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update SelectListItem values. */
|
||||||
|
/* If the dropdown menu currently is being displayed, it'll be reloaded. */
|
||||||
|
this->output_storage->updateValues(storages);
|
||||||
|
|
||||||
|
if (selected > ConfigOutputStorage_UsbHost)
|
||||||
|
{
|
||||||
|
/* Set the SD card as the current output storage. */
|
||||||
|
this->output_storage->setSelectedValue(ConfigOutputStorage_SdCard);
|
||||||
|
|
||||||
|
/* Manually trigger selection event. */
|
||||||
|
/* This will take care of both updating the JSON configuration and saniziting the filename provided by the user. */
|
||||||
|
this->output_storage->getValueSelectedEvent()->fire(ConfigOutputStorage_SdCard);
|
||||||
|
} else {
|
||||||
|
/* Set the current output storage once more. This will make sure the selected device string gets updated. */
|
||||||
|
this->output_storage->setSelectedValue(selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DumpOptionsFrame::onCancel(void)
|
||||||
|
{
|
||||||
|
/* Pop view. */
|
||||||
|
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpOptionsFrame::addView(brls::View *view, bool fill)
|
||||||
|
{
|
||||||
|
this->list->addView(view, fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DumpOptionsFrame::GetFileName(void)
|
||||||
|
{
|
||||||
|
return this->filename->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DumpOptionsFrame::GetOutputStoragePrefix(void)
|
||||||
|
{
|
||||||
|
std::string prefix{};
|
||||||
|
|
||||||
|
u8 selected = static_cast<u8>(this->output_storage ? this->output_storage->getSelectedValue() : configGetInteger("output_storage"));
|
||||||
|
|
||||||
|
switch(selected)
|
||||||
|
{
|
||||||
|
case ConfigOutputStorage_SdCard:
|
||||||
|
prefix = DEVOPTAB_SDMC_DEVICE "/";
|
||||||
|
break;
|
||||||
|
case ConfigOutputStorage_UsbHost:
|
||||||
|
prefix = "/";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
const nxdt::tasks::UmsDeviceVector& ums_devices = this->root_view->GetUmsDevices();
|
||||||
|
prefix = std::string(ums_devices.at(selected - ConfigOutputStorage_Count).first->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
}
|
137
source/gamecard_image_dump_options_frame.cpp
Normal file
137
source/gamecard_image_dump_options_frame.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* gamecard_image_dump_options_frame.cpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2024, DarkMatterCore <pabloacurielz@gmail.com>.
|
||||||
|
*
|
||||||
|
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
|
||||||
|
*
|
||||||
|
* nxdumptool is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* nxdumptool is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gamecard_image_dump_options_frame.hpp>
|
||||||
|
|
||||||
|
namespace i18n = brls::i18n; /* For getStr(). */
|
||||||
|
using namespace i18n::literals; /* For _i18n. */
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
GameCardImageDumpOptionsFrame::GameCardImageDumpOptionsFrame(RootView *root_view, std::string title, std::string raw_filename) : DumpOptionsFrame(root_view, title, raw_filename, ".xci")
|
||||||
|
{
|
||||||
|
/* Prepend KeyArea data. */
|
||||||
|
this->prepend_key_area = new brls::ToggleListItem("dump_options/prepend_key_area/label"_i18n, configGetBoolean("gamecard/prepend_key_area"), "dump_options/prepend_key_area/description"_i18n,
|
||||||
|
"generic/value_enabled"_i18n, "generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->prepend_key_area->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/prepend_key_area", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Prepend Key Area setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->addView(this->prepend_key_area);
|
||||||
|
|
||||||
|
/* Keep certificate. */
|
||||||
|
this->keep_certificate = new brls::ToggleListItem("dump_options/keep_certificate/label"_i18n, configGetBoolean("gamecard/keep_certificate"), "dump_options/keep_certificate/description"_i18n,
|
||||||
|
"generic/value_enabled"_i18n, "generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->keep_certificate->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/keep_certificate", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Keep certificate setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->addView(this->keep_certificate);
|
||||||
|
|
||||||
|
/* Trim dump. */
|
||||||
|
this->trim_dump = new brls::ToggleListItem("dump_options/trim_dump/label"_i18n, configGetBoolean("gamecard/trim_dump"), "dump_options/trim_dump/description"_i18n, "generic/value_enabled"_i18n,
|
||||||
|
"generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->trim_dump->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/trim_dump", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Trim dump setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->addView(this->trim_dump);
|
||||||
|
|
||||||
|
this->calculate_checksum = new brls::ToggleListItem("dump_options/calculate_checksum/label"_i18n, configGetBoolean("gamecard/calculate_checksum"), "dump_options/calculate_checksum/description"_i18n,
|
||||||
|
"generic/value_enabled"_i18n, "generic/value_disabled"_i18n);
|
||||||
|
|
||||||
|
this->calculate_checksum->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
/* Get current value. */
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetBoolean("gamecard/calculate_checksum", value);
|
||||||
|
|
||||||
|
LOG_MSG_DEBUG("Calculate checksum setting changed by user.");
|
||||||
|
});
|
||||||
|
|
||||||
|
this->addView(this->calculate_checksum);
|
||||||
|
|
||||||
|
/* Checksum lookup method. */
|
||||||
|
this->checksum_lookup_method = new brls::SelectListItem("dump_options/checksum_lookup_method/label"_i18n, {
|
||||||
|
"dump_options/checksum_lookup_method/value_00"_i18n,
|
||||||
|
"NSWDB",
|
||||||
|
"No-Intro"
|
||||||
|
}, configGetInteger("gamecard/checksum_lookup_method"), brls::i18n::getStr("dump_options/checksum_lookup_method/description",
|
||||||
|
"dump_options/calculate_checksum/label"_i18n, "NSWDB", NSWDB_XML_NAME, "No-Intro"));
|
||||||
|
|
||||||
|
this->checksum_lookup_method->getValueSelectedEvent()->subscribe([this](int selected) {
|
||||||
|
/* Make sure the current value isn't out of bounds. */
|
||||||
|
if (selected < ConfigChecksumLookupMethod_None || selected >= ConfigChecksumLookupMethod_Count) return;
|
||||||
|
|
||||||
|
/* Update configuration. */
|
||||||
|
configSetInteger("gamecard/checksum_lookup_method", selected);
|
||||||
|
});
|
||||||
|
|
||||||
|
this->addView(this->checksum_lookup_method);
|
||||||
|
|
||||||
|
/* Register dump button callback. */
|
||||||
|
this->RegisterButtonListener([this](brls::View *view) {
|
||||||
|
/* Retrieve configuration values set by the user. */
|
||||||
|
//bool prepend_key_area = this->prepend_key_area_item->getToggleState();
|
||||||
|
//bool keep_certificate = this->keep_certificate_item->getToggleState();
|
||||||
|
bool trim_dump_val = this->trim_dump->getToggleState();
|
||||||
|
//bool calculate_checksum = this->calculate_checksum_item->getToggleState();
|
||||||
|
|
||||||
|
/* Get gamecard size. */
|
||||||
|
u64 gc_size = 0;
|
||||||
|
if ((!trim_dump_val && !gamecardGetTotalSize(&gc_size)) || (trim_dump_val && !gamecardGetTrimmedSize(&gc_size)) || !gc_size)
|
||||||
|
{
|
||||||
|
brls::Application::notify("fail");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display update frame. */
|
||||||
|
//brls::Application::pushView(new OptionsTabUpdateApplicationFrame(), brls::ViewAnimation::SLIDE_LEFT, false);
|
||||||
|
brls::Application::notify(fmt::format("0x{:X}", gc_size));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
#include <nxdt_utils.h>
|
#include <nxdt_utils.h>
|
||||||
#include <gamecard_tab.hpp>
|
#include <gamecard_tab.hpp>
|
||||||
#include <titles_tab.hpp>
|
#include <titles_tab.hpp>
|
||||||
#include <dump_options_frame.hpp>
|
#include <gamecard_image_dump_options_frame.hpp>
|
||||||
|
|
||||||
namespace i18n = brls::i18n; /* For getStr(). */
|
namespace i18n = brls::i18n; /* For getStr(). */
|
||||||
using namespace i18n::literals; /* For _i18n. */
|
using namespace i18n::literals; /* For _i18n. */
|
||||||
|
@ -256,12 +256,8 @@ namespace nxdt::views
|
||||||
brls::ListItem *dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
|
brls::ListItem *dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n);
|
||||||
|
|
||||||
dump_card_image->getClickEvent()->subscribe([this](brls::View *view) {
|
dump_card_image->getClickEvent()->subscribe([this](brls::View *view) {
|
||||||
brls::Image *icon = new brls::Image();
|
std::string& raw_filename = (configGetInteger("naming_convention") == TitleNamingConvention_Full ? raw_filename_full : raw_filename_id_only);
|
||||||
icon->setImage(BOREALIS_ASSET("icon/" APP_TITLE ".jpg"));
|
brls::Application::pushView(new GameCardImageDumpOptionsFrame(this->root_view, "gamecard_tab/list/dump_card_image/label"_i18n, raw_filename), brls::ViewAnimation::SLIDE_LEFT);
|
||||||
icon->setScaleType(brls::ImageScaleType::SCALE);
|
|
||||||
|
|
||||||
brls::Application::pushView(new DumpOptionsFrame(this->root_view, "gamecard_tab/list/dump_card_image/label"_i18n, icon,
|
|
||||||
configGetInteger("naming_convention") == TitleNamingConvention_Full ? raw_filename_full : raw_filename_id_only, ".xci"), brls::ViewAnimation::SLIDE_LEFT);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this->list->addView(dump_card_image);
|
this->list->addView(dump_card_image);
|
||||||
|
|
Loading…
Reference in a new issue