add more info boxes to options, merge option.cpp changes from totalsms.

This commit is contained in:
ITotalJustice
2025-07-30 23:26:15 +01:00
parent 430ee2280a
commit c8644c80cd
6 changed files with 142 additions and 57 deletions

View File

@@ -325,7 +325,7 @@ public:
option::OptionBool m_dump_append_folder_with_xci{"dump", "append_folder_with_xci", true};
option::OptionBool m_dump_trim_xci{"dump", "trim_xci", false};
option::OptionBool m_dump_label_trim_xci{"dump", "label_trim_xci", false};
option::OptionBool m_dump_usb_transfer_stream{"dump", "usb_transfer_stream", true};
option::OptionBool m_dump_usb_transfer_stream{"dump", "usb_transfer_stream", true, false};
option::OptionBool m_dump_convert_to_common_ticket{"dump", "convert_to_common_ticket", true};
// todo: move this into it's own menu

View File

@@ -7,10 +7,11 @@ namespace sphaira::option {
template<typename T>
struct OptionBase {
OptionBase(const std::string& section, const std::string& name, T default_value)
OptionBase(const std::string& section, const std::string& name, T default_value, bool file = true)
: m_section{section}
, m_name{name}
, m_default_value{default_value}
, m_file{file}
{}
auto Get() -> T;
@@ -29,6 +30,7 @@ private:
const std::string m_section;
const std::string m_name;
const T m_default_value;
const bool m_file;
std::optional<T> m_value;
};

View File

@@ -31,6 +31,7 @@ struct MiscMenuEntry {
const char* title;
MiscMenuFunction func;
u8 flag;
const char* info;
auto IsShortcut() const -> bool {
return flag & MiscMenuFlag_Shortcut;

View File

@@ -1619,11 +1619,13 @@ void App::DisplayThemeOptions(bool left_side) {
options->Add<ui::SidebarEntryBool>("Music"_i18n, App::GetThemeMusicEnable(), [](bool& enable){
App::SetThemeMusicEnable(enable);
});
}, "Enable background music.\n"\
"Each theme can have it's own music file."\
"If a theme does not set a music file, then /config/sphaira/themes/default_music.bfstm is loaded instead (if it exists)."_i18n);
options->Add<ui::SidebarEntryBool>("12 Hour Time"_i18n, App::Get12HourTimeEnable(), [](bool& enable){
App::Set12HourTimeEnable(enable);
});
}, "Changes the clock to 12 hour"_i18n);
options->Add<ui::SidebarEntryCallback>("Download Default Music"_i18n, [](){
// check if we already have music
@@ -1640,7 +1642,7 @@ void App::DisplayThemeOptions(bool left_side) {
} else {
download_default_music();
}
});
}, "Downloads the default background music for sphaira to /config/sphaira/themes/default_music.bfstm"_i18n);
}
void App::DisplayNetworkOptions(bool left_side) {
@@ -1662,7 +1664,7 @@ void App::DisplayMiscOptions(bool left_side) {
options->Add<ui::SidebarEntryCallback>(i18n::get(e.title), [e](){
App::Push(e.func(ui::menu::MenuFlag_None));
});
}, i18n::get(e.info));
}
if (App::IsApplication()) {
@@ -1690,7 +1692,9 @@ void App::DisplayMiscOptions(bool left_side) {
}
}
);
});
},
"Launch the built-in web browser.\n\n",
"NOTE: The browser is very limted, some websites will fail to load and there's a 30 minute timeout which closes the browser"_i18n);
}
}
@@ -1733,7 +1737,7 @@ void App::DisplayAdvancedOptions(bool left_side) {
options->Add<ui::SidebarEntryArray>("Text scroll speed"_i18n, text_scroll_speed_items, [](s64& index_out){
App::SetTextScrollSpeed(index_out);
}, App::GetTextScrollSpeed());
}, App::GetTextScrollSpeed(), "Change how fast the scrolling text updates"_i18n);
options->Add<ui::SidebarEntryArray>("Set left-side menu"_i18n, menu_items, [menu_names](s64& index_out){
const auto e = menu_names[index_out];
@@ -1750,7 +1754,7 @@ void App::DisplayAdvancedOptions(bool left_side) {
}
);
}
}, i18n::get(g_app->m_left_menu.Get()));
}, i18n::get(g_app->m_left_menu.Get()), "Set the menu that appears on the left tab."_i18n);
options->Add<ui::SidebarEntryArray>("Set right-side menu"_i18n, menu_items, [menu_names](s64& index_out){
const auto e = menu_names[index_out];
@@ -1767,15 +1771,16 @@ void App::DisplayAdvancedOptions(bool left_side) {
}
);
}
}, i18n::get(g_app->m_right_menu.Get()));
}, i18n::get(g_app->m_right_menu.Get()), "Set the menu that appears on the right tab."_i18n);
options->Add<ui::SidebarEntryCallback>("Install options"_i18n, [left_side](){
App::DisplayInstallOptions(left_side);
});
}, "Change the install options.\n"\
"You can enable installing from here."_i18n);
options->Add<ui::SidebarEntryCallback>("Dump options"_i18n, [left_side](){
App::DisplayDumpOptions(left_side);
});
}, "Change the dump options."_i18n);
static const char* erpt_path = "/atmosphere/erpt_reports";
options->Add<ui::SidebarEntryBool>("Disable erpt_reports"_i18n, fs::FsNativeSd().FileExists(erpt_path), [](bool& enable){
@@ -1891,12 +1896,31 @@ void App::DisplayDumpOptions(bool left_side) {
auto options = std::make_unique<ui::Sidebar>("Dump Options"_i18n, left_side ? ui::Sidebar::Side::LEFT : ui::Sidebar::Side::RIGHT);
ON_SCOPE_EXIT(App::Push(std::move(options)));
options->Add<ui::SidebarEntryBool>("Created nested folder"_i18n, App::GetApp()->m_dump_app_folder);
options->Add<ui::SidebarEntryBool>("Append folder with .xci"_i18n, App::GetApp()->m_dump_append_folder_with_xci);
options->Add<ui::SidebarEntryBool>("Trim XCI"_i18n, App::GetApp()->m_dump_trim_xci);
options->Add<ui::SidebarEntryBool>("Label trimmed XCI"_i18n, App::GetApp()->m_dump_label_trim_xci);
options->Add<ui::SidebarEntryBool>("Multi-threaded USB transfer"_i18n, App::GetApp()->m_dump_usb_transfer_stream);
options->Add<ui::SidebarEntryBool>("Convert to common ticket"_i18n, App::GetApp()->m_dump_convert_to_common_ticket);
options->Add<ui::SidebarEntryBool>(
"Created nested folder"_i18n, App::GetApp()->m_dump_app_folder,
"Creates a folder using the name of the game.\n"\
"For example, /dumps/XCI/name/name.xci"\
"Disabling this would use /dumps/XCI/name.xci"_i18n
);
options->Add<ui::SidebarEntryBool>(
"Append folder with .xci"_i18n, App::GetApp()->m_dump_append_folder_with_xci,
"XCI dumps will name the folder with the .xci extension.\n"\
"For example, /dumps/XCI/name.xci/name.xci\n\n"
"Some devices only function is the xci folder is named exactly the same as the xci."_i18n
);
options->Add<ui::SidebarEntryBool>(
"Trim XCI"_i18n, App::GetApp()->m_dump_trim_xci,
"Removes the unused data at the end of the XCI, making the output smaller."_i18n
);
options->Add<ui::SidebarEntryBool>(
"Label trimmed XCI"_i18n, App::GetApp()->m_dump_label_trim_xci,
"Names the trimmed xci.\n"
"For example, /dumps/XCI/name/name (trimmed).xci"_i18n
);
options->Add<ui::SidebarEntryBool>(
"Convert to common ticket"_i18n, App::GetApp()->m_dump_convert_to_common_ticket,
"Converts personalised ticket to a fake common ticket."_i18n
);
}
App::~App() {

View File

@@ -34,6 +34,7 @@ bool getbool(const char* LocalBuffer, bool def) {
template<typename T>
auto OptionBase<T>::GetInternal(const char* name) -> T {
if (!m_value.has_value()) {
if (m_file) {
if constexpr(std::is_same_v<T, bool>) {
m_value = ini_getbool(m_section.c_str(), name, m_default_value, App::CONFIG_PATH);
} else if constexpr(std::is_same_v<T, long>) {
@@ -43,7 +44,11 @@ auto OptionBase<T>::GetInternal(const char* name) -> T {
ini_gets(m_section.c_str(), name, m_default_value.c_str(), buf, sizeof(buf), App::CONFIG_PATH);
m_value = buf;
}
} else {
m_value = m_default_value;
}
}
return m_value.value();
}
@@ -54,7 +59,7 @@ auto OptionBase<T>::Get() -> T {
template<typename T>
auto OptionBase<T>::GetOr(const char* name) -> T {
if (ini_haskey(m_section.c_str(), m_name.c_str(), App::CONFIG_PATH)) {
if (m_file && ini_haskey(m_section.c_str(), m_name.c_str(), App::CONFIG_PATH)) {
return Get();
} else {
return GetInternal(name);
@@ -64,6 +69,7 @@ auto OptionBase<T>::GetOr(const char* name) -> T {
template<typename T>
void OptionBase<T>::Set(T value) {
m_value = value;
if (m_file) {
if constexpr(std::is_same_v<T, bool>) {
ini_putl(m_section.c_str(), m_name.c_str(), value, App::CONFIG_PATH);
} else if constexpr(std::is_same_v<T, long>) {
@@ -71,6 +77,7 @@ void OptionBase<T>::Set(T value) {
} else if constexpr(std::is_same_v<T, std::string>) {
ini_puts(m_section.c_str(), m_name.c_str(), value.c_str(), App::CONFIG_PATH);
}
}
}
template<typename T>
@@ -81,6 +88,7 @@ auto OptionBase<T>::LoadFrom(const char* section, const char* name, const char*
template<typename T>
auto OptionBase<T>::LoadFrom(const char* name, const char* value) -> bool {
if (m_name == name) {
if (m_file) {
if constexpr(std::is_same_v<T, bool>) {
m_value = getbool(value, m_default_value);
} else if constexpr(std::is_same_v<T, long>) {
@@ -88,6 +96,7 @@ auto OptionBase<T>::LoadFrom(const char* name, const char* value) -> bool {
} else if constexpr(std::is_same_v<T, std::string>) {
m_value = value;
}
}
return true;
}

View File

@@ -49,19 +49,59 @@ auto MiscMenuFuncGenerator(u32 flags) {
}
const MiscMenuEntry MISC_MENU_ENTRIES[] = {
{ .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator<ui::menu::appstore::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Games", .title = "Games", .func = MiscMenuFuncGenerator<ui::menu::game::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "FileBrowser", .title = "FileBrowser", .func = MiscMenuFuncGenerator<ui::menu::filebrowser::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Saves", .title = "Saves", .func = MiscMenuFuncGenerator<ui::menu::save::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "Appstore", .title = "Appstore", .func = MiscMenuFuncGenerator<ui::menu::appstore::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"Download and update apps.\n\n"\
"Internet connection required." },
{ .name = "Games", .title = "Games", .func = MiscMenuFuncGenerator<ui::menu::game::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"View all installed games."\
"In this menu you can launch, backup, create savedata and much more." },
{ .name = "FileBrowser", .title = "FileBrowser", .func = MiscMenuFuncGenerator<ui::menu::filebrowser::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"Browse files on you SD Card."\
"You can move, copy, delete, extract zip, create zip, upload and much more.\n\n"\
"A connected USB/HDD can be opened by mounting it in the advanced options." },
{ .name = "Saves", .title = "Saves", .func = MiscMenuFuncGenerator<ui::menu::save::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"View save data for each user."\
"You can backup and restore saves."\
"Experimental support for backing up system saves is possible." },
{ .name = "Themezer", .title = "Themezer", .func = MiscMenuFuncGenerator<ui::menu::themezer::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"Download themes from https://themezer.net."\
"Themes are downloaded to /themes/sphaira"\
"To install the themes, NXThemesInstaller needs to be installed (can be downloaded via the AppStore)." },
{ .name = "GitHub", .title = "GitHub", .func = MiscMenuFuncGenerator<ui::menu::gh::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"Download releases directly from GitHub."\
"Custom entries can be added to /config/sphaira/github" },
#if ENABLE_NETWORK_INSTALL
{ .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install },
{ .name = "MTP", .title = "MTP Install", .func = MiscMenuFuncGenerator<ui::menu::mtp::Menu>, .flag = MiscMenuFlag_Install },
{ .name = "USB", .title = "USB Install", .func = MiscMenuFuncGenerator<ui::menu::usb::Menu>, .flag = MiscMenuFlag_Install },
{ .name = "FTP", .title = "FTP Install", .func = MiscMenuFuncGenerator<ui::menu::ftp::Menu>, .flag = MiscMenuFlag_Install, .info =
"Install apps via FTP.\n\n"\
"NOTE: This feature does not always work, use at your own risk."\
"If you encounter an issue, do not open an issue, it will not be fixed." },
{ .name = "MTP", .title = "MTP Install", .func = MiscMenuFuncGenerator<ui::menu::mtp::Menu>, .flag = MiscMenuFlag_Install, .info =
"Install apps via MTP.\n\n"\
"NOTE: This feature does not always work, use at your own risk."\
"If you encounter an issue, do not open an issue, it will not be fixed." },
{ .name = "USB", .title = "USB Install", .func = MiscMenuFuncGenerator<ui::menu::usb::Menu>, .flag = MiscMenuFlag_Install, .info =
"Install apps via USB.\n\n"\
"A USB client is required on PC, such as ns-usbloader and fluffy.\n\n"\
"NOTE: This feature does not always work, use at your own risk."\
"If you encounter an issue, do not open an issue, it will not be fixed." },
#endif
{ .name = "GameCard", .title = "GameCard", .func = MiscMenuFuncGenerator<ui::menu::gc::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "IRS", .title = "IRS (Infrared Joycon Camera)", .func = MiscMenuFuncGenerator<ui::menu::irs::Menu>, .flag = MiscMenuFlag_Shortcut },
{ .name = "GameCard", .title = "GameCard", .func = MiscMenuFuncGenerator<ui::menu::gc::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"View info on the inserted Game Card (GC)."\
"You can backup and install the inserted GC."\
"To swap GC's, simply remove the old GC and insert the new one."\
"You do not need to exit the menu." },
{ .name = "IRS", .title = "IRS (Infrared Joycon Camera)", .func = MiscMenuFuncGenerator<ui::menu::irs::Menu>, .flag = MiscMenuFlag_Shortcut, .info =
"InfraRed Sensor (IRS) is the small camera found on right JoyCon." },
};
auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string version) -> Result {
@@ -288,29 +328,37 @@ MainMenu::MainMenu() {
options->Add<SidebarEntryBool>("Ftp"_i18n, App::GetFtpEnable(), [](bool& enable){
App::SetFtpEnable(enable);
});
}, "Enable FTP server to run in the background.\n\n"\
"The default port is 5000 with no user/pass set.\n"\
"You can change this behaviour in /config/ftpsrv/config.ini"_i18n);
options->Add<SidebarEntryBool>("Mtp"_i18n, App::GetMtpEnable(), [](bool& enable){
App::SetMtpEnable(enable);
});
}, "Enable MTP server to run in the background."_i18n);
options->Add<SidebarEntryBool>("Nxlink"_i18n, App::GetNxlinkEnable(), [](bool& enable){
App::SetNxlinkEnable(enable);
});
}, "Enable NXlink server to run in the background."\
"NXlink is used to send .nro's from PC to the switch\n\n"\
"If you are not a developer, you can disable this option."_i18n);
options->Add<SidebarEntryBool>("Hdd"_i18n, App::GetHddEnable(), [](bool& enable){
App::SetHddEnable(enable);
});
}, "Enable mounting of connected USB/HDD devices."\
"Connected devices can be used in the FileBrowser, as well as a backup location when dumping games and saves."_i18n);
options->Add<SidebarEntryBool>("Hdd write protect"_i18n, App::GetWriteProtect(), [](bool& enable){
App::SetWriteProtect(enable);
});
}, "Makes the connected HDD read-only."_i18n);
}, "Toggle FTP, MTP, HDD and NXlink\n\n" \
"If Sphaira has a update available, you can download it from this menu"_i18n);
options->Add<SidebarEntryArray>("Language"_i18n, language_items, [](s64& index_out){
App::SetLanguage(index_out);
}, (s64)App::GetLanguage());
}, (s64)App::GetLanguage(),
"Change the language.\n\n"
"If your language isn't found, or translations are missing, please consider opening a PR at "\
"https://github.com/ITotalJustice/sphaira/pulls"_i18n);
options->Add<SidebarEntryCallback>("Misc"_i18n, [](){
App::DisplayMiscOptions();
@@ -318,7 +366,8 @@ MainMenu::MainMenu() {
options->Add<SidebarEntryCallback>("Advanced"_i18n, [](){
App::DisplayAdvancedOptions();
});
}, "Change the advanced options."\
"Please view the info boxes to better understand each option."_i18n);
}}
));