From 025c7780111e88dcfaf288a14705c5bb41c56cff Mon Sep 17 00:00:00 2001 From: J-D-K Date: Thu, 19 Jun 2025 17:17:35 -0400 Subject: [PATCH] Get Text mode working. --- romfs/Text/ENUS.json | 3 +- source/appstates/BackupMenuState.cpp | 34 ++++++++----- source/appstates/TextTitleSelectState.cpp | 59 +++++++++++++++++++++-- source/appstates/TitleOptionState.cpp | 10 ++-- source/appstates/TitleSelectState.cpp | 12 +++-- 5 files changed, 91 insertions(+), 27 deletions(-) diff --git a/romfs/Text/ENUS.json b/romfs/Text/ENUS.json index 60c89ef..6cfe534 100644 --- a/romfs/Text/ENUS.json +++ b/romfs/Text/ENUS.json @@ -179,7 +179,8 @@ "Backup is empty!", "Error resetting save data!", "Error opening ZIP file for reading!", - "Error occurred deleting backup!" + "Error occurred deleting backup!", + "Error creating backup!" ], "PopMessagesSaveCreate": [ "Save data created for #%s#!", diff --git a/source/appstates/BackupMenuState.cpp b/source/appstates/BackupMenuState.cpp index 1ddae9e..7c5b95b 100644 --- a/source/appstates/BackupMenuState.cpp +++ b/source/appstates/BackupMenuState.cpp @@ -21,6 +21,9 @@ namespace { /// @brief This is the length allotted for naming backups. constexpr size_t SIZE_BACKUP_NAME_LENGTH = 0x80; + + /// @brief This is just so there isn't random .zip comparisons everywhere. + constexpr std::string_view STRING_ZIP_EXTENSION = ".zip"; } // namespace // Declarations here. Definitions after class. @@ -367,6 +370,12 @@ static void create_new_backup(sys::ProgressTask *task, fs::copy_directory(fs::DEFAULT_SAVE_ROOT, targetPath, 0, {}, task); } + // This should actually fatal somehow? + if (!fslib::close_file_system(fs::DEFAULT_SAVE_MOUNT)) + { + logger::log("Error closing save data: %s.", fslib::get_error_string()); + } + // Refresh. spawningState->refresh(); @@ -375,22 +384,20 @@ static void create_new_backup(sys::ProgressTask *task, static void overwrite_backup(sys::ProgressTask *task, std::shared_ptr dataStruct) { + // I hate typing this stuff over and over. + static const char *STRING_ERROR_PREFIX = "Error overwriting backup: %s"; + // Might need this later. FsSaveDataInfo *saveInfo = dataStruct->m_user->get_save_info_by_id(dataStruct->m_titleInfo->get_application_id()); - // directory_exists can also be used to check if the target is a directory. - if (fslib::directory_exists(dataStruct->m_targetPath) && - !fslib::delete_directory_recursively(dataStruct->m_targetPath)) + // Wew this is a fun one to read, but it takes care of everything in one go. + if ((fslib::directory_exists(dataStruct->m_targetPath) && + !fslib::delete_directory_recursively(dataStruct->m_targetPath)) || + (fslib::file_exists(dataStruct->m_targetPath) && !fslib::delete_file(dataStruct->m_targetPath))) { - logger::log("Error overwriting backup: %s", fslib::get_error_string()); - task->finished(); - return; - } // This has an added check for the zip extension so it can't try to overwrite files that aren't supposed to be zip. - else if (fslib::file_exists(dataStruct->m_targetPath) && - std::strcmp("zip", dataStruct->m_targetPath.get_extension()) == 0 && - !fslib::delete_file(dataStruct->m_targetPath)) - { - logger::log("Error overwriting backup: %s", fslib::get_error_string()); + // Try to close this quick. + fslib::close_file_system(fs::DEFAULT_SAVE_MOUNT); + logger::log(STRING_ERROR_PREFIX, fslib::get_error_string()); task->finished(); return; } @@ -399,7 +406,8 @@ static void overwrite_backup(sys::ProgressTask *task, std::shared_ptrm_targetPath.get_extension())) + + if (std::strstr(STRING_ZIP_EXTENSION.data(), dataStruct->m_targetPath.c_string())) { zipFile backupZip = zipOpen64(dataStruct->m_targetPath.c_string(), APPEND_STATUS_CREATE); if (!backupZip) diff --git a/source/appstates/TextTitleSelectState.cpp b/source/appstates/TextTitleSelectState.cpp index f28d865..b6b8d1e 100644 --- a/source/appstates/TextTitleSelectState.cpp +++ b/source/appstates/TextTitleSelectState.cpp @@ -1,8 +1,14 @@ #include "appstates/TextTitleSelectState.hpp" +#include "JKSV.hpp" +#include "appstates/BackupMenuState.hpp" #include "appstates/MainMenuState.hpp" +#include "appstates/TitleOptionState.hpp" #include "colors.hpp" #include "config.hpp" +#include "fs/save_mount.hpp" +#include "fslib.hpp" #include "input.hpp" +#include "logger.hpp" #include "sdl.hpp" #include @@ -26,10 +32,57 @@ void TextTitleSelectState::update(void) { m_titleSelectMenu.update(AppState::has_focus()); - if (input::button_pressed(HidNpadButton_Y)) + // Both title selection states work too differently for this stuff to be shared IMO. + if (input::button_pressed(HidNpadButton_A)) { - config::add_remove_favorite(m_user->get_application_id_at(m_titleSelectMenu.get_selected())); - TextTitleSelectState::refresh(); + // Grab selected. + int selected = m_titleSelectMenu.get_selected(); + + // Grab what we need to continue. + uint64_t applicationID = m_user->get_application_id_at(selected); + FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(applicationID); + data::TitleInfo *titleInfo = data::get_title_info_by_id(m_user->get_application_id_at(selected)); + + // Output path. + fslib::Path targetPath = config::get_working_directory() / titleInfo->get_path_safe_title(); + + if ((fslib::directory_exists(targetPath) || fslib::create_directory(targetPath)) && + fslib::open_save_data_with_save_info(fs::DEFAULT_SAVE_MOUNT, *saveInfo)) + { + JKSV::push_state(std::make_shared(m_user, + titleInfo, + static_cast(saveInfo->save_data_type))); + } + else + { + logger::log(fslib::get_error_string()); + } + } + else if (input::button_pressed(HidNpadButton_X)) + { + int selected = m_titleSelectMenu.get_selected(); + + uint64_t applicationID = m_user->get_application_id_at(selected); + data::TitleInfo *titleInfo = data::get_title_info_by_id(applicationID); + + JKSV::push_state(std::make_shared(m_user, titleInfo, this)); + } + else if (input::button_pressed(HidNpadButton_Y)) + { + uint64_t applicationID = m_user->get_application_id_at(m_titleSelectMenu.get_selected()); + + config::add_remove_favorite(applicationID); + + // We need to resort all users, not just this one. + data::UserList list; + data::get_users(list); + for (data::User *user : list) + { + user->sort_data(); + } + + // Let the main menu state take care of this. + MainMenuState::refresh_view_states(); } else if (input::button_pressed(HidNpadButton_B)) { diff --git a/source/appstates/TitleOptionState.cpp b/source/appstates/TitleOptionState.cpp index dc737b6..e8e9f50 100644 --- a/source/appstates/TitleOptionState.cpp +++ b/source/appstates/TitleOptionState.cpp @@ -439,11 +439,10 @@ static void delete_save_data_from_system(sys::Task *task, std::shared_ptr dataStruct) { - // This is just to make stuff easier to read. + // Grab this stuff to make stuff easier to read and type. data::TitleInfo *titleInfo = dataStruct->m_titleInfo; - - // Grab this quick. FsSaveDataInfo *saveInfo = dataStruct->m_user->get_save_info_by_id(titleInfo->get_application_id()); + if (!saveInfo) { logger::log("Error retrieving save data info to extend!"); @@ -451,7 +450,6 @@ static void extend_save_data(sys::Task *task, std::shared_ptrset_status(strings::get_by_name(strings::names::TITLE_OPTION_STATUS, 3), dataStruct->m_user->get_nickname(), @@ -472,8 +470,8 @@ static void extend_save_data(sys::Task *task, std::shared_ptrget_journal_size_max(saveInfo->save_data_type); + // Grab the journal size. + int64_t journalSize = titleInfo->get_journal_size(saveInfo->save_data_type); // To do: Check this and toast message. fs::extend_save_data(saveInfo, size, journalSize); diff --git a/source/appstates/TitleSelectState.cpp b/source/appstates/TitleSelectState.cpp index 9d93566..0372d8b 100644 --- a/source/appstates/TitleSelectState.cpp +++ b/source/appstates/TitleSelectState.cpp @@ -56,7 +56,7 @@ void TitleSelectState::update(void) } else { - logger::log("%s", fslib::get_error_string()); + logger::log(fslib::get_error_string()); } } else if (input::button_pressed(HidNpadButton_X)) @@ -78,10 +78,14 @@ void TitleSelectState::update(void) config::add_remove_favorite(m_user->get_application_id_at(m_titleView.get_selected())); // Resort the data. - m_user->sort_data(); + data::UserList list; + data::get_users(list); + for (data::User *user : list) + { + user->sort_data(); + } - // Refresh the view. - TitleSelectState::refresh(); + MainMenuState::refresh_view_states(); } }