Fixes and revisions
0
.gitignore
vendored
Normal file → Executable file
0
GD_INSTRUCTIONS.MD
Normal file → Executable file
0
icon.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
0
iconAssets/JKSV_icon.png
Normal file → Executable file
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
0
iconAssets/JKSV_icon.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
inc/appStates/appState.hpp
Normal file → Executable file
4
inc/appStates/backupMenuState.hpp
Normal file → Executable file
|
|
@ -29,10 +29,10 @@ class backupMenuState : public appState
|
|||
std::string m_BackupMenuControlGuide;
|
||||
// Base path for output
|
||||
std::string m_OutputBasePath;
|
||||
// Slide in/out panel
|
||||
std::unique_ptr<ui::slidePanel> m_BackupPanel;
|
||||
// Width of panel/text
|
||||
int m_PanelWidth;
|
||||
// Slide in/out panel
|
||||
std::unique_ptr<ui::slidePanel> m_BackupPanel;
|
||||
// Folder listing
|
||||
std::unique_ptr<fs::directoryListing> m_BackupListing;
|
||||
// Listing to make sure there is a save
|
||||
|
|
|
|||
1
inc/appStates/confirmState.hpp
Normal file → Executable file
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <switch.h>
|
||||
#include "appStates/appState.hpp"
|
||||
#include "system/timer.hpp"
|
||||
#include "system/task.hpp"
|
||||
|
|
|
|||
0
inc/appStates/mainMenuState.hpp
Normal file → Executable file
2
inc/appStates/progressState.hpp
Normal file → Executable file
|
|
@ -10,7 +10,7 @@
|
|||
class progressState : public appState
|
||||
{
|
||||
public:
|
||||
progressState(sys::taskFunction function, std::shared_ptr<sys::progressArgs> args, const uint64_t &maxValue);
|
||||
progressState(sys::taskFunction threadFunction, std::shared_ptr<sys::progressArgs> args, const uint64_t &maxValue);
|
||||
~progressState();
|
||||
void update(void);
|
||||
void render(void);
|
||||
|
|
|
|||
17
inc/appStates/taskState.hpp
Normal file → Executable file
|
|
@ -1,17 +1,32 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <switch.h>
|
||||
#include "appStates/appState.hpp"
|
||||
#include "system/timer.hpp"
|
||||
#include "system/task.hpp"
|
||||
|
||||
class taskState : public appState
|
||||
{
|
||||
public:
|
||||
taskState(sys::taskFunction function, std::shared_ptr<sys::taskArgs> args);
|
||||
taskState(sys::taskFunction threadFunction, std::shared_ptr<sys::taskArgs> args);
|
||||
~taskState();
|
||||
|
||||
void update(void);
|
||||
void render(void);
|
||||
|
||||
// This is so progressState can inherit this function
|
||||
void renderLoadingGlyph(void);
|
||||
|
||||
protected:
|
||||
// Task that is created and runs
|
||||
std::unique_ptr<sys::task> m_Task;
|
||||
// What frame of the glyph array we're on
|
||||
int m_GlyphFrame = 0;
|
||||
// Timer for updating loading glyph
|
||||
std::unique_ptr<sys::timer> m_LoadingGlyphTimer;
|
||||
// Bool for adding subtracting from color modifier
|
||||
bool m_ColorModifier = true;
|
||||
// Color modification for glyph
|
||||
uint8_t m_LoadingGlyphColorMod = 0x00;
|
||||
|
||||
};
|
||||
|
|
|
|||
0
inc/appStates/titleOptionState.hpp
Normal file → Executable file
0
inc/appStates/titleSelectionState.hpp
Normal file → Executable file
0
inc/config.hpp
Normal file → Executable file
0
inc/data/data.hpp
Normal file → Executable file
0
inc/data/titleInfo.hpp
Normal file → Executable file
0
inc/data/user.hpp
Normal file → Executable file
0
inc/data/userSaveInfo.hpp
Normal file → Executable file
3
inc/filesystem/directoryListing.hpp
Normal file → Executable file
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -28,6 +29,6 @@ namespace fs
|
|||
// Stores the path to the directory passed
|
||||
std::string m_DirectoryPath;
|
||||
// Stores the names of items from list
|
||||
std::vector<std::string> m_DirectoryList;
|
||||
std::vector<std::filesystem::directory_entry> m_DirectoryList;
|
||||
};
|
||||
}
|
||||
0
inc/filesystem/fileParser.hpp
Normal file → Executable file
2
inc/filesystem/filesystem.hpp
Normal file → Executable file
|
|
@ -17,6 +17,4 @@ namespace fs
|
|||
void unmountSaveData(void);
|
||||
// Commits to default save path
|
||||
void commitSaveData(void);
|
||||
// Erases current save data from device
|
||||
void eraseSaveData(void);
|
||||
}
|
||||
2
inc/filesystem/io.hpp
Normal file → Executable file
|
|
@ -43,8 +43,6 @@ namespace fs
|
|||
void copyDirectory(const std::string &source, const std::string &destination);
|
||||
// Recursively copies source to destination
|
||||
void copyDirectoryCommit(const std::string &source, const std::string &destination, const uint64_t &journalSize);
|
||||
// std::filesystem::remove all crashes switch? Had to write my own...
|
||||
void deleteDirectoryRecursively(const std::string &target);
|
||||
// These are functions for threaded copying that other parts of JKSV can use.
|
||||
void readThreadFunction(const std::string &source, std::shared_ptr<threadStruct> sharedStruct);
|
||||
void writeThreadFunction(const std::string &destination, std::shared_ptr<threadStruct> sharedStruct);
|
||||
|
|
|
|||
0
inc/filesystem/zip.hpp
Normal file → Executable file
0
inc/graphics/colors.hpp
Normal file → Executable file
0
inc/graphics/graphics.hpp
Normal file → Executable file
0
inc/graphics/systemFont.hpp
Normal file → Executable file
0
inc/graphics/textureNames.hpp
Normal file → Executable file
0
inc/jksv.hpp
Normal file → Executable file
0
inc/log.hpp
Normal file → Executable file
0
inc/stringUtil.hpp
Normal file → Executable file
4
inc/system/input.hpp
Normal file → Executable file
|
|
@ -17,6 +17,10 @@ namespace sys
|
|||
bool buttonHeld(const HidNpadButton &button);
|
||||
bool buttonReleased(const HidNpadButton &button);
|
||||
|
||||
uint64_t buttonsDown(void);
|
||||
uint64_t buttonsHeld(void);
|
||||
uint64_t buttonsReleased(void);
|
||||
|
||||
// Gets input and returns C++ string
|
||||
std::string getString(const std::string &defaultText, const std::string &headerText, const size_t &maximumLength);
|
||||
}
|
||||
|
|
|
|||
0
inc/system/progressArgs.hpp
Normal file → Executable file
12
inc/system/task.hpp
Normal file → Executable file
|
|
@ -12,15 +12,15 @@ namespace sys
|
|||
{
|
||||
class task;
|
||||
|
||||
using taskFunction = std::function<void(task *, std::shared_ptr<sys::taskArgs>)>;
|
||||
using taskFunction = std::function<void(sys::task *, std::shared_ptr<sys::taskArgs>)>;
|
||||
|
||||
class task
|
||||
{
|
||||
public:
|
||||
// taskFunction is
|
||||
task(taskFunction function, std::shared_ptr<taskArgs> args);
|
||||
// taskFunction is
|
||||
task(sys::taskFunction threadFunction, std::shared_ptr<taskArgs> args);
|
||||
~task();
|
||||
// Returns status string of task.
|
||||
// Returns status string of task.
|
||||
std::string getThreadStatus(void);
|
||||
// Sets status of task
|
||||
void setThreadStatus(const std::string &newStatus);
|
||||
|
|
@ -28,9 +28,9 @@ namespace sys
|
|||
void finished(void);
|
||||
// Returns if task
|
||||
bool isRunning(void);
|
||||
|
||||
|
||||
private:
|
||||
// Thread
|
||||
// Thread. Orignally used C++ threads, but without control they choked the main thread.
|
||||
std::unique_ptr<std::thread> m_Thread;
|
||||
// Status string
|
||||
std::string m_ThreadStatus;
|
||||
|
|
|
|||
0
inc/system/taskArgs.hpp
Normal file → Executable file
0
inc/system/timer.hpp
Normal file → Executable file
0
inc/ui/iconMenu.hpp
Normal file → Executable file
2
inc/ui/menu.hpp
Normal file → Executable file
|
|
@ -24,6 +24,8 @@ namespace ui
|
|||
void updateColorPulse(void);
|
||||
// Returns currently selected option
|
||||
int getSelected(void) const;
|
||||
// Sets selected option to newSelected
|
||||
void setSelected(const int &newSelected);
|
||||
// Clears all options from menu
|
||||
void clearMenu(void);
|
||||
|
||||
|
|
|
|||
0
inc/ui/popMessage.hpp
Normal file → Executable file
0
inc/ui/progressBar.hpp
Normal file → Executable file
0
inc/ui/slidePanel.hpp
Normal file → Executable file
0
inc/ui/strings.hpp
Normal file → Executable file
0
inc/ui/titleSelection.hpp
Normal file → Executable file
0
inc/ui/titleTile.hpp
Normal file → Executable file
0
inc/ui/ui.hpp
Normal file → Executable file
0
romfs/icon.png
Normal file → Executable file
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
0
romfs/img/dialogDark/dialogBottomLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
0
romfs/img/dialogDark/dialogBottomRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
0
romfs/img/dialogDark/dialogTopLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 290 B |
0
romfs/img/dialogDark/dialogTopRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
0
romfs/img/icn/icnDefault.png
Normal file → Executable file
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
0
romfs/img/icn/icnDrk.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
romfs/img/icn/icon.msk
Normal file → Executable file
0
romfs/img/icn/iconWhite.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
romfs/img/menu/backgroundDark.png
Normal file → Executable file
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
0
romfs/img/menu/backgroundLight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
0
romfs/img/menu/selectionBottomLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
romfs/img/menu/selectionBottomRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
romfs/img/menu/selectionTopLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
romfs/img/menu/selectionTopRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
0
romfs/img/tboxLght/progBarCoverLeftLight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
0
romfs/img/tboxLght/progBarCoverRightLight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 253 B |
0
romfs/img/tboxLght/tboxCornerBotLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
0
romfs/img/tboxLght/tboxCornerBotRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
0
romfs/img/tboxLght/tboxCornerTopLeft.png
Normal file → Executable file
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 279 B |
0
romfs/img/tboxLght/tboxCornerTopRight.png
Normal file → Executable file
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 285 B |
0
romfs/lang/de.txt
Normal file → Executable file
0
romfs/lang/en-GB.txt
Normal file → Executable file
0
romfs/lang/en-US.txt
Normal file → Executable file
0
romfs/lang/es-419.txt
Normal file → Executable file
0
romfs/lang/es.txt
Normal file → Executable file
0
romfs/lang/fr-CA.txt
Normal file → Executable file
0
romfs/lang/fr.txt
Normal file → Executable file
0
romfs/lang/it.txt
Normal file → Executable file
0
romfs/lang/ja.txt
Normal file → Executable file
0
romfs/lang/ko.txt
Normal file → Executable file
0
romfs/lang/nl.txt
Normal file → Executable file
0
romfs/lang/pt-BR.txt
Normal file → Executable file
0
romfs/lang/pt.txt
Normal file → Executable file
0
romfs/lang/ru.txt
Normal file → Executable file
0
romfs/lang/zh-CN.txt
Normal file → Executable file
0
romfs/lang/zh-TW.txt
Normal file → Executable file
0
src/appStates/appState.cpp
Normal file → Executable file
77
src/appStates/backupMenuState.cpp
Normal file → Executable file
|
|
@ -14,6 +14,14 @@
|
|||
#include "jksv.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
// Names of panels, render targets, and coordinates + dimensions of menu
|
||||
static const char *BACKUP_PANEL_NAME = "backupMenuPanel";
|
||||
static const char *BACKUP_MENU_TARGET_NAME = "backupMenuRenderTarget";
|
||||
static const int BACKUP_MENU_X = 10;
|
||||
static const int BACKUP_MENU_Y = 4;
|
||||
static const int BACKUP_MENU_FONT_SIZE = 18;
|
||||
static const int BACKUP_MENU_SCROLL_LENGTH = 6;
|
||||
|
||||
// This is for backup task
|
||||
struct backupArgs : sys::taskArgs
|
||||
{
|
||||
|
|
@ -37,7 +45,7 @@ struct pathArgs : sys::taskArgs
|
|||
|
||||
// These are the functions used for tasks
|
||||
// Creates a new backup when new is selected. args must be a backupArgs struct as a shared pointer
|
||||
void createNewBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
static void createNewBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
{
|
||||
// Make sure we weren't passed nullptr
|
||||
if (args == nullptr)
|
||||
|
|
@ -98,7 +106,7 @@ void createNewBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
}
|
||||
|
||||
// Overwrites a backup already on SD
|
||||
void overwriteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
static void overwriteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
{
|
||||
// Bail if no args present
|
||||
if (args == nullptr)
|
||||
|
|
@ -107,6 +115,9 @@ void overwriteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
return;
|
||||
}
|
||||
|
||||
// Error code for filesystem
|
||||
std::error_code errorCode;
|
||||
|
||||
// Set status, cast args to type
|
||||
task->setThreadStatus("REPLACE THIS LATER");
|
||||
std::shared_ptr<pathArgs> argsIn = std::static_pointer_cast<pathArgs>(args);
|
||||
|
|
@ -119,12 +130,12 @@ void overwriteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
// Delete backup then recreate directory
|
||||
// Add trailing slash first.
|
||||
std::string target = argsIn->destination + "/";
|
||||
// std::filesystem::remove_all keeps crashing my switch, so I wrote my own again
|
||||
fs::io::deleteDirectoryRecursively(target);
|
||||
// Delete old backup
|
||||
std::filesystem::remove_all(target, errorCode);
|
||||
// Recreate whole path.
|
||||
std::filesystem::create_directories(argsIn->destination);
|
||||
// Create the new backup in the same folder
|
||||
fs::io::copyDirectory(fs::DEFAULT_SAVE_MOUNT_DEVICE, argsIn->destination);
|
||||
fs::io::copyDirectory(fs::DEFAULT_SAVE_MOUNT_DEVICE, target);
|
||||
}
|
||||
else if (std::filesystem::is_directory(argsIn->destination) == false && fileExtension == "zip")
|
||||
{
|
||||
|
|
@ -141,7 +152,7 @@ void overwriteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
|
||||
// Wipes current save for game, then copies backup from SD to filesystem
|
||||
// Note: Needs to be tested better some time
|
||||
void restoreBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
static void restoreBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
{
|
||||
if (args == nullptr)
|
||||
{
|
||||
|
|
@ -149,6 +160,9 @@ void restoreBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
return;
|
||||
}
|
||||
|
||||
// Error code for later
|
||||
std::error_code errorCode;
|
||||
|
||||
// Set status, cast args
|
||||
task->setThreadStatus("REPLACE THIS LATER");
|
||||
std::shared_ptr<pathArgs> argsIn = std::static_pointer_cast<pathArgs>(args);
|
||||
|
|
@ -166,7 +180,7 @@ void restoreBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
if(testListing.getListingCount() > 0)
|
||||
{
|
||||
// Folder isn't empty, erase
|
||||
fs::eraseSaveData();
|
||||
std::filesystem::remove_all(fs::DEFAULT_SAVE_MOUNT_DEVICE, errorCode);
|
||||
// Copy source to save container
|
||||
fs::io::copyDirectoryCommit(source, fs::DEFAULT_SAVE_MOUNT_DEVICE, argsIn->journalSize);
|
||||
}
|
||||
|
|
@ -183,9 +197,11 @@ void restoreBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
// Close zip
|
||||
unzClose(unzip);
|
||||
}
|
||||
|
||||
task->finished();
|
||||
}
|
||||
|
||||
void deleteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
static void deleteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
{
|
||||
if (args == nullptr)
|
||||
{
|
||||
|
|
@ -193,6 +209,9 @@ void deleteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
return;
|
||||
}
|
||||
|
||||
// Error code for filesystem later
|
||||
std::error_code errorCode;
|
||||
|
||||
// Set thread status
|
||||
task->setThreadStatus(ui::strings::getString(LANG_THREAD_DELETE_FILE, 0));
|
||||
|
||||
|
|
@ -201,14 +220,15 @@ void deleteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
|
||||
if (std::filesystem::is_directory(argsIn->destination))
|
||||
{
|
||||
// Doesn't have trailing slash
|
||||
std::string target = argsIn->destination + "/";
|
||||
fs::io::deleteDirectoryRecursively(target);
|
||||
logger::log("%s is directory.", argsIn->destination.c_str());
|
||||
std::uintmax_t deleted = std::filesystem::remove_all(argsIn->destination, errorCode);
|
||||
logger::log("Error code: %s, %i - %u", errorCode.message().c_str(), errorCode.value(), deleted);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger::log("%s is not a directory", argsIn->destination.c_str());
|
||||
// Just remove it since it's probably a zip file
|
||||
std::filesystem::remove(argsIn->destination);
|
||||
std::filesystem::remove(argsIn->destination, errorCode);
|
||||
}
|
||||
// Refresh to reflect changes
|
||||
argsIn->sendingState->loadDirectoryList();
|
||||
|
|
@ -216,27 +236,23 @@ void deleteBackup(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
task->finished();
|
||||
}
|
||||
|
||||
backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : m_CurrentUser(currentUser), m_CurrentUserSaveInfo(currentUserSaveInfo), m_CurrentTitleInfo(currentTitleInfo)
|
||||
backupMenuState::backupMenuState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) :
|
||||
m_CurrentUser(currentUser),
|
||||
m_CurrentUserSaveInfo(currentUserSaveInfo),
|
||||
m_CurrentTitleInfo(currentTitleInfo),
|
||||
m_BackupMenuControlGuide(ui::strings::getString(LANG_FOLDER_GUIDE, 0)),
|
||||
m_OutputBasePath(config::getWorkingDirectory() + m_CurrentTitleInfo->getPathSafeTitle() + "/"),
|
||||
m_PanelWidth(graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18)),
|
||||
m_BackupPanel(std::make_unique<ui::slidePanel>(BACKUP_PANEL_NAME, m_PanelWidth + 64, ui::slidePanelSide::PANEL_SIDE_RIGHT)),
|
||||
m_BackupListing(std::make_unique<fs::directoryListing>(m_OutputBasePath)),
|
||||
m_SaveListing(std::make_unique<fs::directoryListing>(fs::DEFAULT_SAVE_MOUNT_DEVICE)),
|
||||
m_BackupMenu(std::make_unique<ui::menu>(BACKUP_MENU_X, BACKUP_MENU_Y, m_PanelWidth + 44, BACKUP_MENU_FONT_SIZE, BACKUP_MENU_SCROLL_LENGTH))
|
||||
{
|
||||
// This is the path used for all in/output. Create it if it doesn't exist.
|
||||
m_OutputBasePath = config::getWorkingDirectory() + m_CurrentTitleInfo->getPathSafeTitle() + "/";
|
||||
// Make sure path exists
|
||||
std::filesystem::create_directories(m_OutputBasePath);
|
||||
|
||||
// Controls displayed at bottom
|
||||
m_BackupMenuControlGuide = ui::strings::getString(LANG_FOLDER_GUIDE, 0);
|
||||
m_PanelWidth = graphics::systemFont::getTextWidth(m_BackupMenuControlGuide, 18);
|
||||
|
||||
// The actual panel
|
||||
m_BackupPanel = std::make_unique<ui::slidePanel>("backupMenuPanel", m_PanelWidth + 64, ui::slidePanelSide::PANEL_SIDE_RIGHT);
|
||||
// The menu of backups
|
||||
m_BackupMenu = std::make_unique<ui::menu>(10, 4, m_PanelWidth + 44, 18, 6);
|
||||
// Render target that menu is rendered to
|
||||
m_BackupMenuRenderTarget = graphics::textureCreate("backupMenuRenderTarget", m_PanelWidth + 64, 647, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
// Directory listing of backups
|
||||
m_BackupListing = std::make_unique<fs::directoryListing>(m_OutputBasePath);
|
||||
// Directory listing of save
|
||||
m_SaveListing = std::make_unique<fs::directoryListing>(fs::DEFAULT_SAVE_MOUNT_DEVICE);
|
||||
|
||||
m_BackupMenuRenderTarget = graphics::textureCreate(BACKUP_MENU_TARGET_NAME, m_PanelWidth + 64, 647, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
// Call this just to be sure.
|
||||
backupMenuState::loadDirectoryList();
|
||||
}
|
||||
|
||||
|
|
@ -361,6 +377,7 @@ void backupMenuState::loadDirectoryList(void)
|
|||
// Reload list, clear menu
|
||||
m_BackupListing->loadListing();
|
||||
m_BackupMenu->clearMenu();
|
||||
m_BackupMenu->setSelected(0);
|
||||
|
||||
int listingCount = m_BackupListing->getListingCount();
|
||||
m_BackupMenu->addOpt(ui::strings::getString(LANG_FOLDER_MENU_NEW, 0));
|
||||
|
|
|
|||
15
src/appStates/confirmState.cpp
Normal file → Executable file
|
|
@ -8,14 +8,13 @@
|
|||
|
||||
static const int HOLD_TICKS = 1000;
|
||||
|
||||
confirmState::confirmState(const std::string &message, sys::taskFunction onConfirmation, std::shared_ptr<sys::taskArgs> args) : m_Message(message), m_OnConfirmation(onConfirmation), m_Args(args)
|
||||
{
|
||||
// Init timer
|
||||
m_HoldTimer = std::make_unique<sys::timer>(HOLD_TICKS);
|
||||
// Get Text for yes and no
|
||||
m_Yes = ui::strings::getString(LANG_DIALOG_YES, 0);
|
||||
m_No = ui::strings::getString(LANG_DIALOG_NO, 0);
|
||||
}
|
||||
confirmState::confirmState(const std::string &message, sys::taskFunction onConfirmation, std::shared_ptr<sys::taskArgs> args) :
|
||||
m_Message(message),
|
||||
m_Yes(ui::strings::getString(LANG_DIALOG_YES, 0)),
|
||||
m_No(ui::strings::getString(LANG_DIALOG_NO, 0)),
|
||||
m_HoldTimer(std::make_unique<sys::timer>(HOLD_TICKS)),
|
||||
m_OnConfirmation(onConfirmation),
|
||||
m_Args(args) { }
|
||||
|
||||
confirmState::~confirmState() { }
|
||||
|
||||
|
|
|
|||
29
src/appStates/mainMenuState.cpp
Normal file → Executable file
|
|
@ -1,3 +1,4 @@
|
|||
#include <chrono>
|
||||
#include "jksv.hpp"
|
||||
#include "appStates/mainMenuState.hpp"
|
||||
#include "appStates/titleSelectionState.hpp"
|
||||
|
|
@ -10,26 +11,34 @@
|
|||
#include "stringUtil.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
// Main menu coordinates and dimensions
|
||||
static const int MAIN_MENU_X = 50;
|
||||
static const int MAIN_MENU_Y = 16;
|
||||
static const int MAIN_MENU_SCROLL_LENGTH = 1;
|
||||
|
||||
// Texture names
|
||||
static const char *MAIN_MENU_RENDER_TARGET = "mainMenuRenderTarget";
|
||||
static const char *MAIN_MENU_SETTINGS = "mainMenuSettings";
|
||||
static const char *MAIN_MENU_EXTRAS = "mainMenuExtras";
|
||||
|
||||
// Tasks
|
||||
static void backupAllUserSaves(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
||||
static void backupAllUserSaves(void *in)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
mainMenuState::mainMenuState(void)
|
||||
mainMenuState::mainMenuState(void) :
|
||||
m_MainControlGuide(ui::strings::getString(LANG_USER_GUIDE, 0)),
|
||||
m_MainControlGuideX(1220 - graphics::systemFont::getTextWidth(m_MainControlGuide, 18)),
|
||||
m_MainMenu(std::make_unique<ui::iconMenu>(MAIN_MENU_X, MAIN_MENU_Y, MAIN_MENU_SCROLL_LENGTH))
|
||||
{
|
||||
// Setup control guide
|
||||
m_MainControlGuide = ui::strings::getString(LANG_USER_GUIDE, 0);
|
||||
m_MainControlGuideX = 1220 - graphics::systemFont::getTextWidth(m_MainControlGuide, 18);
|
||||
|
||||
// Render target
|
||||
m_RenderTarget = graphics::textureCreate("mainMenuRenderTarget", 200, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
m_RenderTarget = graphics::textureCreate(MAIN_MENU_RENDER_TARGET, 200, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
|
||||
// Load gradient for behind menu
|
||||
m_MenuBackgroundTexture = graphics::textureLoadFromFile(TEXTURE_MENU_BACKGROUND, "romfs:/img/menu/backgroundDark.png");
|
||||
|
||||
// Setup menu
|
||||
m_MainMenu = std::make_unique<ui::iconMenu>(50, 16, 1);
|
||||
m_UserEnd = data::getTotalUsers();
|
||||
for (int i = 0; i < m_UserEnd; i++)
|
||||
{
|
||||
|
|
@ -40,8 +49,8 @@ mainMenuState::mainMenuState(void)
|
|||
// Settings & extras
|
||||
std::string settingsString = ui::strings::getString(LANG_MAIN_MENU_SETTINGS, 0);
|
||||
std::string extrasString = ui::strings::getString(LANG_MAIN_MENU_EXTRAS, 0);
|
||||
m_MainMenu->addOpt(graphics::createIcon("mainMenuSettings", settingsString, 42));
|
||||
m_MainMenu->addOpt(graphics::createIcon("mainMenuExtras", extrasString, 42));
|
||||
m_MainMenu->addOpt(graphics::createIcon(MAIN_MENU_SETTINGS, settingsString, 42));
|
||||
m_MainMenu->addOpt(graphics::createIcon(MAIN_MENU_EXTRAS, extrasString, 42));
|
||||
}
|
||||
|
||||
mainMenuState::~mainMenuState() {}
|
||||
|
|
|
|||
4
src/appStates/progressState.cpp
Normal file → Executable file
|
|
@ -1,8 +1,8 @@
|
|||
#include "appStates/progressState.hpp"
|
||||
|
||||
progressState::progressState(sys::taskFunction function, std::shared_ptr<sys::progressArgs> args, const uint64_t &maxValue)
|
||||
progressState::progressState(sys::taskFunction threadFunction, std::shared_ptr<sys::progressArgs> args, const uint64_t &maxValue)
|
||||
{
|
||||
m_Task = std::make_unique<sys::task>(function, args);
|
||||
m_Task = std::make_unique<sys::task>(threadFunction, args);
|
||||
m_ProgressBar = std::make_unique<ui::progressBar>(maxValue);
|
||||
}
|
||||
|
||||
|
|
|
|||
40
src/appStates/taskState.cpp
Normal file → Executable file
|
|
@ -1,10 +1,20 @@
|
|||
#include "appStates/taskState.hpp"
|
||||
#include "graphics/graphics.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
taskState::taskState(sys::taskFunction function, std::shared_ptr<sys::taskArgs> args)
|
||||
// Time in ticks before changing glyph frames
|
||||
static const int GLYPH_CHANGE_TICKS = 50;
|
||||
|
||||
// These are the actual glyphs
|
||||
static const std::string s_LoadGlyphArray[8] =
|
||||
{
|
||||
m_Task = std::make_unique<sys::task>(function, args);
|
||||
}
|
||||
"\ue020", "\ue021", "\ue022", "\ue023",
|
||||
"\ue024", "\ue025", "\ue026", "\ue027"
|
||||
};
|
||||
|
||||
taskState::taskState(sys::taskFunction threadFunction, std::shared_ptr<sys::taskArgs> args) :
|
||||
m_Task(std::make_unique<sys::task>(threadFunction, args)),
|
||||
m_LoadingGlyphTimer(std::make_unique<sys::timer>(GLYPH_CHANGE_TICKS)) { }
|
||||
|
||||
taskState::~taskState() { }
|
||||
|
||||
|
|
@ -21,8 +31,32 @@ void taskState::render(void)
|
|||
// Get thread status and calculate centered text
|
||||
std::string taskStatus = m_Task->getThreadStatus();
|
||||
int taskStatusX = 640 - (graphics::systemFont::getTextWidth(taskStatus, 24) / 2);
|
||||
|
||||
// Render glyph in bottom left corner
|
||||
renderLoadingGlyph();
|
||||
|
||||
// Dim background and render text to screen
|
||||
graphics::renderRect(NULL, 0, 0, 1280, 720, COLOR_DIM_BACKGROUND);
|
||||
graphics::systemFont::renderText(taskStatus, NULL, taskStatusX, 348, 24, COLOR_WHITE);
|
||||
}
|
||||
|
||||
void taskState::renderLoadingGlyph(void)
|
||||
{
|
||||
// If timer is triggered, update glyph frame
|
||||
if(m_LoadingGlyphTimer->triggered() && ++m_GlyphFrame == 8)
|
||||
{
|
||||
m_GlyphFrame = 0;
|
||||
}
|
||||
|
||||
// If true, we're adding, false subtracting
|
||||
if(m_ColorModifier && (m_LoadingGlyphColorMod += 6) >= 0x72)
|
||||
{
|
||||
m_ColorModifier = false;
|
||||
}
|
||||
else if(m_ColorModifier && (m_LoadingGlyphColorMod -= 3) <= 0x00)
|
||||
{
|
||||
m_ColorModifier = true;
|
||||
}
|
||||
|
||||
graphics::systemFont::renderText(s_LoadGlyphArray[m_GlyphFrame], NULL, 56, 673, 32, createColor(0x00, (0x88 + m_LoadingGlyphColorMod), (0xC5 + (m_LoadingGlyphColorMod / 2)), 0xFF));
|
||||
}
|
||||
53
src/appStates/titleOptionState.cpp
Normal file → Executable file
|
|
@ -1,4 +1,5 @@
|
|||
#include <memory>
|
||||
#include <filesystem>
|
||||
#include "appStates/titleOptionState.hpp"
|
||||
#include "appStates/confirmState.hpp"
|
||||
#include "data/data.hpp"
|
||||
|
|
@ -6,9 +7,21 @@
|
|||
#include "ui/ui.hpp"
|
||||
#include "system/task.hpp"
|
||||
#include "system/input.hpp"
|
||||
#include "stringUtil.hpp"
|
||||
#include "jksv.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
// Texture/target names
|
||||
const char *PANEL_RENDER_TARGET_NAME = "titleOptionPanel";
|
||||
|
||||
// Dimensions and coordinates for panel and menu
|
||||
static const int PANEL_WIDTH = 410;
|
||||
static const int MENU_X = 10;
|
||||
static const int MENU_Y = 32;
|
||||
static const int MENU_WIDTH = 390;
|
||||
static const int MENU_FONT_SIZE = 20;
|
||||
static const int MENU_SCROLL_LENGTH = 7;
|
||||
|
||||
enum
|
||||
{
|
||||
TITLE_INFO,
|
||||
|
|
@ -39,28 +52,28 @@ void resetSaveData(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
task->finished();
|
||||
return;
|
||||
}
|
||||
logger::log("Arg check");
|
||||
|
||||
// Error code for filesystem
|
||||
std::error_code errorCode;
|
||||
|
||||
// Set status
|
||||
task->setThreadStatus(ui::strings::getString(LANG_THREAD_RESET_SAVE_DATA, 0));
|
||||
logger::log("Set status");
|
||||
|
||||
// Cast args
|
||||
std::shared_ptr<titleOptsArgs> argsIn = std::static_pointer_cast<titleOptsArgs>(args);
|
||||
logger::log("Cast pointer");
|
||||
|
||||
if(fs::mountSaveData(argsIn->currentUserSaveInfo->getSaveDataInfo()))
|
||||
{
|
||||
logger::log("Save mounted");
|
||||
// This does everything this needs
|
||||
fs::eraseSaveData();
|
||||
logger::log("Erase Save Data");
|
||||
// Erase save data in container
|
||||
// To do: remove_all keeps failing if the folder has sub dirs. Maybe I should just stick with my own?
|
||||
std::filesystem::remove_all(fs::DEFAULT_SAVE_MOUNT_DEVICE, errorCode);
|
||||
// Commit changes
|
||||
fs::commitSaveData();
|
||||
// Close
|
||||
fs::unmountSaveData();
|
||||
logger::log("unmount");
|
||||
// Display success
|
||||
ui::popMessage::newMessage(ui::strings::getString(LANG_SAVEDATA_RESET_SUCCESS, 0), ui::popMessage::POPMESSAGE_DEFAULT_TICKS);
|
||||
logger::log("POP");
|
||||
std::string successMessage = stringUtil::getFormattedString(ui::strings::getCString(LANG_SAVEDATA_RESET_SUCCESS, 0), argsIn->currentTitleInfo->getTitle().c_str());
|
||||
ui::popMessage::newMessage(successMessage, ui::popMessage::POPMESSAGE_DEFAULT_TICKS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -71,12 +84,13 @@ void resetSaveData(sys::task *task, std::shared_ptr<sys::taskArgs> args)
|
|||
task->finished();
|
||||
}
|
||||
|
||||
titleOptionState::titleOptionState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) : m_CurrentUser(currentUser), m_CurrentUserSaveInfo(currentUserSaveInfo), m_CurrentTitleInfo(currentTitleInfo)
|
||||
titleOptionState::titleOptionState(data::user *currentUser, data::userSaveInfo *currentUserSaveInfo, data::titleInfo *currentTitleInfo) :
|
||||
m_CurrentUser(currentUser),
|
||||
m_CurrentUserSaveInfo(currentUserSaveInfo),
|
||||
m_CurrentTitleInfo(currentTitleInfo),
|
||||
m_SlidePanel(std::make_unique<ui::slidePanel>(PANEL_RENDER_TARGET_NAME, PANEL_WIDTH, ui::PANEL_SIDE_RIGHT)),
|
||||
m_OptionsMenu(std::make_unique<ui::menu>(MENU_X, MENU_Y, MENU_WIDTH, MENU_FONT_SIZE, MENU_SCROLL_LENGTH))
|
||||
{
|
||||
// Slide out panel
|
||||
m_SlidePanel = std::make_unique<ui::slidePanel>("titleOptionPanel", 410, ui::PANEL_SIDE_RIGHT);
|
||||
// Menu
|
||||
m_OptionsMenu = std::make_unique<ui::menu>(10, 32, 390, 20, 7);
|
||||
// Setup menu
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
|
|
@ -105,6 +119,7 @@ void titleOptionState::update(void)
|
|||
// Data to send
|
||||
std::shared_ptr<titleOptsArgs> args = std::make_shared<titleOptsArgs>();
|
||||
args->currentUserSaveInfo = m_CurrentUserSaveInfo;
|
||||
args->currentTitleInfo = m_CurrentTitleInfo;
|
||||
|
||||
// Confirm state
|
||||
std::unique_ptr<appState> confirmReset = std::make_unique<confirmState>(confirmationString, resetSaveData, args);
|
||||
|
|
@ -115,10 +130,10 @@ void titleOptionState::update(void)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ui::popMessage::newMessage("Not implemented yet...", ui::popMessage::POPMESSAGE_DEFAULT_TICKS);
|
||||
}
|
||||
break;
|
||||
{
|
||||
ui::popMessage::newMessage("Not implemented yet...", ui::popMessage::POPMESSAGE_DEFAULT_TICKS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(sys::input::buttonDown(HidNpadButton_B))
|
||||
|
|
|
|||
20
src/appStates/titleSelectionState.cpp
Normal file → Executable file
|
|
@ -9,18 +9,20 @@
|
|||
#include "log.hpp"
|
||||
#include "jksv.hpp"
|
||||
|
||||
// Texture names
|
||||
const char *TITLE_SELECT_RENDER_TARGET = "titleSelectionRenderTarget";
|
||||
|
||||
titleSelectionState::titleSelectionState(data::user *currentUser) : m_CurrentUser(currentUser)
|
||||
// Render target dimensions
|
||||
static const int RENDER_TARGET_WIDTH = 1080;
|
||||
static const int RENDER_TARGET_HEIGHT = 555;
|
||||
|
||||
titleSelectionState::titleSelectionState(data::user *currentUser) :
|
||||
m_CurrentUser(currentUser),
|
||||
m_TitleSelection(std::make_unique<ui::titleSelection>(m_CurrentUser)),
|
||||
m_TitleControlGuide(ui::strings::getString(LANG_TITLE_GUIDE, 0))
|
||||
{
|
||||
// Setup control string
|
||||
m_TitleControlGuide = ui::strings::getString(LANG_TITLE_GUIDE, 0);
|
||||
m_TitleControlGuideX = 1220 - graphics::systemFont::getTextWidth(m_TitleControlGuide, 18);
|
||||
|
||||
// Render target to render everything too
|
||||
m_RenderTarget = graphics::textureCreate("titleSelectionRenderTarget", 1080, 555, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
|
||||
// Icon
|
||||
m_TitleSelection = std::make_unique<ui::titleSelection>(m_CurrentUser);
|
||||
m_RenderTarget = graphics::textureCreate(TITLE_SELECT_RENDER_TARGET, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET);
|
||||
}
|
||||
|
||||
titleSelectionState::~titleSelectionState() {}
|
||||
|
|
|
|||
0
src/config.cpp
Normal file → Executable file
0
src/data/data.cpp
Normal file → Executable file
0
src/data/titleInfo.cpp
Normal file → Executable file
0
src/data/user.cpp
Normal file → Executable file
0
src/data/userSaveInfo.cpp
Normal file → Executable file
23
src/filesystem/directoryListing.cpp
Normal file → Executable file
|
|
@ -14,9 +14,12 @@ void fs::directoryListing::loadListing(void)
|
|||
// Clear vector first JIC reload
|
||||
m_DirectoryList.clear();
|
||||
|
||||
for(const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(m_DirectoryPath))
|
||||
// Error code
|
||||
std::error_code errorCode;
|
||||
|
||||
for(const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(m_DirectoryPath, errorCode))
|
||||
{
|
||||
m_DirectoryList.push_back(entry.path().string());
|
||||
m_DirectoryList.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,26 +30,30 @@ int fs::directoryListing::getListingCount(void) const
|
|||
|
||||
bool fs::directoryListing::itemAtIsDirectory(const int &index) const
|
||||
{
|
||||
return std::filesystem::is_directory(m_DirectoryList.at(index));
|
||||
return m_DirectoryList.at(index).is_directory();
|
||||
}
|
||||
|
||||
std::string fs::directoryListing::getFullPathToItemAt(const int &index) const
|
||||
{
|
||||
return m_DirectoryList.at(index);
|
||||
return m_DirectoryList.at(index).path().string();
|
||||
}
|
||||
|
||||
std::string fs::directoryListing::getItemAt(const int &index) const
|
||||
{
|
||||
size_t lastSlash = m_DirectoryList.at(index).find_last_of('/') + 1;
|
||||
return m_DirectoryList.at(index).substr(lastSlash, m_DirectoryList.at(index).npos);
|
||||
// Get string first
|
||||
std::string itemString = m_DirectoryList.at(index).path().string();
|
||||
// Find last slash
|
||||
size_t lastSlash = itemString.find_last_of('/') + 1;
|
||||
// Return sub string
|
||||
return itemString.substr(lastSlash, itemString.npos);
|
||||
}
|
||||
|
||||
std::string fs::directoryListing::getFilenameAt(const int &index) const
|
||||
{
|
||||
return stringUtil::getFilenameFromString(m_DirectoryList.at(index));
|
||||
return stringUtil::getFilenameFromString(m_DirectoryList.at(index).path().string());
|
||||
}
|
||||
|
||||
std::string fs::directoryListing::getExtensionAt(const int &index) const
|
||||
{
|
||||
return stringUtil::getExtensionFromString(m_DirectoryList.at(index));
|
||||
return stringUtil::getExtensionFromString(m_DirectoryList.at(index).path().string());
|
||||
}
|
||||