mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 12:12:02 +00:00
Implement OptionsTab class.
Other changes: * title: rename TitleFileNameConvention -> TitleNamingConvention. * utils: display Lockpick_RCM's GitHub repository URL if keysLoadKeyset() fails.
This commit is contained in:
parent
64ab1705bc
commit
3afe5caa7a
11 changed files with 159 additions and 27 deletions
|
@ -67,11 +67,12 @@ typedef struct {
|
||||||
} TitleUserApplicationData;
|
} TitleUserApplicationData;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TitleFileNameConvention_Full = 0, ///< Individual titles: "[{Name}] [{TitleId}][v{TitleVersion}][{TitleType}]".
|
TitleNamingConvention_Full = 0, ///< Individual titles: "{Name} [{Id}][v{Version}][{Type}]".
|
||||||
///< Gamecards: "[{Name1}] [{TitleId1}][v{TitleVersion1}] + ... + [{NameN}] [{TitleIdN}][v{TitleVersionN}]".
|
///< Gamecards: "[{Name1}] [{Id1}][v{Version1}] + ... + [{NameN}] [{IdN}][v{VersionN}]".
|
||||||
TitleFileNameConvention_IdAndVersionOnly = 1 ///< Individual titles: "{TitleId}_v{TitleVersion}_{TitleType}".
|
TitleNamingConvention_IdAndVersionOnly = 1, ///< Individual titles: "{Id}_v{Version}_{Type}".
|
||||||
///< Gamecards: "{TitleId1}_v{TitleVersion1}_{TitleType1} + ... + {TitleIdN}_v{TitleVersionN}_{TitleTypeN}".
|
///< Gamecards: "{TitleId1}_v{TitleVersion1}_{TitleType1} + ... + {TitleIdN}_v{TitleVersionN}_{TitleTypeN}".
|
||||||
} TitleFileNameConvention;
|
TitleNamingConvention_Count = 2
|
||||||
|
} TitleNamingConvention;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TitleFileNameIllegalCharReplaceType_None = 0,
|
TitleFileNameIllegalCharReplaceType_None = 0,
|
||||||
|
@ -130,11 +131,11 @@ void titleFreeOrphanTitles(TitleInfo ***orphan_info);
|
||||||
bool titleIsGameCardInfoUpdated(void);
|
bool titleIsGameCardInfoUpdated(void);
|
||||||
|
|
||||||
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output title dumps. Returns NULL if an error occurs.
|
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output title dumps. Returns NULL if an error occurs.
|
||||||
char *titleGenerateFileName(TitleInfo *title_info, u8 name_convention, u8 illegal_char_replace_type);
|
char *titleGenerateFileName(TitleInfo *title_info, u8 naming_convention, u8 illegal_char_replace_type);
|
||||||
|
|
||||||
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output gamecard dumps. Returns NULL if an error occurs.
|
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output gamecard dumps. Returns NULL if an error occurs.
|
||||||
/// A valid gamecard must be inserted, and title info must have been loaded from it accordingly.
|
/// A valid gamecard must be inserted, and title info must have been loaded from it accordingly.
|
||||||
char *titleGenerateGameCardFileName(u8 name_convention, u8 illegal_char_replace_type);
|
char *titleGenerateGameCardFileName(u8 naming_convention, u8 illegal_char_replace_type);
|
||||||
|
|
||||||
/// Returns a pointer to a string holding the name of the provided NcmContentType value. Returns NULL if the provided value is invalid.
|
/// Returns a pointer to a string holding the name of the provided NcmContentType value. Returns NULL if the provided value is invalid.
|
||||||
const char *titleGetNcmContentTypeName(u8 content_type);
|
const char *titleGetNcmContentTypeName(u8 content_type);
|
||||||
|
|
38
include/options_tab.hpp
Normal file
38
include/options_tab.hpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* options_tab.hpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2021, 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 __OPTIONS_TAB_HPP__
|
||||||
|
#define __OPTIONS_TAB_HPP__
|
||||||
|
|
||||||
|
#include <borealis.hpp>
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
class OptionsTab: public brls::List
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OptionsTab(void);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __OPTIONS_TAB_HPP__ */
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6d95c14f2f91dc6c2bcb1d1d0e4ebdd1f00f7c3b
|
Subproject commit bfc32dba9394409691a940896d2a10dfc65c10df
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"overclock": true,
|
"overclock": true,
|
||||||
"name_convention": 0,
|
"naming_convention": 0,
|
||||||
"dump_destination": 0,
|
"dump_destination": 0,
|
||||||
"gamecard": {
|
"gamecard": {
|
||||||
"append_key_area": false,
|
"append_key_area": false,
|
||||||
|
|
20
romfs/i18n/en-US/options_tab.json
Normal file
20
romfs/i18n/en-US/options_tab.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"overclock": {
|
||||||
|
"label": "Overclock",
|
||||||
|
"description": "Overclocks both CPU and MEM to 1785 MHz and 1600 MHz, respectively, in order to speed up dump operations. This is considered a relatively safe action.\n\nIf the application is running under title override mode, and sys-clk is active, and a clock profile has been created for the overriden title, this setting has no effect at all.",
|
||||||
|
"value_enabled": "Yes",
|
||||||
|
"value_disabled": "No"
|
||||||
|
},
|
||||||
|
|
||||||
|
"naming_convention": {
|
||||||
|
"label": "Naming convention",
|
||||||
|
"description": "Sets the naming convention used for all output dumps.\n\n\uE016 Full: \"{Name} [{Id}][v{Version}][{Type}]\".\n\uE016 ID and version only: \"{Id}_v{Version}_{Type}\".\n\nIf \"Full\" is selected, the display version string will also be appended to dumped updates whenever possible.",
|
||||||
|
"value_00": "Full",
|
||||||
|
"value_01": "ID and version only"
|
||||||
|
},
|
||||||
|
|
||||||
|
"update_app": {
|
||||||
|
"label": "Update application",
|
||||||
|
"description": "Checks if an update is available in nxdumptool's GitHub repository. Requires Internet connectivity."
|
||||||
|
}
|
||||||
|
}
|
|
@ -151,6 +151,8 @@ static bool configParseConfigJson(void)
|
||||||
end:
|
end:
|
||||||
if (use_default_config)
|
if (use_default_config)
|
||||||
{
|
{
|
||||||
|
LOG_MSG("Loading default configuration.");
|
||||||
|
|
||||||
/* Free config JSON. */
|
/* Free config JSON. */
|
||||||
configFreeConfigJson();
|
configFreeConfigJson();
|
||||||
|
|
||||||
|
@ -171,7 +173,7 @@ end:
|
||||||
static void configWriteConfigJson(void)
|
static void configWriteConfigJson(void)
|
||||||
{
|
{
|
||||||
if (!g_configJson) return;
|
if (!g_configJson) return;
|
||||||
if (json_object_to_file_ext(CONFIG_PATH, g_configJson, JSON_C_TO_STRING_PRETTY) != 0) configLogJsonError();
|
if (json_object_to_file_ext(CONFIG_PATH, g_configJson, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) != 0) configLogJsonError();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void configFreeConfigJson(void)
|
static void configFreeConfigJson(void)
|
||||||
|
@ -231,7 +233,7 @@ end:
|
||||||
|
|
||||||
static bool configValidateJsonRootObject(const struct json_object *obj)
|
static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
{
|
{
|
||||||
bool ret = false, overclock_found = false, name_convention_found = false, dump_destination_found = false, gamecard_found = false;
|
bool ret = false, overclock_found = false, naming_convention_found = false, dump_destination_found = false, gamecard_found = false;
|
||||||
bool nsp_found = false, ticket_found = false, nca_fs_found = false;
|
bool nsp_found = false, ticket_found = false, nca_fs_found = false;
|
||||||
|
|
||||||
if (!configValidateJsonObject(obj)) goto end;
|
if (!configValidateJsonObject(obj)) goto end;
|
||||||
|
@ -239,7 +241,7 @@ static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
json_object_object_foreach(obj, key, val)
|
json_object_object_foreach(obj, key, val)
|
||||||
{
|
{
|
||||||
JSON_VALIDATE_FIELD(Boolean, overclock);
|
JSON_VALIDATE_FIELD(Boolean, overclock);
|
||||||
JSON_VALIDATE_FIELD(Integer, name_convention, TitleFileNameConvention_Full, TitleFileNameConvention_IdAndVersionOnly);
|
JSON_VALIDATE_FIELD(Integer, naming_convention, TitleNamingConvention_Full, TitleNamingConvention_IdAndVersionOnly);
|
||||||
JSON_VALIDATE_FIELD(Integer, dump_destination, ConfigDumpDestination_SdCard, ConfigDumpDestination_UsbHost);
|
JSON_VALIDATE_FIELD(Integer, dump_destination, ConfigDumpDestination_SdCard, ConfigDumpDestination_UsbHost);
|
||||||
JSON_VALIDATE_OBJECT(GameCard, gamecard);
|
JSON_VALIDATE_OBJECT(GameCard, gamecard);
|
||||||
JSON_VALIDATE_OBJECT(Nsp, nsp);
|
JSON_VALIDATE_OBJECT(Nsp, nsp);
|
||||||
|
@ -248,7 +250,7 @@ static bool configValidateJsonRootObject(const struct json_object *obj)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (overclock_found && name_convention_found && dump_destination_found && gamecard_found && nsp_found && ticket_found && nca_fs_found);
|
ret = (overclock_found && naming_convention_found && dump_destination_found && gamecard_found && nsp_found && ticket_found && nca_fs_found);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -153,7 +153,11 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
|
||||||
if (!umsInitialize()) break;
|
if (!umsInitialize()) break;
|
||||||
|
|
||||||
/* Load keyset. */
|
/* Load keyset. */
|
||||||
if (!keysLoadKeyset()) break;
|
if (!keysLoadKeyset())
|
||||||
|
{
|
||||||
|
LOG_MSG("Failed to load keyset!\nUpdate your keys file with Lockpick_RCM:\n" LOCKPICK_RCM_URL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate NCA crypto buffer. */
|
/* Allocate NCA crypto buffer. */
|
||||||
if (!ncaAllocateCryptoBuffer())
|
if (!ncaAllocateCryptoBuffer())
|
||||||
|
|
|
@ -919,10 +919,10 @@ bool titleIsGameCardInfoUpdated(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *titleGenerateFileName(TitleInfo *title_info, u8 name_convention, u8 illegal_char_replace_type)
|
char *titleGenerateFileName(TitleInfo *title_info, u8 naming_convention, u8 illegal_char_replace_type)
|
||||||
{
|
{
|
||||||
if (!title_info || title_info->meta_key.type < NcmContentMetaType_Application || title_info->meta_key.type > NcmContentMetaType_Delta || name_convention > TitleFileNameConvention_IdAndVersionOnly || \
|
if (!title_info || title_info->meta_key.type < NcmContentMetaType_Application || title_info->meta_key.type > NcmContentMetaType_Delta || naming_convention > TitleNamingConvention_IdAndVersionOnly || \
|
||||||
(name_convention == TitleFileNameConvention_Full && illegal_char_replace_type > TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly))
|
(naming_convention == TitleNamingConvention_Full && illegal_char_replace_type > TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly))
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG("Invalid parameters!");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -932,7 +932,7 @@ char *titleGenerateFileName(TitleInfo *title_info, u8 name_convention, u8 illega
|
||||||
char title_name[0x400] = {0}, *version_str = NULL, *filename = NULL;
|
char title_name[0x400] = {0}, *version_str = NULL, *filename = NULL;
|
||||||
|
|
||||||
/* Generate filename for this title. */
|
/* Generate filename for this title. */
|
||||||
if (name_convention == TitleFileNameConvention_Full)
|
if (naming_convention == TitleNamingConvention_Full)
|
||||||
{
|
{
|
||||||
if (title_info->app_metadata && *(title_info->app_metadata->lang_entry.name))
|
if (title_info->app_metadata && *(title_info->app_metadata->lang_entry.name))
|
||||||
{
|
{
|
||||||
|
@ -951,7 +951,7 @@ char *titleGenerateFileName(TitleInfo *title_info, u8 name_convention, u8 illega
|
||||||
|
|
||||||
sprintf(title_name + strlen(title_name), "[%016lX][v%u][%s]", title_info->meta_key.id, title_info->meta_key.version, g_filenameTypeStrings[type]);
|
sprintf(title_name + strlen(title_name), "[%016lX][v%u][%s]", title_info->meta_key.id, title_info->meta_key.version, g_filenameTypeStrings[type]);
|
||||||
} else
|
} else
|
||||||
if (name_convention == TitleFileNameConvention_IdAndVersionOnly)
|
if (naming_convention == TitleNamingConvention_IdAndVersionOnly)
|
||||||
{
|
{
|
||||||
sprintf(title_name, "%016lX_v%u_%s", title_info->meta_key.id, title_info->meta_key.version, g_filenameTypeStrings[type]);
|
sprintf(title_name, "%016lX_v%u_%s", title_info->meta_key.id, title_info->meta_key.version, g_filenameTypeStrings[type]);
|
||||||
}
|
}
|
||||||
|
@ -963,7 +963,7 @@ char *titleGenerateFileName(TitleInfo *title_info, u8 name_convention, u8 illega
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *titleGenerateGameCardFileName(u8 name_convention, u8 illegal_char_replace_type)
|
char *titleGenerateGameCardFileName(u8 naming_convention, u8 illegal_char_replace_type)
|
||||||
{
|
{
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
||||||
|
@ -978,8 +978,8 @@ char *titleGenerateGameCardFileName(u8 name_convention, u8 illegal_char_replace_
|
||||||
char app_name[0x400] = {0};
|
char app_name[0x400] = {0};
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
if (!g_titleInterfaceInit || !g_titleGameCardAvailable || name_convention > TitleFileNameConvention_IdAndVersionOnly || \
|
if (!g_titleInterfaceInit || !g_titleGameCardAvailable || naming_convention > TitleNamingConvention_IdAndVersionOnly || \
|
||||||
(name_convention == TitleFileNameConvention_Full && illegal_char_replace_type > TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly))
|
(naming_convention == TitleNamingConvention_Full && illegal_char_replace_type > TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly))
|
||||||
{
|
{
|
||||||
LOG_MSG("Invalid parameters!");
|
LOG_MSG("Invalid parameters!");
|
||||||
break;
|
break;
|
||||||
|
@ -1013,7 +1013,7 @@ char *titleGenerateGameCardFileName(u8 name_convention, u8 illegal_char_replace_
|
||||||
/* Generate current user application name. */
|
/* Generate current user application name. */
|
||||||
*app_name = '\0';
|
*app_name = '\0';
|
||||||
|
|
||||||
if (name_convention == TitleFileNameConvention_Full)
|
if (naming_convention == TitleNamingConvention_Full)
|
||||||
{
|
{
|
||||||
if (cur_filename_len) strcat(app_name, " + ");
|
if (cur_filename_len) strcat(app_name, " + ");
|
||||||
|
|
||||||
|
@ -1035,7 +1035,7 @@ char *titleGenerateGameCardFileName(u8 name_convention, u8 illegal_char_replace_
|
||||||
|
|
||||||
sprintf(app_name + strlen(app_name), "[%016lX][v%u]", app_info->meta_key.id, app_version);
|
sprintf(app_name + strlen(app_name), "[%016lX][v%u]", app_info->meta_key.id, app_version);
|
||||||
} else
|
} else
|
||||||
if (name_convention == TitleFileNameConvention_IdAndVersionOnly)
|
if (naming_convention == TitleNamingConvention_IdAndVersionOnly)
|
||||||
{
|
{
|
||||||
if (cur_filename_len) strcat(app_name, "+");
|
if (cur_filename_len) strcat(app_name, "+");
|
||||||
sprintf(app_name + strlen(app_name), "%016lX_v%u", app_info->meta_key.id, app_version);
|
sprintf(app_name + strlen(app_name), "%016lX_v%u", app_info->meta_key.id, app_version);
|
||||||
|
|
67
source/options_tab.cpp
Normal file
67
source/options_tab.cpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* options_tab.cpp
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2021, 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 <nxdt_utils.h>
|
||||||
|
#include <options_tab.hpp>
|
||||||
|
#include <title.h>
|
||||||
|
|
||||||
|
using namespace brls::i18n::literals; /* For _i18n. */
|
||||||
|
|
||||||
|
namespace nxdt::views
|
||||||
|
{
|
||||||
|
OptionsTab::OptionsTab(void) : brls::List()
|
||||||
|
{
|
||||||
|
/* Set custom spacing. */
|
||||||
|
this->setSpacing(this->getSpacing() / 2);
|
||||||
|
this->setMarginBottom(20);
|
||||||
|
|
||||||
|
/* Overclock. */
|
||||||
|
brls::ToggleListItem *overclock = new brls::ToggleListItem("options_tab/overclock/label"_i18n, configGetBoolean("overclock"), \
|
||||||
|
"options_tab/overclock/description"_i18n, "options_tab/overclock/value_enabled"_i18n, \
|
||||||
|
"options_tab/overclock/value_disabled"_i18n);
|
||||||
|
overclock->getClickEvent()->subscribe([](brls::View* view) {
|
||||||
|
brls::ToggleListItem *item = static_cast<brls::ToggleListItem*>(view);
|
||||||
|
bool value = item->getToggleState();
|
||||||
|
utilsOverclockSystem(value);
|
||||||
|
configSetBoolean("overclock", value);
|
||||||
|
});
|
||||||
|
this->addView(overclock);
|
||||||
|
|
||||||
|
/* Naming convention. */
|
||||||
|
brls::SelectListItem *naming_convention = new brls::SelectListItem("options_tab/naming_convention/label"_i18n, {
|
||||||
|
"options_tab/naming_convention/value_00"_i18n,
|
||||||
|
"options_tab/naming_convention/value_01"_i18n
|
||||||
|
}, static_cast<unsigned>(configGetInteger("naming_convention")),
|
||||||
|
"options_tab/naming_convention/description"_i18n);
|
||||||
|
naming_convention->getValueSelectedEvent()->subscribe([](int selected){
|
||||||
|
if (selected < 0 || selected > static_cast<int>(TitleNamingConvention_Count)) return;
|
||||||
|
configSetInteger("naming_convention", selected);
|
||||||
|
});
|
||||||
|
this->addView(naming_convention);
|
||||||
|
|
||||||
|
/* Update application. */
|
||||||
|
if (!envIsNso())
|
||||||
|
{
|
||||||
|
brls::ListItem *update_app = new brls::ListItem("options_tab/update_app/label"_i18n, "options_tab/update_app/description"_i18n);
|
||||||
|
this->addView(update_app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
#include <root_view.hpp>
|
#include <root_view.hpp>
|
||||||
#include <gamecard_tab.hpp>
|
#include <gamecard_tab.hpp>
|
||||||
#include <titles_tab.hpp>
|
#include <titles_tab.hpp>
|
||||||
//#include <options_tab.hpp>
|
#include <options_tab.hpp>
|
||||||
#include <about_tab.hpp>
|
#include <about_tab.hpp>
|
||||||
|
|
||||||
namespace i18n = brls::i18n; /* For getStr(). */
|
namespace i18n = brls::i18n; /* For getStr(). */
|
||||||
|
@ -111,7 +111,7 @@ namespace nxdt::views
|
||||||
|
|
||||||
this->addSeparator();
|
this->addSeparator();
|
||||||
|
|
||||||
this->addTab("root_view/tabs/options"_i18n, new brls::Rectangle(nvgRGB(255, 255, 0)));
|
this->addTab("root_view/tabs/options"_i18n, new OptionsTab());
|
||||||
|
|
||||||
this->addSeparator();
|
this->addSeparator();
|
||||||
|
|
||||||
|
|
2
todo.txt
2
todo.txt
|
@ -23,7 +23,7 @@ todo:
|
||||||
usb: improve abi (make it rest-like?)
|
usb: improve abi (make it rest-like?)
|
||||||
usb: improve cancel mechanism
|
usb: improve cancel mechanism
|
||||||
|
|
||||||
others: config load/save using json
|
others: use hardcoded directories, move data to hardcoded directory if the launch path isn't the right one
|
||||||
others: dump verification via nswdb / no-intro
|
others: dump verification via nswdb / no-intro
|
||||||
others: update application feature
|
others: update application feature
|
||||||
others: fatfs browser for emmc partitions
|
others: fatfs browser for emmc partitions
|
||||||
|
|
Loading…
Reference in a new issue