mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-03-21 17:24:37 -05:00
Merge pull request #287 from J-D-K/dev
Implement File Mode, add noexcept where appropriate, update fslib for full RAII FS.
This commit is contained in:
commit
f052d0b2a7
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -16,3 +16,4 @@ JKSV.pfs0
|
|||
|
||||
#sometimes I give jksv to people and forget about this.
|
||||
JKSV.zip
|
||||
JKSV.nro.zip
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f948cecb43c4f1e089442a8c0fd58df7deefb955
|
||||
Subproject commit 30f56742733a350a1f4788d6fa2bcf26712ae669
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit fa7d0f456c78d7f94b8519260978419b564610b8
|
||||
Subproject commit 779fc5bd8aa4782e376fbce3baa146837f7d4825
|
||||
5
Makefile
5
Makefile
|
|
@ -51,7 +51,7 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
|||
# NOTE: For some reason, devkitpro no longer has freetype-config included? Also, using pkg-config causes conflicts with
|
||||
# my local pkg-config and I don't feel like dealing with CMake for all of this right now.
|
||||
CFLAGS := $(INCLUDE) -D__SWITCH__ `sdl2-config --cflags` `curl-config --cflags`\
|
||||
-g -Wall -O2 -ffunction-sections -ffast-math -fmax-errors=1 \
|
||||
-g -Wall -O3 -ffunction-sections -ffast-math -fmax-errors=1 \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=c++23
|
||||
|
|
@ -172,11 +172,12 @@ clean:
|
|||
@$(MAKE) -C ./Libraries/SDLLib/SDL clean
|
||||
@rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@nxlink $(TARGET).nro
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
debug: $(BUILD)
|
||||
@nxlink -s $(TARGET).nro
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class JKSV
|
|||
|
||||
/// @brief Returns if initializing was successful and JKSV is running.
|
||||
/// @return True or false.
|
||||
bool is_running() const;
|
||||
bool is_running() const noexcept;
|
||||
|
||||
/// @brief Runs JKSV's update routine.
|
||||
void update();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ class BaseState
|
|||
/// @brief Every derived class is required to have this function.
|
||||
virtual void update() = 0;
|
||||
|
||||
/// @brief Sub update routine. Meant to handle minor background tasks. Not meant for full update routines.
|
||||
virtual void sub_update() {};
|
||||
|
||||
/// @brief Every derived class is required to have this function.
|
||||
virtual void render() = 0;
|
||||
|
||||
|
|
@ -45,7 +48,7 @@ class BaseState
|
|||
|
||||
private:
|
||||
/// @brief Stores whether or not the state is currently active.
|
||||
bool m_isActive = true;
|
||||
bool m_isActive{true};
|
||||
|
||||
/// @brief Stores whether or not the state has focus.
|
||||
bool m_hasFocus{};
|
||||
|
|
|
|||
|
|
@ -34,4 +34,22 @@ class ExtrasMenuState final : public BaseState
|
|||
|
||||
/// @brief This function is called when Reinitialize data is selected.
|
||||
void reinitialize_data();
|
||||
|
||||
/// @brief Opens an SD to SD file browser.
|
||||
void sd_to_sd_browser();
|
||||
|
||||
/// @brief Opens the prodinfo-f to sd.
|
||||
void prodinfof_to_sd();
|
||||
|
||||
/// @brief Opens the safe partition to SD.
|
||||
void safe_to_sd();
|
||||
|
||||
/// @brief Opens the system partition to SD.
|
||||
void system_to_sd();
|
||||
|
||||
/// @brief Opens the user partition to SD.
|
||||
void user_to_sd();
|
||||
|
||||
/// @brief Terminates a process.
|
||||
void terminate_process();
|
||||
};
|
||||
|
|
|
|||
160
include/appstates/FileModeState.hpp
Normal file
160
include/appstates/FileModeState.hpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#pragma once
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/BaseState.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "ui/ui.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
class FileModeState final : public BaseState
|
||||
{
|
||||
public:
|
||||
/// @brief Constructs a new FileModeState.
|
||||
FileModeState(std::string_view mountA, std::string_view mountB, int64_t journalSize = 0);
|
||||
|
||||
/// @brief Destructor. Closes the filesystems passed.
|
||||
~FileModeState() {};
|
||||
|
||||
static inline std::shared_ptr<FileModeState> create(std::string_view mountA,
|
||||
std::string_view mountB,
|
||||
int64_t journalSize = 0)
|
||||
{
|
||||
return std::make_shared<FileModeState>(mountA, mountB, journalSize);
|
||||
}
|
||||
|
||||
static inline std::shared_ptr<FileModeState> create_and_push(std::string_view mountA,
|
||||
std::string_view mountB,
|
||||
int64_t journalSize = 0)
|
||||
{
|
||||
auto newState = std::make_shared<FileModeState>(mountA, mountB, journalSize);
|
||||
StateManager::push_state(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
/// @brief Update override.
|
||||
void update() override;
|
||||
|
||||
/// @brief Render override.
|
||||
void render() override;
|
||||
|
||||
/// @brief This thing is a headache without this.
|
||||
friend class FileOptionState;
|
||||
|
||||
private:
|
||||
/// @brief These store the mount points to close the filesystems upon construction.
|
||||
std::string m_mountA;
|
||||
std::string m_mountB;
|
||||
|
||||
/// @brief These are the actual target paths.
|
||||
fslib::Path m_pathA{};
|
||||
fslib::Path m_pathB{};
|
||||
|
||||
/// @brief Directory listings for each respective path.
|
||||
fslib::Directory m_dirA{};
|
||||
fslib::Directory m_dirB{};
|
||||
|
||||
/// @brief Menus for the directory listings.
|
||||
std::shared_ptr<ui::Menu> m_dirMenuA{};
|
||||
std::shared_ptr<ui::Menu> m_dirMenuB{};
|
||||
|
||||
/// @brief Controls which menu/filesystem is currently targetted.
|
||||
bool m_target{};
|
||||
|
||||
/// @brief Stores the size for committing data (if needed) to mountA.
|
||||
int64_t m_journalSize{};
|
||||
|
||||
/// @brief The beginning Y coord of the dialog.
|
||||
double m_y{720.0f};
|
||||
|
||||
/// @brief This is the targetY. Used for the opening and hiding effect.
|
||||
double m_targetY{91.0f};
|
||||
|
||||
/// @brief Config scaling for the "transition"
|
||||
double m_scaling{};
|
||||
|
||||
/// @brief Stores whether or not the dialog has reached its targetted position.
|
||||
bool m_inPlace{};
|
||||
|
||||
/// @brief Frame shared by all instances.
|
||||
static inline std::shared_ptr<ui::Frame> sm_frame{};
|
||||
|
||||
/// @brief This is the render target the browsers are rendered to.
|
||||
static inline sdl::SharedTexture sm_renderTarget{};
|
||||
|
||||
/// @brief Stores a pointer to the guide in the bottom-right corner.
|
||||
static inline const char *sm_controlGuide{};
|
||||
|
||||
/// @brief Calculated X coordinate of the control guide text.
|
||||
static inline int sm_controlGuideX{};
|
||||
|
||||
/// @brief Initializes the members shared by all instances of FileModeState.
|
||||
void initialize_static_members();
|
||||
|
||||
/// @brief Creates valid paths with the mounts passed.
|
||||
void initialize_paths();
|
||||
|
||||
/// @brief Ensures the menus are allocated and setup properly.
|
||||
void initialize_menus();
|
||||
|
||||
/// @brief Loads the current directory listings and menus.
|
||||
void initialize_directory_menu(const fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Updates the dialog's coordinates in the beginning.
|
||||
void update_y_coord() noexcept;
|
||||
|
||||
/// @brief Starts the dialog hiding process.
|
||||
void hide_dialog() noexcept;
|
||||
|
||||
/// @brief Returns whether or not the dialog is hidden.
|
||||
bool is_hidden() noexcept;
|
||||
|
||||
/// @brief Handles changing the current directory or opening the options.
|
||||
void enter_selected(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Opens the little option pop-up thingy.
|
||||
void open_option_menu(fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Changes the current target/controllable menu.
|
||||
void change_target() noexcept;
|
||||
|
||||
/// @brief Function executed when '..' is selected.
|
||||
void up_one_directory(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Appends the entry passed to the path passed and "enters" the directory.
|
||||
/// @param path Working path.
|
||||
/// @param directory Working directory.
|
||||
/// @param menu Working menu.
|
||||
/// @param entry Target entry.
|
||||
void enter_directory(fslib::Path &path,
|
||||
fslib::Directory &directory,
|
||||
ui::Menu &menu,
|
||||
const fslib::DirectoryEntry &entry);
|
||||
|
||||
/// @brief Renders the control guide string on the bottom of the screen.
|
||||
void render_control_guide();
|
||||
|
||||
/// @brief Returns a reference to the currently active menu.
|
||||
ui::Menu &get_source_menu() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the currently inactive menu.
|
||||
ui::Menu &get_destination_menu() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the current "active" path.
|
||||
fslib::Path &get_source_path() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the currently "inactive" path.
|
||||
fslib::Path &get_destination_path() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the "active" directory.
|
||||
fslib::Directory &get_source_directory() noexcept;
|
||||
|
||||
/// @brief Returns a reference ot the currently "inactive" directory.
|
||||
fslib::Directory &get_destination_directory() noexcept;
|
||||
|
||||
/// @brief Returns whether or not a path is at the root.
|
||||
inline bool path_is_root(fslib::Path &path) const { return std::char_traits<char>::length(path.get_path()) <= 1; }
|
||||
|
||||
/// @brief Closes the filesystems passed and deactivates the state.
|
||||
void deactivate_state() noexcept;
|
||||
};
|
||||
135
include/appstates/FileOptionState.hpp
Normal file
135
include/appstates/FileOptionState.hpp
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
#pragma once
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/BaseState.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "ui/ui.hpp"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class FileOptionState final : public BaseState
|
||||
{
|
||||
public:
|
||||
/// @brief FileOptionState.
|
||||
/// @param spawningState Pointer to spawning state to grab its goodies.
|
||||
FileOptionState(FileModeState *spawningState);
|
||||
|
||||
~FileOptionState() {};
|
||||
|
||||
/// @brief Inline creation function.
|
||||
static inline std::shared_ptr<FileOptionState> create(FileModeState *spawningState)
|
||||
{
|
||||
return std::make_shared<FileOptionState>(spawningState);
|
||||
}
|
||||
|
||||
/// @brief Same as above. Pushes state before returning it.
|
||||
static inline std::shared_ptr<FileOptionState> create_and_push(FileModeState *spawningState)
|
||||
{
|
||||
auto newState = FileOptionState::create(spawningState);
|
||||
StateManager::push_state(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
/// @brief Update routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Render routine.
|
||||
void render() override;
|
||||
|
||||
/// @brief Signals to this state to update the source/target menu on the next update() call.
|
||||
void update_source();
|
||||
|
||||
/// @brief Signals to this state to update the destination. Very rarely used.
|
||||
void update_destination();
|
||||
|
||||
// clang-format off
|
||||
struct DataStruct
|
||||
{
|
||||
fslib::Path sourcePath{};
|
||||
fslib::Path destPath{};
|
||||
int64_t journalSize{};
|
||||
FileOptionState *spawningState{};
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
/// @brief This makes some other stuff easier to read and type.
|
||||
using TaskData = std::shared_ptr<FileOptionState::DataStruct>;
|
||||
|
||||
private:
|
||||
/// @brief Pointer to spawning FileMode state.
|
||||
FileModeState *m_spawningState{};
|
||||
|
||||
/// @brief X coordinate. This is set at construction according to the target from the spawning state.
|
||||
int m_x{};
|
||||
|
||||
/// @brief X coordinate for the target to reach.
|
||||
int m_targetX{};
|
||||
|
||||
/// @brief Whether or not the dialog/menu is in place.
|
||||
bool m_inPlace{};
|
||||
|
||||
/// @brief Whether or not the state should be closed.
|
||||
bool m_close{};
|
||||
|
||||
/// @brief Stores whether or not an update is needed on the next update().
|
||||
std::atomic<bool> m_updateSource{};
|
||||
std::atomic<bool> m_updateDest{};
|
||||
|
||||
/// @brief This is the data struct passed to tasks.
|
||||
std::shared_ptr<FileOptionState::DataStruct> m_dataStruct{};
|
||||
|
||||
/// @brief This is shared by all instances.
|
||||
static inline std::shared_ptr<ui::Menu> sm_copyMenu{};
|
||||
|
||||
/// @brief This is shared by all instances.
|
||||
static inline std::shared_ptr<ui::DialogBox> sm_dialog{};
|
||||
|
||||
/// @brief Ensures static members of all instances are allocated.
|
||||
void initialize_static_members();
|
||||
|
||||
/// @brief Sets whether the dialog/menu are positioned left or right depending on the menu active in the spawning state.
|
||||
void set_menu_side();
|
||||
|
||||
/// @brief Assigns the pointer to this.
|
||||
void initialize_data_struct();
|
||||
|
||||
/// @brief Updates the FileModeState's source data.
|
||||
void update_filemode_source();
|
||||
|
||||
/// @brief Updates the FileModeState's destination data.
|
||||
void update_filemode_dest();
|
||||
|
||||
/// @brief Updates the Y coordinate
|
||||
void update_x_coord();
|
||||
|
||||
/// @brief Sets up and begins the copy task.
|
||||
void copy_target();
|
||||
|
||||
/// @brief Sets up and begins the delete task.
|
||||
void delete_target();
|
||||
|
||||
/// @brief Attempts to rename the target.
|
||||
void rename_target();
|
||||
|
||||
/// @brief Attempts to create a new directory.
|
||||
void create_directory();
|
||||
|
||||
/// @brief Gets the properties of a file/folder.
|
||||
void get_show_target_properties();
|
||||
|
||||
/// @brief Gets info and creates a MessageState displaying the properties of the target directory.
|
||||
void get_show_directory_properties(const fslib::Path &path);
|
||||
|
||||
/// @brief Gets info and creates a message displaying the properties of the target file.
|
||||
/// @param path
|
||||
void get_show_file_properties(const fslib::Path &path);
|
||||
|
||||
/// @brief Closes and hides the state.
|
||||
void close();
|
||||
|
||||
/// @brief Returns whether or not the state is closed.
|
||||
bool is_closed();
|
||||
|
||||
/// @brief Sets the menu index back to 0 and deactivates the state.
|
||||
void deactivate_state();
|
||||
};
|
||||
|
|
@ -39,6 +39,9 @@ class TitleOptionState final : public BaseState
|
|||
/// @brief Runs update routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Handles hiding the panel.
|
||||
void sub_update() override;
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
void render() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class UserOptionState final : public BaseState
|
|||
/// @brief Runs the render routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Handles hiding the panel.
|
||||
void sub_update() override;
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
void render() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,52 +27,52 @@ namespace config
|
|||
void save();
|
||||
|
||||
/// @brief Attempts to find and return the value of the key passed.
|
||||
uint8_t get_by_key(std::string_view key) const;
|
||||
uint8_t get_by_key(std::string_view key) const noexcept;
|
||||
|
||||
/// @brief Attempts to toggle the value for the key passed. For simple 1 and 0.
|
||||
void toggle_by_key(std::string_view key);
|
||||
void toggle_by_key(std::string_view key) noexcept;
|
||||
|
||||
/// @brief Attempts to set the key passed to the value passd.
|
||||
void set_by_key(std::string_view key, uint8_t value);
|
||||
void set_by_key(std::string_view key, uint8_t value) noexcept;
|
||||
|
||||
/// @brief Returns the current working directory.
|
||||
fslib::Path get_working_directory() const;
|
||||
|
||||
/// @brief Sets the current work directory if the path passed is valid.
|
||||
bool set_working_directory(const fslib::Path &workDir);
|
||||
bool set_working_directory(const fslib::Path &workDir) noexcept;
|
||||
|
||||
/// @brief Returns the transition scaling speed.
|
||||
double get_animation_scaling() const;
|
||||
double get_animation_scaling() const noexcept;
|
||||
|
||||
/// @brief Sets the current animation scaling speed.
|
||||
void set_animation_scaling(double scaling);
|
||||
void set_animation_scaling(double scaling) noexcept;
|
||||
|
||||
/// @brief Adds a favorite to the favorite titles.
|
||||
void add_favorite(uint64_t applicationID);
|
||||
|
||||
/// @brief Removes a title from the favorites.
|
||||
void remove_favorite(uint64_t applicationID);
|
||||
void remove_favorite(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Returns if the application ID passed is a favorite.
|
||||
bool is_favorite(uint64_t applicationID) const;
|
||||
bool is_favorite(uint64_t applicationID) const noexcept;
|
||||
|
||||
/// @brief Adds the application ID passed to the blacklist.
|
||||
void add_to_blacklist(uint64_t applicationID);
|
||||
|
||||
/// @brief Removes the application ID passed from the blacklist.
|
||||
void remove_from_blacklist(uint64_t applicationID);
|
||||
void remove_from_blacklist(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Writes all of the currently blacklisted titles to the vector passed.
|
||||
void get_blacklist(std::vector<uint64_t> &listOut);
|
||||
|
||||
/// @brief Returns if the application ID passed is found in the blacklist.
|
||||
bool is_blacklisted(uint64_t applicationID) const;
|
||||
bool is_blacklisted(uint64_t applicationID) const noexcept;
|
||||
|
||||
/// @brief Returns if the blacklist is empty.
|
||||
bool blacklist_empty() const;
|
||||
bool blacklist_empty() const noexcept;
|
||||
|
||||
/// @brief Returns if the application ID passed has a custom output path.
|
||||
bool has_custom_path(uint64_t applicationID) const;
|
||||
bool has_custom_path(uint64_t applicationID) const noexcept;
|
||||
|
||||
/// @brief Adds a new output path.
|
||||
void add_custom_path(uint64_t applicationID, std::string_view newPath);
|
||||
|
|
|
|||
|
|
@ -19,16 +19,16 @@ namespace config
|
|||
/// @brief Retrieves the config value according to the key passed.
|
||||
/// @param key Key to retrieve. See config::keys
|
||||
/// @return Key's value if found. 0 if it is not.
|
||||
uint8_t get_by_key(std::string_view key);
|
||||
uint8_t get_by_key(std::string_view key) noexcept;
|
||||
|
||||
/// @brief Toggles the key. This is only for basic true or false settings.
|
||||
/// @param key Key to toggle.
|
||||
void toggle_by_key(std::string_view key);
|
||||
void toggle_by_key(std::string_view key) noexcept;
|
||||
|
||||
/// @brief Sets the key according
|
||||
/// @param key Key to set.
|
||||
/// @param value Value to set the key to.
|
||||
void set_by_key(std::string_view key, uint8_t value);
|
||||
void set_by_key(std::string_view key, uint8_t value) noexcept;
|
||||
|
||||
/// @brief Returns the working directory.
|
||||
/// @return Working directory.
|
||||
|
|
@ -36,15 +36,15 @@ namespace config
|
|||
|
||||
/// @brief Attempts to set the working directory to the one passed.
|
||||
/// @param path Path for JKSV to use.
|
||||
bool set_working_directory(const fslib::Path &path);
|
||||
bool set_working_directory(const fslib::Path &path) noexcept;
|
||||
|
||||
/// @brief Returns the scaling speed of UI transitions and animations.
|
||||
/// @return Scaling variable.
|
||||
double get_animation_scaling();
|
||||
double get_animation_scaling() noexcept;
|
||||
|
||||
/// @brief Sets the UI animation scaling.
|
||||
/// @param newScale New value to set the scaling to.
|
||||
void set_animation_scaling(double newScale);
|
||||
void set_animation_scaling(double newScale) noexcept;
|
||||
|
||||
/// @brief Adds or removes a title from the favorites list.
|
||||
/// @param applicationID Application ID of title to add or remove.
|
||||
|
|
@ -53,11 +53,11 @@ namespace config
|
|||
/// @brief Returns if the title is found in the favorites list.
|
||||
/// @param applicationID Application ID to search for.
|
||||
/// @return True if found. False if not.
|
||||
bool is_favorite(uint64_t applicationID);
|
||||
bool is_favorite(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Adds or removes title from blacklist.
|
||||
/// @param applicationID Application ID to add or remove.
|
||||
void add_remove_blacklist(uint64_t applicationID);
|
||||
void add_remove_blacklist(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Gets the currently blacklisted application IDs.
|
||||
/// @param listOut Vector to store application IDs to.
|
||||
|
|
@ -66,10 +66,10 @@ namespace config
|
|||
/// @brief Returns if the title is found in the blacklist.
|
||||
/// @param applicationID Application ID to search for.
|
||||
/// @return True if found. False if not.
|
||||
bool is_blacklisted(uint64_t applicationID);
|
||||
bool is_blacklisted(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Returns whether or not the blacklist is empty.
|
||||
bool blacklist_is_empty();
|
||||
bool blacklist_is_empty() noexcept;
|
||||
|
||||
/// @brief Adds a custom output path for the title.
|
||||
/// @param applicationID Application ID of title to add a path for.
|
||||
|
|
@ -79,7 +79,7 @@ namespace config
|
|||
/// @brief Searches to see if the application ID passed has a custom output path.
|
||||
/// @param applicationID Application ID to check.
|
||||
/// @return True if it does. False if it doesn't.
|
||||
bool has_custom_path(uint64_t applicationID);
|
||||
bool has_custom_path(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Gets the custom, defined path for the title.
|
||||
/// @param applicationID Application ID of title to get.
|
||||
|
|
|
|||
|
|
@ -1,34 +1,31 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
namespace config
|
||||
namespace config::keys
|
||||
{
|
||||
namespace keys
|
||||
{
|
||||
inline constexpr std::string_view WORKING_DIRECTORY = "WorkingDirectory";
|
||||
inline constexpr std::string_view INCLUDE_DEVICE_SAVES = "IncludeDeviceSaves";
|
||||
inline constexpr std::string_view AUTO_BACKUP_ON_RESTORE = "AutoBackupOnRestore";
|
||||
inline constexpr std::string_view AUTO_NAME_BACKUPS = "AutoNameBackups";
|
||||
inline constexpr std::string_view AUTO_UPLOAD = "AutoUploadToRemote";
|
||||
inline constexpr std::string_view USE_TITLE_IDS = "AlwaysUseTitleID";
|
||||
inline constexpr std::string_view HOLD_FOR_DELETION = "HoldForDeletion";
|
||||
inline constexpr std::string_view HOLD_FOR_RESTORATION = "HoldForRestoration";
|
||||
inline constexpr std::string_view HOLD_FOR_OVERWRITE = "HoldForOverWrite";
|
||||
inline constexpr std::string_view ONLY_LIST_MOUNTABLE = "OnlyListMountable";
|
||||
inline constexpr std::string_view LIST_ACCOUNT_SYS_SAVES = "ListAccountSystemSaves";
|
||||
inline constexpr std::string_view ALLOW_WRITING_TO_SYSTEM = "AllowSystemSaveWriting";
|
||||
inline constexpr std::string_view EXPORT_TO_ZIP = "ExportToZip";
|
||||
inline constexpr std::string_view ZIP_COMPRESSION_LEVEL = "ZipCompressionLevel";
|
||||
inline constexpr std::string_view TITLE_SORT_TYPE = "TitleSortType";
|
||||
inline constexpr std::string_view JKSM_TEXT_MODE = "JKSMTextMode";
|
||||
inline constexpr std::string_view FORCE_ENGLISH = "ForceEnglish";
|
||||
inline constexpr std::string_view SHOW_DEVICE_USER = "ShowDevice";
|
||||
inline constexpr std::string_view SHOW_BCAT_USER = "ShowBCAT";
|
||||
inline constexpr std::string_view SHOW_CACHE_USER = "ShowCache";
|
||||
inline constexpr std::string_view SHOW_SYSTEM_USER = "ShowSystem";
|
||||
inline constexpr std::string_view ENABLE_TRASH_BIN = "EnableTrash";
|
||||
inline constexpr std::string_view UI_ANIMATION_SCALE = "UIAnimationScaling";
|
||||
inline constexpr std::string_view FAVORITES = "Favorites";
|
||||
inline constexpr std::string_view BLACKLIST = "BlackList";
|
||||
} // namespace keys
|
||||
}
|
||||
inline constexpr std::string_view WORKING_DIRECTORY = "WorkingDirectory";
|
||||
inline constexpr std::string_view INCLUDE_DEVICE_SAVES = "IncludeDeviceSaves";
|
||||
inline constexpr std::string_view AUTO_BACKUP_ON_RESTORE = "AutoBackupOnRestore";
|
||||
inline constexpr std::string_view AUTO_NAME_BACKUPS = "AutoNameBackups";
|
||||
inline constexpr std::string_view AUTO_UPLOAD = "AutoUploadToRemote";
|
||||
inline constexpr std::string_view USE_TITLE_IDS = "AlwaysUseTitleID";
|
||||
inline constexpr std::string_view HOLD_FOR_DELETION = "HoldForDeletion";
|
||||
inline constexpr std::string_view HOLD_FOR_RESTORATION = "HoldForRestoration";
|
||||
inline constexpr std::string_view HOLD_FOR_OVERWRITE = "HoldForOverWrite";
|
||||
inline constexpr std::string_view ONLY_LIST_MOUNTABLE = "OnlyListMountable";
|
||||
inline constexpr std::string_view LIST_ACCOUNT_SYS_SAVES = "ListAccountSystemSaves";
|
||||
inline constexpr std::string_view ALLOW_WRITING_TO_SYSTEM = "AllowSystemSaveWriting";
|
||||
inline constexpr std::string_view EXPORT_TO_ZIP = "ExportToZip";
|
||||
inline constexpr std::string_view ZIP_COMPRESSION_LEVEL = "ZipCompressionLevel";
|
||||
inline constexpr std::string_view TITLE_SORT_TYPE = "TitleSortType";
|
||||
inline constexpr std::string_view JKSM_TEXT_MODE = "JKSMTextMode";
|
||||
inline constexpr std::string_view FORCE_ENGLISH = "ForceEnglish";
|
||||
inline constexpr std::string_view SHOW_DEVICE_USER = "ShowDevice";
|
||||
inline constexpr std::string_view SHOW_BCAT_USER = "ShowBCAT";
|
||||
inline constexpr std::string_view SHOW_CACHE_USER = "ShowCache";
|
||||
inline constexpr std::string_view SHOW_SYSTEM_USER = "ShowSystem";
|
||||
inline constexpr std::string_view ENABLE_TRASH_BIN = "EnableTrash";
|
||||
inline constexpr std::string_view UI_ANIMATION_SCALE = "UIAnimationScaling";
|
||||
inline constexpr std::string_view FAVORITES = "Favorites";
|
||||
inline constexpr std::string_view BLACKLIST = "BlackList";
|
||||
}
|
||||
|
|
@ -13,18 +13,25 @@ namespace curl
|
|||
{
|
||||
/// @brief Buffer mutex.
|
||||
std::mutex lock{};
|
||||
|
||||
/// @brief Conditional for when the buffer is full.
|
||||
std::condition_variable condition{};
|
||||
|
||||
/// @brief Shared buffer that is read into.
|
||||
std::vector<sys::byte> sharedBuffer{};
|
||||
|
||||
/// @brief Bool to signal when the buffer is ready/empty.
|
||||
bool bufferReady{};
|
||||
|
||||
/// @brief Destination file to write to.
|
||||
fslib::File *dest{};
|
||||
|
||||
/// @brief Optional. Task to update with progress.
|
||||
sys::ProgressTask *task{};
|
||||
|
||||
/// @brief Current offset in the file.
|
||||
size_t offset{};
|
||||
|
||||
/// @brief Size of the file being downloaded.
|
||||
int64_t fileSize{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace curl
|
|||
{
|
||||
/// @brief Source file to upload from.
|
||||
fslib::File *source{};
|
||||
|
||||
/// @brief Optional. Task to update with progress.
|
||||
sys::ProgressTask *task{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace data
|
|||
void load_title(uint64_t applicationID);
|
||||
|
||||
/// @brief Returns the title info mapped to applicationID. nullptr on not found.
|
||||
data::TitleInfo *get_title_by_id(uint64_t applicationID);
|
||||
data::TitleInfo *get_title_by_id(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Gets a vector of pointers to all of the current title info instances.
|
||||
void get_title_info_list(data::TitleInfoList &listOut);
|
||||
|
|
|
|||
|
|
@ -20,79 +20,76 @@ namespace data
|
|||
public:
|
||||
/// @brief Constructs a TitleInfo instance. Loads control data, icon.
|
||||
/// @param applicationID Application ID of title to load.
|
||||
TitleInfo(uint64_t applicationID);
|
||||
TitleInfo(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Initializes a TitleInfo instance using external (cached) NsApplicationControlData
|
||||
/// @param applicationID Application ID of the title loaded from cache.
|
||||
/// @param controlData Reference to the control data to init from.
|
||||
TitleInfo(uint64_t applicationID, std::unique_ptr<NsApplicationControlData> &controlData);
|
||||
TitleInfo(uint64_t applicationID, NsApplicationControlData &controlData) noexcept;
|
||||
|
||||
/// @brief Move constructor and operator.
|
||||
TitleInfo(TitleInfo &&titleInfo);
|
||||
TitleInfo &operator=(TitleInfo &&TitleInfo);
|
||||
|
||||
// None of this nonesense around these parts.TitleInfo(const TitleInfo &) = delete;
|
||||
// None of this nonesense around these parts.
|
||||
TitleInfo(const TitleInfo &) = delete;
|
||||
TitleInfo &operator=(const TitleInfo &) = delete;
|
||||
|
||||
/// @brief Returns the application ID of the title.
|
||||
/// @return Title's application ID.
|
||||
uint64_t get_application_id() const;
|
||||
uint64_t get_application_id() const noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the control data for the title.
|
||||
/// @return Pointer to control data.
|
||||
NsApplicationControlData *get_control_data();
|
||||
const NsApplicationControlData *get_control_data() const noexcept;
|
||||
|
||||
/// @brief Returns whether or not the title has control data.
|
||||
/// @return Whether or not the title has control data.
|
||||
bool has_control_data() const;
|
||||
bool has_control_data() const noexcept;
|
||||
|
||||
/// @brief Returns the title of the title?
|
||||
/// @return Title directly from the NACP.
|
||||
const char *get_title();
|
||||
const char *get_title() const noexcept;
|
||||
|
||||
/// @brief Returns the path safe version of the title for file system usage.
|
||||
/// @return Path safe version of the title.
|
||||
const char *get_path_safe_title() const;
|
||||
const char *get_path_safe_title() const noexcept;
|
||||
|
||||
/// @brief Returns the publisher of the title.
|
||||
/// @return Publisher string from NACP.
|
||||
const char *get_publisher();
|
||||
const char *get_publisher() const noexcept;
|
||||
|
||||
/// @brief Returns the owner ID of the save data.
|
||||
uint64_t get_save_data_owner_id() const;
|
||||
uint64_t get_save_data_owner_id() const noexcept;
|
||||
|
||||
/// @brief Returns the save data container's base size.
|
||||
/// @param saveType Type of save data to return.
|
||||
/// @return Size of baseline save data if applicable. If not, 0.
|
||||
int64_t get_save_data_size(uint8_t saveType) const;
|
||||
int64_t get_save_data_size(uint8_t saveType) const noexcept;
|
||||
|
||||
/// @brief Returns the maximum size of the save data container.
|
||||
/// @param saveType Type of save data to return.
|
||||
/// @return Maximum size of the save container if applicable. If not, 0.
|
||||
int64_t get_save_data_size_max(uint8_t saveType) const;
|
||||
int64_t get_save_data_size_max(uint8_t saveType) const noexcept;
|
||||
|
||||
/// @brief Returns the journaling size for the save type passed.
|
||||
/// @param saveType Save type to return.
|
||||
/// @return Journal size if applicable. If not, 0.
|
||||
int64_t get_journal_size(uint8_t saveType) const;
|
||||
int64_t get_journal_size(uint8_t saveType) const noexcept;
|
||||
|
||||
/// @brief Returns the maximum journal size for the save type passed.
|
||||
/// @param saveType Save type to return.
|
||||
/// @return Maximum journal size if applicable. If not, 0.
|
||||
int64_t get_journal_size_max(uint8_t saveType) const;
|
||||
int64_t get_journal_size_max(uint8_t saveType) const noexcept;
|
||||
|
||||
/// @brief Returns if a title uses the save type passed.
|
||||
/// @param saveType Save type to check for.
|
||||
/// @return True on success. False on failure.
|
||||
bool has_save_data_type(uint8_t saveType) const;
|
||||
bool has_save_data_type(uint8_t saveType) const noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the icon texture.
|
||||
/// @return Icon
|
||||
sdl::SharedTexture get_icon() const;
|
||||
sdl::SharedTexture get_icon() const noexcept;
|
||||
|
||||
/// @brief Allows the path safe title to be set to a new path.
|
||||
/// @param newPathSafe Buffer containing the new safe path to use.
|
||||
void set_path_safe_title(const char *newPathSafe);
|
||||
void set_path_safe_title(const char *newPathSafe) noexcept;
|
||||
|
||||
/// @brief Loads the icon from the nacp.
|
||||
void load_icon() override;
|
||||
|
|
@ -104,8 +101,11 @@ namespace data
|
|||
/// @brief Stores application ID for easier grabbing since JKSV is all pointers.
|
||||
uint64_t m_applicationID{};
|
||||
|
||||
/// @brief This contains the NACP and the icon.
|
||||
std::unique_ptr<NsApplicationControlData> m_data{};
|
||||
/// @brief Where all the good stuff is.
|
||||
NsApplicationControlData m_data{};
|
||||
|
||||
/// @brief Stores the pointer to the language entry of the title.
|
||||
NacpLanguageEntry *m_entry{};
|
||||
|
||||
/// @brief Saves whether or not the title has control data.
|
||||
bool m_hasData{};
|
||||
|
|
@ -117,6 +117,6 @@ namespace data
|
|||
sdl::SharedTexture m_icon{};
|
||||
|
||||
/// @brief Private function to get/create the path safe title.
|
||||
void get_create_path_safe_title();
|
||||
void get_create_path_safe_title() noexcept;
|
||||
};
|
||||
} // namespace data
|
||||
|
|
|
|||
|
|
@ -29,18 +29,21 @@ namespace data
|
|||
/// @brief Constructs a new user with accountID
|
||||
/// @param accountID AccountID of user.
|
||||
/// @param saveType Save data type account uses.
|
||||
User(AccountUid accountID, FsSaveDataType saveType);
|
||||
User(AccountUid accountID, FsSaveDataType saveType) noexcept;
|
||||
|
||||
/// @brief This is the constructor used to create the fake system users.
|
||||
/// @param accountID AccountID to associate with saveType.
|
||||
/// @param pathSafeNickname The path safe version of the save data since JKSV is in everything the Switch supports.
|
||||
/// @param iconPath Path to the icon to load for account.
|
||||
/// @param saveType Save data type of user.
|
||||
User(AccountUid accountID, std::string_view nickname, std::string_view pathSafeNickname, FsSaveDataType saveType);
|
||||
User(AccountUid accountID,
|
||||
std::string_view nickname,
|
||||
std::string_view pathSafeNickname,
|
||||
FsSaveDataType saveType) noexcept;
|
||||
|
||||
/// @brief Move constructor and operator.
|
||||
User(User &&user);
|
||||
User &operator=(User &&user);
|
||||
User(User &&user) noexcept;
|
||||
User &operator=(User &&user) noexcept;
|
||||
|
||||
// Non of this around these parts.
|
||||
User(const User &) = delete;
|
||||
|
|
@ -52,47 +55,47 @@ namespace data
|
|||
void add_data(const FsSaveDataInfo *saveInfo, const PdmPlayStatistics *playStats);
|
||||
|
||||
/// @brief Clears the user save info vector.
|
||||
void clear_data_entries();
|
||||
void clear_data_entries() noexcept;
|
||||
|
||||
/// @brief Erases data at index.
|
||||
/// @param index Index of save data info to erase.
|
||||
void erase_data(int index);
|
||||
|
||||
/// @brief Runs the sort algo on the vector.
|
||||
void sort_data();
|
||||
void sort_data() noexcept;
|
||||
|
||||
/// @brief Returns the account ID of the user
|
||||
AccountUid get_account_id() const;
|
||||
AccountUid get_account_id() const noexcept;
|
||||
|
||||
/// @brief Returns the primary save data type o
|
||||
FsSaveDataType get_account_save_type() const;
|
||||
FsSaveDataType get_account_save_type() const noexcept;
|
||||
|
||||
/// @brief Returns the user's full UTF-8 nickname.
|
||||
const char *get_nickname() const;
|
||||
const char *get_nickname() const noexcept;
|
||||
|
||||
/// @brief Returns the path safe version of the user's nickname.
|
||||
const char *get_path_safe_nickname() const;
|
||||
const char *get_path_safe_nickname() const noexcept;
|
||||
|
||||
/// @brief Returns the total data entries.
|
||||
size_t get_total_data_entries() const;
|
||||
size_t get_total_data_entries() const noexcept;
|
||||
|
||||
/// @brief Returns the application ID of the title at index.
|
||||
uint64_t get_application_id_at(int index) const;
|
||||
uint64_t get_application_id_at(int index) const noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the save data info at index.
|
||||
FsSaveDataInfo *get_save_info_at(int index);
|
||||
FsSaveDataInfo *get_save_info_at(int index) noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the play statistics at index.
|
||||
PdmPlayStatistics *get_play_stats_at(int index);
|
||||
PdmPlayStatistics *get_play_stats_at(int index) noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the save info of applicationID.
|
||||
FsSaveDataInfo *get_save_info_by_id(uint64_t applicationID);
|
||||
FsSaveDataInfo *get_save_info_by_id(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Returns a reference to the internal map for range based loops.
|
||||
data::UserSaveInfoList &get_user_save_info_list();
|
||||
data::UserSaveInfoList &get_user_save_info_list() noexcept;
|
||||
|
||||
/// @brief Returns a pointer to the play statistics of applicationID
|
||||
PdmPlayStatistics *get_play_stats_by_id(uint64_t applicationID);
|
||||
PdmPlayStatistics *get_play_stats_by_id(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Erases a UserDataEntry according to the application ID passed.
|
||||
/// @param applicationID ID of the save to erase.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace data
|
|||
/// @param accountIDA First account to compare.
|
||||
/// @param accountIDB Second account to compare.
|
||||
/// @return True if both account IDs match.
|
||||
static inline bool operator==(AccountUid accountIDA, AccountUid accountIDB)
|
||||
static inline bool operator==(AccountUid accountIDA, AccountUid accountIDB) noexcept
|
||||
{
|
||||
return (accountIDA.uid[0] == accountIDB.uid[0]) && (accountIDA.uid[1] == accountIDB.uid[1]);
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ static inline bool operator==(AccountUid accountIDA, AccountUid accountIDB)
|
|||
/// @return True if they match. False if they don't.
|
||||
/// @note I'm not 100% sure which uint64_t in the AccountUid struct comes first. I don't know if it's [0][1] or [1][0]. To do:
|
||||
/// Figure that out.
|
||||
static inline bool operator==(AccountUid accountIDA, u128 accountIDB)
|
||||
static inline bool operator==(AccountUid accountIDA, u128 accountIDB) noexcept
|
||||
{
|
||||
return accountIDA.uid[0] == (accountIDB >> 64 & 0xFFFFFFFFFFFFFFFF) &&
|
||||
accountIDA.uid[1] == (accountIDB & 0xFFFFFFFFFFFFFFFF);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace data
|
|||
/// @brief Returns a pointer to the title mapped to applicationID.
|
||||
/// @param applicationID ApplicationID of title to retrieve.
|
||||
/// @return Pointer to data. nullptr if it's not found.
|
||||
data::TitleInfo *get_title_info_by_id(uint64_t applicationID);
|
||||
data::TitleInfo *get_title_info_by_id(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Gets a vector of pointers to the title info.
|
||||
/// @param listOut List to store pointers in.
|
||||
|
|
@ -34,7 +34,7 @@ namespace data
|
|||
/// @brief Returns if the title with applicationID is already loaded to the map.
|
||||
/// @param applicationID Application ID of the title to search for.
|
||||
/// @return True if it has been. False if it hasn't.
|
||||
bool title_exists_in_map(uint64_t applicationID);
|
||||
bool title_exists_in_map(uint64_t applicationID) noexcept;
|
||||
|
||||
/// @brief Gets a vector of pointers with all titles with saveType.
|
||||
/// @param saveType Save data type to check for.
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
namespace error
|
||||
{
|
||||
/// @brief Logs and returns if a call from libnx fails.
|
||||
bool libnx(Result code, const std::source_location &location = std::source_location::current());
|
||||
bool libnx(Result code, const std::source_location &location = std::source_location::current()) noexcept;
|
||||
|
||||
/// @brief Logs and returns if an fslib function fails.
|
||||
bool fslib(bool result, const std::source_location &location = std::source_location::current());
|
||||
bool fslib(bool result, const std::source_location &location = std::source_location::current()) noexcept;
|
||||
|
||||
/// @brief Returns whether or not the pointer passed is null. Records the location in which this occurred.
|
||||
bool is_null(const void *pointer, const std::source_location &location = std::source_location::current());
|
||||
bool is_null(const void *pointer, const std::source_location &location = std::source_location::current()) noexcept;
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
class MiniUnzip
|
||||
class MiniUnzip final
|
||||
{
|
||||
public:
|
||||
MiniUnzip() = default;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
class MiniZip
|
||||
class MiniZip final
|
||||
{
|
||||
public:
|
||||
MiniZip() = default;
|
||||
|
|
@ -41,6 +41,9 @@ namespace fs
|
|||
/// @brief Stores whether or not the zipFile was opened successfully.
|
||||
bool m_isOpen{};
|
||||
|
||||
/// @brief Stores the compression level from config to avoid repeated calls.
|
||||
int m_level{};
|
||||
|
||||
/// @brief Underlying ZIP file.
|
||||
zipFile m_zip{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ namespace fs
|
|||
PathFilter(const fslib::Path &filterPath);
|
||||
|
||||
/// @brief Returns whether or not the filter has valid paths.
|
||||
bool has_paths() const;
|
||||
bool has_paths() const noexcept;
|
||||
|
||||
/// @brief Returns whether or not the path passed is filtered.
|
||||
bool is_filtered(const fslib::Path &path);
|
||||
bool is_filtered(const fslib::Path &path) const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Vector of paths to filter from deletion and backup.
|
||||
std::vector<std::string> m_paths{};
|
||||
std::vector<fslib::Path> m_paths{};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,15 +32,11 @@ namespace fs
|
|||
} __attribute__((packed));
|
||||
// clang-format on
|
||||
|
||||
// I didn't want a separate file for this.
|
||||
bool read_save_data_extra_info(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &dataOut);
|
||||
|
||||
/// @brief Didn't feel like a whole new file just for this. Fills an fs::SaveMetaData struct.
|
||||
bool fill_save_meta_data(const FsSaveDataInfo *saveInfo, SaveMetaData &meta);
|
||||
bool fill_save_meta_data(const FsSaveDataInfo *saveInfo, SaveMetaData &meta) noexcept;
|
||||
|
||||
/// @brief Processes the save meta data and applies it to the passed saveInfo pointer.
|
||||
/// @param saveInfo FsSaveDataInfo to apply the meta to.
|
||||
/// @param meta Save meta data to apply.
|
||||
bool process_save_meta_data(const FsSaveDataInfo *saveInfo, const SaveMetaData &meta);
|
||||
|
||||
bool process_save_meta_data(const FsSaveDataInfo *saveInfo, const SaveMetaData &meta) noexcept;
|
||||
} // namespace fs
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ namespace fs
|
|||
/// @param log Optional. Whether or not logging errors is wanted. True by default.
|
||||
ScopedSaveMount(std::string_view mount, const FsSaveDataInfo *saveInfo, bool log = true);
|
||||
|
||||
ScopedSaveMount(ScopedSaveMount &&scopedSaveMount);
|
||||
ScopedSaveMount &operator=(ScopedSaveMount &&scopedSaveMount);
|
||||
ScopedSaveMount(ScopedSaveMount &&scopedSaveMount) noexcept;
|
||||
ScopedSaveMount &operator=(ScopedSaveMount &&scopedSaveMount) noexcept;
|
||||
|
||||
ScopedSaveMount(const ScopedSaveMount &) = delete;
|
||||
ScopedSaveMount &operator=(const ScopedSaveMount &) = delete;
|
||||
|
|
@ -23,7 +23,7 @@ namespace fs
|
|||
~ScopedSaveMount();
|
||||
|
||||
/// @brief Returns whether or not mounting the data was successful.
|
||||
bool is_open() const;
|
||||
bool is_open() const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Saves a copy of the mount point for destruction.
|
||||
|
|
|
|||
|
|
@ -3,9 +3,16 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
/// @brief Retrieves the total size of the contents of the directory at targetPath.
|
||||
/// @param targetPath Directory to calculate.
|
||||
uint64_t get_directory_total_size(const fslib::Path &targetPath);
|
||||
/// @brief Recursively runs through the path passed and retrieves information.
|
||||
/// @param directoryPath Path of directory.
|
||||
/// @param subDirCount Int64_t to track number of subdirectories with.
|
||||
/// @param fileCount Int64_t to track the number of files.
|
||||
/// @param totalSize Int64_t to track the size of everything.
|
||||
/// @return True on success. False or crash on what I would assume is a stack overflow.
|
||||
bool get_directory_information(const fslib::Path &directoryPath,
|
||||
int64_t &subDirCount,
|
||||
int64_t &fileCount,
|
||||
int64_t &totalSize);
|
||||
|
||||
/// @brief Checks if directory is empty. Didn't feel like this needs its own source file.
|
||||
/// @param directoryPath Path to directory to check.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ namespace fs
|
|||
/// @param journalSize Size of the journal area of the save data.
|
||||
void copy_file_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task = nullptr);
|
||||
|
||||
|
|
@ -36,7 +35,6 @@ namespace fs
|
|||
/// @param journalSize Size of the journaling area of the save.
|
||||
void copy_directory_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task = nullptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "data/data.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace fs
|
||||
|
|
@ -8,23 +9,29 @@ namespace fs
|
|||
/// @param targetUser User to create save data for.
|
||||
/// @param titleInfo Title to create save data for.
|
||||
/// @return True on success. False on failure.
|
||||
bool create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo);
|
||||
bool create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo) noexcept;
|
||||
|
||||
/// @brief Deletes the save data of the FsSaveDataInfo passed.
|
||||
/// @param saveInfo Save data to delete.
|
||||
/// @return True on success. False on failure.
|
||||
bool delete_save_data(const FsSaveDataInfo *saveInfo);
|
||||
bool delete_save_data(const FsSaveDataInfo *saveInfo) noexcept;
|
||||
|
||||
/// @brief Extends the save data of the FsSaveDataInfo struct passed.
|
||||
/// @param saveInfo Pointer to the FsSaveDataInfo struct of the save to extend.
|
||||
/// @param size Size (in MB) to extend the save data to.
|
||||
/// @param journalSize Size of the journaling space.
|
||||
/// @return True on success. False on failure.
|
||||
bool extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize);
|
||||
bool extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize) noexcept;
|
||||
|
||||
/// @brief Returns whether or not the saveInfo passed is system type.
|
||||
/// @param saveInfo FsSaveDataInfo to check.
|
||||
/// @return True if it is. False if it isn't.
|
||||
/// @note The config setting overrides this.
|
||||
bool is_system_save_data(const FsSaveDataInfo *saveInfo);
|
||||
bool is_system_save_data(const FsSaveDataInfo *saveInfo) noexcept;
|
||||
|
||||
/// @brief Reads the extra info of the save container according to the FsSaveDataInfo passed.
|
||||
/// @param saveInfo Pointer to the save info to read.
|
||||
/// @param extraOut Reference to the FsSaveDataExtraData to read to.
|
||||
/// @return True on success. False on failure.
|
||||
bool read_save_extra_data(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &extraOut) noexcept;
|
||||
} // namespace fs
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
namespace fs
|
||||
{
|
||||
/// @brief Default mount point used for JKSV for saves.
|
||||
static constexpr std::string_view DEFAULT_SAVE_MOUNT = "save";
|
||||
inline constexpr std::string_view DEFAULT_SAVE_MOUNT = "save";
|
||||
|
||||
/// @brief Same as above, but as a root directory.
|
||||
static constexpr std::string_view DEFAULT_SAVE_ROOT = "save:/";
|
||||
inline constexpr std::string_view DEFAULT_SAVE_ROOT = "save:/";
|
||||
} // namespace fs
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ namespace fs
|
|||
void copy_zip_to_directory(fs::MiniUnzip &source,
|
||||
const fslib::Path &dest,
|
||||
int64_t journalSize,
|
||||
std::string_view commitDevice,
|
||||
sys::ProgressTask *Task = nullptr);
|
||||
|
||||
/// @brief Returns whether or not zip has files inside besides the save meta.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace colors
|
|||
inline constexpr sdl::Color PINK = {0xFF4444FF};
|
||||
inline constexpr sdl::Color BLUE_GREEN = {0x00FFC5FF};
|
||||
inline constexpr sdl::Color CLEAR_COLOR = {0x2D2D2DFF};
|
||||
inline constexpr sdl::Color CLEAR_PANEL = {0x0D0D0DFF};
|
||||
inline constexpr sdl::Color DIALOG_DARK = {0x505050FF};
|
||||
inline constexpr sdl::Color DIALOG_LIGHT = {0xDCDCDCFF};
|
||||
inline constexpr sdl::Color DIM_BACKGROUND = {0x00000088};
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ namespace input
|
|||
void initialize();
|
||||
|
||||
/// @brief Updates the PadState.
|
||||
void update();
|
||||
void update() noexcept;
|
||||
|
||||
/// @brief Returns if a button was pressed the current frame, but not the previous.
|
||||
/// @param button Button to check.
|
||||
bool button_pressed(HidNpadButton button);
|
||||
bool button_pressed(HidNpadButton button) noexcept;
|
||||
|
||||
/// @brief Returns if the button was pressed or held the previous and current frame.
|
||||
/// @param button Button to check.
|
||||
bool button_held(HidNpadButton button);
|
||||
bool button_held(HidNpadButton button) noexcept;
|
||||
|
||||
/// @brief Returns if the button was pressed or held the previous frame, but not the current.
|
||||
/// @param button Button to check.
|
||||
bool button_released(HidNpadButton button);
|
||||
bool button_released(HidNpadButton button) noexcept;
|
||||
} // namespace input
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ namespace logger
|
|||
/// @brief Logs a formatted string.
|
||||
/// @param format Format of string.
|
||||
/// @param arguments Va arguments.
|
||||
void log(const char *format, ...);
|
||||
void log(const char *format, ...) noexcept;
|
||||
} // namespace logger
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ namespace math
|
|||
class Util
|
||||
{
|
||||
public:
|
||||
static inline Type absolute_distance(Type a, Type b) { return a > b ? a - b : b - a; }
|
||||
static inline Type absolute_distance(Type a, Type b) noexcept { return a > b ? a - b : b - a; }
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ namespace remote
|
|||
|
||||
/// @brief Move constructor.
|
||||
/// @param form Form to copy from.
|
||||
Form(Form &&form);
|
||||
Form(Form &&form) noexcept;
|
||||
|
||||
/// @brief = Operator.
|
||||
/// @param form Form to copy.
|
||||
Form &operator=(const Form &form);
|
||||
Form &operator=(const Form &form) noexcept;
|
||||
|
||||
/// @brief = Move operator.
|
||||
/// @param form Form to rob of its life.
|
||||
|
|
@ -31,10 +31,10 @@ namespace remote
|
|||
Form &append_parameter(std::string_view param, std::string_view value);
|
||||
|
||||
/// @brief Returns the C string of the form string.
|
||||
const char *get() const;
|
||||
const char *get() const noexcept;
|
||||
|
||||
/// @brief Returns m_form.length()
|
||||
size_t length() const;
|
||||
size_t length() const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief String containing the actual data posted.
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace remote
|
|||
bool get_root_id();
|
||||
|
||||
/// @brief Returns whether or not the auth token is still valid for use or needs to be refreshed.
|
||||
bool token_is_valid() const;
|
||||
bool token_is_valid() const noexcept;
|
||||
|
||||
/// @brief Attempts to refresh the auth token if needed.
|
||||
bool refresh_token();
|
||||
|
|
@ -95,6 +95,6 @@ namespace remote
|
|||
/// @param json Json object to check.
|
||||
/// @param log Whether or not to log the error.
|
||||
/// @note This doesn't catch every error. Google's errors aren't consistent.
|
||||
bool error_occurred(json::Object &json, bool log = true);
|
||||
bool error_occurred(json::Object &json, bool log = true) noexcept;
|
||||
};
|
||||
} // namespace remote
|
||||
|
|
|
|||
|
|
@ -16,23 +16,23 @@ namespace remote
|
|||
|
||||
/// @brief Returns the name of the item.
|
||||
/// @return Name of the item.
|
||||
std::string_view get_name() const;
|
||||
std::string_view get_name() const noexcept;
|
||||
|
||||
/// @brief Returns the id of the item.
|
||||
/// @return ID of the item.
|
||||
std::string_view get_id() const;
|
||||
std::string_view get_id() const noexcept;
|
||||
|
||||
/// @brief Returns the parent id of the item.
|
||||
/// @return Parent ID of the item.
|
||||
std::string_view get_parent_id() const;
|
||||
std::string_view get_parent_id() const noexcept;
|
||||
|
||||
/// @brief Gets the size of the item.
|
||||
/// @return Size of the item in bytes.
|
||||
size_t get_size() const;
|
||||
size_t get_size() const noexcept;
|
||||
|
||||
/// @brief Returns whether or not the item is a directory.
|
||||
/// @return Whether or not the item is a directory.
|
||||
bool is_directory() const;
|
||||
bool is_directory() const noexcept;
|
||||
|
||||
/// @brief Sets the name of the item.
|
||||
/// @param name New name of the item.
|
||||
|
|
@ -48,26 +48,26 @@ namespace remote
|
|||
|
||||
/// @brief Sets the size of the item.
|
||||
/// @param size Size of the item.
|
||||
void set_size(size_t size);
|
||||
void set_size(size_t size) noexcept;
|
||||
|
||||
/// @brief Sets whether or not the item is a directory.
|
||||
/// @param directory Whether or not the item is a directory.
|
||||
void set_is_directory(bool directory);
|
||||
void set_is_directory(bool directory) noexcept;
|
||||
|
||||
private:
|
||||
/// @brief The name of the item.
|
||||
std::string m_name;
|
||||
std::string m_name{};
|
||||
|
||||
/// @brief The ID of the item.
|
||||
std::string m_id;
|
||||
std::string m_id{};
|
||||
|
||||
/// @brief Parent ID of the item.
|
||||
std::string m_parent;
|
||||
std::string m_parent{};
|
||||
|
||||
/// @brief Size of the item.
|
||||
size_t m_size;
|
||||
size_t m_size{};
|
||||
|
||||
/// @brief Whether or not the item is a directory.
|
||||
bool m_isDirectory;
|
||||
bool m_isDirectory{};
|
||||
};
|
||||
} // namespace remote
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ namespace remote
|
|||
Storage(std::string_view prefix, bool supportsUtf8 = false);
|
||||
|
||||
/// @brief Returns whether or not the Storage type was successfully. initialized.
|
||||
bool is_initialized() const;
|
||||
bool is_initialized() const noexcept;
|
||||
|
||||
// Directory functions.
|
||||
/// @brief Returns whether or not a directory with name exists within the current parent.
|
||||
/// @param name Name of the directory to search for.
|
||||
bool directory_exists(std::string_view name);
|
||||
bool directory_exists(std::string_view name) const noexcept;
|
||||
|
||||
/// @brief Returns the parent to the root directory.
|
||||
void return_to_root();
|
||||
|
|
@ -48,7 +48,7 @@ namespace remote
|
|||
/// @brief Searches the list for a directory matching name and the current parent.
|
||||
/// @param name Name of the directory to search for.
|
||||
/// @return Pointer to the item representing the directory on success. nullptr on failure/not found.
|
||||
remote::Item *get_directory_by_name(std::string_view name);
|
||||
remote::Item *get_directory_by_name(std::string_view name) noexcept;
|
||||
|
||||
/// @brief Retrieves a listing of the items in the current parent directory.
|
||||
/// @param listOut List to fill.
|
||||
|
|
@ -62,7 +62,7 @@ namespace remote
|
|||
// File functions.
|
||||
/// @brief Returns whether a file with name exists within the current directory.
|
||||
/// @param name Name of the file.
|
||||
bool file_exists(std::string_view name);
|
||||
bool file_exists(std::string_view name) const noexcept;
|
||||
|
||||
/// @brief Uploads a file from the SD card to the remote.
|
||||
/// @param source Path to the file to upload.
|
||||
|
|
@ -83,7 +83,7 @@ namespace remote
|
|||
/// @brief Searches the list for a file matching name and the current parent.
|
||||
/// @param name Name of the file to search for.
|
||||
/// @return Pointer to the item if located. nullptr if not.
|
||||
remote::Item *get_file_by_name(std::string_view name);
|
||||
remote::Item *get_file_by_name(std::string_view name) noexcept;
|
||||
|
||||
// General functions that apply to both.
|
||||
/// @brief Deletes a file or folder from the remote.
|
||||
|
|
@ -96,10 +96,10 @@ namespace remote
|
|||
virtual bool rename_item(remote::Item *item, std::string_view newName) = 0;
|
||||
|
||||
/// @brief Returns whether or not the remote storage type supports UTF-8 for names or requires path safe titles.
|
||||
bool supports_utf8() const;
|
||||
bool supports_utf8() const noexcept;
|
||||
|
||||
/// @brief Returns the prefix for menus.
|
||||
std::string_view get_prefix() const;
|
||||
std::string_view get_prefix() const noexcept;
|
||||
|
||||
protected:
|
||||
/// @brief This is the size of the buffers used for snprintf'ing URLs together.
|
||||
|
|
@ -131,27 +131,34 @@ namespace remote
|
|||
|
||||
/// @brief Searches the list for a directory matching name and the current parent.
|
||||
/// @param name Name to search for.
|
||||
Storage::List::iterator find_directory_by_name(std::string_view name);
|
||||
Storage::List::iterator find_directory_by_name(std::string_view name) noexcept;
|
||||
Storage::List::const_iterator find_directory_by_name(std::string_view name) const noexcept;
|
||||
|
||||
/// @brief Searches the list for a directory matching ID.
|
||||
/// @param id ID of the directory to search for.
|
||||
Storage::List::iterator find_directory_by_id(std::string_view id);
|
||||
Storage::List::iterator find_directory_by_id(std::string_view id) noexcept;
|
||||
Storage::List::const_iterator find_directory_by_id(std::string_view id) const noexcept;
|
||||
|
||||
/// @brief Searches to find if a file with name exists within the current parent.
|
||||
/// @param name Name of the file to search for.
|
||||
Storage::List::iterator find_file_by_name(std::string_view name);
|
||||
Storage::List::iterator find_file_by_name(std::string_view name) noexcept;
|
||||
Storage::List::const_iterator find_file_by_name(std::string_view name) const noexcept;
|
||||
|
||||
/// @brief Searches the list for a file matching ID.
|
||||
/// @param id ID to search for.s
|
||||
Storage::List::iterator find_file_by_id(std::string_view id);
|
||||
Storage::List::iterator find_file_by_id(std::string_view id) noexcept;
|
||||
Storage::List::const_iterator find_file_by_id(std::string_view id) const noexcept;
|
||||
|
||||
/// @brief Locates any item (directory/file) by the id passed.
|
||||
/// @param id ID to search for.
|
||||
Storage::List::iterator find_item_by_id(std::string_view id);
|
||||
Storage::List::iterator find_item_by_id(std::string_view id) noexcept;
|
||||
Storage::List::const_iterator find_item_by_id(std::string_view id) const noexcept;
|
||||
|
||||
/// @brief Searches starting with the iterator start for items that belong to parentID
|
||||
/// @param start Beginning iterator for search.
|
||||
/// @param parentID ParentID to match.
|
||||
Storage::List::iterator find_by_parent_id(Storage::List::iterator start, std::string_view parentID);
|
||||
Storage::List::iterator find_by_parent_id(Storage::List::iterator start, std::string_view parentID) noexcept;
|
||||
Storage::List::const_iterator find_by_parent_id(Storage::List::const_iterator start,
|
||||
std::string_view parentID) const noexcept;
|
||||
};
|
||||
} // namespace remote
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace remote
|
|||
|
||||
/// @brief Move constructor.
|
||||
/// @param url URL to move.
|
||||
URL(URL &&url);
|
||||
URL(URL &&url) noexcept;
|
||||
|
||||
/// @brief Makes a copy of the URL passed.
|
||||
/// @param url remote::URL instance to make a copy of.
|
||||
|
|
@ -29,7 +29,7 @@ namespace remote
|
|||
|
||||
/// @brief Move operator.
|
||||
/// @param url URL to move.
|
||||
URL &operator=(URL &&url);
|
||||
URL &operator=(URL &&url) noexcept;
|
||||
|
||||
/// @brief Sets the base URL. Basically resets the string back to square 0.
|
||||
/// @param base Base URL to start with.
|
||||
|
|
@ -48,7 +48,7 @@ namespace remote
|
|||
URL &append_slash();
|
||||
|
||||
/// @brief Returns the C string of the url string.
|
||||
const char *get() const;
|
||||
const char *get() const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief This is where the actual URL is held.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace remote
|
|||
static constexpr std::string_view PATH_WEBDAV_CONFIG = "sdmc:/config/JKSV/webdav.json";
|
||||
|
||||
/// @brief Returns whether or not the console has an active internet connection.
|
||||
bool has_internet_connection();
|
||||
bool has_internet_connection() noexcept;
|
||||
|
||||
/// @brief Initializes the Storage instance to Google Drive.
|
||||
void initialize_google_drive();
|
||||
|
|
@ -19,5 +19,5 @@ namespace remote
|
|||
void initialize_webdav();
|
||||
|
||||
/// @brief Returns the pointer to the Storage instance.
|
||||
remote::Storage *get_remote_storage();
|
||||
remote::Storage *get_remote_storage() noexcept;
|
||||
} // namespace remote
|
||||
|
|
|
|||
|
|
@ -1,44 +1,46 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
namespace strings
|
||||
namespace strings::names
|
||||
{
|
||||
namespace names
|
||||
{
|
||||
inline constexpr std::string_view BACKUPMENU_MENU = "BackupMenu";
|
||||
inline constexpr std::string_view BACKUPMENU_CONFS = "BackupMenuConfirmations";
|
||||
inline constexpr std::string_view BACKUPMENU_POPS = "BackupMenuPops";
|
||||
inline constexpr std::string_view BACKUPMENU_STATUS = "BackupMenuStatus";
|
||||
inline constexpr std::string_view CONTROL_GUIDES = "ControlGuides";
|
||||
inline constexpr std::string_view DATA_LOADING_STATUS = "DataLoadingStatus";
|
||||
inline constexpr std::string_view EXTRASMENU_MENU = "ExtrasMenu";
|
||||
inline constexpr std::string_view EXTRASMENU_POPS = "ExtrasPops";
|
||||
inline constexpr std::string_view GENERAL_POPS = "GeneralPops";
|
||||
inline constexpr std::string_view GOOGLE_DRIVE = "GoogleDriveStrings";
|
||||
inline constexpr std::string_view HOLDING_STRINGS = "HoldingStrings";
|
||||
inline constexpr std::string_view IO_STATUSES = "IOStatuses";
|
||||
inline constexpr std::string_view IO_POPS = "IOPops";
|
||||
inline constexpr std::string_view KEYBOARD = "KeyboardStrings";
|
||||
inline constexpr std::string_view MAINMENU_CONFS = "MainMenuConfs";
|
||||
inline constexpr std::string_view MAINMENU_POPS = "MainMenuPops";
|
||||
inline constexpr std::string_view ON_OFF = "OnOff";
|
||||
inline constexpr std::string_view REMOTE_POPS = "RemotePops";
|
||||
inline constexpr std::string_view SAVECREATE_POPS = "SaveCreatePops";
|
||||
inline constexpr std::string_view SAVE_DATA_TYPES = "SaveDataTypes";
|
||||
inline constexpr std::string_view SETTINGS_DESCRIPTIONS = "SettingsDescriptions";
|
||||
inline constexpr std::string_view SETTINGS_MENU = "SettingsMenu";
|
||||
inline constexpr std::string_view SETTINGS_POPS = "SettingsPops";
|
||||
inline constexpr std::string_view SORT_TYPES = "SortTypes";
|
||||
inline constexpr std::string_view TITLEINFO = "TitleInfo";
|
||||
inline constexpr std::string_view TITLEOPTION_CONFS = "TitleOptionConfirmations";
|
||||
inline constexpr std::string_view TITLEOPTION_POPS = "TitleOptionPops";
|
||||
inline constexpr std::string_view TITLEOPTION_STATUS = "TitleOptionStatus";
|
||||
inline constexpr std::string_view TITLEOPTION = "TitleOptions";
|
||||
inline constexpr std::string_view TRANSLATION = "TranslationInfo";
|
||||
inline constexpr std::string_view USEROPTION_CONFS = "UserOptionConfirmations";
|
||||
inline constexpr std::string_view USEROPTION_STATUS = "UserOptionStatus";
|
||||
inline constexpr std::string_view USEROPTION_MENU = "UserOptions";
|
||||
inline constexpr std::string_view WEBDAV = "WebDavStrings";
|
||||
inline constexpr std::string_view YES_NO_OK = "YesNoOK";
|
||||
}
|
||||
inline constexpr std::string_view BACKUPMENU_MENU = "BackupMenu";
|
||||
inline constexpr std::string_view BACKUPMENU_CONFS = "BackupMenuConfirmations";
|
||||
inline constexpr std::string_view BACKUPMENU_POPS = "BackupMenuPops";
|
||||
inline constexpr std::string_view BACKUPMENU_STATUS = "BackupMenuStatus";
|
||||
inline constexpr std::string_view CONTROL_GUIDES = "ControlGuides";
|
||||
inline constexpr std::string_view DATA_LOADING_STATUS = "DataLoadingStatus";
|
||||
inline constexpr std::string_view EXTRASMENU_MENU = "ExtrasMenu";
|
||||
inline constexpr std::string_view EXTRASMENU_POPS = "ExtrasPops";
|
||||
inline constexpr std::string_view FILEOPTION_MENU = "FileOptionMenu";
|
||||
inline constexpr std::string_view FILEOPTION_CONFS = "FileOptionConfs";
|
||||
inline constexpr std::string_view FILEOPTION_MESSAGES = "FileOptionMessages";
|
||||
inline constexpr std::string_view FILEOPTION_STATUS = "FileOptionStatus";
|
||||
inline constexpr std::string_view FILEMODE_POPS = "FileModePops";
|
||||
inline constexpr std::string_view GENERAL_POPS = "GeneralPops";
|
||||
inline constexpr std::string_view GOOGLE_DRIVE = "GoogleDriveStrings";
|
||||
inline constexpr std::string_view HOLDING_STRINGS = "HoldingStrings";
|
||||
inline constexpr std::string_view IO_STATUSES = "IOStatuses";
|
||||
inline constexpr std::string_view IO_POPS = "IOPops";
|
||||
inline constexpr std::string_view KEYBOARD = "KeyboardStrings";
|
||||
inline constexpr std::string_view MAINMENU_CONFS = "MainMenuConfs";
|
||||
inline constexpr std::string_view MAINMENU_POPS = "MainMenuPops";
|
||||
inline constexpr std::string_view ON_OFF = "OnOff";
|
||||
inline constexpr std::string_view REMOTE_POPS = "RemotePops";
|
||||
inline constexpr std::string_view SAVECREATE_POPS = "SaveCreatePops";
|
||||
inline constexpr std::string_view SAVE_DATA_TYPES = "SaveDataTypes";
|
||||
inline constexpr std::string_view SETTINGS_DESCRIPTIONS = "SettingsDescriptions";
|
||||
inline constexpr std::string_view SETTINGS_MENU = "SettingsMenu";
|
||||
inline constexpr std::string_view SETTINGS_POPS = "SettingsPops";
|
||||
inline constexpr std::string_view SORT_TYPES = "SortTypes";
|
||||
inline constexpr std::string_view TITLEINFO = "TitleInfo";
|
||||
inline constexpr std::string_view TITLEOPTION_CONFS = "TitleOptionConfirmations";
|
||||
inline constexpr std::string_view TITLEOPTION_POPS = "TitleOptionPops";
|
||||
inline constexpr std::string_view TITLEOPTION_STATUS = "TitleOptionStatus";
|
||||
inline constexpr std::string_view TITLEOPTION = "TitleOptions";
|
||||
inline constexpr std::string_view TRANSLATION = "TranslationInfo";
|
||||
inline constexpr std::string_view USEROPTION_CONFS = "UserOptionConfirmations";
|
||||
inline constexpr std::string_view USEROPTION_STATUS = "UserOptionStatus";
|
||||
inline constexpr std::string_view USEROPTION_MENU = "UserOptions";
|
||||
inline constexpr std::string_view WEBDAV = "WebDavStrings";
|
||||
inline constexpr std::string_view YES_NO_OK = "YesNoOK";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ namespace strings
|
|||
bool initialize();
|
||||
|
||||
// Returns string with name and index. Returns nullptr if string doesn't exist.
|
||||
const char *get_by_name(std::string_view name, int index);
|
||||
const char *get_by_name(std::string_view name, int index) noexcept;
|
||||
} // namespace strings
|
||||
|
|
|
|||
|
|
@ -24,22 +24,22 @@ namespace sys
|
|||
|
||||
/// @brief Resets the progress and sets a new goal.
|
||||
/// @param goal The goal we all strive for.
|
||||
void reset(double goal);
|
||||
void reset(double goal) noexcept;
|
||||
|
||||
/// @brief Updates the current progress.
|
||||
/// @param current The current progress value.
|
||||
void update_current(double current);
|
||||
void update_current(double current) noexcept;
|
||||
|
||||
/// @brief Increases the current progress by a set amount.
|
||||
void increase_current(double amount);
|
||||
void increase_current(double amount) noexcept;
|
||||
|
||||
/// @brief Returns the goal value.
|
||||
/// @return Goal
|
||||
double get_goal() const;
|
||||
double get_goal() const noexcept;
|
||||
|
||||
/// @brief Returns the current progress.
|
||||
/// @return Current progress.
|
||||
double get_progress() const;
|
||||
double get_progress() const noexcept;
|
||||
|
||||
private:
|
||||
// Current value and goal
|
||||
|
|
|
|||
|
|
@ -31,18 +31,18 @@ namespace sys
|
|||
|
||||
/// @brief Returns if the thread has signaled it's finished running.
|
||||
/// @return True if the thread is still running. False if it isn't.
|
||||
bool is_running() const;
|
||||
bool is_running() const noexcept;
|
||||
|
||||
/// @brief Allows thread to signal it's finished.
|
||||
/// @note Spawned task threads must call this when their work is finished.
|
||||
void complete();
|
||||
void complete() noexcept;
|
||||
|
||||
/// @brief Sets the task/threads current status string. Thread safe.
|
||||
void set_status(std::string_view status);
|
||||
|
||||
/// @brief Returns the status string. Thread safe.
|
||||
/// @return Copy of the status string.
|
||||
std::string get_status();
|
||||
std::string get_status() noexcept;
|
||||
|
||||
protected:
|
||||
// Whether task is still running.
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ namespace sys
|
|||
|
||||
/// @brief Constructs a new timer.
|
||||
/// @param triggerTicks Number of ticks the timer is triggered at.
|
||||
Timer(uint64_t triggerTicks);
|
||||
Timer(uint64_t triggerTicks) noexcept;
|
||||
|
||||
/// @brief Starts the timer.
|
||||
/// @param triggerTicks Number of ticks to trigger at.
|
||||
void start(uint64_t triggerTicks);
|
||||
void start(uint64_t triggerTicks) noexcept;
|
||||
|
||||
/// @brief Updates and returns if the timer was triggered.
|
||||
/// @return True if timer is triggered. False if it isn't.
|
||||
bool is_triggered();
|
||||
bool is_triggered() noexcept;
|
||||
|
||||
/// @brief Forces the timer to restart.
|
||||
void restart();
|
||||
void restart() noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Tick count when the timer starts.
|
||||
|
|
|
|||
|
|
@ -4,40 +4,37 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::backup
|
||||
{
|
||||
namespace backup
|
||||
{
|
||||
/// @brief Task/thread function executed when a new backup is created.
|
||||
void create_new_backup_local(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
fslib::Path target,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
void create_new_backup_remote(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
std::string remoteName,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
/// @brief Task/thread function executed when a new backup is created.
|
||||
void create_new_backup_local(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
fslib::Path target,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
void create_new_backup_remote(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
std::string remoteName,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
|
||||
/// @brief Overwrites a pre-existing backup.
|
||||
void overwrite_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void overwrite_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Overwrites a pre-existing backup.
|
||||
void overwrite_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void overwrite_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Restores a backup
|
||||
void restore_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void restore_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Restores a backup
|
||||
void restore_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void restore_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes a backup
|
||||
void delete_backup_local(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
void delete_backup_remote(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Deletes a backup
|
||||
void delete_backup_local(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
void delete_backup_remote(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Uploads a backup
|
||||
void upload_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Uploads a backup
|
||||
void upload_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Patches a pre-existing backup on the remote storage.
|
||||
void patch_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
}
|
||||
/// @brief Patches a pre-existing backup on the remote storage.
|
||||
void patch_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
12
include/tasks/fileoptions.hpp
Normal file
12
include/tasks/fileoptions.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include "appstates/FileOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks::fileoptions
|
||||
{
|
||||
/// @brief Copies the source to destination passed through taskData.
|
||||
void copy_source_to_destination(sys::ProgressTask *task, FileOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes the source path passed through taskData
|
||||
void delete_target(sys::Task *task, FileOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
@ -2,11 +2,8 @@
|
|||
#include "appstates/MainMenuState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::mainmenu
|
||||
{
|
||||
namespace mainmenu
|
||||
{
|
||||
void backup_all_for_all_local(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
void backup_all_for_all_remote(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
}
|
||||
void backup_all_for_all_local(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
void backup_all_for_all_remote(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@
|
|||
#include "data/data.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::savecreate
|
||||
{
|
||||
namespace savecreate
|
||||
{
|
||||
void create_save_data_for(sys::Task *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
SaveCreateState *spawningState);
|
||||
}
|
||||
void create_save_data_for(sys::Task *task, data::User *user, data::TitleInfo *titleInfo, SaveCreateState *spawningState);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,26 +3,23 @@
|
|||
#include "appstates/TitleOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::titleoptions
|
||||
{
|
||||
namespace titleoptions
|
||||
{
|
||||
/// @brief Adds a title to the blacklist. Needs to be task formatted to work with confirmations.
|
||||
void blacklist_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Adds a title to the blacklist. Needs to be task formatted to work with confirmations.
|
||||
void blacklist_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Wipes deletes all local backups for the current title.
|
||||
void delete_all_local_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Wipes deletes all local backups for the current title.
|
||||
void delete_all_local_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes all backups found on the remote storage service.
|
||||
void delete_all_remote_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Deletes all backups found on the remote storage service.
|
||||
void delete_all_remote_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Resets save data for the current title.
|
||||
void reset_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Resets save data for the current title.
|
||||
void reset_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes the save data from the system the same way Data Management does.
|
||||
void delete_save_data_from_system(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Deletes the save data from the system the same way Data Management does.
|
||||
void delete_save_data_from_system(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Extends the save container for the current save info.
|
||||
void extend_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
}
|
||||
/// @brief Extends the save container for the current save info.
|
||||
void extend_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,10 @@
|
|||
#include "appstates/UserOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::useroptions
|
||||
{
|
||||
namespace useroptions
|
||||
{
|
||||
void backup_all_for_user_local(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void backup_all_for_user_remote(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void create_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
void delete_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
}
|
||||
void backup_all_for_user_local(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void backup_all_for_user_remote(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void create_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
void delete_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ namespace ui
|
|||
/// @param height Height of the box in pixels.
|
||||
BoundingBox(int x, int y, int width, int height);
|
||||
|
||||
/// @brief Required destructor.
|
||||
~BoundingBox() {};
|
||||
|
||||
/// @brief Creates a returns a new BoundingBox. See constructor.
|
||||
static inline std::shared_ptr<ui::BoundingBox> create(int x, int y, int width, int height)
|
||||
{
|
||||
|
|
@ -32,18 +29,17 @@ namespace ui
|
|||
/// @brief Render override.
|
||||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Sets the X and Y coord.
|
||||
/// @param x New X coord.
|
||||
/// @param y New Y coord.
|
||||
void set_xy(int x, int y);
|
||||
/// @brief Sets the X coord.
|
||||
void set_x(int x) noexcept;
|
||||
|
||||
/// @brief Sets the width and height of the bounding box.
|
||||
/// @param width New width.
|
||||
/// @param height New height.
|
||||
void set_width_height(int width, int height);
|
||||
/// @brief Sets the Y coord.
|
||||
void set_y(int y) noexcept;
|
||||
|
||||
/// @brief Passing this to the set functions will keep the same coord.
|
||||
static inline constexpr int NO_SET = -1;
|
||||
/// @brief Sets the width.
|
||||
void set_width(int width) noexcept;
|
||||
|
||||
/// @brief Sets the height.
|
||||
void set_height(int height) noexcept;
|
||||
|
||||
private:
|
||||
/// @brief X coord to render to.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "sdl.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui
|
||||
|
|
@ -12,11 +13,11 @@ namespace ui
|
|||
ColorMod() = default;
|
||||
|
||||
/// @brief Updates the color modification variable.
|
||||
void update();
|
||||
void update() noexcept;
|
||||
|
||||
/// @brief Operator that allows using this as an sdl::Color directly.
|
||||
/// @note Since all of these pulse the same color, no sense in not doing this.
|
||||
operator sdl::Color() const;
|
||||
operator sdl::Color() const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Whether we're adding or subtracting from the color value.
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@ namespace ui
|
|||
/// @param type Optional. The type of box. Default is dark since JKSV rewrite doesn't do theme detection.
|
||||
DialogBox(int x, int y, int width, int height, DialogBox::Type type = DialogBox::Type::Dark);
|
||||
|
||||
/// @brief Required destructor.
|
||||
~DialogBox() {};
|
||||
|
||||
/// @brief Creates and returns a new DialogBox instance. See constructor.
|
||||
static inline std::shared_ptr<ui::DialogBox> create(int x,
|
||||
int y,
|
||||
|
|
@ -43,14 +40,17 @@ namespace ui
|
|||
/// @param hasFocus This is ignored.
|
||||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Sets the X and coords for the dialog box.
|
||||
void set_xy(int x, int y);
|
||||
/// @brief Sets the X render coord.
|
||||
void set_x(int x) noexcept;
|
||||
|
||||
/// @brief Sets the width and height of the dialog.
|
||||
void set_width_height(int width, int height);
|
||||
/// @brief Sets the X render coord.
|
||||
void set_y(int y) noexcept;
|
||||
|
||||
/// @brief Pass with the set functions to not change.
|
||||
static inline constexpr int NO_SET = -1;
|
||||
/// @brief Sets the width.
|
||||
void set_width(int width) noexcept;
|
||||
|
||||
/// @brief Sets the height.
|
||||
void set_height(int height) noexcept;
|
||||
|
||||
private:
|
||||
/// @brief X render coord.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace ui
|
|||
Element() = default;
|
||||
|
||||
/// @brief Virtual destructor.
|
||||
virtual ~Element() {};
|
||||
virtual ~Element() noexcept {};
|
||||
|
||||
/// @brief Virtual update method. All derived classes must have this.
|
||||
/// @param HasFocus Whether or not the state containing the element currently has focus.
|
||||
|
|
|
|||
58
include/ui/Frame.hpp
Normal file
58
include/ui/Frame.hpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
#include "sdl.hpp"
|
||||
#include "ui/Element.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class Frame final : public ui::Element
|
||||
{
|
||||
public:
|
||||
/// @brief Constructs a new frame.
|
||||
Frame(int x, int y, int width, int height);
|
||||
|
||||
/// @brief Inline function to make constructing nicer.
|
||||
static inline std::shared_ptr<ui::Frame> create(int x, int y, int width, int height)
|
||||
{
|
||||
return std::make_shared<ui::Frame>(x, y, width, height);
|
||||
}
|
||||
|
||||
/// @brief Doesn't need to do anything for this.
|
||||
void update(bool hasFocus) override {};
|
||||
|
||||
/// @brief Renders the frame to the target passed.
|
||||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Sets the X coord.
|
||||
void set_x(int x) noexcept;
|
||||
|
||||
/// @brief Sets the Y coord.
|
||||
void set_y(int y) noexcept;
|
||||
|
||||
/// @brief Sets the width of the frame.
|
||||
void set_width(int width) noexcept;
|
||||
|
||||
/// @brief Sets the height of the frame.
|
||||
void set_height(int height) noexcept;
|
||||
|
||||
private:
|
||||
/// @brief X rendering coord.
|
||||
int m_x{};
|
||||
|
||||
/// @brief Y rendering coord.
|
||||
int m_y{};
|
||||
|
||||
/// @brief Rendering width.
|
||||
int m_width{};
|
||||
|
||||
/// @brief Rendering height.
|
||||
int m_height{};
|
||||
|
||||
/// @brief This texture is shared by all instances.
|
||||
static inline sdl::SharedTexture sm_frameCorners{};
|
||||
|
||||
/// @brief Ensures the texture is loading if it hasn't been.
|
||||
void initialize_static_members();
|
||||
};
|
||||
}
|
||||
|
|
@ -18,9 +18,6 @@ namespace ui
|
|||
/// @param renderTargetHeight Height of the render target to calculate how many options can be displayed at once.
|
||||
IconMenu(int x, int y, int renderTargetHeight);
|
||||
|
||||
/// @brief Required destructor.
|
||||
~IconMenu() {};
|
||||
|
||||
/// @brief Creates and returns a new IconMenu instance.
|
||||
static inline std::shared_ptr<ui::IconMenu> create(int x, int y, int renderTargetHeight)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,15 +51,24 @@ namespace ui
|
|||
|
||||
/// @brief Returns the index of the currently selected menu option.
|
||||
/// @return Index of currently selected option.
|
||||
int get_selected() const;
|
||||
int get_selected() const noexcept;
|
||||
|
||||
/// @brief Sets the selected item.
|
||||
/// @param selected Value to set selected to.
|
||||
void set_selected(int selected);
|
||||
|
||||
/// @brief Updates the X render coordinate.
|
||||
void set_x(int x) noexcept;
|
||||
|
||||
/// @brief Updates the Y render coordinate.
|
||||
void set_y(int y) noexcept;
|
||||
|
||||
/// @brief This is a workaround function until I find something better.
|
||||
/// @param width New width of the menu in pixels.
|
||||
void set_width(int width);
|
||||
void set_width(int width) noexcept;
|
||||
|
||||
/// @brief Returns if the menu has no options.
|
||||
bool is_empty() const noexcept;
|
||||
|
||||
/// @brief Resets the menu and returns it to an empty, default state.
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ namespace ui
|
|||
void render();
|
||||
|
||||
/// @brief Returns whether or not the message can be purged.
|
||||
bool finished() const;
|
||||
bool finished() const noexcept;
|
||||
|
||||
/// @brief Returns the text of the message.
|
||||
std::string_view get_message() const;
|
||||
std::string_view get_message() const noexcept;
|
||||
|
||||
private:
|
||||
// Every message begins off screen.
|
||||
|
|
@ -65,9 +65,9 @@ namespace ui
|
|||
std::shared_ptr<ui::DialogBox> m_dialog{};
|
||||
|
||||
/// @brief Updates the Y Coord to match the target passed.
|
||||
void update_y(double targetY);
|
||||
void update_y(double targetY) noexcept;
|
||||
|
||||
/// @brief Updates the current end offset of the text.
|
||||
void update_text_offset();
|
||||
void update_text_offset() noexcept;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ namespace ui
|
|||
/// @param hasFocus Whether or not the calling state has focus.
|
||||
void update(bool hasFocus) override;
|
||||
|
||||
/// @brief Sub update routine. Allows the panel to hide and unhide itself even when not in focus.
|
||||
void sub_update();
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
/// @param target Target to render to.
|
||||
/// @param hasFocus Whether or the the calling state has focus.
|
||||
|
|
@ -44,18 +47,27 @@ namespace ui
|
|||
void clear_target();
|
||||
|
||||
/// @brief Resets the panel back to its default state.
|
||||
void reset();
|
||||
void reset() noexcept;
|
||||
|
||||
/// @brief Closes the panel.
|
||||
void close();
|
||||
void close() noexcept;
|
||||
|
||||
/// @brief Hides the panel temporarily.
|
||||
void hide() noexcept;
|
||||
|
||||
/// @brief Unhides the panel.
|
||||
void unhide() noexcept;
|
||||
|
||||
/// @brief Returns if the panel is fully open.
|
||||
/// @return If the panel is fully open.
|
||||
bool is_open() const;
|
||||
bool is_open() const noexcept;
|
||||
|
||||
/// @brief Returns if the panel is fully closed.
|
||||
/// @return If the panel is fully closed.
|
||||
bool is_closed();
|
||||
bool is_closed() noexcept;
|
||||
|
||||
/// @brief Returns whether or not the panel is hidden.
|
||||
bool is_hidden() const noexcept;
|
||||
|
||||
/// @brief Pushes a new element to the element vector.
|
||||
/// @param newElement New element to push.
|
||||
|
|
@ -66,7 +78,7 @@ namespace ui
|
|||
|
||||
/// @brief Returns a pointer to the render target of the panel.
|
||||
/// @return Raw SDL_Texture pointer to target.
|
||||
sdl::SharedTexture &get_target();
|
||||
sdl::SharedTexture &get_target() noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Bool for whether panel is fully open or not.
|
||||
|
|
@ -75,6 +87,9 @@ namespace ui
|
|||
/// @brief Whether or not to close panel.
|
||||
bool m_closePanel{};
|
||||
|
||||
/// @brief Whether or not to hide the panel.
|
||||
bool m_hidePanel{};
|
||||
|
||||
/// @brief Current X coordinate to render to. Panels are always 720 pixels in height so no Y is required.
|
||||
double m_x{};
|
||||
|
||||
|
|
@ -93,10 +108,16 @@ namespace ui
|
|||
/// @brief Vector of elements.
|
||||
std::vector<std::shared_ptr<ui::Element>> m_elements{};
|
||||
|
||||
void slide_out_left();
|
||||
/// @brief Handles sliding out logic.
|
||||
void slide_out() noexcept;
|
||||
|
||||
void slide_out_right();
|
||||
/// @brief Slides the panel out from the left side.
|
||||
void slide_out_left() noexcept;
|
||||
|
||||
int get_absolute_x_distance();
|
||||
/// @brief Slides the panel out from the right side.
|
||||
void slide_out_right() noexcept;
|
||||
|
||||
/// @brief Contains the logic for hiding/closing the panel.
|
||||
void close_hide_panel() noexcept;
|
||||
};
|
||||
} // namespace ui
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ namespace ui
|
|||
sdl::Color clearColor,
|
||||
bool center = true);
|
||||
|
||||
/// @brief Required destructor.
|
||||
~TextScroll() {};
|
||||
|
||||
/// @brief Creates and returns a new TextScroll. See constructor.
|
||||
static inline std::shared_ptr<ui::TextScroll> create(std::string_view text,
|
||||
int x,
|
||||
|
|
@ -76,14 +73,11 @@ namespace ui
|
|||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Returns the current text being used for scrolling.
|
||||
std::string_view get_text() const;
|
||||
std::string_view get_text() const noexcept;
|
||||
|
||||
/// @brief Sets and allows changing the text scrolled.
|
||||
void set_text(std::string_view text, bool center);
|
||||
|
||||
/// @brief Allows setting of the X and Y render coordinates.
|
||||
void set_xy(int x, int y);
|
||||
|
||||
private:
|
||||
/// @brief Text to display.
|
||||
std::string m_text{};
|
||||
|
|
|
|||
|
|
@ -23,22 +23,22 @@ namespace ui
|
|||
void render(sdl::SharedTexture &target, int x, int y);
|
||||
|
||||
/// @brief Resets the width and height of the tile.
|
||||
void reset();
|
||||
void reset() noexcept;
|
||||
|
||||
/// @brief Returns the render width in pixels.
|
||||
/// @return Render width.
|
||||
int get_width() const;
|
||||
int get_width() const noexcept;
|
||||
|
||||
/// @brief Returns the render height in pixels.
|
||||
/// @return Render height.
|
||||
int get_height() const;
|
||||
int get_height() const noexcept;
|
||||
|
||||
private:
|
||||
/// @brief Width in pixels to render icon at.
|
||||
int m_renderWidth = 128;
|
||||
int m_renderWidth{128};
|
||||
|
||||
/// @brief Height in pixels to render icon at.
|
||||
int m_renderHeight = 128;
|
||||
int m_renderHeight{128};
|
||||
|
||||
/// @brief Whether or not the title is a favorite.
|
||||
bool m_isFavorite{};
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ namespace ui
|
|||
/// @param user User to use.
|
||||
TitleView(data::User *user);
|
||||
|
||||
/// @brief Required destructor.
|
||||
~TitleView() {};
|
||||
|
||||
static inline std::shared_ptr<ui::TitleView> create(data::User *user)
|
||||
{
|
||||
return std::make_shared<ui::TitleView>(user);
|
||||
|
|
@ -37,10 +34,10 @@ namespace ui
|
|||
|
||||
/// @brief Returns index of the currently selected tile.
|
||||
/// @return Index of currently selected tile.
|
||||
int get_selected() const;
|
||||
int get_selected() const noexcept;
|
||||
|
||||
/// @brief Sets the currently selected item.
|
||||
void set_selected(int selected);
|
||||
void set_selected(int selected) noexcept;
|
||||
|
||||
/// @brief Forces a refresh of the view.
|
||||
void refresh();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "ui/ColorMod.hpp"
|
||||
#include "ui/DialogBox.hpp"
|
||||
#include "ui/Element.hpp"
|
||||
#include "ui/Frame.hpp"
|
||||
#include "ui/IconMenu.hpp"
|
||||
#include "ui/Menu.hpp"
|
||||
#include "ui/PopMessageManager.hpp"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
"0: [A] Select [Y] Dump All Saves [X] User Options",
|
||||
"1: [A] Select [L] [R] Jump [Y] Favorite [X] Title Options [B] Back",
|
||||
"2: [A] Select [Y] Restore [X] Delete [ZR] Upload [B] Close",
|
||||
"3: [A] Toggle [-] Description [X] Defaults [B] Back"
|
||||
"3: [A] Toggle [-] Description [X] Defaults [B] Back",
|
||||
"4: [A] Enter [B] Back/Up [X] Options [ZL]/[ZR] Change Target [-] Close"
|
||||
],
|
||||
"DataLoadingStatus": [
|
||||
"0: Loading user accounts from system...",
|
||||
|
|
@ -58,6 +59,35 @@
|
|||
"0: Data reinitialized!",
|
||||
"1: Data reinitialization failed!"
|
||||
],
|
||||
"FileOptionMenu": [
|
||||
"0: Copy",
|
||||
"1: Delete",
|
||||
"2: Rename",
|
||||
"3: Create Folder",
|
||||
"4: Properties",
|
||||
"5: Close"
|
||||
],
|
||||
"FileOptionConfs": [
|
||||
"0: Are you sure you want to copy #%s# to #%s#?",
|
||||
"1: Are you sure you want to delete #%s#?"
|
||||
],
|
||||
"FileOptionMessages": [
|
||||
"0: #%s#:\n\t\tSub Directories: %lli\n\t\tFile count: %lli\n\t\tTotal Size: %s",
|
||||
"1: #%s#:\n\t\tSize: %s\n\t\tFirst created: %s\n\t\tLast modified: %s\n\t\tLast Accessed: %s"
|
||||
],
|
||||
"FileOptionStatus": [
|
||||
"0: Reading #%s#'s data..."
|
||||
],
|
||||
"FileModePops": [
|
||||
"0: Copied #%s#!",
|
||||
"1: Failed to copy #%s#!",
|
||||
"2: Deleted #%s#!",
|
||||
"3: Failed to delete #%s#!",
|
||||
"4: Renamed #%s# to #%s#!",
|
||||
"5: Failed to rename #%s#!",
|
||||
"6: Created #%s#!",
|
||||
"7: Failed to create #%s#!"
|
||||
],
|
||||
"GeneralPops": [
|
||||
"0: Unable to exit JKSV while tasks are running!"
|
||||
],
|
||||
|
|
@ -92,7 +122,8 @@
|
|||
"5: Enter a new name for the target item.",
|
||||
"6: Enter a name for the new folder.",
|
||||
"7: Enter a new output folder name for %s.",
|
||||
"8: Enter how much to expand (in MB)."
|
||||
"8: Enter how much to expand (in MB).",
|
||||
"9: Enter a new name for %s."
|
||||
],
|
||||
"MainMenuConfs": [
|
||||
"0: Are you sure you want to backup the save data for every user on this system? This can take an *extremely* long time!"
|
||||
|
|
@ -258,4 +289,4 @@
|
|||
"1: No [B]",
|
||||
"2: OK [A]"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
romfs/Textures/Frame.png
Normal file
BIN
romfs/Textures/Frame.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 312 B |
|
|
@ -1,15 +1,16 @@
|
|||
#include "JKSV.hpp"
|
||||
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "curl/curl.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "sdl.hpp"
|
||||
|
|
@ -30,9 +31,21 @@ namespace
|
|||
/// @brief Build month.
|
||||
constexpr uint8_t BUILD_MON = 8;
|
||||
/// @brief Build day.
|
||||
constexpr uint8_t BUILD_DAY = 25;
|
||||
constexpr uint8_t BUILD_DAY = 29;
|
||||
/// @brief Year.
|
||||
constexpr uint16_t BUILD_YEAR = 2025;
|
||||
|
||||
/// @brief Config for socket.
|
||||
constexpr SocketInitConfig SOCKET_INIT_CONFIG = {.tcp_tx_buf_size = 0x20000,
|
||||
.tcp_rx_buf_size = 0x20000,
|
||||
.tcp_tx_buf_max_size = 0x80000,
|
||||
.tcp_rx_buf_max_size = 0x80000,
|
||||
.udp_tx_buf_size = 0x2400,
|
||||
.udp_rx_buf_size = 0xA500,
|
||||
.sb_efficiency = 8,
|
||||
.num_bsd_sessions = 3,
|
||||
.bsd_service_type = BsdServiceType_User};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -86,11 +99,11 @@ JKSV::~JKSV()
|
|||
JKSV::exit_services();
|
||||
sdl::text::exit();
|
||||
sdl::exit();
|
||||
fslib::exit();
|
||||
|
||||
appletSetCpuBoostMode(ApmCpuBoostMode_Normal);
|
||||
}
|
||||
|
||||
bool JKSV::is_running() const { return m_isRunning; }
|
||||
bool JKSV::is_running() const noexcept { return m_isRunning; }
|
||||
|
||||
void JKSV::update()
|
||||
{
|
||||
|
|
@ -133,10 +146,11 @@ void JKSV::render()
|
|||
bool JKSV::initialize_filesystem()
|
||||
{
|
||||
// This needs to be in this specific order
|
||||
const bool fslib = fslib::initialize();
|
||||
const bool fslib = fslib::is_initialized();
|
||||
const bool romfs = initialize_service(romfsInit, "RomFS");
|
||||
const bool fslibDev = fslib && fslib::dev::initialize_sdmc();
|
||||
if (!fslib || !romfs || !fslibDev) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +164,7 @@ bool JKSV::initialize_services()
|
|||
serviceInit = serviceInit && initialize_service(pmshellInitialize, "PMShell");
|
||||
serviceInit = serviceInit && initialize_service(setInitialize, "Set");
|
||||
serviceInit = serviceInit && initialize_service(setsysInitialize, "SetSys");
|
||||
serviceInit = serviceInit && initialize_service(socketInitializeDefault, "Socket");
|
||||
serviceInit = serviceInit && initialize_service(socketInitialize, "Socket", &SOCKET_INIT_CONFIG);
|
||||
serviceInit = serviceInit && initialize_service(nifmInitialize, "NIFM", NifmServiceType_User);
|
||||
return serviceInit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ void StateManager::update()
|
|||
|
||||
if (stateVector.empty()) { return; }
|
||||
|
||||
// Run sub update routines.
|
||||
for (auto &state : stateVector) { state->sub_update(); }
|
||||
|
||||
std::shared_ptr<BaseState> &back = stateVector.back();
|
||||
if (!back->has_focus()) { back->give_focus(); }
|
||||
back->update();
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#include "appstates/FadeState.hpp"
|
||||
#include "appstates/ProgressState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -127,7 +127,7 @@ void BackupMenuState::refresh()
|
|||
}
|
||||
|
||||
int index{};
|
||||
for (const fslib::DirectoryEntry &entry : m_directoryListing.list())
|
||||
for (const fslib::DirectoryEntry &entry : m_directoryListing)
|
||||
{
|
||||
sm_backupMenu->add_option(entry.get_filename());
|
||||
m_menuEntries.push_back({MenuEntryType::Local, index++});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "appstates/BaseState.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
#include "appstates/MainMenuState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
BlacklistEditState::BlacklistEditState()
|
||||
: BaseState()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include "appstates/ExtrasMenuState.hpp"
|
||||
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
|
|
@ -50,7 +52,13 @@ void ExtrasMenuState::update()
|
|||
{
|
||||
switch (m_extrasMenu.get_selected())
|
||||
{
|
||||
case REINIT_DATA: ExtrasMenuState::reinitialize_data(); break;
|
||||
case REINIT_DATA: ExtrasMenuState::reinitialize_data(); break;
|
||||
case SD_TO_SD_BROWSER: ExtrasMenuState::sd_to_sd_browser(); break;
|
||||
case BIS_PRODINFO_F: ExtrasMenuState::prodinfof_to_sd(); break;
|
||||
case BIS_SAFE: ExtrasMenuState::safe_to_sd(); break;
|
||||
case BIS_SYSTEM: ExtrasMenuState::system_to_sd(); break;
|
||||
case BIS_USER: ExtrasMenuState::user_to_sd(); break;
|
||||
case TERMINATE_PROCESS: ExtrasMenuState::terminate_process(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { BaseState::deactivate(); }
|
||||
|
|
@ -75,6 +83,42 @@ void ExtrasMenuState::initialize_menu()
|
|||
|
||||
void ExtrasMenuState::reinitialize_data() { data::launch_initialization(true, finish_reinitialization); }
|
||||
|
||||
void ExtrasMenuState::sd_to_sd_browser() { FileModeState::create_and_push("sdmc", "sdmc", false); }
|
||||
|
||||
void ExtrasMenuState::prodinfof_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("prodinfo-f", FsBisPartitionId_CalibrationFile));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("prodinfo-f", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::safe_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("safe", FsBisPartitionId_SafeMode));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("safe", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::system_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("system", FsBisPartitionId_System));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("system", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::user_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("user", FsBisPartitionId_User));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("user", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::terminate_process() {}
|
||||
|
||||
static void finish_reinitialization()
|
||||
{
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
|
|
|
|||
223
source/appstates/FileModeState.cpp
Normal file
223
source/appstates/FileModeState.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#include "appstates/FileModeState.hpp"
|
||||
|
||||
#include "appstates/FileOptionState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
FileModeState::FileModeState(std::string_view mountA, std::string_view mountB, int64_t journalSize)
|
||||
: m_mountA(mountA)
|
||||
, m_mountB(mountB)
|
||||
, m_journalSize(journalSize)
|
||||
, m_y(720.f)
|
||||
, m_targetY(91.0f)
|
||||
, m_scaling(config::get_animation_scaling())
|
||||
{
|
||||
FileModeState::initialize_static_members();
|
||||
FileModeState::initialize_paths();
|
||||
FileModeState::initialize_menus();
|
||||
}
|
||||
|
||||
void FileModeState::update()
|
||||
{
|
||||
FileModeState::update_y_coord();
|
||||
if (!m_inPlace) { return; }
|
||||
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
ui::Menu &menu = FileModeState::get_source_menu();
|
||||
fslib::Path &path = FileModeState::get_source_path();
|
||||
fslib::Directory &directory = FileModeState::get_source_directory();
|
||||
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
const bool xPressed = input::button_pressed(HidNpadButton_X);
|
||||
const bool zlZRPressed = input::button_pressed(HidNpadButton_ZL) || input::button_pressed(HidNpadButton_ZR);
|
||||
const bool minusPressed = input::button_pressed(HidNpadButton_Minus);
|
||||
|
||||
if (aPressed) { FileModeState::enter_selected(path, directory, menu); }
|
||||
else if (bPressed) { FileModeState::up_one_directory(path, directory, menu); }
|
||||
else if (xPressed) { FileModeState::open_option_menu(directory, menu); }
|
||||
else if (zlZRPressed) { FileModeState::change_target(); }
|
||||
else if (minusPressed) { FileModeState::hide_dialog(); }
|
||||
else if (FileModeState::is_hidden()) { FileModeState::deactivate_state(); }
|
||||
|
||||
menu.update(hasFocus);
|
||||
}
|
||||
|
||||
void FileModeState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_renderTarget->clear(colors::TRANSPARENT);
|
||||
|
||||
// This is here so it's rendered underneath the pop-up frame.
|
||||
if (hasFocus) { FileModeState::render_control_guide(); }
|
||||
|
||||
sdl::render_line(sm_renderTarget, 617, 0, 617, 538, colors::WHITE);
|
||||
sdl::render_line(sm_renderTarget, 618, 0, 618, 538, colors::DIALOG_DARK);
|
||||
|
||||
m_dirMenuA->render(sm_renderTarget, hasFocus && m_target == false);
|
||||
m_dirMenuB->render(sm_renderTarget, hasFocus && m_target);
|
||||
|
||||
sm_frame->render(sdl::Texture::Null, true);
|
||||
sm_renderTarget->render(sdl::Texture::Null, 23, m_y + 12);
|
||||
}
|
||||
|
||||
void FileModeState::initialize_static_members()
|
||||
{
|
||||
static constexpr std::string_view RENDER_TARGET_NAME = "FMRenderTarget";
|
||||
|
||||
static constexpr int CONTROL_GUIDE_START_X = 1220;
|
||||
|
||||
if (sm_frame && sm_renderTarget) { return; }
|
||||
|
||||
sm_frame = ui::Frame::create(15, 720, 1250, 555);
|
||||
sm_renderTarget = sdl::TextureManager::load(RENDER_TARGET_NAME, 1234, 538, SDL_TEXTUREACCESS_TARGET);
|
||||
sm_controlGuide = strings::get_by_name(strings::names::CONTROL_GUIDES, 4);
|
||||
sm_controlGuideX = CONTROL_GUIDE_START_X - sdl::text::get_width(22, sm_controlGuide);
|
||||
}
|
||||
|
||||
void FileModeState::initialize_paths()
|
||||
{
|
||||
const std::string pathA = m_mountA + ":/";
|
||||
const std::string pathB = m_mountB + ":/";
|
||||
|
||||
m_pathA = pathA;
|
||||
m_pathB = pathB;
|
||||
}
|
||||
|
||||
void FileModeState::initialize_menus()
|
||||
{
|
||||
m_dirMenuA = ui::Menu::create(8, 8, 594, 22, 538);
|
||||
m_dirMenuB = ui::Menu::create(626, 8, 594, 22, 538);
|
||||
|
||||
FileModeState::initialize_directory_menu(m_pathA, m_dirA, *m_dirMenuA.get());
|
||||
FileModeState::initialize_directory_menu(m_pathB, m_dirB, *m_dirMenuB.get());
|
||||
}
|
||||
|
||||
void FileModeState::initialize_directory_menu(const fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
static constexpr const char *DIR_PREFIX = "[D] ";
|
||||
static constexpr const char *FILE_PREFIX = "[F] ";
|
||||
|
||||
directory.open(path);
|
||||
if (!directory.is_open()) { return; }
|
||||
|
||||
menu.reset();
|
||||
menu.add_option(".");
|
||||
menu.add_option("..");
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : directory)
|
||||
{
|
||||
std::string option{};
|
||||
if (entry.is_directory()) { option = DIR_PREFIX; }
|
||||
else { option = FILE_PREFIX; }
|
||||
|
||||
option += entry.get_filename();
|
||||
menu.add_option(option);
|
||||
}
|
||||
}
|
||||
|
||||
void FileModeState::update_y_coord() noexcept
|
||||
{
|
||||
if (m_y == m_targetY) { return; }
|
||||
|
||||
const double add = (m_targetY - m_y) / m_scaling;
|
||||
const double distance = math::Util<double>::absolute_distance(m_targetY, m_y);
|
||||
m_y += std::round(add);
|
||||
|
||||
// The second condition is a fix for when scaling is 1.
|
||||
if (distance <= 4 || m_y == m_targetY)
|
||||
{
|
||||
m_y = m_targetY;
|
||||
m_inPlace = true;
|
||||
}
|
||||
|
||||
sm_frame->set_y(m_y);
|
||||
}
|
||||
|
||||
void FileModeState::hide_dialog() noexcept
|
||||
{
|
||||
if (!m_inPlace) { return; }
|
||||
m_targetY = 720;
|
||||
}
|
||||
|
||||
bool FileModeState::is_hidden() noexcept { return m_inPlace && m_targetY == 720; }
|
||||
|
||||
void FileModeState::enter_selected(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
const int selected = menu.get_selected();
|
||||
|
||||
if (selected == 1) { FileModeState::up_one_directory(path, directory, menu); }
|
||||
else
|
||||
{
|
||||
const int dirIndex = selected - 2;
|
||||
const fslib::DirectoryEntry &entry = directory[dirIndex];
|
||||
if (entry.is_directory()) { FileModeState::enter_directory(path, directory, menu, entry); }
|
||||
}
|
||||
}
|
||||
|
||||
void FileModeState::open_option_menu(fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
const int selected = menu.get_selected();
|
||||
|
||||
if (selected == 0 || selected > 1) { FileOptionState::create_and_push(this); }
|
||||
}
|
||||
|
||||
void FileModeState::change_target() { m_target = m_target ? false : true; }
|
||||
|
||||
void FileModeState::up_one_directory(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
if (FileModeState::path_is_root(path)) { return; }
|
||||
|
||||
size_t lastSlash = path.find_last_of('/');
|
||||
if (lastSlash == path.NOT_FOUND) { return; }
|
||||
else if (lastSlash <= 0) { lastSlash = 1; }
|
||||
|
||||
fslib::Path newPath{path.sub_path(lastSlash)};
|
||||
path = std::move(newPath);
|
||||
FileModeState::initialize_directory_menu(path, directory, menu);
|
||||
}
|
||||
|
||||
void FileModeState::enter_directory(fslib::Path &path,
|
||||
fslib::Directory &directory,
|
||||
ui::Menu &menu,
|
||||
const fslib::DirectoryEntry &entry)
|
||||
{
|
||||
if (!entry.is_directory()) { return; }
|
||||
|
||||
path /= entry.get_filename();
|
||||
FileModeState::initialize_directory_menu(path, directory, menu);
|
||||
}
|
||||
|
||||
void FileModeState::render_control_guide()
|
||||
{
|
||||
sdl::text::render(sdl::Texture::Null, sm_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, sm_controlGuide);
|
||||
}
|
||||
|
||||
ui::Menu &FileModeState::get_source_menu() noexcept { return m_target ? *m_dirMenuB.get() : *m_dirMenuA.get(); }
|
||||
|
||||
ui::Menu &FileModeState::get_destination_menu() noexcept { return m_target ? *m_dirMenuA.get() : *m_dirMenuB.get(); }
|
||||
|
||||
fslib::Path &FileModeState::get_source_path() noexcept { return m_target ? m_pathB : m_pathA; }
|
||||
|
||||
fslib::Path &FileModeState::get_destination_path() noexcept { return m_target ? m_pathA : m_pathB; }
|
||||
|
||||
fslib::Directory &FileModeState::get_source_directory() noexcept { return m_target ? m_dirB : m_dirA; }
|
||||
|
||||
fslib::Directory &FileModeState::get_destination_directory() noexcept { return m_target ? m_dirA : m_dirB; }
|
||||
|
||||
void FileModeState::deactivate_state() noexcept
|
||||
{
|
||||
sm_frame->set_y(720);
|
||||
fslib::close_file_system(m_mountA);
|
||||
fslib::close_file_system(m_mountB);
|
||||
BaseState::deactivate();
|
||||
}
|
||||
430
source/appstates/FileOptionState.cpp
Normal file
430
source/appstates/FileOptionState.cpp
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
#include "appstates/FileOptionState.hpp"
|
||||
|
||||
#include "appstates/ConfirmState.hpp"
|
||||
#include "appstates/MessageState.hpp"
|
||||
#include "appstates/ProgressState.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "tasks/fileoptions.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
namespace
|
||||
{
|
||||
enum
|
||||
{
|
||||
COPY,
|
||||
DELETE,
|
||||
RENAME,
|
||||
CREATE_DIR,
|
||||
PROPERTIES,
|
||||
CLOSE
|
||||
};
|
||||
|
||||
// These make things easier to read and type.
|
||||
using TaskConfirm = ConfirmState<sys::Task, TaskState, FileOptionState::DataStruct>;
|
||||
using ProgressConfirm = ConfirmState<sys::ProgressTask, ProgressState, FileOptionState::DataStruct>;
|
||||
}
|
||||
|
||||
// Defined at bottom.
|
||||
static std::string get_size_string(int64_t totalSize);
|
||||
|
||||
FileOptionState::FileOptionState(FileModeState *spawningState)
|
||||
: m_spawningState(spawningState)
|
||||
, m_dataStruct(std::make_shared<FileOptionState::DataStruct>())
|
||||
{
|
||||
FileOptionState::initialize_static_members();
|
||||
FileOptionState::set_menu_side();
|
||||
FileOptionState::initialize_data_struct();
|
||||
}
|
||||
|
||||
void FileOptionState::update()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
FileOptionState::update_x_coord();
|
||||
if (!m_inPlace) { return; }
|
||||
|
||||
if (m_updateSource)
|
||||
{
|
||||
FileOptionState::update_filemode_source();
|
||||
m_updateSource = false;
|
||||
}
|
||||
else if (m_updateDest)
|
||||
{
|
||||
FileOptionState::update_filemode_dest();
|
||||
m_updateDest = false;
|
||||
}
|
||||
|
||||
sm_copyMenu->update(hasFocus);
|
||||
const int selected = sm_copyMenu->get_selected();
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
|
||||
if (aPressed)
|
||||
{
|
||||
switch (selected)
|
||||
{
|
||||
case COPY: FileOptionState::copy_target(); break;
|
||||
case DELETE: FileOptionState::delete_target(); break;
|
||||
case RENAME: FileOptionState::rename_target(); break;
|
||||
case CREATE_DIR: FileOptionState::create_directory(); break;
|
||||
case PROPERTIES: FileOptionState::get_show_target_properties(); break;
|
||||
case CLOSE: FileOptionState::close(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { FileOptionState::close(); }
|
||||
else if (FileOptionState::is_closed()) { FileOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void FileOptionState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_dialog->render(sdl::Texture::Null, hasFocus);
|
||||
sm_copyMenu->render(sdl::Texture::Null, hasFocus);
|
||||
|
||||
// I just didn't like this disappearing.
|
||||
m_spawningState->render_control_guide();
|
||||
}
|
||||
|
||||
void FileOptionState::update_source() { m_updateSource = true; }
|
||||
|
||||
void FileOptionState::update_destination() { m_updateDest = true; }
|
||||
|
||||
void FileOptionState::initialize_static_members()
|
||||
{
|
||||
if (sm_copyMenu && sm_dialog) { return; }
|
||||
|
||||
sm_copyMenu = ui::Menu::create(0, 236, 234, 20, 720); // High target height is a workaround.
|
||||
sm_dialog = ui::DialogBox::create(520, 218, 256, 256);
|
||||
|
||||
// This never changes, so...
|
||||
for (int i = 0; const char *menuOption = strings::get_by_name(strings::names::FILEOPTION_MENU, i); i++)
|
||||
{
|
||||
sm_copyMenu->add_option(menuOption);
|
||||
}
|
||||
}
|
||||
|
||||
void FileOptionState::set_menu_side()
|
||||
{
|
||||
const bool target = m_spawningState->m_target;
|
||||
m_x = target ? 1280 : -240;
|
||||
|
||||
m_targetX = target ? 840 : 200;
|
||||
sm_dialog->set_x(m_x);
|
||||
sm_copyMenu->set_x(m_x + 9);
|
||||
}
|
||||
|
||||
void FileOptionState::initialize_data_struct() { m_dataStruct->spawningState = this; }
|
||||
|
||||
void FileOptionState::update_filemode_source()
|
||||
{
|
||||
const fslib::Path &sourcePath = m_spawningState->get_source_path();
|
||||
fslib::Directory &sourceDir = m_spawningState->get_source_directory();
|
||||
ui::Menu &sourceMenu = m_spawningState->get_source_menu();
|
||||
|
||||
m_spawningState->initialize_directory_menu(sourcePath, sourceDir, sourceMenu);
|
||||
}
|
||||
|
||||
void FileOptionState::update_filemode_dest()
|
||||
{
|
||||
const fslib::Path &destPath = m_spawningState->get_destination_path();
|
||||
fslib::Directory &destDir = m_spawningState->get_destination_directory();
|
||||
ui::Menu &destMenu = m_spawningState->get_destination_menu();
|
||||
|
||||
m_spawningState->initialize_directory_menu(destPath, destDir, destMenu);
|
||||
}
|
||||
|
||||
void FileOptionState::update_x_coord()
|
||||
{
|
||||
if (m_x == m_targetX) { return; }
|
||||
|
||||
// We're going to borrow the scaling from the FileMode
|
||||
const int add = (m_targetX - m_x) / m_spawningState->m_scaling;
|
||||
m_x += add;
|
||||
|
||||
const int distance = math::Util<int>::absolute_distance(m_x, m_targetX);
|
||||
if (distance <= 4)
|
||||
{
|
||||
m_x = m_targetX;
|
||||
m_inPlace = true;
|
||||
}
|
||||
sm_dialog->set_x(m_x);
|
||||
sm_copyMenu->set_x(m_x + 9);
|
||||
}
|
||||
|
||||
void FileOptionState::copy_target()
|
||||
{
|
||||
const int64_t journalSize = m_spawningState->m_journalSize;
|
||||
|
||||
const fslib::Path &sourcePath = m_spawningState->get_source_path();
|
||||
const fslib::Directory &sourceDir = m_spawningState->get_source_directory();
|
||||
const ui::Menu &sourceMenu = m_spawningState->get_source_menu();
|
||||
|
||||
const fslib::Path &destPath = m_spawningState->get_destination_path();
|
||||
const fslib::Directory &destDir = m_spawningState->get_destination_directory();
|
||||
const ui::Menu &destMenu = m_spawningState->get_destination_menu();
|
||||
|
||||
const int sourceSelected = sourceMenu.get_selected();
|
||||
const int destSelected = destMenu.get_selected();
|
||||
|
||||
const int sourceIndex = sourceSelected - 2;
|
||||
const int destIndex = destSelected - 2;
|
||||
|
||||
fslib::Path fullSource{sourcePath};
|
||||
if (sourceSelected > 1) { fullSource /= sourceDir[sourceIndex]; }
|
||||
|
||||
fslib::Path fullDest{destPath};
|
||||
if (destSelected == 0 && sourceSelected > 1) { fullDest /= sourceDir[sourceIndex]; }
|
||||
if (destSelected > 1)
|
||||
{
|
||||
fullDest /= destDir[destIndex];
|
||||
if (sourceSelected > 1) { fullDest /= sourceDir[sourceIndex]; }
|
||||
}
|
||||
|
||||
// Reminder: JK, you move these. That's why the string is blank if they're declared past this point.
|
||||
const std::string sourceString = fullSource.string();
|
||||
const std::string destString = fullDest.string();
|
||||
m_dataStruct->sourcePath = std::move(fullSource);
|
||||
m_dataStruct->destPath = std::move(fullDest);
|
||||
m_dataStruct->journalSize = journalSize;
|
||||
|
||||
const char *copyFormat = strings::get_by_name(strings::names::FILEOPTION_CONFS, 0);
|
||||
const std::string query = stringutil::get_formatted_string(copyFormat, sourceString.c_str(), destString.c_str());
|
||||
|
||||
ProgressConfirm::create_push_fade(query, false, tasks::fileoptions::copy_source_to_destination, m_dataStruct);
|
||||
}
|
||||
|
||||
void FileOptionState::delete_target()
|
||||
{
|
||||
const fslib::Path &targetPath = m_spawningState->get_source_path();
|
||||
const fslib::Directory &targetDir = m_spawningState->get_source_directory();
|
||||
const ui::Menu &targetMenu = m_spawningState->get_source_menu();
|
||||
|
||||
fslib::Path fullTarget{targetPath};
|
||||
const int selected = targetMenu.get_selected();
|
||||
if (selected == 0) { return; } // I have no way to handle this right now.
|
||||
else if (selected > 1)
|
||||
{
|
||||
const int dirIndex = selected - 2;
|
||||
fullTarget /= targetDir[dirIndex];
|
||||
}
|
||||
|
||||
const char *deleteFormat = strings::get_by_name(strings::names::FILEOPTION_CONFS, 1);
|
||||
const std::string query = stringutil::get_formatted_string(deleteFormat, fullTarget.string().c_str());
|
||||
|
||||
m_dataStruct->sourcePath = std::move(fullTarget);
|
||||
m_dataStruct->journalSize = m_spawningState->m_journalSize;
|
||||
|
||||
TaskConfirm::create_push_fade(query, true, tasks::fileoptions::delete_target, m_dataStruct);
|
||||
}
|
||||
|
||||
void FileOptionState::rename_target()
|
||||
{
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
const fslib::Path &targetPath = m_spawningState->get_source_path();
|
||||
fslib::Directory &targetDir = m_spawningState->get_source_directory();
|
||||
ui::Menu &targetMenu = m_spawningState->get_source_menu();
|
||||
const int selected = targetMenu.get_selected();
|
||||
if (selected < 2) { return; }
|
||||
|
||||
char nameBuffer[FS_MAX_PATH] = {0};
|
||||
const int dirIndex = selected - 2;
|
||||
const char *filename = targetDir[dirIndex].get_filename();
|
||||
const char *keyboardFormat = strings::get_by_name(strings::names::KEYBOARD, 9);
|
||||
const std::string keyboardHeader = stringutil::get_formatted_string(keyboardFormat, filename);
|
||||
const bool validInput = keyboard::get_input(SwkbdType_QWERTY, filename, keyboardHeader, nameBuffer, FS_MAX_PATH);
|
||||
if (!validInput) { return; }
|
||||
|
||||
const fslib::Path oldPath{targetPath / filename};
|
||||
const fslib::Path newPath{targetPath / nameBuffer};
|
||||
|
||||
const std::string oldString = oldPath.string();
|
||||
const std::string newString = newPath.string();
|
||||
|
||||
// If this is false and there's a journaling size set, we need to commit on renaming for it to stick.
|
||||
const bool isSource = !m_spawningState->m_target;
|
||||
const int64_t journalSize = m_spawningState->m_journalSize;
|
||||
const bool commitNeeded = isSource && journalSize > 0;
|
||||
|
||||
const bool isDir = fslib::directory_exists(oldPath);
|
||||
const bool dirError = isDir && error::fslib(fslib::rename_directory(oldPath, newPath));
|
||||
const bool fileError = !isDir && error::fslib(fslib::rename_file(oldPath, newPath));
|
||||
const bool commitError = commitNeeded && error::fslib(fslib::commit_data_to_file_system(oldPath.get_device_name()));
|
||||
if (dirError && fileError && commitError)
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 5);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, filename);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 4);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, filename, nameBuffer);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
|
||||
m_spawningState->initialize_directory_menu(targetPath, targetDir, targetMenu);
|
||||
}
|
||||
|
||||
void FileOptionState::create_directory()
|
||||
{
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
const fslib::Path &targetPath = m_spawningState->get_source_path();
|
||||
fslib::Directory &targetDir = m_spawningState->get_source_directory();
|
||||
ui::Menu &targetMenu = m_spawningState->get_source_menu();
|
||||
const int64_t journalSize = m_spawningState->m_journalSize;
|
||||
|
||||
char nameBuffer[FS_MAX_PATH] = {0};
|
||||
const char *keyboardHeader = strings::get_by_name(strings::names::KEYBOARD, 6);
|
||||
const bool validInput = keyboard::get_input(SwkbdType_QWERTY, {}, keyboardHeader, nameBuffer, FS_MAX_PATH);
|
||||
if (!validInput) { return; }
|
||||
|
||||
const fslib::Path fullTarget{targetPath / nameBuffer};
|
||||
const bool commitRequired = journalSize > 0;
|
||||
const bool createError = error::fslib(fslib::create_directory(fullTarget));
|
||||
const bool commitError = !createError && error::fslib(fslib::commit_data_to_file_system(fullTarget.get_device_name()));
|
||||
if (createError || (commitRequired && commitError))
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 7);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, nameBuffer);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 6);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, nameBuffer);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
|
||||
m_spawningState->initialize_directory_menu(targetPath, targetDir, targetMenu);
|
||||
}
|
||||
|
||||
void FileOptionState::get_show_target_properties()
|
||||
{
|
||||
const fslib::Path &sourcePath = m_spawningState->get_source_path();
|
||||
const fslib::Directory &sourceDir = m_spawningState->get_source_directory();
|
||||
const ui::Menu &sourceMenu = m_spawningState->get_source_menu();
|
||||
|
||||
fslib::Path targetPath{sourcePath};
|
||||
const int selected = sourceMenu.get_selected();
|
||||
if (selected > 1)
|
||||
{
|
||||
const int dirIndex = selected - 2;
|
||||
targetPath /= sourceDir[dirIndex];
|
||||
}
|
||||
|
||||
const bool isDir = fslib::directory_exists(targetPath);
|
||||
if (isDir) { FileOptionState::get_show_directory_properties(targetPath); }
|
||||
else { FileOptionState::get_show_file_properties(targetPath); }
|
||||
}
|
||||
|
||||
void FileOptionState::get_show_directory_properties(const fslib::Path &path)
|
||||
{
|
||||
int64_t subDirCount{};
|
||||
int64_t fileCount{};
|
||||
int64_t totalSize{};
|
||||
const bool getInfo = fs::get_directory_information(path, subDirCount, fileCount, totalSize);
|
||||
if (!getInfo) { return; }
|
||||
|
||||
const char *messageFormat = strings::get_by_name(strings::names::FILEOPTION_MESSAGES, 0);
|
||||
const std::string pathString = path.string(); // This is needed as backup incase of root directories.
|
||||
const std::string sizeString = get_size_string(totalSize);
|
||||
const std::string message =
|
||||
stringutil::get_formatted_string(messageFormat, pathString.c_str(), subDirCount, fileCount, sizeString.c_str());
|
||||
|
||||
MessageState::create_and_push(message);
|
||||
}
|
||||
|
||||
void FileOptionState::get_show_file_properties(const fslib::Path &path)
|
||||
{
|
||||
|
||||
static constexpr size_t BUFFER_SIZE = 0x40;
|
||||
|
||||
FsTimeStampRaw timestamp{};
|
||||
const int64_t fileSize = fslib::get_file_size(path);
|
||||
error::fslib(fslib::get_file_timestamp(path, timestamp)); // Recorded, but not required. This doesn't work int saves.
|
||||
if (fileSize == -1) { return; }
|
||||
|
||||
// I don't like this, but it's the easiest way to pull this off.
|
||||
const std::time_t created = static_cast<std::time_t>(timestamp.created);
|
||||
const std::time_t modified = static_cast<std::time_t>(timestamp.modified);
|
||||
const std::time_t accessed = static_cast<std::time_t>(timestamp.accessed);
|
||||
|
||||
const std::tm createdTm = *std::localtime(&created);
|
||||
const std::tm modifiedTm = *std::localtime(&modified);
|
||||
const std::tm accessedTm = *std::localtime(&accessed);
|
||||
|
||||
char createdBuffer[BUFFER_SIZE] = {0};
|
||||
char lastModified[BUFFER_SIZE] = {0};
|
||||
char lastAccessed[BUFFER_SIZE] = {0};
|
||||
|
||||
std::strftime(createdBuffer, BUFFER_SIZE, "%c", &createdTm);
|
||||
std::strftime(lastModified, BUFFER_SIZE, "%c", &modifiedTm);
|
||||
std::strftime(lastAccessed, BUFFER_SIZE, "%c", &accessedTm);
|
||||
|
||||
const char *messageFormat = strings::get_by_name(strings::names::FILEOPTION_MESSAGES, 1);
|
||||
const std::string pathString = path.string();
|
||||
const std::string sizeString = get_size_string(fileSize);
|
||||
const std::string message = stringutil::get_formatted_string(messageFormat,
|
||||
pathString.c_str(),
|
||||
sizeString.c_str(),
|
||||
createdBuffer,
|
||||
lastModified,
|
||||
lastAccessed);
|
||||
|
||||
MessageState::create_and_push(message);
|
||||
}
|
||||
|
||||
void FileOptionState::close()
|
||||
{
|
||||
const bool target = m_spawningState->m_target;
|
||||
|
||||
m_close = true;
|
||||
m_targetX = target ? 1280 : -240;
|
||||
}
|
||||
|
||||
bool FileOptionState::is_closed() { return m_close && m_x == m_targetX; }
|
||||
|
||||
void FileOptionState::deactivate_state()
|
||||
{
|
||||
sm_copyMenu->set_selected(0);
|
||||
BaseState::deactivate();
|
||||
}
|
||||
|
||||
static std::string get_size_string(int64_t totalSize)
|
||||
{
|
||||
static constexpr int64_t THRESHOLD_BYTES = 0x400;
|
||||
static constexpr int64_t THRESHOLD_KB = 0x100000;
|
||||
static constexpr int64_t THRESHOLD_MB = 0x40000000;
|
||||
|
||||
std::string sizeString{};
|
||||
if (totalSize > THRESHOLD_MB)
|
||||
{
|
||||
const double gigabytes = static_cast<double>(totalSize) / static_cast<double>(THRESHOLD_MB);
|
||||
sizeString = stringutil::get_formatted_string("%.02f GB", gigabytes);
|
||||
}
|
||||
else if (totalSize < THRESHOLD_BYTES) { sizeString = stringutil::get_formatted_string("%lli bytes", totalSize); }
|
||||
else if (totalSize < THRESHOLD_KB)
|
||||
{
|
||||
const double kilobytes = static_cast<double>(totalSize) / static_cast<double>(THRESHOLD_BYTES);
|
||||
sizeString = stringutil::get_formatted_string("%.02f KB", kilobytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
const double megabytes = static_cast<double>(totalSize) / static_cast<double>(THRESHOLD_KB);
|
||||
sizeString = stringutil::get_formatted_string("%.02f MB", megabytes);
|
||||
}
|
||||
|
||||
return sizeString;
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
#include "StateManager.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
#include "appstates/MessageState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -157,10 +157,10 @@ void SettingsState::change_working_directory()
|
|||
const char *popSuccessFormat = strings::get_by_name(strings::names::SETTINGS_POPS, 1);
|
||||
const char *popFailed = strings::get_by_name(strings::names::SETTINGS_POPS, 2);
|
||||
|
||||
const fslib::Path oldPath{config::get_working_directory()};
|
||||
const std::string oldPath = config::get_working_directory().string();
|
||||
std::array<char, FS_MAX_PATH> pathBuffer = {0};
|
||||
|
||||
const bool input = keyboard::get_input(SwkbdType_Normal, oldPath.full_path(), inputHeader, pathBuffer.data(), FS_MAX_PATH);
|
||||
const bool input = keyboard::get_input(SwkbdType_Normal, oldPath, inputHeader, pathBuffer.data(), FS_MAX_PATH);
|
||||
if (!input) { return; }
|
||||
|
||||
const fslib::Path newPath{pathBuffer.data()};
|
||||
|
|
@ -179,7 +179,8 @@ void SettingsState::change_working_directory()
|
|||
return;
|
||||
}
|
||||
|
||||
const std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPath.full_path());
|
||||
const std::string newPathString = newPath.string();
|
||||
const std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPathString);
|
||||
ui::PopMessageManager::push_message(popTicks, popMessage);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "appstates/TitleInfoState.hpp"
|
||||
|
||||
#include "StateManager.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/ConfirmState.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "appstates/TitleInfoState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -57,25 +58,20 @@ void TitleOptionState::update()
|
|||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_slidePanel->update(hasFocus);
|
||||
const bool isOpen = sm_slidePanel->is_open();
|
||||
if (!isOpen) { return; }
|
||||
|
||||
const bool isOpen = sm_slidePanel->is_open();
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
const int selected = sm_titleOptionMenu->get_selected();
|
||||
|
||||
// This is kind of tricky to handle, because the blacklist function uses both.
|
||||
if (m_refreshRequired)
|
||||
{
|
||||
// Refresh the views.
|
||||
MainMenuState::refresh_view_states();
|
||||
m_refreshRequired = false;
|
||||
// Return so nothing else happens. Not sure I like this, but w/e.
|
||||
return;
|
||||
}
|
||||
if (m_exitRequired) { sm_slidePanel->close(); }
|
||||
|
||||
if (aPressed)
|
||||
if (aPressed && isOpen)
|
||||
{
|
||||
switch (selected)
|
||||
{
|
||||
|
|
@ -91,10 +87,16 @@ void TitleOptionState::update()
|
|||
case EXPORT_SVI: TitleOptionState::export_svi_file(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { sm_slidePanel->close(); }
|
||||
else if (bPressed || m_exitRequired)
|
||||
{
|
||||
sm_slidePanel->close();
|
||||
m_exitRequired = false;
|
||||
}
|
||||
else if (sm_slidePanel->is_closed()) { TitleOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void TitleOptionState::sub_update() { sm_slidePanel->sub_update(); }
|
||||
|
||||
void TitleOptionState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
|
@ -131,6 +133,7 @@ void TitleOptionState::initialize_data_struct()
|
|||
|
||||
void TitleOptionState::create_push_info_state()
|
||||
{
|
||||
sm_slidePanel->hide();
|
||||
auto titleInfoState = TitleInfoState::create(m_user, m_titleInfo);
|
||||
StateManager::push_state(titleInfoState);
|
||||
}
|
||||
|
|
@ -194,7 +197,18 @@ void TitleOptionState::change_output_directory()
|
|||
ui::PopMessageManager::push_message(popTicks, popSuccess);
|
||||
}
|
||||
|
||||
void TitleOptionState::create_push_file_mode() {}
|
||||
void TitleOptionState::create_push_file_mode()
|
||||
{
|
||||
const uint64_t applicationID = m_titleInfo->get_application_id();
|
||||
const FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(applicationID);
|
||||
if (error::is_null(saveInfo)) { return; }
|
||||
|
||||
const bool saveOpened = fslib::open_save_data_with_save_info(fs::DEFAULT_SAVE_MOUNT, *saveInfo);
|
||||
if (!saveOpened) { return; }
|
||||
|
||||
sm_slidePanel->hide();
|
||||
FileModeState::create_and_push(fs::DEFAULT_SAVE_MOUNT, "sdmc", true);
|
||||
}
|
||||
|
||||
void TitleOptionState::delete_all_local_backups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -78,6 +78,8 @@ void UserOptionState::update()
|
|||
else if (sm_menuPanel->is_closed()) { UserOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void UserOptionState::sub_update() { sm_menuPanel->sub_update(); }
|
||||
|
||||
void UserOptionState::render()
|
||||
{
|
||||
// Render target user's title selection screen.
|
||||
|
|
@ -131,7 +133,11 @@ void UserOptionState::backup_all()
|
|||
else { ProgressConfirm::create_and_push(query, true, tasks::useroptions::backup_all_for_user_local, m_dataStruct); }
|
||||
}
|
||||
|
||||
void UserOptionState::create_save_create() { SaveCreateState::create_and_push(m_user, m_titleSelect); }
|
||||
void UserOptionState::create_save_create()
|
||||
{
|
||||
sm_menuPanel->hide();
|
||||
SaveCreateState::create_and_push(m_user, m_titleSelect);
|
||||
}
|
||||
|
||||
void UserOptionState::create_all_save_data()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include "JSON.hpp"
|
||||
#include "config/keys.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
@ -68,14 +67,14 @@ bool config::ConfigContext::load()
|
|||
|
||||
void config::ConfigContext::save() { ConfigContext::save_config_file(); }
|
||||
|
||||
uint8_t config::ConfigContext::get_by_key(std::string_view key) const
|
||||
uint8_t config::ConfigContext::get_by_key(std::string_view key) const noexcept
|
||||
{
|
||||
const auto findKey = m_configMap.find(key);
|
||||
if (findKey == m_configMap.end()) { return 0; }
|
||||
return findKey->second;
|
||||
}
|
||||
|
||||
void config::ConfigContext::toggle_by_key(std::string_view key)
|
||||
void config::ConfigContext::toggle_by_key(std::string_view key) noexcept
|
||||
{
|
||||
auto findKey = m_configMap.find(key);
|
||||
if (findKey == m_configMap.end()) { return; }
|
||||
|
|
@ -84,7 +83,7 @@ void config::ConfigContext::toggle_by_key(std::string_view key)
|
|||
findKey->second = value ? 0 : 1;
|
||||
}
|
||||
|
||||
void config::ConfigContext::set_by_key(std::string_view key, uint8_t value)
|
||||
void config::ConfigContext::set_by_key(std::string_view key, uint8_t value) noexcept
|
||||
{
|
||||
auto findKey = m_configMap.find(key);
|
||||
if (findKey == m_configMap.end()) { return; }
|
||||
|
|
@ -92,9 +91,9 @@ void config::ConfigContext::set_by_key(std::string_view key, uint8_t value)
|
|||
findKey->second = value;
|
||||
}
|
||||
|
||||
fslib::Path config::ConfigContext::get_working_directory() const { return m_workingDirectory; }
|
||||
fslib::Path config::ConfigContext::get_working_directory() const noexcept { return m_workingDirectory; }
|
||||
|
||||
bool config::ConfigContext::set_working_directory(const fslib::Path &workDir)
|
||||
bool config::ConfigContext::set_working_directory(const fslib::Path &workDir) noexcept
|
||||
{
|
||||
if (!workDir.is_valid()) { return false; }
|
||||
|
||||
|
|
@ -102,9 +101,9 @@ bool config::ConfigContext::set_working_directory(const fslib::Path &workDir)
|
|||
return true;
|
||||
}
|
||||
|
||||
double config::ConfigContext::get_animation_scaling() const { return m_animationScaling; }
|
||||
double config::ConfigContext::get_animation_scaling() const noexcept { return m_animationScaling; }
|
||||
|
||||
void config::ConfigContext::set_animation_scaling(double scaling) { m_animationScaling = scaling; }
|
||||
void config::ConfigContext::set_animation_scaling(double scaling) noexcept { m_animationScaling = scaling; }
|
||||
|
||||
void config::ConfigContext::add_favorite(uint64_t applicationID)
|
||||
{
|
||||
|
|
@ -114,7 +113,7 @@ void config::ConfigContext::add_favorite(uint64_t applicationID)
|
|||
ConfigContext::save_config_file();
|
||||
}
|
||||
|
||||
void config::ConfigContext::remove_favorite(uint64_t applicationID)
|
||||
void config::ConfigContext::remove_favorite(uint64_t applicationID) noexcept
|
||||
{
|
||||
const auto findFav = ConfigContext::find_application_id(m_favorites, applicationID);
|
||||
if (findFav == m_favorites.end()) { return; }
|
||||
|
|
@ -122,7 +121,7 @@ void config::ConfigContext::remove_favorite(uint64_t applicationID)
|
|||
ConfigContext::save_config_file();
|
||||
}
|
||||
|
||||
bool config::ConfigContext::is_favorite(uint64_t applicationID) const
|
||||
bool config::ConfigContext::is_favorite(uint64_t applicationID) const noexcept
|
||||
{
|
||||
return ConfigContext::find_application_id(m_favorites, applicationID) != m_favorites.end();
|
||||
}
|
||||
|
|
@ -134,7 +133,7 @@ void config::ConfigContext::add_to_blacklist(uint64_t applicationID)
|
|||
m_blacklist.push_back(applicationID);
|
||||
}
|
||||
|
||||
void config::ConfigContext::remove_from_blacklist(uint64_t applicationID)
|
||||
void config::ConfigContext::remove_from_blacklist(uint64_t applicationID) noexcept
|
||||
{
|
||||
const auto findTitle = ConfigContext::find_application_id(m_blacklist, applicationID);
|
||||
if (findTitle == m_blacklist.end()) { return; }
|
||||
|
|
@ -146,14 +145,14 @@ void config::ConfigContext::get_blacklist(std::vector<uint64_t> &listOut)
|
|||
listOut.assign(m_blacklist.begin(), m_blacklist.end());
|
||||
}
|
||||
|
||||
bool config::ConfigContext::is_blacklisted(uint64_t applicationID) const
|
||||
bool config::ConfigContext::is_blacklisted(uint64_t applicationID) const noexcept
|
||||
{
|
||||
return ConfigContext::find_application_id(m_blacklist, applicationID) != m_blacklist.end();
|
||||
}
|
||||
|
||||
bool config::ConfigContext::blacklist_empty() const { return m_blacklist.empty(); }
|
||||
bool config::ConfigContext::blacklist_empty() const noexcept { return m_blacklist.empty(); }
|
||||
|
||||
bool config::ConfigContext::has_custom_path(uint64_t applicationID) const
|
||||
bool config::ConfigContext::has_custom_path(uint64_t applicationID) const noexcept
|
||||
{
|
||||
return m_paths.find(applicationID) != m_paths.end();
|
||||
}
|
||||
|
|
@ -181,7 +180,7 @@ bool config::ConfigContext::load_config_file()
|
|||
const bool exists = fslib::file_exists(configPath);
|
||||
if (!exists) { return false; }
|
||||
|
||||
json::Object configJSON = json::new_object(json_object_from_file, configPath.full_path());
|
||||
json::Object configJSON = json::new_object(json_object_from_file, PATH_CONFIG_FILE.data());
|
||||
if (!configJSON) { return false; }
|
||||
|
||||
json_object_iterator configIter = json::iter_begin(configJSON);
|
||||
|
|
@ -212,7 +211,8 @@ void config::ConfigContext::save_config_file()
|
|||
json::Object configJSON = json::new_object(json_object_new_object);
|
||||
if (!configJSON) { return; }
|
||||
|
||||
json_object *workDir = json_object_new_string(m_workingDirectory.full_path());
|
||||
const std::string workDirString = m_workingDirectory.string();
|
||||
json_object *workDir = json_object_new_string(workDirString.c_str());
|
||||
json::add_object(configJSON, config::keys::WORKING_DIRECTORY, workDir);
|
||||
|
||||
for (const auto &[key, value] : m_configMap)
|
||||
|
|
|
|||
|
|
@ -20,15 +20,15 @@ void config::reset_to_default() { s_context.reset(); }
|
|||
|
||||
void config::save() { s_context.save(); }
|
||||
|
||||
uint8_t config::get_by_key(std::string_view key) { return s_context.get_by_key(key); }
|
||||
uint8_t config::get_by_key(std::string_view key) noexcept { return s_context.get_by_key(key); }
|
||||
|
||||
void config::toggle_by_key(std::string_view key) { s_context.toggle_by_key(key); }
|
||||
void config::toggle_by_key(std::string_view key) noexcept { s_context.toggle_by_key(key); }
|
||||
|
||||
void config::set_by_key(std::string_view key, uint8_t value) { s_context.set_by_key(key, value); }
|
||||
void config::set_by_key(std::string_view key, uint8_t value) noexcept { s_context.set_by_key(key, value); }
|
||||
|
||||
fslib::Path config::get_working_directory() { return s_context.get_working_directory(); }
|
||||
|
||||
bool config::set_working_directory(const fslib::Path &path)
|
||||
bool config::set_working_directory(const fslib::Path &path) noexcept
|
||||
{
|
||||
const bool pathSet = s_context.set_working_directory(path);
|
||||
if (!pathSet) { return false; }
|
||||
|
|
@ -37,9 +37,9 @@ bool config::set_working_directory(const fslib::Path &path)
|
|||
return true;
|
||||
}
|
||||
|
||||
double config::get_animation_scaling() { return s_context.get_animation_scaling(); }
|
||||
double config::get_animation_scaling() noexcept { return s_context.get_animation_scaling(); }
|
||||
|
||||
void config::set_animation_scaling(double newScale) { s_context.set_animation_scaling(newScale); }
|
||||
void config::set_animation_scaling(double newScale) noexcept { s_context.set_animation_scaling(newScale); }
|
||||
|
||||
void config::add_remove_favorite(uint64_t applicationID)
|
||||
{
|
||||
|
|
@ -49,7 +49,7 @@ void config::add_remove_favorite(uint64_t applicationID)
|
|||
s_context.save();
|
||||
}
|
||||
|
||||
bool config::is_favorite(uint64_t applicationID) { return s_context.is_favorite(applicationID); }
|
||||
bool config::is_favorite(uint64_t applicationID) noexcept { return s_context.is_favorite(applicationID); }
|
||||
|
||||
void config::add_remove_blacklist(uint64_t applicationID)
|
||||
{
|
||||
|
|
@ -61,16 +61,16 @@ void config::add_remove_blacklist(uint64_t applicationID)
|
|||
|
||||
void config::get_blacklisted_titles(std::vector<uint64_t> &listOut) { s_context.get_blacklist(listOut); }
|
||||
|
||||
bool config::is_blacklisted(uint64_t applicationID) { return s_context.is_blacklisted(applicationID); }
|
||||
bool config::is_blacklisted(uint64_t applicationID) noexcept { return s_context.is_blacklisted(applicationID); }
|
||||
|
||||
bool config::blacklist_is_empty() { return s_context.blacklist_empty(); }
|
||||
bool config::blacklist_is_empty() noexcept { return s_context.blacklist_empty(); }
|
||||
|
||||
void config::add_custom_path(uint64_t applicationID, std::string_view customPath)
|
||||
{
|
||||
s_context.add_custom_path(applicationID, customPath);
|
||||
}
|
||||
|
||||
bool config::has_custom_path(uint64_t applicationID) { return s_context.has_custom_path(applicationID); }
|
||||
bool config::has_custom_path(uint64_t applicationID) noexcept { return s_context.has_custom_path(applicationID); }
|
||||
|
||||
void config::get_custom_path(uint64_t applicationID, char *pathOut, size_t pathOutSize)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "curl/curl.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "data/DataContext.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -128,11 +128,11 @@ bool data::DataContext::title_is_loaded(uint64_t applicationID)
|
|||
void data::DataContext::load_title(uint64_t applicationID)
|
||||
{
|
||||
std::scoped_lock titleGuard{m_titleMutex, m_iconQueueMutex};
|
||||
m_titleInfo.emplace(applicationID, applicationID);
|
||||
m_titleInfo.try_emplace(applicationID, applicationID);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
}
|
||||
|
||||
data::TitleInfo *data::DataContext::get_title_by_id(uint64_t applicationID)
|
||||
data::TitleInfo *data::DataContext::get_title_by_id(uint64_t applicationID) noexcept
|
||||
{
|
||||
std::lock_guard titleGuard{m_titleMutex};
|
||||
auto findTitle = m_titleInfo.find(applicationID);
|
||||
|
|
@ -171,7 +171,8 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
|
||||
task->set_status(statusLoadingSvi);
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sviDir.list())
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
for (const fslib::DirectoryEntry &entry : sviDir)
|
||||
{
|
||||
const fslib::Path target{sviPath / entry};
|
||||
fslib::File sviFile{target, FsOpenMode_Read};
|
||||
|
|
@ -180,7 +181,6 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
|
||||
uint32_t magic{};
|
||||
uint64_t applicationID{};
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
const bool magicRead = sviFile.read(&magic, SIZE_UINT32) == SIZE_UINT32;
|
||||
const bool idRead = sviFile.read(&applicationID, SIZE_UINT64) == SIZE_UINT64;
|
||||
const bool exists = DataContext::title_is_loaded(applicationID);
|
||||
|
|
@ -190,8 +190,7 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
if (!dataRead) { continue; }
|
||||
|
||||
std::scoped_lock multiGuard{m_iconQueueMutex, m_titleMutex};
|
||||
data::TitleInfo newTitle{applicationID, controlData};
|
||||
m_titleInfo.emplace(applicationID, std::move(newTitle));
|
||||
m_titleInfo.try_emplace(applicationID, applicationID, *controlData);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
}
|
||||
}
|
||||
|
|
@ -214,8 +213,8 @@ bool data::DataContext::read_cache(sys::Task *task)
|
|||
const char *statusLoadingCache = strings::get_by_name(strings::names::DATA_LOADING_STATUS, 4);
|
||||
task->set_status(statusLoadingCache);
|
||||
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
do {
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
const bool dataRead = cacheZip.read(controlData.get(), SIZE_CTRL_DATA) == SIZE_CTRL_DATA;
|
||||
if (!dataRead) { continue; }
|
||||
|
||||
|
|
@ -228,8 +227,7 @@ bool data::DataContext::read_cache(sys::Task *task)
|
|||
|
||||
std::scoped_lock multiGuard{m_iconQueueMutex, m_titleMutex};
|
||||
|
||||
data::TitleInfo newTitle{applicationID, controlData};
|
||||
m_titleInfo.emplace(applicationID, std::move(newTitle));
|
||||
m_titleInfo.try_emplace(applicationID, applicationID, *controlData);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
} while (cacheZip.next_file());
|
||||
m_cacheIsValid = true;
|
||||
|
|
|
|||
|
|
@ -1,38 +1,34 @@
|
|||
#include "data/TitleInfo.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "graphics/gfxutil.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID)
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID) noexcept
|
||||
: m_applicationID(applicationID)
|
||||
, m_data(std::make_unique<NsApplicationControlData>())
|
||||
{
|
||||
static constexpr size_t SIZE_CTRL_DATA = sizeof(NsApplicationControlData);
|
||||
|
||||
uint64_t controlSize{};
|
||||
NacpLanguageEntry *entry{};
|
||||
NsApplicationControlData *data = m_data.get();
|
||||
|
||||
// This will filter from even trying to fetch control data for system titles.
|
||||
const bool isSystem = applicationID & 0x8000000000000000;
|
||||
const bool getError = !isSystem && error::libnx(nsGetApplicationControlData(NsApplicationControlSource_Storage,
|
||||
m_applicationID,
|
||||
data,
|
||||
&m_data,
|
||||
SIZE_CTRL_DATA,
|
||||
&controlSize));
|
||||
const bool entryError = !getError && error::libnx(nacpGetLanguageEntry(&data->nacp, &entry));
|
||||
const bool entryError = !getError && error::libnx(nacpGetLanguageEntry(&m_data.nacp, &m_entry));
|
||||
if (isSystem || getError)
|
||||
{
|
||||
const std::string appIDHex = stringutil::get_formatted_string("%04X", m_applicationID & 0xFFFF);
|
||||
char *name = data->nacp.lang[SetLanguage_ENUS].name; // I'm hoping this is enough?
|
||||
char *name = m_data.nacp.lang[SetLanguage_ENUS].name; // I'm hoping this is enough?
|
||||
|
||||
std::memset(data, 0x00, SIZE_CTRL_DATA);
|
||||
std::snprintf(name, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID);
|
||||
TitleInfo::get_create_path_safe_title();
|
||||
}
|
||||
|
|
@ -44,67 +40,35 @@ data::TitleInfo::TitleInfo(uint64_t applicationID)
|
|||
}
|
||||
|
||||
// To do: Make this safer...
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID, std::unique_ptr<NsApplicationControlData> &controlData)
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID, NsApplicationControlData &controlData) noexcept
|
||||
: m_applicationID(applicationID)
|
||||
, m_data(std::move(controlData))
|
||||
{
|
||||
m_hasData = true;
|
||||
m_data = controlData;
|
||||
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
if (entryError) { std::snprintf(entry->name, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID); }
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data.nacp, &m_entry));
|
||||
if (entryError) { std::snprintf(m_entry->name, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID); }
|
||||
|
||||
TitleInfo::get_create_path_safe_title();
|
||||
}
|
||||
|
||||
data::TitleInfo::TitleInfo(data::TitleInfo &&titleInfo) { *this = std::move(titleInfo); }
|
||||
uint64_t data::TitleInfo::get_application_id() const noexcept { return m_applicationID; }
|
||||
|
||||
data::TitleInfo &data::TitleInfo::operator=(data::TitleInfo &&titleInfo)
|
||||
const NsApplicationControlData *data::TitleInfo::get_control_data() const noexcept { return &m_data; }
|
||||
|
||||
bool data::TitleInfo::has_control_data() const noexcept { return m_hasData; }
|
||||
|
||||
const char *data::TitleInfo::get_title() const noexcept { return m_entry->name; }
|
||||
|
||||
const char *data::TitleInfo::get_path_safe_title() const noexcept { return m_pathSafeTitle; }
|
||||
|
||||
const char *data::TitleInfo::get_publisher() const noexcept { return m_entry->author; }
|
||||
|
||||
uint64_t data::TitleInfo::get_save_data_owner_id() const noexcept { return m_data.nacp.save_data_owner_id; }
|
||||
|
||||
int64_t data::TitleInfo::get_save_data_size(uint8_t saveType) const noexcept
|
||||
{
|
||||
m_applicationID = titleInfo.m_applicationID;
|
||||
m_data = std::move(titleInfo.m_data);
|
||||
m_hasData = titleInfo.m_hasData;
|
||||
std::memcpy(m_pathSafeTitle, titleInfo.m_pathSafeTitle, TitleInfo::SIZE_PATH_SAFE);
|
||||
m_icon = titleInfo.m_icon;
|
||||
|
||||
titleInfo.m_applicationID = 0;
|
||||
titleInfo.m_data = nullptr;
|
||||
titleInfo.m_hasData = false;
|
||||
std::memset(titleInfo.m_pathSafeTitle, 0x00, TitleInfo::SIZE_PATH_SAFE);
|
||||
titleInfo.m_icon = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t data::TitleInfo::get_application_id() const { return m_applicationID; }
|
||||
|
||||
NsApplicationControlData *data::TitleInfo::get_control_data() { return m_data.get(); }
|
||||
|
||||
bool data::TitleInfo::has_control_data() const { return m_hasData; }
|
||||
|
||||
const char *data::TitleInfo::get_title()
|
||||
{
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
if (entryError) { return nullptr; }
|
||||
return entry->name;
|
||||
}
|
||||
|
||||
const char *data::TitleInfo::get_path_safe_title() const { return m_pathSafeTitle; }
|
||||
|
||||
const char *data::TitleInfo::get_publisher()
|
||||
{
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
if (entryError) { return nullptr; }
|
||||
return entry->author;
|
||||
}
|
||||
|
||||
uint64_t data::TitleInfo::get_save_data_owner_id() const { return m_data->nacp.save_data_owner_id; }
|
||||
|
||||
int64_t data::TitleInfo::get_save_data_size(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_size;
|
||||
|
|
@ -116,9 +80,9 @@ int64_t data::TitleInfo::get_save_data_size(uint8_t saveType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
int64_t data::TitleInfo::get_save_data_size_max(uint8_t saveType) const
|
||||
int64_t data::TitleInfo::get_save_data_size_max(uint8_t saveType) const noexcept
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return std::max(nacp.user_account_save_data_size, nacp.user_account_save_data_size_max);
|
||||
|
|
@ -130,9 +94,9 @@ int64_t data::TitleInfo::get_save_data_size_max(uint8_t saveType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
int64_t data::TitleInfo::get_journal_size(uint8_t saveType) const
|
||||
int64_t data::TitleInfo::get_journal_size(uint8_t saveType) const noexcept
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_journal_size;
|
||||
|
|
@ -144,9 +108,9 @@ int64_t data::TitleInfo::get_journal_size(uint8_t saveType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
int64_t data::TitleInfo::get_journal_size_max(uint8_t saveType) const
|
||||
int64_t data::TitleInfo::get_journal_size_max(uint8_t saveType) const noexcept
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account:
|
||||
|
|
@ -160,9 +124,9 @@ int64_t data::TitleInfo::get_journal_size_max(uint8_t saveType) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool data::TitleInfo::has_save_data_type(uint8_t saveType) const
|
||||
bool data::TitleInfo::has_save_data_type(uint8_t saveType) const noexcept
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_size > 0 || nacp.user_account_save_data_size_max > 0;
|
||||
|
|
@ -173,9 +137,9 @@ bool data::TitleInfo::has_save_data_type(uint8_t saveType) const
|
|||
return false;
|
||||
}
|
||||
|
||||
sdl::SharedTexture data::TitleInfo::get_icon() const { return m_icon; }
|
||||
sdl::SharedTexture data::TitleInfo::get_icon() const noexcept { return m_icon; }
|
||||
|
||||
void data::TitleInfo::set_path_safe_title(const char *newPathSafe)
|
||||
void data::TitleInfo::set_path_safe_title(const char *newPathSafe) noexcept
|
||||
{
|
||||
const size_t length = std::char_traits<char>::length(newPathSafe);
|
||||
if (length >= TitleInfo::SIZE_PATH_SAFE) { return; }
|
||||
|
|
@ -184,10 +148,9 @@ void data::TitleInfo::set_path_safe_title(const char *newPathSafe)
|
|||
std::memcpy(m_pathSafeTitle, newPathSafe, length);
|
||||
}
|
||||
|
||||
void data::TitleInfo::get_create_path_safe_title()
|
||||
void data::TitleInfo::get_create_path_safe_title() noexcept
|
||||
{
|
||||
const uint64_t applicationID = TitleInfo::get_application_id();
|
||||
NacpLanguageEntry *entry{};
|
||||
|
||||
const bool hasCustom = config::has_custom_path(applicationID);
|
||||
if (hasCustom)
|
||||
|
|
@ -197,13 +160,8 @@ void data::TitleInfo::get_create_path_safe_title()
|
|||
}
|
||||
|
||||
const bool useTitleId = config::get_by_key(config::keys::USE_TITLE_IDS);
|
||||
const bool entryError = !useTitleId && error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
const bool sanitized =
|
||||
!useTitleId && !entryError && stringutil::sanitize_string_for_path(entry->name, m_pathSafeTitle, SIZE_PATH_SAFE);
|
||||
if (useTitleId || entryError || !sanitized)
|
||||
{
|
||||
std::snprintf(m_pathSafeTitle, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID);
|
||||
}
|
||||
const bool sanitized = !useTitleId && stringutil::sanitize_string_for_path(m_entry->name, m_pathSafeTitle, SIZE_PATH_SAFE);
|
||||
if (useTitleId || !sanitized) { std::snprintf(m_pathSafeTitle, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID); }
|
||||
}
|
||||
|
||||
void data::TitleInfo::load_icon()
|
||||
|
|
@ -214,7 +172,7 @@ void data::TitleInfo::load_icon()
|
|||
if (m_hasData)
|
||||
{
|
||||
const std::string textureName = stringutil::get_formatted_string("%016llX", m_applicationID);
|
||||
m_icon = sdl::TextureManager::load(textureName, m_data->icon, SIZE_ICON);
|
||||
m_icon = sdl::TextureManager::load(textureName, m_data.icon, SIZE_ICON);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "graphics/gfxutil.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -33,7 +33,7 @@ namespace
|
|||
// Function used to sort user data. Definition at the bottom.
|
||||
static bool sort_user_data(const data::UserDataEntry &entryA, const data::UserDataEntry &entryB);
|
||||
|
||||
data::User::User(AccountUid accountID, FsSaveDataType saveType)
|
||||
data::User::User(AccountUid accountID, FsSaveDataType saveType) noexcept
|
||||
: m_accountID{accountID}
|
||||
, m_saveType{saveType}
|
||||
{
|
||||
|
|
@ -47,7 +47,10 @@ data::User::User(AccountUid accountID, FsSaveDataType saveType)
|
|||
accountProfileClose(&profile);
|
||||
}
|
||||
|
||||
data::User::User(AccountUid accountID, std::string_view nickname, std::string_view pathSafeNickname, FsSaveDataType saveType)
|
||||
data::User::User(AccountUid accountID,
|
||||
std::string_view nickname,
|
||||
std::string_view pathSafeNickname,
|
||||
FsSaveDataType saveType) noexcept
|
||||
: m_accountID{accountID}
|
||||
, m_saveType{saveType}
|
||||
{
|
||||
|
|
@ -55,9 +58,9 @@ data::User::User(AccountUid accountID, std::string_view nickname, std::string_vi
|
|||
std::memcpy(m_pathSafeNickname, pathSafeNickname.data(), pathSafeNickname.length());
|
||||
}
|
||||
|
||||
data::User::User(data::User &&user) { *this = std::move(user); }
|
||||
data::User::User(data::User &&user) noexcept { *this = std::move(user); }
|
||||
|
||||
data::User &data::User::operator=(data::User &&user)
|
||||
data::User &data::User::operator=(data::User &&user) noexcept
|
||||
{
|
||||
static constexpr size_t SIZE_NICKNAME = 0x20;
|
||||
|
||||
|
|
@ -88,50 +91,50 @@ void data::User::add_data(const FsSaveDataInfo *saveInfo, const PdmPlayStatistic
|
|||
m_userData.push_back(std::move(vectorPair));
|
||||
}
|
||||
|
||||
void data::User::clear_data_entries() { m_userData.clear(); }
|
||||
void data::User::clear_data_entries() noexcept { m_userData.clear(); }
|
||||
|
||||
void data::User::erase_data(int index) { m_userData.erase(m_userData.begin() + index); }
|
||||
|
||||
void data::User::sort_data() { std::sort(m_userData.begin(), m_userData.end(), sort_user_data); }
|
||||
void data::User::sort_data() noexcept { std::sort(m_userData.begin(), m_userData.end(), sort_user_data); }
|
||||
|
||||
AccountUid data::User::get_account_id() const { return m_accountID; }
|
||||
AccountUid data::User::get_account_id() const noexcept { return m_accountID; }
|
||||
|
||||
FsSaveDataType data::User::get_account_save_type() const { return m_saveType; }
|
||||
FsSaveDataType data::User::get_account_save_type() const noexcept { return m_saveType; }
|
||||
|
||||
const char *data::User::get_nickname() const { return m_nickname; }
|
||||
const char *data::User::get_nickname() const noexcept { return m_nickname; }
|
||||
|
||||
const char *data::User::get_path_safe_nickname() const { return m_pathSafeNickname; }
|
||||
const char *data::User::get_path_safe_nickname() const noexcept { return m_pathSafeNickname; }
|
||||
|
||||
size_t data::User::get_total_data_entries() const { return m_userData.size(); }
|
||||
size_t data::User::get_total_data_entries() const noexcept { return m_userData.size(); }
|
||||
|
||||
uint64_t data::User::get_application_id_at(int index) const
|
||||
uint64_t data::User::get_application_id_at(int index) const noexcept
|
||||
{
|
||||
if (!User::index_check(index)) { return 0; }
|
||||
return m_userData.at(index).first;
|
||||
}
|
||||
|
||||
FsSaveDataInfo *data::User::get_save_info_at(int index)
|
||||
FsSaveDataInfo *data::User::get_save_info_at(int index) noexcept
|
||||
{
|
||||
if (!User::index_check(index)) { return nullptr; }
|
||||
return &m_userData.at(index).second.first;
|
||||
}
|
||||
|
||||
PdmPlayStatistics *data::User::get_play_stats_at(int index)
|
||||
PdmPlayStatistics *data::User::get_play_stats_at(int index) noexcept
|
||||
{
|
||||
if (!User::index_check(index)) { return nullptr; }
|
||||
return &m_userData.at(index).second.second;
|
||||
}
|
||||
|
||||
FsSaveDataInfo *data::User::get_save_info_by_id(uint64_t applicationID)
|
||||
FsSaveDataInfo *data::User::get_save_info_by_id(uint64_t applicationID) noexcept
|
||||
{
|
||||
auto target = User::find_title_by_id(applicationID);
|
||||
if (target == m_userData.end()) { return nullptr; }
|
||||
return &target->second.first;
|
||||
}
|
||||
|
||||
data::UserSaveInfoList &data::User::get_user_save_info_list() { return m_userData; }
|
||||
data::UserSaveInfoList &data::User::get_user_save_info_list() noexcept { return m_userData; }
|
||||
|
||||
PdmPlayStatistics *data::User::get_play_stats_by_id(uint64_t applicationID)
|
||||
PdmPlayStatistics *data::User::get_play_stats_by_id(uint64_t applicationID) noexcept
|
||||
{
|
||||
auto target = User::find_title_by_id(applicationID);
|
||||
if (target == m_userData.end()) { return nullptr; }
|
||||
|
|
@ -164,15 +167,12 @@ void data::User::load_user_data()
|
|||
|
||||
while (infoReader.read())
|
||||
{
|
||||
const int64_t readCount = infoReader.get_read_count();
|
||||
|
||||
for (int64_t i = 0; i < readCount; i++)
|
||||
for (const FsSaveDataInfo &saveInfo : infoReader)
|
||||
{
|
||||
const FsSaveDataInfo &saveInfo = infoReader[i];
|
||||
const uint64_t saveInfoAppID = saveInfo.application_id;
|
||||
const uint64_t saveInfoSysID = saveInfo.system_save_data_id;
|
||||
const uint64_t applicationID = saveInfoAppID != 0 ? saveInfoAppID : saveInfoSysID;
|
||||
const uint8_t saveDataType = saveInfo.save_data_type;
|
||||
const uint64_t saveInfoAppID = saveInfo.application_id;
|
||||
const uint64_t saveInfoSysID = saveInfo.system_save_data_id;
|
||||
const uint64_t applicationID = saveInfoAppID != 0 ? saveInfoAppID : saveInfoSysID;
|
||||
const uint8_t saveDataType = saveInfo.save_data_type;
|
||||
const bool isSystemSave = saveDataType == FsSaveDataType_System || saveDataType == FsSaveDataType_SystemBcat;
|
||||
|
||||
const bool isBlacklisted = config::is_blacklisted(applicationID);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include "appstates/DataLoadingState.hpp"
|
||||
#include "data/DataContext.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
|
@ -23,11 +24,14 @@ void data::launch_initialization(bool clearCache, std::function<void()> onDestru
|
|||
|
||||
void data::get_users(data::UserList &userList) { s_context.get_users(userList); }
|
||||
|
||||
data::TitleInfo *data::get_title_info_by_id(uint64_t applicationID) { return s_context.get_title_by_id(applicationID); }
|
||||
data::TitleInfo *data::get_title_info_by_id(uint64_t applicationID) noexcept
|
||||
{
|
||||
return s_context.get_title_by_id(applicationID);
|
||||
}
|
||||
|
||||
void data::load_title_to_map(uint64_t applicationID) { s_context.load_title(applicationID); }
|
||||
|
||||
bool data::title_exists_in_map(uint64_t applicationID) { return s_context.title_is_loaded(applicationID); }
|
||||
bool data::title_exists_in_map(uint64_t applicationID) noexcept { return s_context.title_is_loaded(applicationID); }
|
||||
|
||||
void data::get_title_info_list(data::TitleInfoList &listOut) { s_context.get_title_info_list(listOut); }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include "fslib.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
#include <string_view>
|
||||
|
||||
/// @brief Prepares and makes sure the strings match the format I actually want!
|
||||
static void prep_locations(std::string_view &file, std::string_view &function, const std::source_location &location);
|
||||
static void prep_locations(std::string_view &file, std::string_view &function, const std::source_location &location) noexcept;
|
||||
|
||||
bool error::libnx(Result code, const std::source_location &location)
|
||||
bool error::libnx(Result code, const std::source_location &location) noexcept
|
||||
{
|
||||
if (code == 0) { return false; }
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ bool error::libnx(Result code, const std::source_location &location)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool error::fslib(bool result, const std::source_location &location)
|
||||
bool error::fslib(bool result, const std::source_location &location) noexcept
|
||||
{
|
||||
if (result) { return false; }
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ bool error::fslib(bool result, const std::source_location &location)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool error::is_null(const void *pointer, const std::source_location &location)
|
||||
bool error::is_null(const void *pointer, const std::source_location &location) noexcept
|
||||
{
|
||||
if (pointer) { return false; }
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ bool error::is_null(const void *pointer, const std::source_location &location)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void prep_locations(std::string_view &file, std::string_view &function, const std::source_location &location)
|
||||
static void prep_locations(std::string_view &file, std::string_view &function, const std::source_location &location) noexcept
|
||||
{
|
||||
file = location.file_name();
|
||||
function = location.function_name();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "fs/MiniUnzip.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
fs::MiniUnzip::MiniUnzip(const fslib::Path &path) { MiniUnzip::open(path); }
|
||||
|
|
@ -12,7 +12,9 @@ bool fs::MiniUnzip::is_open() const { return m_isOpen; }
|
|||
bool fs::MiniUnzip::open(const fslib::Path &path)
|
||||
{
|
||||
MiniUnzip::close();
|
||||
m_unz = unzOpen64(path.full_path());
|
||||
|
||||
const std::string pathString = path.string();
|
||||
m_unz = unzOpen64(pathString.c_str());
|
||||
if (error::is_null(m_unz) || !MiniUnzip::reset()) { return false; }
|
||||
m_isOpen = true;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
#include "fs/MiniZip.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
// Definition at bottom.
|
||||
static zip_fileinfo create_zip_file_info();
|
||||
|
||||
fs::MiniZip::MiniZip(const fslib::Path &path) { MiniZip::open(path); }
|
||||
fs::MiniZip::MiniZip(const fslib::Path &path)
|
||||
: m_level(config::get_by_key(config::keys::ZIP_COMPRESSION_LEVEL))
|
||||
{
|
||||
MiniZip::open(path);
|
||||
}
|
||||
|
||||
fs::MiniZip::~MiniZip() { MiniZip::close(); }
|
||||
|
||||
|
|
@ -17,7 +22,9 @@ bool fs::MiniZip::is_open() const { return m_isOpen; }
|
|||
bool fs::MiniZip::open(const fslib::Path &path)
|
||||
{
|
||||
MiniZip::close();
|
||||
m_zip = zipOpen64(path.full_path(), APPEND_STATUS_CREATE);
|
||||
|
||||
const std::string pathString = path.string();
|
||||
m_zip = zipOpen64(pathString.c_str(), APPEND_STATUS_CREATE);
|
||||
if (error::is_null(m_zip)) { return false; }
|
||||
m_isOpen = true;
|
||||
return true;
|
||||
|
|
@ -32,19 +39,21 @@ void fs::MiniZip::close()
|
|||
|
||||
bool fs::MiniZip::open_new_file(std::string_view filename, bool trimPath, size_t trimPlaces)
|
||||
{
|
||||
const uint8_t zipLevel = config::get_by_key(config::keys::ZIP_COMPRESSION_LEVEL);
|
||||
|
||||
const size_t pathBegin = filename.find_first_of('/');
|
||||
if (pathBegin != filename.npos) { filename = filename.substr(pathBegin + 1); }
|
||||
|
||||
const zip_fileinfo fileInfo = create_zip_file_info();
|
||||
return zipOpenNewFileInZip64(m_zip, filename.data(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, zipLevel, 0) ==
|
||||
return zipOpenNewFileInZip64(m_zip, filename.data(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, m_level, 0) ==
|
||||
ZIP_OK;
|
||||
}
|
||||
|
||||
bool fs::MiniZip::close_current_file() { return zipCloseFileInZip(m_zip) == ZIP_OK; }
|
||||
|
||||
bool fs::MiniZip::write(const void *buffer, size_t dataSize) { return zipWriteInFileInZip(m_zip, buffer, dataSize) == ZIP_OK; }
|
||||
bool fs::MiniZip::write(const void *buffer, size_t dataSize)
|
||||
{
|
||||
if (!m_isOpen) { return false; }
|
||||
return zipWriteInFileInZip(m_zip, buffer, dataSize) == ZIP_OK;
|
||||
}
|
||||
|
||||
static zip_fileinfo create_zip_file_info()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
fs::PathFilter::PathFilter(const fslib::Path &filePath)
|
||||
{
|
||||
json::Object filterJSON = json::new_object(json_object_from_file, filePath.full_path());
|
||||
const std::string pathString = filePath.string();
|
||||
json::Object filterJSON = json::new_object(json_object_from_file, pathString.c_str());
|
||||
if (!filterJSON) { return; }
|
||||
|
||||
json_object *filter = json::get_object(filterJSON, "filters");
|
||||
|
|
@ -21,9 +22,9 @@ fs::PathFilter::PathFilter(const fslib::Path &filePath)
|
|||
}
|
||||
}
|
||||
|
||||
bool fs::PathFilter::has_paths() const { return !m_paths.empty(); }
|
||||
bool fs::PathFilter::has_paths() const noexcept { return !m_paths.empty(); }
|
||||
|
||||
bool fs::PathFilter::is_filtered(const fslib::Path &path)
|
||||
bool fs::PathFilter::is_filtered(const fslib::Path &path) const noexcept
|
||||
{
|
||||
return std::find(m_paths.begin(), m_paths.end(), path.full_path()) != m_paths.end();
|
||||
return std::find(m_paths.begin(), m_paths.end(), path) != m_paths.end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,20 @@
|
|||
#include "fs/SaveMetaData.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/directory_functions.hpp"
|
||||
#include "fs/save_data_functions.hpp"
|
||||
#include "fs/save_mount.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr size_t SIZE_EXTRA_DATA = sizeof(FsSaveDataExtraData);
|
||||
}
|
||||
|
||||
bool fs::read_save_data_extra_info(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &dataOut)
|
||||
{
|
||||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
const uint64_t saveDataID = saveInfo->save_data_id;
|
||||
|
||||
const bool readError =
|
||||
error::libnx(fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(&dataOut, SIZE_EXTRA_DATA, spaceID, saveDataID));
|
||||
if (readError) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::fill_save_meta_data(const FsSaveDataInfo *saveInfo, fs::SaveMetaData &meta)
|
||||
bool fs::fill_save_meta_data(const FsSaveDataInfo *saveInfo, fs::SaveMetaData &meta) noexcept
|
||||
{
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool extraRead = fs::read_save_data_extra_info(saveInfo, extraData);
|
||||
const bool extraRead = fs::read_save_extra_data(saveInfo, extraData);
|
||||
if (!extraRead) { return false; }
|
||||
|
||||
meta = {.magic = fs::SAVE_META_MAGIC,
|
||||
|
|
@ -46,10 +35,10 @@ bool fs::fill_save_meta_data(const FsSaveDataInfo *saveInfo, fs::SaveMetaData &m
|
|||
return true;
|
||||
}
|
||||
|
||||
bool fs::process_save_meta_data(const FsSaveDataInfo *saveInfo, const SaveMetaData &meta)
|
||||
bool fs::process_save_meta_data(const FsSaveDataInfo *saveInfo, const SaveMetaData &meta) noexcept
|
||||
{
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool extraRead = fs::read_save_data_extra_info(saveInfo, extraData);
|
||||
const bool extraRead = fs::read_save_extra_data(saveInfo, extraData);
|
||||
if (!extraRead) { return false; }
|
||||
|
||||
const bool needsExtend = extraData.data_size < meta.saveDataSize;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "fs/ScopedSaveMount.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
fs::ScopedSaveMount::ScopedSaveMount(std::string_view mount, const FsSaveDataInfo *saveInfo, bool log)
|
||||
: m_mountPoint(mount)
|
||||
|
|
@ -11,9 +11,9 @@ fs::ScopedSaveMount::ScopedSaveMount(std::string_view mount, const FsSaveDataInf
|
|||
else { m_isOpen = fslib::open_save_data_with_save_info(m_mountPoint, *saveInfo); }
|
||||
}
|
||||
|
||||
fs::ScopedSaveMount::ScopedSaveMount(ScopedSaveMount &&scopedSaveMount) { *this = std::move(scopedSaveMount); }
|
||||
fs::ScopedSaveMount::ScopedSaveMount(ScopedSaveMount &&scopedSaveMount) noexcept { *this = std::move(scopedSaveMount); }
|
||||
|
||||
fs::ScopedSaveMount &fs::ScopedSaveMount::operator=(ScopedSaveMount &&scopedSaveMount)
|
||||
fs::ScopedSaveMount &fs::ScopedSaveMount::operator=(ScopedSaveMount &&scopedSaveMount) noexcept
|
||||
{
|
||||
m_mountPoint = std::move(scopedSaveMount.m_mountPoint);
|
||||
m_isOpen = scopedSaveMount.m_isOpen;
|
||||
|
|
@ -27,4 +27,4 @@ fs::ScopedSaveMount::~ScopedSaveMount()
|
|||
else { fslib::close_file_system(m_mountPoint); }
|
||||
}
|
||||
|
||||
bool fs::ScopedSaveMount::is_open() const { return m_isOpen; }
|
||||
bool fs::ScopedSaveMount::is_open() const noexcept { return m_isOpen; }
|
||||
|
|
|
|||
|
|
@ -1,24 +1,34 @@
|
|||
#include "fs/directory_functions.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/SaveMetaData.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
uint64_t fs::get_directory_total_size(const fslib::Path &targetPath)
|
||||
bool fs::get_directory_information(const fslib::Path &directoryPath,
|
||||
int64_t &subDirCount,
|
||||
int64_t &fileCount,
|
||||
int64_t &totalSize)
|
||||
{
|
||||
fslib::Directory targetDir{targetPath};
|
||||
if (!targetDir.is_open()) { return 0; }
|
||||
fslib::Directory dir{directoryPath};
|
||||
if (error::fslib(dir.is_open())) { return false; }
|
||||
|
||||
uint64_t directorySize = 0;
|
||||
for (const fslib::DirectoryEntry &entry : targetDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : dir)
|
||||
{
|
||||
if (entry.is_directory())
|
||||
{
|
||||
const fslib::Path newTarget{targetPath / entry};
|
||||
directorySize += fs::get_directory_total_size(newTarget);
|
||||
const fslib::Path newPath{directoryPath / entry};
|
||||
const bool getInfo = fs::get_directory_information(newPath, subDirCount, fileCount, totalSize);
|
||||
if (!getInfo) { return false; }
|
||||
++subDirCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalSize += entry.get_size();
|
||||
++fileCount;
|
||||
}
|
||||
else { directorySize += entry.get_size(); }
|
||||
}
|
||||
|
||||
return directorySize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::directory_has_contents(const fslib::Path &directoryPath)
|
||||
|
|
@ -26,7 +36,7 @@ bool fs::directory_has_contents(const fslib::Path &directoryPath)
|
|||
fslib::Directory testDir{directoryPath};
|
||||
if (!testDir.is_open()) { return false; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : testDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : testDir)
|
||||
{
|
||||
if (entry.get_filename() != fs::NAME_SAVE_META) { return true; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "fs/io.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/SaveMetaData.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
|
@ -70,7 +70,8 @@ void fs::copy_file(const fslib::Path &source, const fslib::Path &destination, sy
|
|||
const int64_t sourceSize = sourceFile.get_size();
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(statusTemplate, source.full_path());
|
||||
const std::string sourceString = source.string();
|
||||
const std::string status = stringutil::get_formatted_string(statusTemplate, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(sourceSize));
|
||||
}
|
||||
|
|
@ -111,7 +112,6 @@ void fs::copy_file(const fslib::Path &source, const fslib::Path &destination, sy
|
|||
|
||||
void fs::copy_file_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task)
|
||||
{
|
||||
|
|
@ -126,7 +126,8 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
const int64_t sourceSize = sourceFile.get_size();
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(copyingStatus, source.full_path());
|
||||
const std::string sourceString = source.string();
|
||||
const std::string status = stringutil::get_formatted_string(copyingStatus, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(sourceSize));
|
||||
}
|
||||
|
|
@ -163,7 +164,7 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
if (needsCommit)
|
||||
{
|
||||
destFile.close();
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(device));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(destination.get_device_name()));
|
||||
// To do: Handle this better. Threads current have no way of communicating errors.
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
|
||||
|
|
@ -180,7 +181,7 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
readThread.join();
|
||||
destFile.close();
|
||||
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(device));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(destination.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +190,7 @@ void fs::copy_directory(const fslib::Path &source, const fslib::Path &destinatio
|
|||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const char *filename = entry.get_filename();
|
||||
if (filename == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -210,14 +211,13 @@ void fs::copy_directory(const fslib::Path &source, const fslib::Path &destinatio
|
|||
|
||||
void fs::copy_directory_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task)
|
||||
{
|
||||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const char *filename = entry.get_filename();
|
||||
if (filename == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -230,8 +230,8 @@ void fs::copy_directory_commit(const fslib::Path &source,
|
|||
const bool createError = !destExists && error::fslib(fslib::create_directory(fullDest));
|
||||
if (!destExists && createError) { continue; }
|
||||
|
||||
fs::copy_directory_commit(fullSource, fullDest, device, journalSize, task);
|
||||
fs::copy_directory_commit(fullSource, fullDest, journalSize, task);
|
||||
}
|
||||
else { fs::copy_file_commit(fullSource, fullDest, device, journalSize, task); }
|
||||
else { fs::copy_file_commit(fullSource, fullDest, journalSize, task); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "fs/save_data_functions.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo)
|
||||
bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo) noexcept
|
||||
{
|
||||
static constexpr FsSaveDataMetaInfo saveMeta = {.size = 0x40060, .type = FsSaveDataMetaType_Thumbnail};
|
||||
|
||||
|
|
@ -29,11 +29,10 @@ bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo
|
|||
.save_data_space_id = FsSaveDataSpaceId_User};
|
||||
|
||||
// I want this recorded.
|
||||
const bool createError = error::libnx(fsCreateSaveDataFileSystem(&saveAttributes, &saveCreation, &saveMeta));
|
||||
return createError == false;
|
||||
return error::libnx(fsCreateSaveDataFileSystem(&saveAttributes, &saveCreation, &saveMeta)) == false;
|
||||
}
|
||||
|
||||
bool fs::delete_save_data(const FsSaveDataInfo *saveInfo)
|
||||
bool fs::delete_save_data(const FsSaveDataInfo *saveInfo) noexcept
|
||||
{
|
||||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
const bool isSystem = fs::is_system_save_data(saveInfo);
|
||||
|
|
@ -47,8 +46,7 @@ bool fs::delete_save_data(const FsSaveDataInfo *saveInfo)
|
|||
.save_data_rank = saveInfo->save_data_rank,
|
||||
.save_data_index = saveInfo->save_data_index};
|
||||
|
||||
const bool deleteError = error::libnx(fsDeleteSaveDataFileSystemBySaveDataAttribute(spaceID, &saveAttributes));
|
||||
return deleteError == false;
|
||||
return error::libnx(fsDeleteSaveDataFileSystemBySaveDataAttribute(spaceID, &saveAttributes)) == false;
|
||||
}
|
||||
|
||||
bool fs::extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize)
|
||||
|
|
@ -56,11 +54,22 @@ bool fs::extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t
|
|||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
const uint64_t saveID = saveInfo->save_data_id;
|
||||
|
||||
const bool extendError = error::libnx(fsExtendSaveDataFileSystem(spaceID, saveID, size, journalSize));
|
||||
return extendError == false;
|
||||
return error::libnx(fsExtendSaveDataFileSystem(spaceID, saveID, size, journalSize)) == false;
|
||||
}
|
||||
|
||||
bool fs::is_system_save_data(const FsSaveDataInfo *saveInfo)
|
||||
bool fs::is_system_save_data(const FsSaveDataInfo *saveInfo) noexcept
|
||||
{
|
||||
return saveInfo->save_data_type == FsSaveDataType_System || saveInfo->save_data_type == FsSaveDataType_SystemBcat;
|
||||
}
|
||||
|
||||
bool fs::read_save_extra_data(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &extraOut) noexcept
|
||||
{
|
||||
static constexpr size_t EXTRA_SIZE = sizeof(FsSaveDataExtraData);
|
||||
|
||||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
|
||||
const bool readError = error::libnx(
|
||||
fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(&extraOut, EXTRA_SIZE, spaceID, saveInfo->save_data_id));
|
||||
|
||||
return !readError;
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "fs/zip.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/SaveMetaData.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
namespace
|
||||
{
|
||||
/// @brief Buffer size used for writing files to ZIP.
|
||||
constexpr size_t SIZE_ZIP_BUFFER = 0x100000;
|
||||
constexpr size_t SIZE_ZIP_BUFFER = 0x10000;
|
||||
|
||||
/// @brief Buffer size used for decompressing files from ZIP.
|
||||
constexpr size_t SIZE_UNZIP_BUFFER = 0x600000;
|
||||
|
|
@ -100,14 +100,15 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const fslib::Path fullSource{source / entry};
|
||||
if (entry.is_directory()) { fs::copy_directory_to_zip(fullSource, dest, task); }
|
||||
else
|
||||
{
|
||||
fslib::File sourceFile{fullSource, FsOpenMode_Read};
|
||||
const bool newZipFile = dest.open_new_file(fullSource.full_path());
|
||||
const std::string sourceString = fullSource.string();
|
||||
const bool newZipFile = dest.open_new_file(sourceString);
|
||||
if (error::fslib(sourceFile.is_open()) || !newZipFile) { continue; }
|
||||
|
||||
const int64_t fileSize = sourceFile.get_size();
|
||||
|
|
@ -117,7 +118,7 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(ioStatus, fullSource.full_path());
|
||||
const std::string status = stringutil::get_formatted_string(ioStatus, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(fileSize));
|
||||
}
|
||||
|
|
@ -158,17 +159,13 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
}
|
||||
}
|
||||
|
||||
void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
||||
const fslib::Path &dest,
|
||||
int64_t journalSize,
|
||||
std::string_view commitDevice,
|
||||
sys::ProgressTask *task)
|
||||
void fs::copy_zip_to_directory(fs::MiniUnzip &unzip, const fslib::Path &dest, int64_t journalSize, sys::ProgressTask *task)
|
||||
{
|
||||
if (!unzip.reset()) { return; }
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
const char *popCommitFailed = strings::get_by_name(strings::names::IO_POPS, 0);
|
||||
const char *statusTemplate = strings::get_by_name(strings::names::IO_STATUSES, 2);
|
||||
const bool needCommits = journalSize > 0 && !commitDevice.empty();
|
||||
const bool needCommits = journalSize > 0;
|
||||
|
||||
do {
|
||||
if (unzip.get_filename() == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -178,9 +175,10 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
if (lastDir == fullDest.NOT_FOUND) { continue; }
|
||||
|
||||
const fslib::Path dirPath{fullDest.sub_path(lastDir)};
|
||||
const bool exists = dirPath.is_valid() && fslib::directory_exists(dirPath);
|
||||
const bool createError = dirPath.is_valid() && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
if (dirPath.is_valid() && !exists && createError) { continue; }
|
||||
const bool isValid = dirPath.is_valid();
|
||||
const bool exists = isValid && fslib::directory_exists(dirPath);
|
||||
const bool createError = isValid && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
if (isValid && !exists && createError) { continue; }
|
||||
|
||||
const int64_t fileSize = unzip.get_uncompressed_size();
|
||||
fslib::File destFile{fullDest, FsOpenMode_Create | FsOpenMode_Write, fileSize};
|
||||
|
|
@ -203,8 +201,8 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
bool &bufferReady = sharedData->bufferReady;
|
||||
std::unique_ptr<sys::byte[]> &sharedBuffer = sharedData->sharedBuffer;
|
||||
|
||||
std::thread readThread(unzipReadThreadFunction, std::ref(unzip), sharedData);
|
||||
int64_t journalCount{};
|
||||
std::thread readThread(unzipReadThreadFunction, std::ref(unzip), sharedData);
|
||||
for (int64_t i = 0; i < fileSize;)
|
||||
{
|
||||
ssize_t localRead{};
|
||||
|
|
@ -223,7 +221,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
if (commitNeeded)
|
||||
{
|
||||
destFile.close();
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(commitDevice));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); } // To do: How to recover?
|
||||
|
||||
destFile.open(fullDest, FsOpenMode_Write);
|
||||
|
|
@ -240,7 +238,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
readThread.join();
|
||||
destFile.close();
|
||||
|
||||
const bool commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(commitDevice));
|
||||
const bool commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
} while (unzip.next_file());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,16 +11,19 @@ void input::initialize()
|
|||
padInitializeDefault(&s_gamepad);
|
||||
}
|
||||
|
||||
void input::update() { padUpdate(&s_gamepad); }
|
||||
void input::update() noexcept { padUpdate(&s_gamepad); }
|
||||
|
||||
bool input::button_pressed(HidNpadButton button)
|
||||
bool input::button_pressed(HidNpadButton button) noexcept
|
||||
{
|
||||
return (s_gamepad.buttons_cur & button) && !(s_gamepad.buttons_old & button);
|
||||
}
|
||||
|
||||
bool input::button_held(HidNpadButton button) { return (s_gamepad.buttons_cur & button) && (s_gamepad.buttons_old & button); }
|
||||
bool input::button_held(HidNpadButton button) noexcept
|
||||
{
|
||||
return (s_gamepad.buttons_cur & button) && (s_gamepad.buttons_old & button);
|
||||
}
|
||||
|
||||
bool input::button_released(HidNpadButton button)
|
||||
bool input::button_released(HidNpadButton button) noexcept
|
||||
{
|
||||
return (s_gamepad.buttons_old & button) && !(s_gamepad.buttons_cur & button);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "keyboard.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user