Minor code revisions in preparation for cache system on 20.0+

This commit is contained in:
J-D-K 2025-05-28 18:33:58 -04:00
parent 291d2fd82f
commit c094030c52
19 changed files with 1599 additions and 959 deletions

136
.clang-format Normal file
View File

@ -0,0 +1,136 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: true
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Right
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
...

9
.clang-tidy Normal file
View File

@ -0,0 +1,9 @@
---
Checks: 'clang-analyzer-*,cppcoreguidelines-*,modernize-*,bugprone-*,performance-*,readability-*,readability-non-const-parameter,misc-const-correctness,misc-use-anonymous-namespace,google-explicit-constructor,-modernize-use-trailing-return-type,-bugprone-exception-escape,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers,-bugprone-easily-swappable-parameters,-cppcoreguidelines-non-private-member-variables-in-classes'
WarningsAsErrors: ''
HeaderFilterRegex: ''
CheckOptions:
- key: readability-magic-numbers.IgnoredFloatingPointValues
value: '0.0;1.0;100.0;'
- key: readability-magic-numbers.IgnoredIntegerValues
value: '0;1;2;3;4;5;6;7;8;9;'

11
.gitattributes vendored Normal file
View File

@ -0,0 +1,11 @@
# Set the default behavior for all files.
* text=auto eol=lf
# Normalized and converts to native line endings on checkout.
*.c text
*.cc text
*.cxx
*.cpp text
*.h text
*.hxx text
*.hpp text

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ build/
.vscode/
*.cbp
*.layout
.editorconfig
.idea/
cmake-build-debug/

View File

@ -1,8 +1,9 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
#include <vector>
namespace cfg
{
@ -17,18 +18,18 @@ namespace cfg
void loadConfig();
void saveConfig();
bool isBlacklisted(const uint64_t& tid);
bool isBlacklisted(uint64_t tid);
void addTitleToBlacklist(void *a);
void removeTitleFromBlacklist(const uint64_t& tid);
void removeTitleFromBlacklist(uint64_t tid);
bool isFavorite(const uint64_t& tid);
void addTitleToFavorites(const uint64_t& tid);
bool isFavorite(uint64_t tid);
void addTitleToFavorites(uint64_t tid);
bool isDefined(const uint64_t& tid);
void pathDefAdd(const uint64_t& tid, const std::string& newPath);
std::string getPathDefinition(const uint64_t& tid);
bool isDefined(uint64_t tid);
void pathDefAdd(uint64_t tid, const std::string &newPath);
std::string getPathDefinition(uint64_t tid);
void addPathToFilter(const uint64_t& tid, const std::string& _p);
void addPathToFilter(uint64_t tid, const std::string &_p);
extern std::unordered_map<std::string, bool> config;
extern std::vector<uint64_t> blacklist;
@ -36,4 +37,4 @@ namespace cfg
extern uint8_t sortType;
extern std::string driveClientID, driveClientSecret, driveRefreshToken;
extern std::string webdavOrigin, webdavBasePath, webdavUser, webdavPassword;
}
} // namespace cfg

View File

@ -1,87 +1,115 @@
#pragma once
#include <switch.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <vector>
#include "gfx.h"
#define BLD_MON 11
#define BLD_DAY 5
#define BLD_YEAR 2024
#define BLD_MON 5
#define BLD_DAY 28
#define BLD_YEAR 2025
namespace data
{
//Loads user + title info
// Loads user + title info
void init();
void exit();
bool loadUsersTitles(bool clearUsers);
void sortUserTitles();
//Draws some stats to the upper left corner
// Draws some stats to the upper left corner
void dispStats();
//Global stuff for all titles/saves
// Global stuff for all titles/saves
typedef struct
{
NacpStruct nacp;
std::string title, safeTitle, author;//Shortcuts sorta.
SDL_Texture *icon = NULL;
bool fav;
/// @brief Control data.
NsApplicationControlData data;
/// @brief Saves whether or not the title has valid control data.
bool hasControlData = false;
std::string title, safeTitle, author;
SDL_Texture *icon = NULL;
bool fav;
} titleInfo;
//Holds stuff specific to user's titles/saves
// Holds stuff specific to user's titles/saves
typedef struct
{
//Makes it easier to grab id
uint64_t tid;
FsSaveDataInfo saveInfo;
PdmPlayStatistics playStats;
// Makes it easier to grab id
uint64_t tid;
FsSaveDataInfo saveInfo;
PdmPlayStatistics playStats;
} userTitleInfo;
//Class to store user info + titles
// Class to store user info + titles
class user
{
public:
user() = default;
user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName);
user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName, SDL_Texture *img);
user(AccountUid _id, const std::string &_backupName, const std::string &_safeBackupName);
user(AccountUid _id, const std::string &_backupName, const std::string &_safeBackupName, SDL_Texture *img);
//Sets ID
void setUID(const AccountUid& _id);
// Sets ID
void setUID(AccountUid _id);
//Assigns icon
void assignIcon(SDL_Texture *_icn) { userIcon = _icn; }
// Assigns icon
void assignIcon(SDL_Texture *_icn)
{
userIcon = _icn;
}
//Returns user ID
AccountUid getUID() const { return userID; }
u128 getUID128() const { return uID128; }
// Returns user ID
AccountUid getUID() const
{
return userID;
}
u128 getUID128() const
{
return uID128;
}
//Returns username
std::string getUsername() const { return username; }
std::string getUsernameSafe() const { return userSafe; }
// Returns username
std::string getUsername() const
{
return username;
}
std::string getUsernameSafe() const
{
return userSafe;
}
SDL_Texture *getUserIcon(){ return userIcon; }
void delIcon(){ SDL_DestroyTexture(userIcon); }
SDL_Texture *getUserIcon()
{
return userIcon;
}
void delIcon()
{
SDL_DestroyTexture(userIcon);
}
std::vector<data::userTitleInfo> titleInfo;
void addUserTitleInfo(const uint64_t& _tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats);
void addUserTitleInfo(const uint64_t &_tid,
const FsSaveDataInfo *_saveInfo,
const PdmPlayStatistics *_stats);
private:
AccountUid userID;
u128 uID128;
std::string username, userSafe;
//User icon
// User icon
SDL_Texture *userIcon;
};
//User vector
// User vector
extern std::vector<user> users;
//Title data/info map
// Title data/info map
extern std::unordered_map<uint64_t, data::titleInfo> titles;
//Sets/Retrieves current user/title
// Sets/Retrieves current user/title
void setUserIndex(unsigned _sUser);
data::user *getCurrentUser();
unsigned getCurrentUserIndex();
@ -90,14 +118,14 @@ namespace data
data::userTitleInfo *getCurrentUserTitleInfo();
unsigned getCurrentUserTitleInfoIndex();
//Gets pointer to info that also has title + nacp
data::titleInfo *getTitleInfoByTID(const uint64_t& tid);
// Gets pointer to info that also has title + nacp
data::titleInfo *getTitleInfoByTID(const uint64_t &tid);
//More shortcut functions
std::string getTitleNameByTID(const uint64_t& tid);
std::string getTitleSafeNameByTID(const uint64_t& tid);
SDL_Texture *getTitleIconByTID(const uint64_t& tid);
int getTitleIndexInUser(const data::user& u, const uint64_t& tid);
// More shortcut functions
std::string getTitleNameByTID(const uint64_t &tid);
std::string getTitleSafeNameByTID(const uint64_t &tid);
SDL_Texture *getTitleIconByTID(const uint64_t &tid);
int getTitleIndexInUser(const data::user &u, const uint64_t &tid);
extern SetLanguage sysLang;
}
} // namespace data

View File

@ -1,14 +1,14 @@
#pragma once
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include <minizip/zip.h>
#include "fs/fstype.h"
#include "fs/file.h"
#include "fs/dir.h"
#include "fs/zip.h"
#include "fs/file.h"
#include "fs/fsfile.h"
#include "fs/fstype.h"
#include "fs/remote.h"
#include "fs/zip.h"
#include "ui/miscui.h"
#define BUFF_SIZE 0x4000
@ -17,19 +17,29 @@
namespace fs
{
copyArgs *copyArgsCreate(const std::string& src, const std::string& dst, const std::string& dev, zipFile z, unzFile unz, bool _cleanup, bool _trimZipPath, uint8_t _trimPlaces);
copyArgs *copyArgsCreate(const std::string &src,
const std::string &dst,
const std::string &dev,
zipFile z,
unzFile unz,
bool _cleanup,
bool _trimZipPath,
uint8_t _trimPlaces);
void copyArgsDestroy(copyArgs *c);
void init();
bool mountSave(const FsSaveDataInfo& _m);
inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; }
bool commitToDevice(const std::string& dev);
bool mountSave(const FsSaveDataInfo &_m);
inline bool unmountSave()
{
return fsdevUnmountDevice("sv") == 0;
}
bool commitToDevice(const std::string &dev);
std::string getWorkDir();
void setWorkDir(const std::string& _w);
void setWorkDir(const std::string &_w);
//Loads paths to filter from backup/deletion
void loadPathFilters(const uint64_t& tid);
bool pathIsFiltered(const std::string& _path);
void loadPathFilters(uint64_t tid);
bool pathIsFiltered(const std::string &_path);
void freePathFilters();
void createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, threadInfo *t);
@ -52,4 +62,4 @@ namespace fs
void logOpen();
void logWrite(const char *fmt, ...);
}
} // namespace fs

View File

@ -1,31 +1,41 @@
#pragma once
#include <string>
#include "type.h"
#include <string>
#include <vector>
namespace fs
{
void mkDir(const std::string& _p);
void mkDirRec(const std::string& _p);
void delDir(const std::string& _p);
bool dirNotEmpty(const std::string& _dir);
bool isDir(const std::string& _path);
void mkDir(const std::string &_p);
void mkDirRec(const std::string &_p);
void delDir(const std::string &_p);
bool dirNotEmpty(const std::string &_dir);
bool isDir(const std::string &_path);
//threadInfo is optional. Only for updating task status.
void copyDirToDir(const std::string& src, const std::string& dst, threadInfo *t);
void copyDirToDirThreaded(const std::string& src, const std::string& dst);
void copyDirToDirCommit(const std::string& src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyDirToDirCommitThreaded(const std::string& src, const std::string& dst, const std::string& dev);
void getDirProps(const std::string& path, unsigned& dirCount, unsigned& fileCount, uint64_t& totalSize);
void copyDirToDir(const std::string &src, const std::string &dst, threadInfo *t);
void copyDirToDirThreaded(const std::string &src, const std::string &dst);
void copyDirToDirCommit(const std::string &src, const std::string &dst, const std::string &dev, threadInfo *t);
void copyDirToDirCommitThreaded(const std::string &src, const std::string &dst, const std::string &dev);
void getDirProps(const std::string &path, unsigned &dirCount, unsigned &fileCount, uint64_t &totalSize);
class dirItem
{
public:
dirItem(const std::string& pathTo, const std::string& sItem);
std::string getItm() const { return itm; }
dirItem(const std::string &pathTo, const std::string &sItem);
std::string getItm() const
{
return itm;
}
std::string getName() const;
std::string getExt() const;
bool isDir() const { return dir; }
bool isDir() const
{
return dir;
}
private:
std::string itm;
@ -37,18 +47,37 @@ namespace fs
{
public:
dirList() = default;
dirList(const std::string& _path, bool ignoreDotFiles = false);
void reassign(const std::string& _path);
dirList(const std::string &_path, bool ignoreDotFiles = false);
void reassign(const std::string &_path);
void rescan();
std::string getItem(int index) const { return item[index].getItm(); }
std::string getItemExt(int index) const { return item[index].getExt(); }
bool isDir(int index) const { return item[index].isDir(); }
unsigned getCount() const { return item.size(); }
fs::dirItem *getDirItemAt(unsigned int _ind) { return &item[_ind]; }
std::string getItem(int index) const
{
return item[index].getItm();
}
std::string getItemExt(int index) const
{
return item[index].getExt();
}
bool isDir(int index) const
{
return item[index].isDir();
}
unsigned getCount() const
{
return item.size();
}
fs::dirItem *getDirItemAt(unsigned int _ind)
{
return &item[_ind];
}
private:
std::string path;
std::vector<dirItem> item;
};
}
} // namespace fs

View File

@ -4,7 +4,7 @@ namespace ui
{
void fmInit();
void fmExit();
void fmPrep(const FsSaveDataType& _type, const std::string& _dev, const std::string& _baseSDMC, bool _commit);
void fmPrep(FsSaveDataType _type, const std::string &_dev, const std::string &_baseSDMC, bool _commit);
void fmUpdate();
void fmDraw(SDL_Texture *target);
}
} // namespace ui

View File

@ -1,10 +1,10 @@
#pragma once
#include <vector>
#include <SDL2/SDL.h>
#include <vector>
#include "type.h"
#include "gfx.h"
#include "type.h"
#define POP_FRAME_DEFAULT 130
@ -26,50 +26,60 @@ namespace ui
{
typedef struct
{
std::string text;
bool hold;
funcPtr confFunc, cancelFunc;
void *args;
unsigned lgFrame = 0, frameCount = 0;//To count frames cause I don't have time and am lazy
std::string text;
bool hold;
funcPtr confFunc, cancelFunc;
void *args;
unsigned lgFrame = 0, frameCount = 0; //To count frames cause I don't have time and am lazy
} confirmArgs;
typedef struct
{
funcPtr func = NULL;
void *args = NULL;
HidNpadButton button = (HidNpadButton)0;
funcPtr func = NULL;
void *args = NULL;
HidNpadButton button = (HidNpadButton)0;
} menuOptEvent;
typedef struct
{
SDL_Texture *icn = NULL;
std::string txt;
int txtWidth;
std::vector<menuOptEvent> events;
SDL_Texture *icn = NULL;
std::string txt;
int txtWidth;
std::vector<menuOptEvent> events;
} menuOpt;
class menu
{
public:
menu() = default;
menu(const int& _x, const int& _y, const int& _rW, const int& _fS, const int& _mL);
menu(int _x, int _y, int _rW, int _fS, int _mL);
void editParam(int _param, int newVal);
//Gets executed when menu changes at all
void setOnChangeFunc(funcPtr func) { onChange = func; }
void setOnChangeFunc(funcPtr func)
{
onChange = func;
}
//executed when .update() is called.
void setCallback(funcPtr _callback, void *args) { callback = _callback; callbackArgs = args; }
void setCallback(funcPtr _callback, void *args)
{
callback = _callback;
callbackArgs = args;
}
//Adds option.
int addOpt(SDL_Texture *_icn, const std::string& add);
int addOpt(SDL_Texture *_icn, const std::string &add);
//Adds an function to be executed on pressing button specified
void optAddButtonEvent(unsigned _ind, HidNpadButton _button, funcPtr _func, void *args);
//Changes opt text
void editOpt(int ind, SDL_Texture *_icn, const std::string& ch);
size_t getOptCount() { return opt.size(); }
int getOptPos(const std::string& txt);
void editOpt(int ind, SDL_Texture *_icn, const std::string &ch);
size_t getOptCount()
{
return opt.size();
}
int getOptPos(const std::string &txt);
//Clears menu stuff
~menu();
@ -78,10 +88,16 @@ namespace ui
void update();
//Returns selected option
int getSelected() { return selected; }
int getSelected()
{
return selected;
}
//Returns menu option count
int getCount() { return opt.size(); }
int getCount()
{
return opt.size();
}
//Draws the menu at x and y. rectWidth is the width of the rectangle drawn under the selected
void draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText);
@ -90,11 +106,17 @@ namespace ui
void reset();
//Resets selected + start
void resetSel() { selected = 0; }
void resetSel()
{
selected = 0;
}
//Enables control/disables drawing select box
void setActive(bool _set);
bool getActive() { return isActive; }
bool getActive()
{
return isActive;
}
private:
//drawing x and y + rectangle width/height. Height is calc'd with font size
@ -118,15 +140,18 @@ namespace ui
public:
//Constructor. _max is the maximum value
progBar() = default;
progBar(const uint64_t& _max) { max = _max; }
progBar(uint64_t _max) : max(_max) {};
void setMax(const uint64_t& _max) { max = _max; };
void setMax(uint64_t _max)
{
max = _max;
}
//Updates progress
void update(const uint64_t& _prog);
void update(uint64_t _prog);
//Draws with text at top
void draw(const std::string& text);
void draw(const std::string &text);
private:
uint64_t max = 0, prog = 0;
@ -135,8 +160,8 @@ namespace ui
typedef struct
{
std::string message;
int rectWidth = 0, frames = 0, y = 720;
std::string message;
int rectWidth = 0, frames = 0, y = 720;
} popMessage;
class popMessageMngr
@ -146,20 +171,26 @@ namespace ui
void update();
void popMessageAdd(const std::string& mess, int frameTime);
void popMessageAdd(const std::string &mess, int frameTime);
void draw();
private:
std::vector<popMessage> popQueue;//All graphics need to be on main thread. Directly adding will cause text issues
std::vector<popMessage>
popQueue; //All graphics need to be on main thread. Directly adding will cause text issues
std::vector<popMessage> message;
};
//General use
ui::confirmArgs *confirmArgsCreate(bool _hold, funcPtr _confFunc, funcPtr _cancelFunc, void *_funcArgs, const char *fmt, ...);
ui::confirmArgs *confirmArgsCreate(bool _hold,
funcPtr _confFunc,
funcPtr _cancelFunc,
void *_funcArgs,
const char *fmt,
...);
void confirm(void *a);
void showMessage(const char *fmt, ...);
bool confirmTransfer(const std::string& f, const std::string& t);
bool confirmDelete(const std::string& p);
bool confirmTransfer(const std::string &f, const std::string &t);
bool confirmDelete(const std::string &p);
void drawBoundBox(SDL_Texture *target, int x, int y, int w, int h, uint8_t clrSh);
void drawTextbox(SDL_Texture *target, int x, int y, int w, int h);
}
} // namespace ui

View File

@ -1,9 +1,9 @@
#pragma once
#include "data.h"
#include "ui.h"
#include "file.h"
#include "gfx.h"
#include "ui.h"
namespace util
{
@ -71,34 +71,39 @@ namespace util
std::string getDateTime(int fmt);
//Copys dir list to a menu with 'D: ' + 'F: '
void copyDirListToMenu(const fs::dirList& d, ui::menu& m);
void copyDirListToMenu(const fs::dirList &d, ui::menu &m);
//Removes last folder from '_path'
void removeLastFolderFromString(std::string& _path);
size_t getTotalPlacesInPath(const std::string& _path);
void trimPath(std::string& _path, uint8_t _places);
void removeLastFolderFromString(std::string &_path);
size_t getTotalPlacesInPath(const std::string &_path);
void trimPath(std::string &_path, uint8_t _places);
inline bool isASCII(const uint32_t& t)
inline bool isASCII(uint32_t t)
{
return t > 30 && t < 127;
}
std::string safeString(const std::string& s);
std::string safeString(const std::string &s);
std::string getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
std::string getStringInput(SwkbdType _type,
const std::string &def,
const std::string &head,
size_t maxLength,
unsigned dictCnt,
const std::string dictWords[]);
std::string getExtensionFromString(const std::string& get);
std::string getFilenameFromPath(const std::string& get);
std::string getExtensionFromString(const std::string &get);
std::string getFilenameFromPath(const std::string &get);
std::string generateAbbrev(const uint64_t& tid);
std::string generateAbbrev(uint64_t tid);
//removes char from C++ string
void stripChar(char _c, std::string& _s);
void stripChar(char _c, std::string &_s);
void replaceStr(std::string& _str, const std::string& _find, const std::string& _rep);
void replaceStr(std::string &_str, const std::string &_find, const std::string &_rep);
//For future external translation support. Replaces [button] with button chars
void replaceButtonsInString(std::string& rep);
void replaceButtonsInString(std::string &rep);
//Creates a basic generic icon for stuff without one
SDL_Texture *createIconGeneric(const char *txt, int fontSize, bool clearBack);
@ -116,35 +121,33 @@ namespace util
return ret;
}
inline std::string getIDStr(const uint64_t& _id)
inline std::string getIDStr(uint64_t _id)
{
char tmp[18];
sprintf(tmp, "%016lX", _id);
return std::string(tmp);
}
inline std::string getIDStrLower(const uint64_t& _id)
inline std::string getIDStrLower(uint64_t _id)
{
char tmp[18];
sprintf(tmp, "%08X", (uint32_t)_id);
return std::string(tmp);
}
inline std::string generatePathByTID(const uint64_t& tid)
inline std::string generatePathByTID(uint64_t tid)
{
return fs::getWorkDir() + data::getTitleSafeNameByTID(tid) + "/";
}
std::string getSizeString(const uint64_t& _size);
std::string getSizeString(uint64_t _size);
inline void createTitleDirectoryByTID(const uint64_t& tid)
inline void createTitleDirectoryByTID(uint64_t tid)
{
std::string makePath = fs::getWorkDir() + data::getTitleSafeNameByTID(tid);
mkdir(makePath.c_str(), 777);
}
Result accountDeleteUser(AccountUid *uid);
void sysBoost();
void sysNormal();
@ -155,4 +158,4 @@ namespace util
}
void checkForUpdate(void *a);
}
} // namespace util

View File

@ -1,14 +1,14 @@
#include <switch.h>
#include <string>
#include <unordered_map>
#include <json-c/json.h>
#include <string>
#include <switch.h>
#include <unordered_map>
#include "cfg.h"
#include "data.h"
#include "file.h"
#include "type.h"
#include "ui.h"
#include "util.h"
#include "type.h"
std::unordered_map<std::string, bool> cfg::config;
std::vector<uint64_t> cfg::blacklist;
@ -19,21 +19,38 @@ std::string cfg::driveClientID, cfg::driveClientSecret, cfg::driveRefreshToken;
std::string cfg::webdavOrigin, cfg::webdavBasePath, cfg::webdavUser, cfg::webdavPassword;
const char *cfgPath = "sdmc:/config/JKSV/JKSV.cfg", *titleDefPath = "sdmc:/config/JKSV/titleDefs.txt", *workDirLegacy = "sdmc:/switch/jksv_dir.txt";
static std::unordered_map<std::string, unsigned> cfgStrings =
{
{"workDir", 0}, {"includeDeviceSaves", 1}, {"autoBackup", 2}, {"overclock", 3}, {"holdToDelete", 4}, {"holdToRestore", 5},
{"holdToOverwrite", 6}, {"forceMount", 7}, {"accountSystemSaves", 8}, {"allowSystemSaveWrite", 9}, {"directFSCommands", 10},
{"exportToZIP", 11}, {"languageOverride", 12}, {"enableTrashBin", 13}, {"titleSortType", 14}, {"animationScale", 15},
{"favorite", 16}, {"blacklist", 17}, {"autoName", 18}, {"driveRefreshToken", 19},
const char *cfgPath = "sdmc:/config/JKSV/JKSV.cfg", *titleDefPath = "sdmc:/config/JKSV/titleDefs.txt",
*workDirLegacy = "sdmc:/switch/jksv_dir.txt";
static std::unordered_map<std::string, unsigned> cfgStrings = {
{"workDir", 0},
{"includeDeviceSaves", 1},
{"autoBackup", 2},
{"overclock", 3},
{"holdToDelete", 4},
{"holdToRestore", 5},
{"holdToOverwrite", 6},
{"forceMount", 7},
{"accountSystemSaves", 8},
{"allowSystemSaveWrite", 9},
{"directFSCommands", 10},
{"exportToZIP", 11},
{"languageOverride", 12},
{"enableTrashBin", 13},
{"titleSortType", 14},
{"animationScale", 15},
{"favorite", 16},
{"blacklist", 17},
{"autoName", 18},
{"driveRefreshToken", 19},
};
const std::string _true_ = "true", _false_ = "false";
bool cfg::isBlacklisted(const uint64_t& tid)
bool cfg::isBlacklisted(uint64_t tid)
{
for(uint64_t& bid : cfg::blacklist)
if(tid == bid) return true;
for (uint64_t &bid : cfg::blacklist)
if (tid == bid)
return true;
return false;
}
@ -45,21 +62,22 @@ void cfg::addTitleToBlacklist(void *a)
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
uint64_t tid = d->tid;
cfg::blacklist.push_back(tid);
for(data::user& u : data::users)
for (data::user &u : data::users)
{
for(unsigned i = 0; i < u.titleInfo.size(); i++)
if(u.titleInfo[i].tid == tid) u.titleInfo.erase(u.titleInfo.begin() + i);
for (unsigned i = 0; i < u.titleInfo.size(); i++)
if (u.titleInfo[i].tid == tid)
u.titleInfo.erase(u.titleInfo.begin() + i);
}
ui::ttlRefresh();
cfg::saveConfig();
t->finished = true;
}
void cfg::removeTitleFromBlacklist(const uint64_t& tid)
void cfg::removeTitleFromBlacklist(uint64_t tid)
{
for(unsigned i = 0; i < cfg::blacklist.size(); i++)
for (unsigned i = 0; i < cfg::blacklist.size(); i++)
{
if(cfg::blacklist[i] == tid)
if (cfg::blacklist[i] == tid)
cfg::blacklist.erase(cfg::blacklist.begin() + i);
}
data::loadUsersTitles(false);
@ -67,27 +85,28 @@ void cfg::removeTitleFromBlacklist(const uint64_t& tid)
cfg::saveConfig();
}
bool cfg::isFavorite(const uint64_t& tid)
bool cfg::isFavorite(uint64_t tid)
{
for(uint64_t& fid : cfg::favorites)
if(tid == fid) return true;
for (uint64_t &fid : cfg::favorites)
if (tid == fid)
return true;
return false;
}
static int getFavoriteIndex(const uint64_t& tid)
static int getFavoriteIndex(uint64_t tid)
{
for(unsigned i = 0; i < cfg::favorites.size(); i++)
for (unsigned i = 0; i < cfg::favorites.size(); i++)
{
if(tid == cfg::favorites[i])
if (tid == cfg::favorites[i])
return i;
}
return -1;
}
void cfg::addTitleToFavorites(const uint64_t& tid)
void cfg::addTitleToFavorites(uint64_t tid)
{
if(cfg::isFavorite(tid))
if (cfg::isFavorite(tid))
{
int rem = getFavoriteIndex(tid);
cfg::favorites.erase(cfg::favorites.begin() + rem);
@ -100,20 +119,21 @@ void cfg::addTitleToFavorites(const uint64_t& tid)
cfg::saveConfig();
}
bool cfg::isDefined(const uint64_t& tid)
bool cfg::isDefined(uint64_t tid)
{
for(auto& def : pathDefs)
if(def.first == tid) return true;
for (auto &def : pathDefs)
if (def.first == tid)
return true;
return false;
}
void cfg::pathDefAdd(const uint64_t& tid, const std::string& newPath)
void cfg::pathDefAdd(uint64_t tid, const std::string &newPath)
{
data::titleInfo *t = data::getTitleInfoByTID(tid);
std::string oldSafe = t->safeTitle;
std::string tmp = util::safeString(newPath);
if(!tmp.empty())
if (!tmp.empty())
{
pathDefs[tid] = tmp;
t->safeTitle = tmp;
@ -122,18 +142,21 @@ void cfg::pathDefAdd(const uint64_t& tid, const std::string& newPath)
std::string newOutput = fs::getWorkDir() + tmp;
rename(oldOutput.c_str(), newOutput.c_str());
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popChangeOutputFolder", 0), oldSafe.c_str(), tmp.c_str());
ui::showPopMessage(POP_FRAME_DEFAULT,
ui::getUICString("popChangeOutputFolder", 0),
oldSafe.c_str(),
tmp.c_str());
}
else
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popChangeOutputError", 0), newPath.c_str());
}
std::string cfg::getPathDefinition(const uint64_t& tid)
std::string cfg::getPathDefinition(uint64_t tid)
{
return pathDefs[tid];
}
void cfg::addPathToFilter(const uint64_t& tid, const std::string& _p)
void cfg::addPathToFilter(uint64_t tid, const std::string &_p)
{
char outpath[128];
sprintf(outpath, "sdmc:/config/JKSV/0x%016lX_filter.txt", tid);
@ -163,7 +186,7 @@ void cfg::resetConfig()
cfg::config["autoUpload"] = false;
}
static inline bool textToBool(const std::string& _txt)
static inline bool textToBool(const std::string &_txt)
{
return _txt == _true_ ? true : false;
}
@ -175,7 +198,7 @@ static inline std::string boolToText(bool _b)
static inline std::string sortTypeText()
{
switch(cfg::sortType)
switch (cfg::sortType)
{
case cfg::ALPHA:
return "ALPHA";
@ -194,7 +217,7 @@ static inline std::string sortTypeText()
static void loadWorkDirLegacy()
{
if(fs::fileExists(workDirLegacy))
if (fs::fileExists(workDirLegacy))
{
char tmp[256];
memset(tmp, 0, 256);
@ -213,14 +236,14 @@ static void loadWorkDirLegacy()
static void loadConfigLegacy()
{
std::string legacyCfgPath = fs::getWorkDir() + "cfg.bin";
if(fs::fileExists(legacyCfgPath))
if (fs::fileExists(legacyCfgPath))
{
FILE *oldCfg = fopen(legacyCfgPath.c_str(), "rb");
uint64_t cfgIn = 0;
fread(&cfgIn, sizeof(uint64_t), 1, oldCfg);
fread(&cfg::sortType, 1, 1, oldCfg);
fread(&ui::animScale, sizeof(float), 1, oldCfg);
if(ui::animScale == 0)
if (ui::animScale == 0)
ui::animScale = 3.0f;
fclose(oldCfg);
@ -244,10 +267,10 @@ static void loadConfigLegacy()
static void loadFavoritesLegacy()
{
std::string legacyFavPath = fs::getWorkDir() + "favorites.txt";
if(fs::fileExists(legacyFavPath))
if (fs::fileExists(legacyFavPath))
{
fs::dataFile fav(legacyFavPath);
while(fav.readNextLine(false))
while (fav.readNextLine(false))
cfg::favorites.push_back(strtoul(fav.getLine().c_str(), NULL, 16));
fav.close();
fs::delfile(legacyFavPath);
@ -257,10 +280,10 @@ static void loadFavoritesLegacy()
static void loadBlacklistLegacy()
{
std::string legacyBlPath = fs::getWorkDir() + "blacklist.txt";
if(fs::fileExists(legacyBlPath))
if (fs::fileExists(legacyBlPath))
{
fs::dataFile bl(legacyBlPath);
while(bl.readNextLine(false))
while (bl.readNextLine(false))
cfg::blacklist.push_back(strtoul(bl.getLine().c_str(), NULL, 16));
bl.close();
fs::delfile(legacyBlPath);
@ -270,10 +293,10 @@ static void loadBlacklistLegacy()
static void loadTitleDefsLegacy()
{
std::string titleDefLegacy = fs::getWorkDir() + "titleDefs.txt";
if(fs::fileExists(titleDefLegacy))
if (fs::fileExists(titleDefLegacy))
{
fs::dataFile getPaths(titleDefLegacy);
while(getPaths.readNextLine(true))
while (getPaths.readNextLine(true))
{
uint64_t tid = strtoul(getPaths.getName().c_str(), NULL, 16);
pathDefs[tid] = getPaths.getNextValueStr();
@ -286,10 +309,10 @@ static void loadTitleDefsLegacy()
//Oops
static void loadTitleDefs()
{
if(fs::fileExists(titleDefPath))
if (fs::fileExists(titleDefPath))
{
fs::dataFile getPaths(titleDefPath);
while(getPaths.readNextLine(true))
while (getPaths.readNextLine(true))
{
uint64_t tid = strtoul(getPaths.getName().c_str(), NULL, 16);
pathDefs[tid] = getPaths.getNextValueStr();
@ -302,25 +325,25 @@ static void loadDriveConfig()
// Start Google Drive
fs::dirList cfgList("/config/JKSV/", true);
std::string clientSecretPath;
for(unsigned i = 0; i < cfgList.getCount(); i++)
for (unsigned i = 0; i < cfgList.getCount(); i++)
{
std::string itemName = cfgList.getItem(i);
if(itemName.find("client_secret") != itemName.npos)
if (itemName.find("client_secret") != itemName.npos)
{
clientSecretPath = "/config/JKSV/" + cfgList.getItem(i);
break;
}
}
if(!clientSecretPath.empty())
if (!clientSecretPath.empty())
{
json_object *installed, *clientID, *clientSecret, *driveJSON = json_object_from_file(clientSecretPath.c_str());
if (driveJSON)
if (driveJSON)
{
if(json_object_object_get_ex(driveJSON, "installed", &installed))
if (json_object_object_get_ex(driveJSON, "installed", &installed))
{
if(json_object_object_get_ex(installed, "client_id", &clientID)
&& json_object_object_get_ex(installed, "client_secret", &clientSecret))
if (json_object_object_get_ex(installed, "client_id", &clientID) &&
json_object_object_get_ex(installed, "client_secret", &clientSecret))
{
cfg::driveClientID = json_object_get_string(clientID);
cfg::driveClientSecret = json_object_get_string(clientSecret);
@ -336,16 +359,20 @@ static void loadDriveConfig()
json_object *origin, *basepath, *username, *password;
if (webdavJSON)
{
if (json_object_object_get_ex(webdavJSON, "origin", &origin)) {
if (json_object_object_get_ex(webdavJSON, "origin", &origin))
{
cfg::webdavOrigin = json_object_get_string(origin);
}
if (json_object_object_get_ex(webdavJSON, "basepath", &basepath)) {
if (json_object_object_get_ex(webdavJSON, "basepath", &basepath))
{
cfg::webdavBasePath = json_object_get_string(basepath);
}
if (json_object_object_get_ex(webdavJSON, "username", &username)) {
if (json_object_object_get_ex(webdavJSON, "username", &username))
{
cfg::webdavUser = json_object_get_string(username);
}
if (json_object_object_get_ex(webdavJSON, "password", &password)) {
if (json_object_object_get_ex(webdavJSON, "password", &password))
{
cfg::webdavPassword = json_object_get_string(password);
}
json_object_put(webdavJSON);
@ -362,15 +389,15 @@ void cfg::loadConfig()
loadTitleDefsLegacy();
loadTitleDefs();
if(fs::fileExists(cfgPath))
if (fs::fileExists(cfgPath))
{
fs::dataFile cfgRead(cfgPath);
while(cfgRead.readNextLine(true))
while (cfgRead.readNextLine(true))
{
std::string varName = cfgRead.getName();
if(cfgStrings.find(varName) != cfgStrings.end())
if (cfgStrings.find(varName) != cfgStrings.end())
{
switch(cfgStrings[varName])
switch (cfgStrings[varName])
{
case 0:
fs::setWorkDir(cfgRead.getNextValueStr());
@ -429,37 +456,37 @@ void cfg::loadConfig()
break;
case 14:
{
std::string getSort = cfgRead.getNextValueStr();
if(getSort == "ALPHA")
cfg::sortType = cfg::ALPHA;
else if(getSort == "MOST_PLAYED")
cfg::sortType = cfg::MOST_PLAYED;
else
cfg::sortType = cfg::LAST_PLAYED;
}
break;
{
std::string getSort = cfgRead.getNextValueStr();
if (getSort == "ALPHA")
cfg::sortType = cfg::ALPHA;
else if (getSort == "MOST_PLAYED")
cfg::sortType = cfg::MOST_PLAYED;
else
cfg::sortType = cfg::LAST_PLAYED;
}
break;
case 15:
{
std::string animFloat = cfgRead.getNextValueStr();
ui::animScale = strtof(animFloat.c_str(), NULL);
}
break;
{
std::string animFloat = cfgRead.getNextValueStr();
ui::animScale = strtof(animFloat.c_str(), NULL);
}
break;
case 16:
{
std::string tid = cfgRead.getNextValueStr();
cfg::favorites.push_back(strtoul(tid.c_str(), NULL, 16));
}
break;
{
std::string tid = cfgRead.getNextValueStr();
cfg::favorites.push_back(strtoul(tid.c_str(), NULL, 16));
}
break;
case 17:
{
std::string tid = cfgRead.getNextValueStr();
cfg::blacklist.push_back(strtoul(tid.c_str(), NULL, 16));
}
break;
{
std::string tid = cfgRead.getNextValueStr();
cfg::blacklist.push_back(strtoul(tid.c_str(), NULL, 16));
}
break;
case 18:
cfg::config["autoName"] = textToBool(cfgRead.getNextValueStr());
@ -485,7 +512,7 @@ void cfg::loadConfig()
static void savePathDefs()
{
FILE *pathOut = fopen(titleDefPath, "w");
for(auto& p : pathDefs)
for (auto &p : pathDefs)
fprintf(pathOut, "0x%016lX = \"%s\"\n", p.first, p.second.c_str());
fclose(pathOut);
}
@ -511,24 +538,24 @@ void cfg::saveConfig()
fprintf(cfgOut, "titleSortType = %s\n", sortTypeText().c_str());
fprintf(cfgOut, "animationScale = %f\n", ui::animScale);
if(!cfg::driveRefreshToken.empty())
if (!cfg::driveRefreshToken.empty())
fprintf(cfgOut, "driveRefreshToken = %s\n", cfg::driveRefreshToken.c_str());
if(!cfg::favorites.empty())
if (!cfg::favorites.empty())
{
fprintf(cfgOut, "\n#favorites\n");
for(uint64_t& f : cfg::favorites)
for (uint64_t &f : cfg::favorites)
fprintf(cfgOut, "favorite = 0x%016lX\n", f);
}
if(!cfg::blacklist.empty())
if (!cfg::blacklist.empty())
{
fprintf(cfgOut, "\n#blacklist\n");
for(uint64_t& b : cfg::blacklist)
for (uint64_t &b : cfg::blacklist)
fprintf(cfgOut, "blacklist = 0x%016lX\n", b);
}
fclose(cfgOut);
if(!pathDefs.empty())
if (!pathDefs.empty())
savePathDefs();
}

View File

@ -1,54 +1,76 @@
#include <vector>
#include <unordered_map>
#include <string>
#include <cstring>
#include <algorithm>
#include <array>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <memory>
#include <string>
#include <string_view>
#include <switch.h>
#include <unordered_map>
#include <vector>
#include "cfg.h"
#include "data.h"
#include "file.h"
#include "util.h"
#include "type.h"
#include "cfg.h"
#include "util.h"
//FsSaveDataSpaceId_All doesn't work for SD
static const unsigned saveOrder [] = { 0, 1, 2, 3, 4, 100, 101 };
namespace
{
/// @brief This is the string used for when a publisher isn't found in the NACP.
constexpr std::string_view STRING_UNKOWN_AUTHOR = "Someone?";
/// @brief This array holds the order in which to scan save data space IDs since the all pseudo value from libnx doesn't seem to work.
constexpr std::array<FsSaveDataSpaceId, 7> ORDER_SAVE_DATA_SPACES = {FsSaveDataSpaceId_System,
FsSaveDataSpaceId_User,
FsSaveDataSpaceId_SdSystem,
FsSaveDataSpaceId_Temporary,
FsSaveDataSpaceId_SdUser,
FsSaveDataSpaceId_ProperSystem,
FsSaveDataSpaceId_SafeMode};
/// @brief This saves whether or not the System BCAT user was pushed.
bool s_systemBCATPushed = false;
/// @brief This saves whether or not the Temporary save user was pushed.
bool s_temporaryPushed = false;
} // namespace
/// @brief External variables I used to track selected user/title.
int selUser = 0, selData = 0;
//User vector
/// @brief This vector holds the user instances.
std::vector<data::user> data::users;
//System language
/// @brief System language. I don't know why this is here in data?
SetLanguage data::sysLang;
//For other save types
static bool sysBCATPushed = false, tempPushed = false;
/// @brief This is the map of titleInfo.
std::unordered_map<uint64_t, data::titleInfo> data::titles;
//Sorts titles by sortType
static struct
{
bool operator()(const data::userTitleInfo& a, const data::userTitleInfo& b)
{
//Favorites override EVERYTHING
if(cfg::isFavorite(a.tid) != cfg::isFavorite(b.tid)) return cfg::isFavorite(a.tid);
switch(cfg::sortType)
bool operator()(const data::userTitleInfo &a, const data::userTitleInfo &b)
{
case cfg::ALPHA:
//Favorites override EVERYTHING
if (cfg::isFavorite(a.tid) != cfg::isFavorite(b.tid))
return cfg::isFavorite(a.tid);
switch (cfg::sortType)
{
case cfg::ALPHA:
{
std::string titleA = data::getTitleNameByTID(a.tid);
std::string titleB = data::getTitleNameByTID(b.tid);
uint32_t pointA, pointB;
for(unsigned i = 0, j = 0; i < titleA.length(); )
for (unsigned i = 0, j = 0; i < titleA.length();)
{
ssize_t aCnt = decode_utf8(&pointA, (const uint8_t *)&titleA.data()[i]);
ssize_t bCnt = decode_utf8(&pointB, (const uint8_t *)&titleB.data()[j]);
pointA = tolower(pointA), pointB = tolower(pointB);
if(pointA != pointB)
if (pointA != pointB)
return pointA < pointB;
i += aCnt;
@ -57,115 +79,185 @@ static struct
}
break;
case cfg::MOST_PLAYED:
return a.playStats.playtime > b.playStats.playtime;
break;
case cfg::MOST_PLAYED:
return a.playStats.playtime > b.playStats.playtime;
break;
case cfg::LAST_PLAYED:
return a.playStats.last_timestamp_user> b.playStats.last_timestamp_user;
break;
case cfg::LAST_PLAYED:
return a.playStats.last_timestamp_user > b.playStats.last_timestamp_user;
break;
}
return false;
}
return false;
}
} sortTitles;
//Returns -1 for new
static int getUserIndex(const AccountUid& id)
static int getUserIndex(AccountUid id)
{
u128 nId = util::accountUIDToU128(id);
for(unsigned i = 0; i < data::users.size(); i++)
if(data::users[i].getUID128() == nId) return i;
for (unsigned i = 0; i < data::users.size(); i++)
if (data::users[i].getUID128() == nId)
return i;
return -1;
}
static inline bool accountSystemSaveCheck(const FsSaveDataInfo& _inf)
static inline bool accountSystemSaveCheck(const FsSaveDataInfo &_inf)
{
if(_inf.save_data_type == FsSaveDataType_System && util::accountUIDToU128(_inf.uid) != 0 && !cfg::config["accSysSave"])
if (_inf.save_data_type == FsSaveDataType_System && util::accountUIDToU128(_inf.uid) != 0 &&
!cfg::config["accSysSave"])
return false;
return true;
}
//Minimal init/test to avoid loading and creating things I don't need
static bool testMount(const FsSaveDataInfo& _inf)
static bool testMount(const FsSaveDataInfo &_inf)
{
bool ret = false;
if(!cfg::config["forceMount"])
if (!cfg::config["forceMount"])
return true;
if((ret = fs::mountSave(_inf)))
if ((ret = fs::mountSave(_inf)))
fs::unmountSave();
return ret;
}
static inline void addTitleToList(const uint64_t& tid)
/// @brief This version of the function uses the title/application ID to pull the data from the system.
/// @param titleID Title/Application ID of the title to add.
static void add_title_to_list(uint64_t titleID)
{
uint64_t outSize = 0;
NsApplicationControlData *ctrlData = new NsApplicationControlData;
NacpLanguageEntry *ent;
Result ctrlRes = nsGetApplicationControlData(NsApplicationControlSource_Storage, tid, ctrlData, sizeof(NsApplicationControlData), &outSize);
Result nacpRes = nacpGetLanguageEntry(&ctrlData->nacp, &ent);
size_t iconSize = outSize - sizeof(ctrlData->nacp);
// This is the output size of the control data.
uint64_t dataSize = 0;
// This is the size of the icon.
size_t iconSize = 0;
// Nacp language entry pointer.
NacpLanguageEntry *entry = nullptr;
if(R_SUCCEEDED(ctrlRes) && !(outSize < sizeof(ctrlData->nacp)) && R_SUCCEEDED(nacpRes) && iconSize > 0)
// Try to read the control data directly into the map.
Result nsError = nsGetApplicationControlData(NsApplicationControlSource_Storage,
titleID,
&data::titles[titleID].data,
sizeof(NsApplicationControlData),
&dataSize);
// At this point, regardless, the title should exist in the map. Using a reference from here on out.
data::titleInfo &info = data::titles[titleID];
// Calc icon size. Not sure this is really needed?
iconSize = dataSize - sizeof(NacpStruct);
// If that failed, run the backup routine and bail.
if (R_FAILED(nsError) || dataSize < sizeof(info.data.nacp) || iconSize <= 0 ||
R_FAILED(nacpGetLanguageEntry(&info.data.nacp, &entry)))
{
//Copy nacp
memcpy(&data::titles[tid].nacp, &ctrlData->nacp, sizeof(NacpStruct));
// Clear the NACP.
std::memset(&info.data.nacp, 0x00, sizeof(NacpStruct));
//Setup 'shortcuts' to strings
NacpLanguageEntry *ent;
nacpGetLanguageEntry(&data::titles[tid].nacp, &ent);
if(strlen(ent->name) == 0)
data::titles[tid].title = ctrlData->nacp.lang[SetLanguage_ENUS].name;
// Set the title and publisher.
info.title = util::getIDStr(titleID);
info.author = STRING_UNKOWN_AUTHOR;
// Check if the title has a path defined in the config.
if (cfg::isDefined(titleID))
{
info.safeTitle = cfg::getPathDefinition(titleID);
}
else
data::titles[tid].title = ent->name;
data::titles[tid].author = ent->author;
if(cfg::isDefined(tid))
data::titles[tid].safeTitle = cfg::getPathDefinition(tid);
else if((data::titles[tid].safeTitle = util::safeString(ent->name)) == "")
data::titles[tid].safeTitle = util::getIDStr(tid);
{
info.safeTitle = util::getIDStr(titleID);
}
if(cfg::isFavorite(tid))
data::titles[tid].fav = true;
data::titles[tid].icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, ctrlData->icon, iconSize);
if(!data::titles[tid].icon)
data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32, true);
// Create the icon.
std::string idHex = util::getIDStrLower(titleID);
info.icon = util::createIconGeneric(idHex.c_str(), 32, true);
// Bail. Do not continue. We're done.
return;
}
else
{
memset(&data::titles[tid].nacp, 0, sizeof(NacpStruct));
data::titles[tid].title = util::getIDStr(tid);
data::titles[tid].author = "Someone?";
if(cfg::isDefined(tid))
data::titles[tid].safeTitle = cfg::getPathDefinition(tid);
// Check to make sure the title isn't blank. If it is, use English.
if (std::char_traits<char>::length(entry->name) == 0)
{
info.title = info.data.nacp.lang[SetLanguage_ENUS].name;
}
else
data::titles[tid].safeTitle = util::getIDStr(tid);
{
info.title = entry->name;
}
data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32, true);
// Check the same for author/publisher.
if (std::char_traits<char>::length(entry->author) == 0)
{
info.author = info.data.nacp.lang[SetLanguage_ENUS].author;
}
else
{
info.author = entry->author;
}
// Load the icon from the control data.
info.icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, info.data.icon, iconSize);
// Make sure to save that the title has valid control data.
info.hasControlData = true;
}
delete ctrlData;
}
static inline bool titleIsLoaded(const uint64_t& tid)
{
auto findTid = data::titles.find(tid);
return findTid == data::titles.end() ? false : true;
}
static void loadUserAccounts()
{
s32 total = 0;
AccountUid *uids = new AccountUid[8];
if(R_SUCCEEDED(accountListAllUsers(uids, 8, &total)))
// The following is universal whether the title has control data or not.
// Set the safe path title. Note: I hate the second else if statement, but screw it. Rewrite avoids this kind of stuff.
if (cfg::isDefined(titleID))
{
for(int i = 0; i < total; i++)
data::users.emplace_back(uids[i], "", "");
info.safeTitle = cfg::getPathDefinition(titleID);
}
else if ((info.safeTitle = util::safeString(entry->name)) == "")
{
info.safeTitle = util::getIDStr(titleID);
}
// Favorite check.
if (cfg::isFavorite(titleID))
{
info.fav = true;
}
}
/// @brief Adds a title to the map using the application ID and cached control data.
/// @param titleID Application ID of the title.
/// @param data Reference to the data to use.
static void add_title_to_list(uint64_t titleID, NsApplicationControlData &data)
{
// Start by memcpy'ing the data over.
std::memcpy(&data::titles[titleID].data, &data, sizeof(NsApplicationControlData));
// Since this function is always being fed cached data, we're going to assume everything else is good.
}
static inline bool titleIsLoaded(uint64_t titleID)
{
return data::titles.find(titleID) != data::titles.end();
}
static void loadUserAccounts(void)
{
// Total accounts listed.
int total = 0;
// Switch has eight accounts max.
AccountUid accounts[8] = {0};
if (R_FAILED(accountListAllUsers(accounts, 8, &total)))
{
// Rewrite logs this.
return;
}
for (int i = 0; i < total; i++)
{
// Maybe to do: This looks stupid. Overload constructors?
data::users.emplace_back(accounts[i], "", "");
}
delete[] uids;
}
//This can load titles installed without having save data
@ -173,56 +265,96 @@ static void loadTitlesFromRecords()
{
NsApplicationRecord nsRecord;
int32_t entryCount = 0, recordOffset = 0;
while(R_SUCCEEDED(nsListApplicationRecord(&nsRecord, 1, recordOffset++, &entryCount)) && entryCount > 0)
while (R_SUCCEEDED(nsListApplicationRecord(&nsRecord, 1, recordOffset++, &entryCount)) && entryCount > 0)
{
if(!titleIsLoaded(nsRecord.application_id))
addTitleToList(nsRecord.application_id);
if (!titleIsLoaded(nsRecord.application_id))
{
add_title_to_list(nsRecord.application_id);
}
}
}
static void importSVIs()
static void import_svi_files(void)
{
std::string sviDir = fs::getWorkDir() + "svi/";
fs::dirList sviList(sviDir);
if(sviList.getCount() > 0)
// This is the path used. JKSV master was written before fslib.
std::string sviPath = fs::getWorkDir() + "svi";
// Get the listing and check to make sure there was actually something in it.
fs::dirList sviList(sviPath);
if (sviList.getCount() <= 0)
{
for(unsigned i = 0; i < sviList.getCount(); i++)
// Just return and don't do anything.
return;
}
// Loop through the listing and load them all.
for (unsigned int i = 0; i < sviList.getCount(); i++)
{
// Full path to the file.
std::string fullPath = sviPath + "/" + sviList.getItem(i);
// Grab the size of the SVI before continuing.
size_t sviSize = fs::fsize(fullPath);
// Application ID
uint64_t applicationID = 0;
// Language entry.
NacpLanguageEntry *entry = nullptr;
// Icon size.
size_t iconSize = 0;
// Open the file and read the application ID.
std::FILE *sviFile = std::fopen(sviPath.c_str(), "rb");
std::fread(&applicationID, 1, sizeof(uint64_t), sviFile);
// If it already exists in the map, just continue.
if (titleIsLoaded(applicationID))
{
uint64_t tid = 0;
NacpStruct *nacp = new NacpStruct;
NacpLanguageEntry *ent;
std::string sviPath = fs::getWorkDir() + "svi/" + sviList.getItem(i);
size_t iconSize = fs::fsize(sviPath) - (sizeof(uint64_t) + sizeof(NacpStruct));
uint8_t *iconBuffer = new uint8_t[iconSize];
FILE *sviIn = fopen(sviPath.c_str(), "rb");
fread(&tid, sizeof(uint64_t), 1, sviIn);
fread(nacp, sizeof(NacpStruct), 1, sviIn);
fread(iconBuffer, 1, iconSize, sviIn);
if(!titleIsLoaded(tid))
{
nacpGetLanguageEntry(nacp, &ent);
memcpy(&data::titles[tid].nacp, nacp, sizeof(NacpStruct));
data::titles[tid].title = ent->name;
data::titles[tid].author = ent->author;
if(cfg::isDefined(tid))
data::titles[tid].safeTitle = cfg::getPathDefinition(tid);
else if((data::titles[tid].safeTitle = util::safeString(ent->name)) == "")
data::titles[tid].safeTitle = util::getIDStr(tid);
if(cfg::isFavorite(tid))
data::titles[tid].fav = true;
if(!data::titles[tid].icon && iconSize > 0)
data::titles[tid].icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, iconBuffer, iconSize);
else if(!data::titles[tid].icon && iconSize == 0)
data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32, true);
}
delete nacp;
delete[] iconBuffer;
fclose(sviIn);
std::fclose(sviFile);
continue;
}
// Read the NACP data into the map directly.
std::fread(&data::titles[applicationID].data.nacp, 1, sizeof(NacpStruct), sviFile);
// Calculate the icon size and read that too. The ControlData has memory set aside for the icon anyway.
iconSize = fs::fsize(fullPath) - (sizeof(uint64_t) + sizeof(NacpStruct));
std::fread(&data::titles[applicationID].data.icon, 1, iconSize, sviFile);
// Think I should be safe to use a reference now?
data::titleInfo &info = data::titles[applicationID];
// Setup the title stuff.
if (R_FAILED(nacpGetLanguageEntry(&info.data.nacp, &entry)))
{
// Default to English.
info.title = info.data.nacp.lang[SetLanguage_ENUS].name;
info.author = info.data.nacp.lang[SetLanguage_ENUS].author;
}
else
{
info.title = entry->name;
info.author = entry->author;
}
// Safe path.
if (cfg::isDefined(applicationID))
{
info.safeTitle = cfg::getPathDefinition(applicationID);
}
else if ((info.safeTitle = util::safeString(info.title)).empty())
{
info.safeTitle = util::getIDStr(applicationID);
}
// Favorite
if (cfg::isFavorite(applicationID))
{
info.fav = true;
}
// Just going to assume this is good.
info.icon = gfx::texMgr->textureLoadFromMem(IMG_FMT_JPG, info.data.icon, iconSize);
}
}
@ -234,21 +366,25 @@ bool data::loadUsersTitles(bool clearUsers)
s64 total = 0;
loadTitlesFromRecords();
importSVIs();
import_svi_files();
//Clear titles
for(data::user& u : data::users)
for (data::user &u : data::users)
{
u.titleInfo.clear();
if(clearUsers)
}
if (clearUsers)
{
systemUserCount = 4;
for(data::user& u : data::users)
for (data::user &u : data::users)
{
u.delIcon();
}
data::users.clear();
loadUserAccounts();
sysBCATPushed = false;
tempPushed = false;
s_systemBCATPushed = false;
s_temporaryPushed = false;
users.emplace_back(util::u128ToAccountUID(3), ui::getUIString("saveTypeMainMenu", 0), "Device");
users.emplace_back(util::u128ToAccountUID(2), ui::getUIString("saveTypeMainMenu", 1), "BCAT");
@ -256,27 +392,29 @@ bool data::loadUsersTitles(bool clearUsers)
users.emplace_back(util::u128ToAccountUID(0), ui::getUIString("saveTypeMainMenu", 3), "System");
}
for(unsigned i = 0; i < 7; i++)
for (unsigned i = 0; i < 7; i++)
{
if(R_FAILED(fsOpenSaveDataInfoReader(&it, (FsSaveDataSpaceId)saveOrder[i])))
if (R_FAILED(fsOpenSaveDataInfoReader(&it, ORDER_SAVE_DATA_SPACES.at(i))))
continue;
while(R_SUCCEEDED(fsSaveDataInfoReaderRead(&it, &info, 1, &total)) && total != 0)
while (R_SUCCEEDED(fsSaveDataInfoReaderRead(&it, &info, 1, &total)) && total != 0)
{
uint64_t tid = 0;
if(info.save_data_type == FsSaveDataType_System || info.save_data_type == FsSaveDataType_SystemBcat)
if (info.save_data_type == FsSaveDataType_System || info.save_data_type == FsSaveDataType_SystemBcat)
tid = info.system_save_data_id;
else
tid = info.application_id;
if(!titleIsLoaded(tid))
addTitleToList(tid);
if (!titleIsLoaded(tid))
{
add_title_to_list(tid);
}
//Don't bother with this stuff
if(cfg::isBlacklisted(tid) || !accountSystemSaveCheck(info) || !testMount(info))
if (cfg::isBlacklisted(tid) || !accountSystemSaveCheck(info) || !testMount(info))
continue;
switch(info.save_data_type)
switch (info.save_data_type)
{
case FsSaveDataType_Bcat:
info.uid = util::u128ToAccountUID(2);
@ -288,11 +426,13 @@ bool data::loadUsersTitles(bool clearUsers)
case FsSaveDataType_SystemBcat:
info.uid = util::u128ToAccountUID(4);
if(!sysBCATPushed)
if (!s_systemBCATPushed)
{
++systemUserCount;
sysBCATPushed = true;
users.emplace_back(util::u128ToAccountUID(4), ui::getUIString("saveTypeMainMenu", 4), "System BCAT");
s_systemBCATPushed = true;
users.emplace_back(util::u128ToAccountUID(4),
ui::getUIString("saveTypeMainMenu", 4),
"System BCAT");
}
break;
@ -302,25 +442,30 @@ bool data::loadUsersTitles(bool clearUsers)
case FsSaveDataType_Temporary:
info.uid = util::u128ToAccountUID(6);
if(!tempPushed)
if (!s_temporaryPushed)
{
++systemUserCount;
tempPushed = true;
users.emplace_back(util::u128ToAccountUID(6), ui::getUIString("saveTypeMainMenu", 5), "Temporary");
s_temporaryPushed = true;
users.emplace_back(util::u128ToAccountUID(6),
ui::getUIString("saveTypeMainMenu", 5),
"Temporary");
}
break;
}
int u = getUserIndex(info.uid);
if(u == -1)
if (u == -1)
{
users.emplace(data::users.end() - systemUserCount, info.uid, "", "");
u = getUserIndex(info.uid);
}
PdmPlayStatistics playStats;
if(info.save_data_type == FsSaveDataType_Account || info.save_data_type == FsSaveDataType_Device)
pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(info.application_id, info.uid, false, &playStats);
if (info.save_data_type == FsSaveDataType_Account || info.save_data_type == FsSaveDataType_Device)
pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(info.application_id,
info.uid,
false,
&playStats);
else
memset(&playStats, 0, sizeof(PdmPlayStatistics));
users[u].addUserTitleInfo(tid, &info, &playStats);
@ -328,15 +473,15 @@ bool data::loadUsersTitles(bool clearUsers)
fsSaveDataInfoReaderClose(&it);
}
if(cfg::config["incDev"])
if (cfg::config["incDev"])
{
//Get reference to device save user
unsigned devPos = getUserIndex(util::u128ToAccountUID(3));
data::user& dev = data::users[devPos];
for(unsigned i = 0; i < devPos; i++)
data::user &dev = data::users[devPos];
for (unsigned i = 0; i < devPos; i++)
{
//Not needed but makes this easier to read
data::user& u = data::users[i];
data::user &u = data::users[i];
u.titleInfo.insert(u.titleInfo.end(), dev.titleInfo.begin(), dev.titleInfo.end());
}
}
@ -349,7 +494,7 @@ bool data::loadUsersTitles(bool clearUsers)
void data::sortUserTitles()
{
for(data::user& u : data::users)
for (data::user &u : data::users)
std::sort(u.titleInfo.begin(), u.titleInfo.end(), sortTitles);
}
@ -393,39 +538,39 @@ unsigned data::getCurrentUserTitleInfoIndex()
return selData;
}
data::titleInfo *data::getTitleInfoByTID(const uint64_t& tid)
data::titleInfo *data::getTitleInfoByTID(const uint64_t &tid)
{
if(titles.find(tid) != titles.end())
if (titles.find(tid) != titles.end())
return &titles[tid];
return NULL;
}
std::string data::getTitleNameByTID(const uint64_t& tid)
std::string data::getTitleNameByTID(const uint64_t &tid)
{
return titles[tid].title;
}
std::string data::getTitleSafeNameByTID(const uint64_t& tid)
std::string data::getTitleSafeNameByTID(const uint64_t &tid)
{
return titles[tid].safeTitle;
}
SDL_Texture *data::getTitleIconByTID(const uint64_t& tid)
SDL_Texture *data::getTitleIconByTID(const uint64_t &tid)
{
return titles[tid].icon;
}
int data::getTitleIndexInUser(const data::user& u, const uint64_t& tid)
int data::getTitleIndexInUser(const data::user &u, const uint64_t &tid)
{
for(unsigned i = 0; i < u.titleInfo.size(); i++)
for (unsigned i = 0; i < u.titleInfo.size(); i++)
{
if(u.titleInfo[i].tid == tid)
if (u.titleInfo[i].tid == tid)
return i;
}
return -1;
}
data::user::user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName)
data::user::user(AccountUid _id, const std::string &_backupName, const std::string &_safeBackupName)
{
userID = _id;
uID128 = util::accountUIDToU128(_id);
@ -433,11 +578,11 @@ data::user::user(const AccountUid& _id, const std::string& _backupName, const st
AccountProfile prof;
AccountProfileBase base;
if(R_SUCCEEDED(accountGetProfile(&prof, userID)) && R_SUCCEEDED(accountProfileGet(&prof, NULL, &base)))
if (R_SUCCEEDED(accountGetProfile(&prof, userID)) && R_SUCCEEDED(accountProfileGet(&prof, NULL, &base)))
{
username = base.nickname;
userSafe = util::safeString(username);
if(userSafe.empty())
if (userSafe.empty())
{
char tmp[32];
sprintf(tmp, "Acc%08X", (uint32_t)uID128);
@ -462,20 +607,21 @@ data::user::user(const AccountUid& _id, const std::string& _backupName, const st
titles.reserve(64);
}
data::user::user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName, SDL_Texture *img) : user(_id, _backupName, _safeBackupName)
data::user::user(AccountUid _id, const std::string &_backupName, const std::string &_safeBackupName, SDL_Texture *img)
: user(_id, _backupName, _safeBackupName)
{
delIcon();
userIcon = img;
titles.reserve(64);
}
void data::user::setUID(const AccountUid& _id)
void data::user::setUID(AccountUid _id)
{
userID = _id;
uID128 = util::accountUIDToU128(_id);
}
void data::user::addUserTitleInfo(const uint64_t& tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats)
void data::user::addUserTitleInfo(const uint64_t &tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats)
{
data::userTitleInfo newInfo;
newInfo.tid = tid;
@ -484,7 +630,7 @@ void data::user::addUserTitleInfo(const uint64_t& tid, const FsSaveDataInfo *_sa
titleInfo.push_back(newInfo);
}
static const SDL_Color green = {0x00, 0xDD, 0x00, 0xFF};
static constexpr SDL_Color green = {0x00, 0xDD, 0x00, 0xFF};
void data::dispStats()
{
@ -493,11 +639,11 @@ void data::dispStats()
//Easiest/laziest way to do this
std::string stats = ui::getUICString("debugStatus", 0) + std::to_string(users.size()) + "\n";
for(data::user& u : data::users)
for (data::user &u : data::users)
stats += u.getUsername() + ": " + std::to_string(u.titleInfo.size()) + "\n";
stats += ui::getUICString("debugStatus", 1) + cu->getUsername() + "\n";
stats += ui::getUICString("debugStatus", 2) + data::getTitleNameByTID(d->tid) + "\n";
stats += ui::getUICString("debugStatus", 3) + data::getTitleSafeNameByTID(d->tid) + "\n";
stats += ui::getUICString("debugStatus", 4) + std::to_string(cfg::sortType) + "\n";
gfx::drawTextf(NULL, 16, 2, 2, &green, stats.c_str());
}
}

View File

@ -1,8 +1,8 @@
#include <switch.h>
#include <string>
#include <switch.h>
#include "fs.h"
#include "cfg.h"
#include "fs.h"
#include "util.h"
static std::string wd = "sdmc:/JKSV/";
@ -22,65 +22,65 @@ void fs::init()
fs::logOpen();
}
bool fs::mountSave(const FsSaveDataInfo& _m)
bool fs::mountSave(const FsSaveDataInfo &_m)
{
Result svOpen;
FsSaveDataAttribute attr = {0};
switch(_m.save_data_type)
switch (_m.save_data_type)
{
case FsSaveDataType_System:
case FsSaveDataType_SystemBcat:
{
attr.uid = _m.uid;
attr.system_save_data_id = _m.system_save_data_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystemBySystemSaveDataId(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.uid = _m.uid;
attr.system_save_data_id = _m.system_save_data_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystemBySystemSaveDataId(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Account:
{
attr.uid = _m.uid;
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
attr.save_data_rank = _m.save_data_rank;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.uid = _m.uid;
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
attr.save_data_rank = _m.save_data_rank;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Device:
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Device;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Device;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Bcat:
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Bcat;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Bcat;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Cache:
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Cache;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Cache;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Temporary:
{
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
{
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr);
}
break;
default:
svOpen = 1;
@ -90,11 +90,11 @@ bool fs::mountSave(const FsSaveDataInfo& _m)
return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1;
}
bool fs::commitToDevice(const std::string& dev)
bool fs::commitToDevice(const std::string &dev)
{
bool ret = true;
Result res = fsdevCommitDevice(dev.c_str());
if(R_FAILED(res))
if (R_FAILED(res))
{
fs::logWrite("Error committing file to device -> 0x%X\n", res);
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popErrorCommittingFile", 0));
@ -103,31 +103,37 @@ bool fs::commitToDevice(const std::string& dev)
return ret;
}
std::string fs::getWorkDir() { return wd; }
std::string fs::getWorkDir()
{
return wd;
}
void fs::setWorkDir(const std::string& _w) { wd = _w; }
void fs::setWorkDir(const std::string &_w)
{
wd = _w;
}
void fs::loadPathFilters(const uint64_t& tid)
void fs::loadPathFilters(uint64_t tid)
{
char path[256];
sprintf(path, "sdmc:/config/JKSV/0x%016lX_filter.txt", tid);
if(fs::fileExists(path))
if (fs::fileExists(path))
{
fs::dataFile filter(path);
while(filter.readNextLine(false))
while (filter.readNextLine(false))
pathFilter.push_back(filter.getLine());
}
}
bool fs::pathIsFiltered(const std::string& _path)
bool fs::pathIsFiltered(const std::string &_path)
{
if(pathFilter.empty())
if (pathFilter.empty())
return false;
for(std::string& _p : pathFilter)
for (std::string &_p : pathFilter)
{
if(_path == _p)
if (_path == _p)
return true;
}
@ -142,16 +148,18 @@ void fs::freePathFilters()
void fs::createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, threadInfo *t)
{
data::titleInfo *tinfo = data::getTitleInfoByTID(_tid);
if(t)
if (t)
t->status->setStatus(ui::getUICString("threadStatusCreatingSaveData", 0), tinfo->title.c_str());
uint16_t cacheIndex = 0;
std::string indexStr;
if(_type == FsSaveDataType_Cache && !(indexStr = util::getStringInput(SwkbdType_NumPad, "0", ui::getUIString("swkbdSaveIndex", 0), 2, 0, NULL)).empty())
if (_type == FsSaveDataType_Cache &&
!(indexStr = util::getStringInput(SwkbdType_NumPad, "0", ui::getUIString("swkbdSaveIndex", 0), 2, 0, NULL))
.empty())
cacheIndex = strtoul(indexStr.c_str(), NULL, 10);
else if(_type == FsSaveDataType_Cache && indexStr.empty())
else if (_type == FsSaveDataType_Cache && indexStr.empty())
{
if(t)
if (t)
t->finished = true;
return;
}
@ -168,54 +176,72 @@ void fs::createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, th
FsSaveDataCreationInfo crt;
memset(&crt, 0, sizeof(FsSaveDataCreationInfo));
int64_t saveSize = 0, journalSize = 0;
switch(_type)
// Grab a pointer to the nacp of the title data.
NacpStruct *nacp = &tinfo->data.nacp;
switch (_type)
{
case FsSaveDataType_Account:
saveSize = tinfo->nacp.user_account_save_data_size;
journalSize = tinfo->nacp.user_account_save_data_journal_size;
break;
{
saveSize = nacp->user_account_save_data_size;
journalSize = nacp->user_account_save_data_journal_size;
}
break;
case FsSaveDataType_Device:
saveSize = tinfo->nacp.device_save_data_size;
journalSize = tinfo->nacp.device_save_data_journal_size;
break;
{
saveSize = nacp->device_save_data_size;
journalSize = nacp->device_save_data_journal_size;
}
break;
case FsSaveDataType_Bcat:
saveSize = tinfo->nacp.bcat_delivery_cache_storage_size;
journalSize = tinfo->nacp.bcat_delivery_cache_storage_size;
break;
{
saveSize = nacp->bcat_delivery_cache_storage_size;
journalSize = nacp->bcat_delivery_cache_storage_size;
}
break;
case FsSaveDataType_Cache:
{
saveSize = 32 * 1024 * 1024;
if(tinfo->nacp.cache_storage_journal_size > tinfo->nacp.cache_storage_data_and_journal_size_max)
journalSize = tinfo->nacp.cache_storage_journal_size;
if (nacp->cache_storage_journal_size > nacp->cache_storage_data_and_journal_size_max)
{
journalSize = nacp->cache_storage_journal_size;
}
else
journalSize = tinfo->nacp.cache_storage_data_and_journal_size_max;
break;
{
journalSize = nacp->cache_storage_data_and_journal_size_max;
}
}
break;
default:
if(t)
{
if (t)
t->finished = true;
return;
break;
}
break;
}
crt.save_data_size = saveSize;
crt.journal_size = journalSize;
crt.available_size = 0x4000;
crt.owner_id = _type == FsSaveDataType_Bcat ? 0x010000000000000C : tinfo->nacp.save_data_owner_id;
crt.owner_id = _type == FsSaveDataType_Bcat ? 0x010000000000000C : nacp->save_data_owner_id;
crt.flags = 0;
crt.save_data_space_id = FsSaveDataSpaceId_User;
FsSaveDataMetaInfo meta;
memset(&meta, 0, sizeof(FsSaveDataMetaInfo));
if(_type != FsSaveDataType_Bcat)
if (_type != FsSaveDataType_Bcat)
{
meta.size = 0x40060;
meta.type = FsSaveDataMetaType_Thumbnail;
}
Result res = 0;
if(R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &crt, &meta)))
if (R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &crt, &meta)))
{
util::createTitleDirectoryByTID(_tid);
data::loadUsersTitles(false);
@ -248,14 +274,15 @@ void fs::createSaveDataThreaded(FsSaveDataType _type, uint64_t _tid, AccountUid
bool fs::extendSaveData(const data::userTitleInfo *tinfo, uint64_t extSize, threadInfo *t)
{
if(t)
t->status->setStatus(ui::getUICString("threadStatusExtendingSaveData", 0), data::getTitleNameByTID(tinfo->tid).c_str());
if (t)
t->status->setStatus(ui::getUICString("threadStatusExtendingSaveData", 0),
data::getTitleNameByTID(tinfo->tid).c_str());
uint64_t journal = fs::getJournalSizeMax(tinfo);
uint64_t saveID = tinfo->saveInfo.save_data_id;
uint64_t saveID = tinfo->saveInfo.save_data_id;
FsSaveDataSpaceId space = (FsSaveDataSpaceId)tinfo->saveInfo.save_data_space_id;
Result res = 0;
if(R_FAILED((res = fsExtendSaveDataFileSystem(space, saveID, extSize, journal))))
if (R_FAILED((res = fsExtendSaveDataFileSystem(space, saveID, extSize, journal))))
{
int64_t totalSize = 0;
fs::mountSave(tinfo->saveInfo);
@ -290,30 +317,48 @@ uint64_t fs::getJournalSize(const data::userTitleInfo *tinfo)
{
uint64_t ret = 0;
data::titleInfo *t = data::getTitleInfoByTID(tinfo->tid);
switch(tinfo->saveInfo.save_data_type)
// NACP pointer.
NacpStruct *nacp = &t->data.nacp;
switch (tinfo->saveInfo.save_data_type)
{
case FsSaveDataType_Account:
ret = t->nacp.user_account_save_data_journal_size;
break;
{
ret = nacp->user_account_save_data_journal_size;
}
break;
case FsSaveDataType_Device:
ret = t->nacp.device_save_data_journal_size;
break;
{
ret = nacp->device_save_data_journal_size;
}
break;
case FsSaveDataType_Bcat:
ret = t->nacp.bcat_delivery_cache_storage_size;
break;
{
ret = nacp->bcat_delivery_cache_storage_size;
}
break;
case FsSaveDataType_Cache:
if(t->nacp.cache_storage_journal_size > 0)
ret = t->nacp.cache_storage_journal_size;
{
if (nacp->cache_storage_journal_size > 0)
{
ret = nacp->cache_storage_journal_size;
}
else
ret = t->nacp.cache_storage_data_and_journal_size_max;
break;
{
ret = nacp->cache_storage_data_and_journal_size_max;
}
}
break;
default:
{
ret = BUFF_SIZE;
break;
}
break;
}
return ret;
}
@ -322,37 +367,51 @@ uint64_t fs::getJournalSizeMax(const data::userTitleInfo *tinfo)
{
uint64_t ret = 0;
data::titleInfo *extend = data::getTitleInfoByTID(tinfo->tid);
switch(tinfo->saveInfo.save_data_type)
// NACP pointer
NacpStruct *nacp = &extend->data.nacp;
switch (tinfo->saveInfo.save_data_type)
{
case FsSaveDataType_Account:
if(extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size)
ret = extend->nacp.user_account_save_data_journal_size_max;
{
if (nacp->user_account_save_data_journal_size_max > nacp->user_account_save_data_journal_size)
ret = nacp->user_account_save_data_journal_size_max;
else
ret = extend->nacp.user_account_save_data_journal_size;
break;
ret = nacp->user_account_save_data_journal_size;
}
break;
case FsSaveDataType_Bcat:
ret = extend->nacp.bcat_delivery_cache_storage_size;
break;
{
ret = nacp->bcat_delivery_cache_storage_size;
}
break;
case FsSaveDataType_Cache:
if(extend->nacp.cache_storage_data_and_journal_size_max > extend->nacp.cache_storage_journal_size)
ret = extend->nacp.cache_storage_data_and_journal_size_max;
{
if (nacp->cache_storage_data_and_journal_size_max > nacp->cache_storage_journal_size)
ret = nacp->cache_storage_data_and_journal_size_max;
else
ret = extend->nacp.cache_storage_journal_size;
break;
ret = nacp->cache_storage_journal_size;
}
break;
case FsSaveDataType_Device:
if(extend->nacp.device_save_data_journal_size_max > extend->nacp.device_save_data_journal_size)
ret = extend->nacp.device_save_data_journal_size_max;
{
if (nacp->device_save_data_journal_size_max > nacp->device_save_data_journal_size)
ret = nacp->device_save_data_journal_size_max;
else
ret = extend->nacp.device_save_data_journal_size;
break;
ret = nacp->device_save_data_journal_size;
}
break;
default:
{
//will just fail
ret = 0;
break;
}
break;
}
return ret;
}
@ -373,7 +432,7 @@ void fs::wipeSave()
void fs::createNewBackup(void *a)
{
if(!fs::dirNotEmpty("sv:/"))
if (!fs::dirNotEmpty("sv:/"))
{
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popSaveIsEmpty", 0));
return;
@ -387,43 +446,39 @@ void fs::createNewBackup(void *a)
std::string out;
if(held & HidNpadButton_R || cfg::config["autoName"])
if (held & HidNpadButton_R || cfg::config["autoName"])
out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
else if(held & HidNpadButton_L)
else if (held & HidNpadButton_L)
out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
else if(held & HidNpadButton_ZL)
else if (held & HidNpadButton_ZL)
out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE);
else
{
const std::string dict[] =
{
util::getDateTime(util::DATE_FMT_YMD),
util::getDateTime(util::DATE_FMT_YDM),
util::getDateTime(util::DATE_FMT_HOYSTE),
util::getDateTime(util::DATE_FMT_JHK),
util::getDateTime(util::DATE_FMT_ASC),
u->getUsernameSafe(),
t->safeTitle,
util::generateAbbrev(d->tid),
".zip"
};
const std::string dict[] = {util::getDateTime(util::DATE_FMT_YMD),
util::getDateTime(util::DATE_FMT_YDM),
util::getDateTime(util::DATE_FMT_HOYSTE),
util::getDateTime(util::DATE_FMT_JHK),
util::getDateTime(util::DATE_FMT_ASC),
u->getUsernameSafe(),
t->safeTitle,
util::generateAbbrev(d->tid),
".zip"};
std::string defaultText = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
out = util::getStringInput(SwkbdType_QWERTY, defaultText, ui::getUIString("swkbdEnterName", 0), 64, 9, dict);
out = util::safeString(out);
}
if(!out.empty())
if (!out.empty())
{
std::string ext = util::getExtensionFromString(out);
std::string path = util::generatePathByTID(d->tid) + out;
if(cfg::config["zip"] || ext == "zip")
if (cfg::config["zip"] || ext == "zip")
{
if(ext != "zip")//data::zip is on but extension is not zip
if (ext != "zip") //data::zip is on but extension is not zip
path += ".zip";
zipFile zip = zipOpen64(path.c_str(), 0);
fs::copyDirToZipThreaded("sv:/", zip, false, 0);
}
else
{
@ -440,14 +495,14 @@ void fs::overwriteBackup(void *a)
threadInfo *t = (threadInfo *)a;
std::string *dst = (std::string *)t->argPtr;
bool saveHasFiles = fs::dirNotEmpty("sv:/");
if(fs::isDir(*dst) && saveHasFiles)
if (fs::isDir(*dst) && saveHasFiles)
{
fs::delDir(*dst);
fs::mkDir(*dst);
dst->append("/");
fs::copyDirToDirThreaded("sv:/", *dst);
}
else if(!fs::isDir(*dst) && util::getExtensionFromString(*dst) == "zip" && saveHasFiles)
else if (!fs::isDir(*dst) && util::getExtensionFromString(*dst) == "zip" && saveHasFiles)
{
fs::delfile(*dst);
zipFile zip = zipOpen64(dst->c_str(), 0);
@ -463,34 +518,36 @@ void fs::restoreBackup(void *a)
std::string *restore = (std::string *)t->argPtr;
data::user *u = data::getCurrentUser();
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
if((utinfo->saveInfo.save_data_type != FsSaveDataType_System || cfg::config["sysSaveWrite"]))
if ((utinfo->saveInfo.save_data_type != FsSaveDataType_System || cfg::config["sysSaveWrite"]))
{
bool saveHasFiles = fs::dirNotEmpty("sv:/");
if(cfg::config["autoBack"] && cfg::config["zip"] && saveHasFiles)
if (cfg::config["autoBack"] && cfg::config["zip"] && saveHasFiles)
{
std::string autoZip = util::generatePathByTID(utinfo->tid) + "/AUTO " + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
std::string autoZip = util::generatePathByTID(utinfo->tid) + "/AUTO " + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + ".zip";
zipFile zip = zipOpen64(autoZip.c_str(), 0);
fs::copyDirToZipThreaded("sv:/", zip, false, 0);
}
else if(cfg::config["autoBack"] && saveHasFiles)
else if (cfg::config["autoBack"] && saveHasFiles)
{
std::string autoFolder = util::generatePathByTID(utinfo->tid) + "/AUTO - " + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
std::string autoFolder = util::generatePathByTID(utinfo->tid) + "/AUTO - " + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(autoFolder.substr(0, autoFolder.length() - 1));
fs::copyDirToDirThreaded("sv:/", autoFolder);
}
if(fs::isDir(*restore))
if (fs::isDir(*restore))
{
restore->append("/");
if(fs::dirNotEmpty(*restore))
if (fs::dirNotEmpty(*restore))
{
t->status->setStatus(ui::getUICString("threadStatusCalculatingSaveSize", 0));
unsigned dirCount = 0, fileCount = 0;
uint64_t saveSize = 0;
int64_t availSize = 0;
int64_t availSize = 0;
fs::getDirProps(*restore, dirCount, fileCount, saveSize);
fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &availSize);
if((int)saveSize > availSize)
if ((int)saveSize > availSize)
{
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
fs::unmountSave();
@ -504,16 +561,16 @@ void fs::restoreBackup(void *a)
else
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popFolderIsEmpty", 0));
}
else if(!fs::isDir(*restore) && util::getExtensionFromString(*restore) == "zip")
else if (!fs::isDir(*restore) && util::getExtensionFromString(*restore) == "zip")
{
unzFile unz = unzOpen64(restore->c_str());
if(unz && fs::zipNotEmpty(unz))
if (unz && fs::zipNotEmpty(unz))
{
t->status->setStatus(ui::getUICString("threadStatusCalculatingSaveSize", 0));
uint64_t saveSize = fs::getZipTotalSize(unz);
int64_t availSize = 0;
int64_t availSize = 0;
fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &availSize);
if((int)saveSize > availSize)
if ((int)saveSize > availSize)
{
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
fs::unmountSave();
@ -536,7 +593,7 @@ void fs::restoreBackup(void *a)
fs::copyFileCommitThreaded(*restore, dstPath, "sv");
}
}
if(cfg::config["autoBack"])
if (cfg::config["autoBack"])
ui::fldRefreshMenu();
delete restore;
@ -551,7 +608,7 @@ void fs::deleteBackup(void *a)
t->status->setStatus(ui::getUICString("threadStatusDeletingFile", 0));
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
if(cfg::config["trashBin"])
if (cfg::config["trashBin"])
{
std::string oldPath = *deletePath;
std::string trashPath = wd + "_TRASH_/" + data::getTitleSafeNameByTID(utinfo->tid);
@ -561,7 +618,7 @@ void fs::deleteBackup(void *a)
rename(oldPath.c_str(), trashPath.c_str());
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupMovedToTrash", 0), backupName.c_str());
}
else if(fs::isDir(*deletePath))
else if (fs::isDir(*deletePath))
{
*deletePath += "/";
fs::delDir(*deletePath);
@ -584,23 +641,25 @@ void fs::dumpAllUserSaves(void *a)
t->argPtr = c;
data::user *u = data::getCurrentUser();
for(unsigned i = 0; i < u->titleInfo.size(); i++)
for (unsigned i = 0; i < u->titleInfo.size(); i++)
{
bool saveMounted = fs::mountSave(u->titleInfo[i].saveInfo);
util::createTitleDirectoryByTID(u->titleInfo[i].tid);
if(saveMounted && fs::dirNotEmpty("sv:/") && cfg::config["zip"])
if (saveMounted && fs::dirNotEmpty("sv:/") && cfg::config["zip"])
{
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + ".zip";
zipFile zip = zipOpen64(dst.c_str(), 0);
fs::copyDirToZip("sv:/", zip, false, 0, t);
zipClose(zip, NULL);
fs::freePathFilters();
}
else if(saveMounted && fs::dirNotEmpty("sv:/"))
else if (saveMounted && fs::dirNotEmpty("sv:/"))
{
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(dst.substr(0, dst.length() - 1));
fs::copyDirToDir("sv:/", dst, t);
fs::freePathFilters();
@ -617,26 +676,28 @@ void fs::dumpAllUsersAllSaves(void *a)
fs::copyArgs *c = fs::copyArgsCreate("", "", "", NULL, NULL, false, false, 0);
t->argPtr = c;
unsigned curUser = 0;
while(data::users[curUser].getUID128() != 2)
while (data::users[curUser].getUID128() != 2)
{
data::user *u = &data::users[curUser++];
for(unsigned i = 0; i < u->titleInfo.size(); i++)
for (unsigned i = 0; i < u->titleInfo.size(); i++)
{
bool saveMounted = fs::mountSave(u->titleInfo[i].saveInfo);
util::createTitleDirectoryByTID(u->titleInfo[i].tid);
if(saveMounted && fs::dirNotEmpty("sv:/") && cfg::config["zip"])
if (saveMounted && fs::dirNotEmpty("sv:/") && cfg::config["zip"])
{
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + ".zip";
zipFile zip = zipOpen64(dst.c_str(), 0);
fs::copyDirToZip("sv:/", zip, false, 0, t);
zipClose(zip, NULL);
fs::freePathFilters();
}
else if(saveMounted && fs::dirNotEmpty("sv:/"))
else if (saveMounted && fs::dirNotEmpty("sv:/"))
{
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(dst.substr(0, dst.length() - 1));
fs::copyDirToDir("sv:/", dst, t);
fs::freePathFilters();
@ -667,4 +728,3 @@ void fs::logWrite(const char *fmt, ...)
fsfwrite(tmp, 1, strlen(tmp), debLog);
fsfclose(debLog);
}

View File

@ -1,11 +1,11 @@
#include <string>
#include "ui.h"
#include "file.h"
#include "util.h"
#include "fm.h"
#include "cfg.h"
#include "file.h"
#include "fm.h"
#include "type.h"
#include "ui.h"
#include "util.h"
//This is going to be a mess but the old one was too.
//It gets more complicated because of system saves and committing.
@ -16,9 +16,9 @@
//Struct to hold info so i don't have to if else if if if
typedef struct
{
std::string *path;
ui::menu *m;
fs::dirList *d;
std::string *path;
ui::menu *m;
fs::dirList *d;
} menuFuncArgs;
static ui::slideOutPanel *devPanel, *sdPanel;
@ -42,7 +42,7 @@ static void refreshMenu(void *a)
d->reassign(*ma->path);
util::copyDirListToMenu(*d, *m);
for(int i = 1; i < m->getCount(); i++)
for (int i = 1; i < m->getCount(); i++)
{
m->optAddButtonEvent(i, HidNpadButton_A, _listFunctionA, ma);
}
@ -53,10 +53,10 @@ static void refreshMenu(void *a)
static void _devMenuCallback(void *a)
{
menuFuncArgs *ma = (menuFuncArgs *)a;
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
if(*ma->path != dev && *ma->path != "sdmc:/")
if (*ma->path != dev && *ma->path != "sdmc:/")
{
util::removeLastFolderFromString(*ma->path);
threadInfo fake;
@ -75,7 +75,7 @@ static void _devMenuCallback(void *a)
static void _devCopyMenuCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
devCopyMenu->setActive(false);
@ -88,10 +88,10 @@ static void _devCopyMenuCallback(void *a)
static void _sdMenuCallback(void *a)
{
menuFuncArgs *ma = (menuFuncArgs *)a;
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
if(*ma->path != dev && *ma->path != "sdmc:/")
if (*ma->path != dev && *ma->path != "sdmc:/")
{
util::removeLastFolderFromString(*ma->path);
threadInfo fake;
@ -110,7 +110,7 @@ static void _sdMenuCallback(void *a)
static void _sdCopyMenuCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
sdCopyMenu->setActive(false);
@ -141,13 +141,13 @@ static void _listFunctionA(void *a)
int sel = m->getSelected();
bool isDir = d->isDir(sel - 2);
if(sel == 1 && (*ma->path != dev && *ma->path != "sdmc:/"))
if (sel == 1 && (*ma->path != dev && *ma->path != "sdmc:/"))
{
util::removeLastFolderFromString(*ma->path);
d->reassign(*ma->path);
util::copyDirListToMenu(*d, *m);
}
else if(sel > 1 && isDir)
else if (sel > 1 && isDir)
{
std::string addToPath = d->getItem(sel - 2);
*ma->path += addToPath + "/";
@ -155,7 +155,7 @@ static void _listFunctionA(void *a)
util::copyDirListToMenu(*d, *m);
}
for(int i = 1; i < m->getCount(); i++)
for (int i = 1; i < m->getCount(); i++)
m->optAddButtonEvent(i, HidNpadButton_A, _listFunctionA, ma);
}
@ -167,49 +167,49 @@ static void _copyMenuCopy_t(void *a)
fs::dirList *d = ma->d;
int sel = m->getSelected();
if(ma == devArgs)
if (ma == devArgs)
{
if(sel == 0)
if (sel == 0)
fs::copyDirToDirThreaded(*ma->path, *sdmcArgs->path);
else if(sel > 1 && d->isDir(sel - 2))
else if (sel > 1 && d->isDir(sel - 2))
{
std::string srcPath = *ma->path + d->getItem(sel - 2) + "/";
std::string dstPath = *sdmcArgs->path + d->getItem(sel - 2) + "/";
mkdir(dstPath.substr(0, dstPath.length() - 1).c_str(), 777);
fs::copyDirToDirThreaded(srcPath, dstPath);
}
else if(sel > 1)
else if (sel > 1)
{
std::string srcPath = *ma->path + d->getItem(sel - 2);
std::string dstPath = *sdmcArgs->path + d->getItem(sel - 2);
fs::copyFileThreaded(srcPath, dstPath);
}
}
else if(ma == sdmcArgs)
else if (ma == sdmcArgs)
{
//I know
if(sel == 0)
if (sel == 0)
{
if(commit)
if (commit)
fs::copyDirToDirCommitThreaded(*ma->path, *devArgs->path, dev);
else
fs::copyDirToDirThreaded(*ma->path, *devArgs->path);
}
else if(sel > 1 && d->isDir(sel - 2))
else if (sel > 1 && d->isDir(sel - 2))
{
std::string srcPath = *ma->path + d->getItem(sel - 2) + "/";
std::string dstPath = *devArgs->path + d->getItem(sel - 2) + "/";
mkdir(dstPath.substr(0, dstPath.length() - 1).c_str(), 777);
if(commit)
if (commit)
fs::copyDirToDirCommitThreaded(srcPath, dstPath, dev);
else
fs::copyDirToDirThreaded(srcPath, dstPath);
}
else if(sel > 1)
else if (sel > 1)
{
std::string srcPath = *ma->path + d->getItem(sel - 2);
std::string dstPath = *devArgs->path + d->getItem(sel - 2);
if(commit)
if (commit)
fs::copyFileCommitThreaded(srcPath, dstPath, dev);
else
fs::copyFileThreaded(srcPath, dstPath);
@ -229,30 +229,36 @@ static void _copyMenuCopy(void *a)
std::string srcPath, dstPath;
int sel = m->getSelected();
if(sel == 0 && ma == devArgs)
if (sel == 0 && ma == devArgs)
{
srcPath = *ma->path;
dstPath = *sdmcArgs->path;
}
else if(sel > 1 && ma == devArgs)
else if (sel > 1 && ma == devArgs)
{
srcPath = *ma->path + d->getItem(sel - 2);
dstPath = *sdmcArgs->path + d->getItem(sel - 2);
}
else if(sel == 0 && ma == sdmcArgs)
else if (sel == 0 && ma == sdmcArgs)
{
srcPath = *ma->path;
dstPath = *devArgs->path;
}
else if(sel > 1 && ma == sdmcArgs)
else if (sel > 1 && ma == sdmcArgs)
{
srcPath = *ma->path + d->getItem(m->getSelected() - 2);
dstPath = *devArgs->path + d->getItem(m->getSelected() - 2);
}
if(ma == devArgs || (ma == sdmcArgs && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"])))
if (ma == devArgs || (ma == sdmcArgs && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"])))
{
ui::confirmArgs *send = ui::confirmArgsCreate(false, _copyMenuCopy_t, NULL, ma, ui::getUICString("confirmCopy", 0), srcPath.c_str(), dstPath.c_str());
ui::confirmArgs *send = ui::confirmArgsCreate(false,
_copyMenuCopy_t,
NULL,
ma,
ui::getUICString("confirmCopy", 0),
srcPath.c_str(),
dstPath.c_str());
ui::confirm(send);
}
}
@ -267,39 +273,39 @@ static void _copyMenuDelete_t(void *a)
t->status->setStatus(ui::getUICString("threadStatusDeletingFile", 0));
int sel = m->getSelected();
if(ma == devArgs)
if (ma == devArgs)
{
if(sel == 0 && *ma->path != "sdmc:/")
if (sel == 0 && *ma->path != "sdmc:/")
{
fs::delDir(*ma->path);
if(commit)
if (commit)
fs::commitToDevice(dev);
}
else if(sel > 1 && d->isDir(sel - 2))
else if (sel > 1 && d->isDir(sel - 2))
{
std::string delPath = *ma->path + d->getItem(sel - 2) + "/";
fs::delDir(delPath);
if(commit)
if (commit)
fs::commitToDevice(dev);
}
else if(sel > 1)
else if (sel > 1)
{
std::string delPath = *ma->path + d->getItem(sel - 2);
fs::delfile(delPath);
if(commit)
if (commit)
fs::commitToDevice(dev);
}
}
else
{
if(sel == 0 && *ma->path != "sdmc:/")
if (sel == 0 && *ma->path != "sdmc:/")
fs::delDir(*ma->path);
else if(sel > 1 && d->isDir(sel - 2))
else if (sel > 1 && d->isDir(sel - 2))
{
std::string delPath = *ma->path + d->getItem(sel - 2) + "/";
fs::delDir(delPath);
}
else if(sel > 1)
else if (sel > 1)
{
std::string delPath = *ma->path + d->getItem(sel - 2);
fs::delfile(delPath);
@ -319,14 +325,20 @@ static void _copyMenuDelete(void *a)
int sel = m->getSelected();
std::string itmPath;
if(sel == 0)
if (sel == 0)
itmPath = *ma->path;
else if(sel > 1)
else if (sel > 1)
itmPath = *ma->path + d->getItem(sel - 2);
if(ma == sdmcArgs || (ma == devArgs && (sel == 0 || sel > 1) && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"])))
if (ma == sdmcArgs ||
(ma == devArgs && (sel == 0 || sel > 1) && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"])))
{
ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"], _copyMenuDelete_t, NULL, a, ui::getUICString("confirmDelete", 0), itmPath.c_str());
ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"],
_copyMenuDelete_t,
NULL,
a,
ui::getUICString("confirmDelete", 0),
itmPath.c_str());
ui::confirm(send);
}
}
@ -338,13 +350,14 @@ static void _copyMenuRename(void *a)
fs::dirList *d = ma->d;
int sel = m->getSelected();
if(sel > 1)
if (sel > 1)
{
std::string getNewName = util::getStringInput(SwkbdType_QWERTY, d->getItem(sel - 2), ui::getUIString("swkbdRename", 0), 64, 0, NULL);
if(!getNewName.empty())
std::string getNewName =
util::getStringInput(SwkbdType_QWERTY, d->getItem(sel - 2), ui::getUIString("swkbdRename", 0), 64, 0, NULL);
if (!getNewName.empty())
{
std::string prevPath = *ma->path + d->getItem(sel - 2);
std::string newPath = *ma->path + getNewName;
std::string newPath = *ma->path + getNewName;
rename(prevPath.c_str(), newPath.c_str());
}
threadInfo fake;
@ -358,8 +371,13 @@ static void _copyMenuRename(void *a)
static void _copyMenuMkDir(void *a)
{
menuFuncArgs *ma = (menuFuncArgs *)a;
std::string getNewFolder = util::getStringInput(SwkbdType_QWERTY, ui::getUIString("fileModeMenuMkDir", 0), ui::getUIString("swkbdMkDir", 0), 64, 0, NULL);
if(!getNewFolder.empty())
std::string getNewFolder = util::getStringInput(SwkbdType_QWERTY,
ui::getUIString("fileModeMenuMkDir", 0),
ui::getUIString("swkbdMkDir", 0),
64,
0,
NULL);
if (!getNewFolder.empty())
{
std::string createPath = *ma->path + getNewFolder;
mkdir(createPath.c_str(), 777);
@ -379,7 +397,11 @@ static void _copyMenuGetShowDirProps_t(void *a)
uint64_t totalSize = 0;
t->status->setStatus(ui::getUICString("threadStatusGetDirProps", 0));
fs::getDirProps(*p, dirCount, fileCount, totalSize);
ui::showMessage(ui::getUICString("fileModeFolderProperties", 0), p->c_str(), dirCount, fileCount, util::getSizeString(totalSize).c_str());
ui::showMessage(ui::getUICString("fileModeFolderProperties", 0),
p->c_str(),
dirCount,
fileCount,
util::getSizeString(totalSize).c_str());
delete p;
t->finished = true;
}
@ -391,18 +413,18 @@ static void _copyMenuGetProps(void *a)
fs::dirList *d = ma->d;
int sel = m->getSelected();
if(sel == 0)
if (sel == 0)
{
std::string *folderPath = new std::string(*ma->path);
ui::newThread(_copyMenuGetShowDirProps_t, folderPath, NULL);
}
else if(sel > 1 && d->isDir(sel - 2))
else if (sel > 1 && d->isDir(sel - 2))
{
std::string *folderPath = new std::string;
folderPath->assign(*ma->path + d->getItem(sel - 2) + "/");
ui::newThread(_copyMenuGetShowDirProps_t, folderPath, NULL);
}
else if(sel > 1)
else if (sel > 1)
{
std::string filePath = *ma->path + d->getItem(sel - 2);
fs::getShowFileProps(filePath);
@ -412,7 +434,7 @@ static void _copyMenuGetProps(void *a)
static void _copyMenuClose(void *a)
{
menuFuncArgs *ma = (menuFuncArgs *)a;
if(ma == devArgs)
if (ma == devArgs)
{
devCopyMenu->setActive(false);
devMenu->setActive(true);
@ -433,7 +455,7 @@ static void _devMenuAddToPathFilter(void *a)
fs::dirList *d = ma->d;
int sel = m->getSelected();
if(sel > 1)
if (sel > 1)
{
data::userTitleInfo *tinfo = data::getCurrentUserTitleInfo();
std::string filterPath = *ma->path + d->getItem(sel - 2);
@ -461,7 +483,7 @@ void ui::fmInit()
devCopyMenu->setActive(false);
devCopyMenu->setCallback(_devCopyMenuCallback, NULL);
devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 0) + "SDMC");
for(int i = 1; i < 4; i++)
for (int i = 1; i < 4; i++)
devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", i));
//Manually do this so I can place the last option higher up
devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 6));
@ -486,7 +508,7 @@ void ui::fmInit()
sdCopyMenu = new ui::menu(10, 210, 268, 20, 5);
sdCopyMenu->setActive(false);
sdCopyMenu->setCallback(_sdCopyMenuCallback, NULL);
for(int i = 0; i < 6; i++)
for (int i = 0; i < 6; i++)
sdCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", i));
sdCopyMenu->optAddButtonEvent(0, HidNpadButton_A, _copyMenuCopy, sdmcArgs);
sdCopyMenu->optAddButtonEvent(1, HidNpadButton_A, _copyMenuDelete, sdmcArgs);
@ -497,7 +519,7 @@ void ui::fmInit()
ui::registerPanel(sdPanel);
devList = new fs::dirList;
sdList = new fs::dirList;
sdList = new fs::dirList;
devArgs->d = devList;
sdmcArgs->d = sdList;
}
@ -514,10 +536,10 @@ void ui::fmExit()
delete sdmcArgs;
}
void ui::fmPrep(const FsSaveDataType& _type, const std::string& _dev, const std::string& _baseSDMC, bool _commit)
void ui::fmPrep(FsSaveDataType _type, const std::string &_dev, const std::string &_baseSDMC, bool _commit)
{
type = _type;
dev = _dev;
dev = _dev;
commit = _commit;
devPath = _dev;
sdPath = _baseSDMC;
@ -527,24 +549,24 @@ void ui::fmPrep(const FsSaveDataType& _type, const std::string& _dev, const std:
devList->reassign(dev);
sdList->reassign(sdPath);
util::copyDirListToMenu(*devList, *devMenu);
for(int i = 1; i < devMenu->getCount(); i++)
for (int i = 1; i < devMenu->getCount(); i++)
devMenu->optAddButtonEvent(i, HidNpadButton_A, _listFunctionA, devArgs);
util::copyDirListToMenu(*sdList, *sdMenu);
for(int i = 1; i < sdMenu->getCount(); i++)
for (int i = 1; i < sdMenu->getCount(); i++)
sdMenu->optAddButtonEvent(i, HidNpadButton_A, _listFunctionA, sdmcArgs);
}
void ui::fmUpdate()
{
//For now? Maybe forever?
if(devMenu->getActive() || sdMenu->getActive())
if (devMenu->getActive() || sdMenu->getActive())
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_ZL:
case HidNpadButton_ZR:
if(devMenu->getActive())
if (devMenu->getActive())
{
devMenu->setActive(false);
sdMenu->setActive(true);
@ -558,15 +580,15 @@ void ui::fmUpdate()
case HidNpadButton_Minus:
//Can't be 100% sure it's fs's sv
if(dev != "sdmc:/")
if (dev != "sdmc:/")
fsdevUnmountDevice(dev.c_str());
if(ui::prevState == EX_MNU)
if (ui::prevState == EX_MNU)
{
ui::usrSelPanel->openPanel();
ui::changeState(EX_MNU);
}
else if(ui::prevState == TTL_SEL)
else if (ui::prevState == TTL_SEL)
{
ui::usrSelPanel->openPanel();
ui::ttlOptsPanel->openPanel();

View File

@ -1,25 +1,25 @@
#include <cstring>
#include <cstdarg>
#include <cmath>
#include <cstdarg>
#include <cstring>
#include <switch.h>
#include "gfx.h"
#include "ui.h"
#include "miscui.h"
#include "util.h"
#include "type.h"
#include "ui.h"
#include "util.h"
static const SDL_Color divLight = {0x6D, 0x6D, 0x6D, 0xFF};
static const SDL_Color divDark = {0xCC, 0xCC, 0xCC, 0xFF};
static const SDL_Color shadow = {0x66, 0x66, 0x66, 0xFF};
static const SDL_Color divLight = {0x6D, 0x6D, 0x6D, 0xFF};
static const SDL_Color divDark = {0xCC, 0xCC, 0xCC, 0xFF};
static const SDL_Color shadow = {0x66, 0x66, 0x66, 0xFF};
static const SDL_Color fillBack = {0x66, 0x66, 0x66, 0xFF};
static const SDL_Color fillBar = {0x00, 0xDD, 0x00, 0xFF};
static const SDL_Color fillBack = {0x66, 0x66, 0x66, 0xFF};
static const SDL_Color fillBar = {0x00, 0xDD, 0x00, 0xFF};
static const SDL_Color menuColorLight = {0x32, 0x50, 0xF0, 0xFF};
static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF};
static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF};
ui::menu::menu(const int& _x, const int& _y, const int& _rW, const int& _fS, const int& _mL)
ui::menu::menu(int _x, int _y, int _rW, int _fS, int _mL)
{
x = _x;
mY = _y;
@ -37,7 +37,7 @@ ui::menu::menu(const int& _x, const int& _y, const int& _rW, const int& _fS, con
void ui::menu::editParam(int _param, int newVal)
{
switch(_param)
switch (_param)
{
case MENU_X:
x = newVal;
@ -50,14 +50,22 @@ void ui::menu::editParam(int _param, int newVal)
case MENU_RECT_WIDTH:
rW = newVal;
SDL_DestroyTexture(optTex);
optTex = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, rW, rH);
optTex = SDL_CreateTexture(gfx::render,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET,
rW,
rH);
SDL_SetTextureBlendMode(optTex, SDL_BLENDMODE_BLEND);
break;
case MENU_RECT_HEIGHT:
rH = newVal;
SDL_DestroyTexture(optTex);
optTex = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, rW, rH);
optTex = SDL_CreateTexture(gfx::render,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET,
rW,
rH);
SDL_SetTextureBlendMode(optTex, SDL_BLENDMODE_BLEND);
break;
@ -71,7 +79,7 @@ void ui::menu::editParam(int _param, int newVal)
}
}
int ui::menu::addOpt(SDL_Texture *_icn, const std::string& add)
int ui::menu::addOpt(SDL_Texture *_icn, const std::string &add)
{
ui::menuOpt newOpt;
newOpt.txt = add;
@ -81,9 +89,9 @@ int ui::menu::addOpt(SDL_Texture *_icn, const std::string& add)
return opt.size() - 1;
}
void ui::menu::editOpt(int ind, SDL_Texture *_icn, const std::string& ch)
void ui::menu::editOpt(int ind, SDL_Texture *_icn, const std::string &ch)
{
if(!opt[ind].icn && _icn)
if (!opt[ind].icn && _icn)
opt[ind].icn = _icn;
opt[ind].txt = ch;
@ -96,11 +104,11 @@ void ui::menu::optAddButtonEvent(unsigned _ind, HidNpadButton _button, funcPtr _
opt[_ind].events.push_back(newEvent);
}
int ui::menu::getOptPos(const std::string& txt)
int ui::menu::getOptPos(const std::string &txt)
{
for(unsigned i = 0; i < opt.size(); i++)
for (unsigned i = 0; i < opt.size(); i++)
{
if(opt[i].txt == txt)
if (opt[i].txt == txt)
return i;
}
return -1;
@ -114,49 +122,49 @@ ui::menu::~menu()
void ui::menu::update()
{
if(!isActive)
if (!isActive)
return;
uint64_t down = ui::padKeysDown();
uint64_t held = ui::padKeysHeld();
if(held & HidNpadButton_AnyUp || held & HidNpadButton_AnyDown)
if (held & HidNpadButton_AnyUp || held & HidNpadButton_AnyDown)
++fc;
else
fc = 0;
if(fc > 10)
if (fc > 10)
fc = 0;
int oldSel = selected;
int mSize = opt.size() - 1;
bool change = false;
if( (down & HidNpadButton_AnyUp) || ((held & HidNpadButton_AnyUp) && fc == 10) )
if ((down & HidNpadButton_AnyUp) || ((held & HidNpadButton_AnyUp) && fc == 10))
{
if(--selected < 0)
if (--selected < 0)
selected = mSize;
change = true;
}
else if( (down & HidNpadButton_AnyDown) || ((held & HidNpadButton_AnyDown) && fc == 10))
else if ((down & HidNpadButton_AnyDown) || ((held & HidNpadButton_AnyDown) && fc == 10))
{
if(++selected > mSize)
if (++selected > mSize)
selected = 0;
change = true;
}
else if(down & HidNpadButton_AnyLeft)
else if (down & HidNpadButton_AnyLeft)
{
selected -= mL;
if(selected < 0)
if (selected < 0)
selected = 0;
change = true;
}
else if(down & HidNpadButton_AnyRight)
else if (down & HidNpadButton_AnyRight)
{
selected += mL;
if(selected > mSize)
if (selected > mSize)
selected = mSize;
change = true;
@ -164,120 +172,145 @@ void ui::menu::update()
++hoverCount;
if(!change && hoverCount >= 90)
if (!change && hoverCount >= 90)
hover = true;
else if(change)
else if (change)
{
hoverCount = 0;
hover = false;
}
if(down && !opt[selected].events.empty())
if (down && !opt[selected].events.empty())
{
for(ui::menuOptEvent& e : opt[selected].events)
for (ui::menuOptEvent &e : opt[selected].events)
{
if((down & e.button) && e.func)
if ((down & e.button) && e.func)
(*e.func)(e.args);
}
}
if(selected <= mL)
if (selected <= mL)
tY = mY;
else if(selected >= (mSize - mL) && mSize > mL * 2)
else if (selected >= (mSize - mL) && mSize > mL * 2)
tY = mY + -(rH * (mSize - (mL * 2)));
else if(selected > mL && selected < (mSize - mL))
else if (selected > mL && selected < (mSize - mL))
tY = -(rH * (selected - mL));
if(selected != oldSel && onChange)
if (selected != oldSel && onChange)
(*onChange)(NULL);
if(callback)
if (callback)
(*callback)(callbackArgs);
}
void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText)
{
if(opt.size() < 1)
if (opt.size() < 1)
return;
int tH = 0;
SDL_QueryTexture(target, NULL, NULL, NULL, &tH);
if(y != tY)
if (y != tY)
{
float add = (float)((float)tY - (float)y) / ui::animScale;
y += ceil(add);
}
if(clrAdd)
if (clrAdd)
{
clrSh += 6;
if(clrSh >= 0x72)
if (clrSh >= 0x72)
clrAdd = false;
}
else
{
clrSh -= 3;
if(clrSh <= 0x00)
if (clrSh <= 0x00)
clrAdd = true;
}
for(int i = 0, tY = y; i < (int)opt.size(); i++, tY += rH)
for (int i = 0, tY = y; i < (int)opt.size(); i++, tY += rH)
{
if(tY < -rH || tY > tH)
if (tY < -rH || tY > tH)
continue;
gfx::clearTarget(optTex, &ui::transparent);
//Todo: Clean this up maybe
if(i == selected && drawText)
if (i == selected && drawText)
{
if(isActive)
if (isActive)
ui::drawBoundBox(target, x, y + (i * rH), rW, rH, clrSh);
gfx::drawRect(target, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, x + 10, ((y + (rH / 2 - fSize / 2)) + (i * rH)) - 2, 4, fSize + 4);
gfx::drawRect(target,
ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark,
x + 10,
((y + (rH / 2 - fSize / 2)) + (i * rH)) - 2,
4,
fSize + 4);
static int dX = 0;
if(hover && opt[i].txtWidth > rW - 24)
if (hover && opt[i].txtWidth > rW - 24)
{
if((dX -= 2) <= -(opt[i].txtWidth + spcWidth))
if ((dX -= 2) <= -(opt[i].txtWidth + spcWidth))
{
dX = 0;
hoverCount = 0;
hover = false;
}
gfx::drawTextf(optTex, fSize, dX, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str());
gfx::drawTextf(optTex, fSize, dX + opt[i].txtWidth + spcWidth, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str());
gfx::drawTextf(optTex,
fSize,
dX,
((rH - 8) / 2) - fSize / 2,
ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark,
opt[i].txt.c_str());
gfx::drawTextf(optTex,
fSize,
dX + opt[i].txtWidth + spcWidth,
((rH - 8) / 2) - fSize / 2,
ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark,
opt[i].txt.c_str());
}
else
{
dX = 0;
gfx::drawTextf(optTex, fSize, 0, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str());
gfx::drawTextf(optTex,
fSize,
0,
((rH - 8) / 2) - fSize / 2,
ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark,
opt[i].txt.c_str());
}
gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH)));
}
else if(i == selected && !drawText && opt[i].icn)
else if (i == selected && !drawText && opt[i].icn)
{
int w, h;
SDL_QueryTexture(opt[i].icn, NULL, NULL, &w, &h);
float scale = (float)fSize / (float)h;
int dW = scale * w;
int dH = scale * h;
if(isActive)
if (isActive)
ui::drawBoundBox(target, x, y + (i * rH), rW, rH, clrSh);
gfx::drawRect(target, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, x + 10, ((y + (rH / 2 - fSize / 2)) + (i * rH)) - 2, 4, fSize + 4);
gfx::drawRect(target,
ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark,
x + 10,
((y + (rH / 2 - fSize / 2)) + (i * rH)) - 2,
4,
fSize + 4);
gfx::texDrawStretch(optTex, opt[i].icn, 0, ((rH - 8) / 2) - fSize / 2, dW, dH);
gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH)));
}
else if(drawText)
else if (drawText)
{
gfx::clearTarget(optTex, &ui::transparent);
gfx::drawTextf(optTex, fSize, 0, ((rH - 8) / 2) - fSize / 2, textClr, opt[i].txt.c_str());
gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH)));
}
else if(!drawText && opt[i].icn)
else if (!drawText && opt[i].icn)
{
int w, h;
SDL_QueryTexture(opt[i].icn, NULL, NULL, &w, &h);
@ -304,15 +337,15 @@ void ui::menu::setActive(bool _set)
isActive = _set;
}
void ui::progBar::update(const uint64_t& _prog)
void ui::progBar::update(uint64_t _prog)
{
prog = _prog;
if(max > 0)
if (max > 0)
width = (float)((float)prog / (float)max) * 648.0f;
}
void ui::progBar::draw(const std::string& text)
void ui::progBar::draw(const std::string &text)
{
char progStr[64];
sprintf(progStr, "%.2fMB / %.2fMB", (float)prog / 1024.0f / 1024.0f, (float)max / 1024.0f / 1024.0f);
@ -334,29 +367,29 @@ ui::popMessageMngr::~popMessageMngr()
void ui::popMessageMngr::update()
{
//Anything that needs graphics/text must be processed on main thread
for(ui::popMessage& p : popQueue)
for (ui::popMessage &p : popQueue)
{
p.rectWidth = gfx::getTextWidth(p.message.c_str(), 24) + 32;
message.push_back(p);
}
popQueue.clear();
for(unsigned i = 0; i < message.size(); i++)
for (unsigned i = 0; i < message.size(); i++)
{
message[i].frames--;
if(message[i].frames <= 0)
if (message[i].frames <= 0)
message.erase(message.begin() + i);
}
}
void ui::popMessageMngr::popMessageAdd(const std::string& mess, int frameTime)
void ui::popMessageMngr::popMessageAdd(const std::string &mess, int frameTime)
{
//Suppress multiple of the same
int lastMessageIndex = message.size() - 1;
std::string lastMessage;
if(lastMessageIndex >= 0)
if (lastMessageIndex >= 0)
lastMessage = message[lastMessageIndex].message;
if(lastMessage != mess)
if (lastMessage != mess)
{
ui::popMessage newPop = {mess, 0, frameTime};
popQueue.push_back(newPop);
@ -366,10 +399,10 @@ void ui::popMessageMngr::popMessageAdd(const std::string& mess, int frameTime)
void ui::popMessageMngr::draw()
{
int y = 640;
for(auto& p : message)
for (auto &p : message)
{
y -= 48;
if(p.y != y)
if (p.y != y)
p.y += (y - p.y) / ui::animScale;
gfx::drawRect(NULL, &ui::tboxClr, 64, p.y, p.rectWidth, 40);
@ -377,7 +410,12 @@ void ui::popMessageMngr::draw()
}
}
ui::confirmArgs *ui::confirmArgsCreate(bool _hold, funcPtr _confFunc, funcPtr _cancelFunc, void *_funcArgs, const char *fmt, ...)
ui::confirmArgs *ui::confirmArgsCreate(bool _hold,
funcPtr _confFunc,
funcPtr _cancelFunc,
void *_funcArgs,
const char *fmt,
...)
{
char tmp[1024];
va_list args;
@ -401,35 +439,35 @@ void confirm_t(void *a)
threadInfo *t = (threadInfo *)a;
ui::confirmArgs *c = (ui::confirmArgs *)t->argPtr;
while(true)
while (true)
{
uint64_t down = ui::padKeysDown();
uint64_t held = ui::padKeysHeld();
if((down & HidNpadButton_A) && !c->hold)
if ((down & HidNpadButton_A) && !c->hold)
{
ui::newThread(c->confFunc, c->args, NULL);
break;
}
else if((held & HidNpadButton_A) && c->hold)
else if ((held & HidNpadButton_A) && c->hold)
{
if(c->frameCount % 4 == 0 && ++c->lgFrame > 7)
if (c->frameCount % 4 == 0 && ++c->lgFrame > 7)
c->lgFrame = 0;
if(c->frameCount >= 120)
if (c->frameCount >= 120)
{
ui::newThread(c->confFunc, c->args, NULL);
break;
}
}
else if(down & HidNpadButton_B)
else if (down & HidNpadButton_B)
{
if(c->cancelFunc)
if (c->cancelFunc)
(*c->cancelFunc)(c->args);
break;
}
svcSleepThread(1e+9 / 60);//Close enough
svcSleepThread(1e+9 / 60); //Close enough
}
delete c;
t->finished = true;
@ -440,19 +478,19 @@ void confirmDrawFunc(void *a)
{
threadInfo *t = (threadInfo *)a;
ui::confirmArgs *c = (ui::confirmArgs *)t->argPtr;
if(!t->finished)
if (!t->finished)
{
std::string yesTxt = ui::getUIString("dialogYes", 0);
unsigned yesX = 0;
if((ui::padKeysHeld() & HidNpadButton_A) && c->hold)
if ((ui::padKeysHeld() & HidNpadButton_A) && c->hold)
{
c->frameCount++;
if(c->frameCount <= 40)
if (c->frameCount <= 40)
yesTxt = ui::getUIString("holdingText", 0);
else if(c->frameCount <= 80)
else if (c->frameCount <= 80)
yesTxt = ui::getUIString("holdingText", 1);
else if(c->frameCount <= 120)
else if (c->frameCount <= 120)
yesTxt = ui::getUICString("holdingText", 2);
yesTxt += ui::loadGlyphArray[c->lgFrame];
@ -481,9 +519,9 @@ static void showMessage_t(void *a)
{
threadInfo *t = (threadInfo *)a;
std::string *text = (std::string *)t->argPtr;
while(true)
while (true)
{
if(ui::padKeysDown() & HidNpadButton_A)
if (ui::padKeysDown() & HidNpadButton_A)
break;
svcSleepThread(1e+9 / 60);
@ -496,7 +534,7 @@ static void showMessageDrawFunc(void *a)
{
threadInfo *t = (threadInfo *)a;
std::string *text = (std::string *)t->argPtr;
if(!t->finished)
if (!t->finished)
{
unsigned okX = 640 - (gfx::getTextWidth(ui::getUICString("dialogOK", 0), 18) / 2);
ui::drawTextbox(NULL, 280, 262, 720, 256);
@ -526,7 +564,7 @@ void ui::drawTextbox(SDL_Texture *target, int x, int y, int w, int h)
gfx::texDraw(target, ui::cornerTopRight, (x + w) - 32, y);
//middle
gfx::drawRect(target, &ui::tboxClr, x, y + 32, w, h - 64);
gfx::drawRect(target, &ui::tboxClr, x, y + 32, w, h - 64);
//bottom
gfx::texDraw(target, ui::cornerBottomLeft, x, (y + h) - 32);
@ -539,7 +577,7 @@ void ui::drawBoundBox(SDL_Texture *target, int x, int y, int w, int h, uint8_t c
SDL_SetRenderTarget(gfx::render, target);
SDL_Color rectClr;
if(ui::thmID == ColorSetId_Light)
if (ui::thmID == ColorSetId_Light)
rectClr = {0xFD, 0xFD, 0xFD, 0xFF};
else
rectClr = {0x21, 0x22, 0x21, 0xFF};

View File

@ -1,10 +1,10 @@
#include <vector>
#include "ui.h"
#include "ttl.h"
#include "file.h"
#include "util.h"
#include "cfg.h"
#include "file.h"
#include "ttl.h"
#include "ui.h"
#include "util.h"
static int ttlHelpX = 0;
static std::vector<ui::titleview *> ttlViews;
@ -16,7 +16,7 @@ static Mutex ttlViewLock = 0;
void ui::ttlRefresh()
{
mutexLock(&ttlViewLock);
for(int i = 0; i < (int)data::users.size(); i++)
for (int i = 0; i < (int)data::users.size(); i++)
ttlViews[i]->refresh();
mutexUnlock(&ttlViewLock);
}
@ -29,12 +29,12 @@ static void ttlViewCallback(void *a)
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
uint64_t tid = d->tid;
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_A:
if(fs::mountSave(d->saveInfo))
if (fs::mountSave(d->saveInfo))
{
ttlViews[curUserIndex]->setActive(false, true);
ttlViews[curUserIndex]->setActive(false, true);
ui::fldPopulateMenu();
}
break;
@ -52,28 +52,28 @@ static void ttlViewCallback(void *a)
break;
case HidNpadButton_Y:
{
cfg::addTitleToFavorites(tid);
int newSel = data::getTitleIndexInUser(data::users[curUserIndex], tid);
ttlViews[curUserIndex]->setSelected(newSel);
}
break;
{
cfg::addTitleToFavorites(tid);
int newSel = data::getTitleIndexInUser(data::users[curUserIndex], tid);
ttlViews[curUserIndex]->setSelected(newSel);
}
break;
}
}
static void ttlOptsCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
{
int curUserIndex = data::getCurrentUserIndex();
ttlOpts->setActive(false);
ui::ttlOptsPanel->closePanel();
ttlViews[curUserIndex]->setActive(true, true);
ui::updateInput();
}
break;
{
int curUserIndex = data::getCurrentUserIndex();
ttlOpts->setActive(false);
ui::ttlOptsPanel->closePanel();
ttlViews[curUserIndex]->setActive(true, true);
ui::updateInput();
}
break;
}
}
@ -86,14 +86,14 @@ static void ttlOptsPanelDraw(void *a)
static void ttlOptsShowInfoPanel(void *)
{
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
data::titleInfo *tinfo = data::getTitleInfoByTID(utinfo->tid);
data::titleInfo *tinfo = data::getTitleInfoByTID(utinfo->tid);
char tmp[256];
sprintf(tmp, ui::getUICString("infoStatus", 4), tinfo->author.c_str());
size_t titleWidth = gfx::getTextWidth(tinfo->title.c_str(), 18);
size_t pubWidth = gfx::getTextWidth(tmp, 18);
if(titleWidth > 410 || pubWidth > 410)
if (titleWidth > 410 || pubWidth > 410)
{
size_t newWidth = titleWidth > pubWidth ? titleWidth : pubWidth;
infoPanel->resizePanel(newWidth + 40, 720, 0);
@ -109,7 +109,12 @@ static void ttlOptsShowInfoPanel(void *)
static void ttlOptsBlacklistTitle(void *a)
{
std::string title = data::getTitleNameByTID(data::getCurrentUserTitleInfo()->tid);
ui::confirmArgs *conf = ui::confirmArgsCreate(false, cfg::addTitleToBlacklist, NULL, NULL, ui::getUICString("confirmBlacklist", 0), title.c_str());
ui::confirmArgs *conf = ui::confirmArgsCreate(false,
cfg::addTitleToBlacklist,
NULL,
NULL,
ui::getUICString("confirmBlacklist", 0),
title.c_str());
ui::confirm(conf);
}
@ -117,15 +122,16 @@ static void ttlOptsDefinePath(void *a)
{
uint64_t tid = data::getCurrentUserTitleInfo()->tid;
std::string safeTitle = data::getTitleInfoByTID(tid)->safeTitle;
std::string newSafeTitle = util::getStringInput(SwkbdType_QWERTY, safeTitle, ui::getUICString("swkbdNewSafeTitle", 0), 0x200, 0, NULL);
if(!newSafeTitle.empty())
std::string newSafeTitle =
util::getStringInput(SwkbdType_QWERTY, safeTitle, ui::getUICString("swkbdNewSafeTitle", 0), 0x200, 0, NULL);
if (!newSafeTitle.empty())
cfg::pathDefAdd(tid, newSafeTitle);
}
static void ttlOptsToFileMode(void *a)
{
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
if(fs::mountSave(d->saveInfo))
if (fs::mountSave(d->saveInfo))
{
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
std::string sdmcPath = util::generatePathByTID(utinfo->tid);
@ -143,10 +149,10 @@ static void ttlOptsDeleteAllBackups_t(void *a)
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
std::string targetPath = util::generatePathByTID(d->tid);
fs::dirList *backupList = new fs::dirList(targetPath);
for(unsigned i = 0; i < backupList->getCount(); i++)
for (unsigned i = 0; i < backupList->getCount(); i++)
{
std::string delPath = targetPath + backupList->getItem(i);
if(backupList->isDir(i))
if (backupList->isDir(i))
{
delPath += "/";
fs::delDir(delPath);
@ -163,7 +169,12 @@ static void ttlOptsDeleteAllBackups(void *a)
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
std::string currentTitle = data::getTitleNameByTID(d->tid);
ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsDeleteAllBackups_t, NULL, NULL, ui::getUICString("confirmDeleteBackupsTitle", 0), currentTitle.c_str());
ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"],
ttlOptsDeleteAllBackups_t,
NULL,
NULL,
ui::getUICString("confirmDeleteBackupsTitle", 0),
currentTitle.c_str());
ui::confirm(send);
}
@ -185,10 +196,15 @@ static void ttlOptsResetSaveData_t(void *a)
static void ttlOptsResetSaveData(void *a)
{
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
if(d->saveInfo.save_data_type != FsSaveDataType_System)
if (d->saveInfo.save_data_type != FsSaveDataType_System)
{
std::string title = data::getTitleNameByTID(d->tid);
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsResetSaveData_t, NULL, NULL, ui::getUICString("confirmResetSaveData", 0), title.c_str());
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"],
ttlOptsResetSaveData_t,
NULL,
NULL,
ui::getUICString("confirmResetSaveData", 0),
title.c_str());
ui::confirm(conf);
}
}
@ -202,13 +218,14 @@ static void ttlOptsDeleteSaveData_t(void *a)
std::string title = data::getTitleNameByTID(d->tid);
t->status->setStatus(ui::getUICString("threadStatusDeletingSaveData", 0), title.c_str());
if(R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)d->saveInfo.save_data_space_id, d->saveInfo.save_data_id)))
if (R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)d->saveInfo.save_data_space_id,
d->saveInfo.save_data_id)))
{
data::loadUsersTitles(false);
if(u->titleInfo.size() == 0)
if (u->titleInfo.size() == 0)
{
//Kick back to user
ui::ttlOptsPanel->closePanel();//JIC
ui::ttlOptsPanel->closePanel(); //JIC
ttlOpts->setActive(false);
ttlViews[userIndex]->setActive(false, false);
ui::usrMenu->setActive(true);
@ -223,10 +240,15 @@ static void ttlOptsDeleteSaveData_t(void *a)
static void ttlOptsDeleteSaveData(void *a)
{
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
if(d->saveInfo.save_data_type != FsSaveDataType_System)
if (d->saveInfo.save_data_type != FsSaveDataType_System)
{
std::string title = data::getTitleNameByTID(d->tid);
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsDeleteSaveData_t, NULL, NULL, ui::getUICString("confirmDeleteSaveData", 0), title.c_str());
ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"],
ttlOptsDeleteSaveData_t,
NULL,
NULL,
ui::getUICString("confirmDeleteSaveData", 0),
title.c_str());
ui::confirm(conf);
}
}
@ -234,9 +256,10 @@ static void ttlOptsDeleteSaveData(void *a)
static void ttlOptsExtendSaveData(void *a)
{
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
if(d->saveInfo.save_data_type != FsSaveDataType_System)
if (d->saveInfo.save_data_type != FsSaveDataType_System)
{
std::string expSizeStr = util::getStringInput(SwkbdType_NumPad, "", ui::getUICString("swkbdExpandSize", 0), 4, 0, NULL);
std::string expSizeStr =
util::getStringInput(SwkbdType_NumPad, "", ui::getUICString("swkbdExpandSize", 0), 4, 0, NULL);
uint64_t extMB = strtoul(expSizeStr.c_str(), NULL, 10) * 0x100000;
fs::extendSaveDataThreaded(d, extMB);
}
@ -244,27 +267,36 @@ static void ttlOptsExtendSaveData(void *a)
static void ttlOptsExportSVI(void *a)
{
data::userTitleInfo *ut = data::getCurrentUserTitleInfo();
data::titleInfo *t = data::getTitleInfoByTID(ut->tid);
std::string out = fs::getWorkDir() + "svi/";
fs::mkDir(out.substr(0, out.length() - 1));
out += util::getIDStr(ut->tid) + ".svi";
FILE *svi = fopen(out.c_str(), "wb");
if(svi)
{
//Grab icon
NsApplicationControlData *ctrlData = new NsApplicationControlData;
uint64_t ctrlSize = 0;
nsGetApplicationControlData(NsApplicationControlSource_Storage, ut->tid, ctrlData, sizeof(NsApplicationControlData), &ctrlSize);
size_t jpegSize = ctrlSize - sizeof(ctrlData->nacp);
// Grab the current user title info.
data::userTitleInfo *userInfo = data::getCurrentUserTitleInfo();
fwrite(&ut->tid, sizeof(uint64_t), 1, svi);
fwrite(&t->nacp, sizeof(NacpStruct), 1, svi);
fwrite(ctrlData->icon, 1, jpegSize, svi);
fclose(svi);
delete ctrlData;
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popSVIExported", 0));
// Use that to grab the corresponding title info.
data::titleInfo *info = data::getTitleInfoByTID(userInfo->tid);
// Ensure the svi directory exists.
std::string sviPath = fs::getWorkDir() + "svi/";
fs::mkDir(sviPath.substr(0, sviPath.length() - 1));
// Append the application ID and extension.
sviPath += util::getIDStr(userInfo->tid) + ".svi";
// Try to open the file for writing.
std::FILE *sviFile = std::fopen(sviPath.data(), "wb");
if (!sviFile)
{
return;
}
// Write the application ID
std::fwrite(&userInfo->tid, 1, sizeof(uint64_t), sviFile);
// Control data.
std::fwrite(&info->data, 1, sizeof(NacpStruct), sviFile);
// Close the file.
std::fclose(sviFile);
// Toast.
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popSVIExported", 0));
}
static void infoPanelDraw(void *a)
@ -292,7 +324,13 @@ static void infoPanelDraw(void *a)
drawY += 40;
gfx::drawRect(panel, &ui::rectSh, 10, drawY, rectWidth, 38);
gfx::drawTextf(panel, 18, 20, drawY + 10, &ui::txtCont, ui::getUICString("infoStatus", 1), d->saveInfo.save_data_id);
gfx::drawTextf(panel,
18,
20,
drawY + 10,
&ui::txtCont,
ui::getUICString("infoStatus", 1),
d->saveInfo.save_data_id);
drawY += 40;
uint32_t hours, mins;
@ -303,28 +341,52 @@ static void infoPanelDraw(void *a)
drawY += 40;
gfx::drawRect(panel, &ui::rectSh, 10, drawY, rectWidth, 38);
gfx::drawTextf(panel, 18, 20, drawY + 10, &ui::txtCont, ui::getUICString("infoStatus", 3), d->playStats.total_launches);
gfx::drawTextf(panel,
18,
20,
drawY + 10,
&ui::txtCont,
ui::getUICString("infoStatus", 3),
d->playStats.total_launches);
drawY += 40;
gfx::drawRect(panel, &ui::rectLt, 10, drawY, rectWidth, 38);
gfx::drawTextf(panel, 18, 20, drawY + 10, &ui::txtCont, ui::getUICString("infoStatus", 5), ui::getUICString("saveDataTypeText", d->saveInfo.save_data_type));
gfx::drawTextf(panel,
18,
20,
drawY + 10,
&ui::txtCont,
ui::getUICString("infoStatus", 5),
ui::getUICString("saveDataTypeText", d->saveInfo.save_data_type));
drawY += 40;
uint8_t saveType = d->saveInfo.save_data_type;
if(saveType == FsSaveDataType_Cache)
if (saveType == FsSaveDataType_Cache)
{
gfx::drawRect(panel, &ui::rectSh, 10, drawY, rectWidth, 38);
gfx::drawTextf(panel, 18, 20, drawY + 10, &ui::txtCont, ui::getUICString("infoStatus", 6), d->saveInfo.save_data_index);
gfx::drawTextf(panel,
18,
20,
drawY + 10,
&ui::txtCont,
ui::getUICString("infoStatus", 6),
d->saveInfo.save_data_index);
drawY += 40;
}
gfx::drawRect(panel, saveType == FsSaveDataType_Cache ? &ui::rectLt : &ui::rectSh, 10, drawY, rectWidth, 38);
gfx::drawTextf(panel, 18, 20, drawY + 10, &ui::txtCont, ui::getUICString("infoStatus", 7), data::getCurrentUser()->getUsername().c_str());
gfx::drawTextf(panel,
18,
20,
drawY + 10,
&ui::txtCont,
ui::getUICString("infoStatus", 7),
data::getCurrentUser()->getUsername().c_str());
}
static void infoPanelCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
infoPanel->closePanel();
@ -339,7 +401,7 @@ void ui::ttlInit()
{
ttlHelpX = 1220 - gfx::getTextWidth(ui::getUICString("helpTitle", 0), 18);
for(data::user& u : data::users)
for (data::user &u : data::users)
ttlViews.emplace_back(new ui::titleview(u, 128, 128, 16, 16, 7, ttlViewCallback));
ttlOpts = new ui::menu(10, 32, 390, 20, 7);
@ -354,7 +416,7 @@ void ui::ttlInit()
infoPanel->setCallback(infoPanelCallback, NULL);
ttlOpts->setActive(false);
for(int i = 0; i < 9; i++)
for (int i = 0; i < 9; i++)
ttlOpts->addOpt(NULL, ui::getUIString("titleOptions", i));
//Information
@ -379,9 +441,9 @@ void ui::ttlInit()
void ui::ttlExit()
{
for(ui::titleview *t : ttlViews)
for (ui::titleview *t : ttlViews)
delete t;
delete ttlOptsPanel;
delete ttlOpts;
delete infoPanel;
@ -409,6 +471,6 @@ void ui::ttlDraw(SDL_Texture *target)
mutexLock(&ttlViewLock);
ttlViews[curUserIndex]->draw(target);
mutexUnlock(&ttlViewLock);
if(ui::mstate == TTL_SEL && !fldPanel->isOpen())
if (ui::mstate == TTL_SEL && !fldPanel->isOpen())
gfx::drawTextf(NULL, 18, ttlHelpX, 673, &ui::txtCont, ui::getUICString("helpTitle", 0));
}

View File

@ -1,16 +1,16 @@
#include <string>
#include <vector>
#include <algorithm>
#include <string>
#include <switch.h>
#include <vector>
#include "file.h"
#include "data.h"
#include "file.h"
#include "type.h"
#include "ui.h"
#include "util.h"
#include "type.h"
#include "usr.h"
#include "ttl.h"
#include "usr.h"
static const char *settText = ui::getUICString("mainMenuSettings", 0), *extText = ui::getUICString("mainMenuExtras", 0);
@ -34,30 +34,30 @@ static unsigned usrHelpX = 0;
//Sort save create tids alphabetically by title from data
static struct
{
bool operator()(const uint64_t& tid1, const uint64_t& tid2)
{
std::string tid1Title = data::getTitleNameByTID(tid1);
std::string tid2Title = data::getTitleNameByTID(tid2);
uint32_t pointA = 0, pointB = 0;
for(unsigned i = 0, j = 0; i < tid1Title.length(); )
bool operator()(const uint64_t &tid1, const uint64_t &tid2)
{
ssize_t tid1Cnt = decode_utf8(&pointA, (const uint8_t *)&tid1Title.c_str()[i]);
ssize_t tid2Cnt = decode_utf8(&pointB, (const uint8_t *)&tid2Title.c_str()[j]);
std::string tid1Title = data::getTitleNameByTID(tid1);
std::string tid2Title = data::getTitleNameByTID(tid2);
pointA = tolower(pointA), pointB = tolower(pointB);
if(pointA != pointB)
return pointA < pointB;
uint32_t pointA = 0, pointB = 0;
for (unsigned i = 0, j = 0; i < tid1Title.length();)
{
ssize_t tid1Cnt = decode_utf8(&pointA, (const uint8_t *)&tid1Title.c_str()[i]);
ssize_t tid2Cnt = decode_utf8(&pointB, (const uint8_t *)&tid2Title.c_str()[j]);
i += tid1Cnt, j += tid2Cnt;
pointA = tolower(pointA), pointB = tolower(pointB);
if (pointA != pointB)
return pointA < pointB;
i += tid1Cnt, j += tid2Cnt;
}
return false;
}
return false;
}
} sortCreateTIDs;
static void onMainChange(void *a)
{
if(ui::usrMenu->getSelected() < (int)data::users.size())
if (ui::usrMenu->getSelected() < (int)data::users.size())
{
unsigned setUser = ui::usrMenu->getSelected();
data::setUserIndex(setUser);
@ -87,7 +87,7 @@ static void toEXT(void *a)
static void usrOptCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
usrOptPanel->closePanel();
@ -99,7 +99,7 @@ static void usrOptCallback(void *a)
static void saveCreateCallback(void *a)
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_B:
usrOptMenu->setActive(true);
@ -126,32 +126,32 @@ static void usrOptSaveCreate(void *a)
ui::updateInput();
int sel = m->getSelected();
bool closeUsrOpt = false;
if(sel == devPos && deviceSaveMenu->getOptCount() > 0)
if (sel == devPos && deviceSaveMenu->getOptCount() > 0)
{
deviceSaveMenu->setActive(true);
deviceSavePanel->openPanel();
closeUsrOpt = true;
}
else if(sel == bcatPos && bcatSaveMenu->getOptCount() > 0)
else if (sel == bcatPos && bcatSaveMenu->getOptCount() > 0)
{
bcatSaveMenu->setActive(true);
bcatSavePanel->openPanel();
closeUsrOpt = true;
}
else if(sel == cachePos && cacheSaveMenu->getOptCount() > 0)
else if (sel == cachePos && cacheSaveMenu->getOptCount() > 0)
{
cacheSaveMenu->setActive(true);
cacheSavePanel->openPanel();
closeUsrOpt = true;
}
else if(sel < devPos)
else if (sel < devPos)
{
saveCreateMenu->setActive(true);
saveCreatePanel->openPanel();
closeUsrOpt = true;
}
if(closeUsrOpt)
if (closeUsrOpt)
{
usrOptMenu->setActive(false);
usrOptPanel->closePanel();
@ -166,11 +166,13 @@ static void usrOptDeleteAllUserSaves_t(void *a)
int curUserIndex = data::getCurrentUserIndex();
int devUser = ui::usrMenu->getOptPos(ui::getUICString("saveTypeMainMenu", 0));
for(data::userTitleInfo& tinf : u->titleInfo)
for (data::userTitleInfo &tinf : u->titleInfo)
{
if(tinf.saveInfo.save_data_type != FsSaveDataType_System && (tinf.saveInfo.save_data_type != FsSaveDataType_Device || curUserIndex == devUser))
if (tinf.saveInfo.save_data_type != FsSaveDataType_System &&
(tinf.saveInfo.save_data_type != FsSaveDataType_Device || curUserIndex == devUser))
{
t->status->setStatus(ui::getUICString("threadStatusDeletingSaveData", 0), data::getTitleNameByTID(tinf.tid).c_str());
t->status->setStatus(ui::getUICString("threadStatusDeletingSaveData", 0),
data::getTitleNameByTID(tinf.tid).c_str());
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tinf.saveInfo.save_data_id);
}
}
@ -182,7 +184,12 @@ static void usrOptDeleteAllUserSaves_t(void *a)
static void usrOptDeleteAllUserSaves(void *a)
{
data::user *u = data::getCurrentUser();
ui::confirmArgs *conf = ui::confirmArgsCreate(true, usrOptDeleteAllUserSaves_t, NULL, NULL, ui::getUICString("saveDataDeleteAllUser", 0), u->getUsername().c_str());
ui::confirmArgs *conf = ui::confirmArgsCreate(true,
usrOptDeleteAllUserSaves_t,
NULL,
NULL,
ui::getUICString("saveDataDeleteAllUser", 0),
u->getUsername().c_str());
ui::confirm(conf);
}
@ -228,9 +235,9 @@ static void createSaveData(void *a)
//Device, BCAT, and Cache are hardcoded user IDs in JKSV's data
uint64_t tid = 0;
switch(uid)
switch (uid)
{
case 0://This is system
case 0: //This is system
break;
case 2:
@ -262,20 +269,20 @@ static void usrOptCreateAllSaves_t(void *a)
int devPos = ui::usrMenu->getOptPos(ui::getUICString("saveTypeMainMenu", 0));
int bcatPos = ui::usrMenu->getOptPos(ui::getUICString("saveTypeMainMenu", 1));
int sel = ui::usrMenu->getSelected();
if(sel < devPos)
if (sel < devPos)
{
AccountUid uid = u->getUID();
for(unsigned i = 0; i < accSids.size(); i++)
for (unsigned i = 0; i < accSids.size(); i++)
fs::createSaveData(FsSaveDataType_Account, accSids[i], uid, t);
}
else if(sel == devPos)
else if (sel == devPos)
{
for(unsigned i = 0; i < devSids.size(); i++)
for (unsigned i = 0; i < devSids.size(); i++)
fs::createSaveData(FsSaveDataType_Device, devSids[i], util::u128ToAccountUID(0), t);
}
else if(sel == bcatPos)
else if (sel == bcatPos)
{
for(unsigned i = 0; i < bcatSids.size(); i++)
for (unsigned i = 0; i < bcatSids.size(); i++)
fs::createSaveData(FsSaveDataType_Bcat, bcatSids[i], util::u128ToAccountUID(0), t);
}
t->finished = true;
@ -284,7 +291,12 @@ static void usrOptCreateAllSaves_t(void *a)
static void usrOptCreateAllSaves(void *a)
{
data::user *u = data::getCurrentUser();
ui::confirmArgs *conf = ui::confirmArgsCreate(true, usrOptCreateAllSaves_t, NULL, NULL, ui::getUICString("confirmCreateAllSaveData", 0), u->getUsername().c_str());
ui::confirmArgs *conf = ui::confirmArgsCreate(true,
usrOptCreateAllSaves_t,
NULL,
NULL,
ui::getUICString("confirmCreateAllSaveData", 0),
u->getUsername().c_str());
ui::confirm(conf);
}
@ -302,20 +314,21 @@ static void initSaveCreateMenus()
cacheSids.clear();
//Group into vectors to match
for(auto& t : data::titles)
for (auto &t : data::titles)
{
NacpStruct *nacp = &t.second.nacp;
NacpStruct *nacp = &t.second.data.nacp;
if(nacp->user_account_save_data_size > 0)
if (nacp->user_account_save_data_size > 0)
accSids.push_back(t.first);
if(nacp->device_save_data_size > 0)
if (nacp->device_save_data_size > 0)
devSids.push_back(t.first);
if(nacp->bcat_delivery_cache_storage_size > 0)
if (nacp->bcat_delivery_cache_storage_size > 0)
bcatSids.push_back(t.first);
if(nacp->cache_storage_size > 0 || nacp->cache_storage_journal_size > 0 || nacp->cache_storage_data_and_journal_size_max > 0)
if (nacp->cache_storage_size > 0 || nacp->cache_storage_journal_size > 0 ||
nacp->cache_storage_data_and_journal_size_max > 0)
cacheSids.push_back(t.first);
}
@ -325,25 +338,25 @@ static void initSaveCreateMenus()
std::sort(bcatSids.begin(), bcatSids.end(), sortCreateTIDs);
std::sort(cacheSids.begin(), cacheSids.end(), sortCreateTIDs);
for(unsigned i = 0; i < accSids.size(); i++)
for (unsigned i = 0; i < accSids.size(); i++)
{
saveCreateMenu->addOpt(NULL, data::getTitleNameByTID(accSids[i]));
saveCreateMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL);
}
for(unsigned i = 0; i < devSids.size(); i++)
for (unsigned i = 0; i < devSids.size(); i++)
{
deviceSaveMenu->addOpt(NULL, data::getTitleNameByTID(devSids[i]));
deviceSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL);
}
for(unsigned i = 0; i < bcatSids.size(); i++)
for (unsigned i = 0; i < bcatSids.size(); i++)
{
bcatSaveMenu->addOpt(NULL, data::getTitleNameByTID(bcatSids[i]));
bcatSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL);
}
for(unsigned i = 0; i < cacheSids.size(); i++)
for (unsigned i = 0; i < cacheSids.size(); i++)
{
cacheSaveMenu->addOpt(NULL, data::getTitleNameByTID(cacheSids[i]));
cacheSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL);
@ -373,7 +386,7 @@ void ui::usrInit()
cacheSaveMenu->setActive(false);
cacheSaveMenu->setCallback(saveCreateCallback, NULL);
for(data::user u : data::users)
for (data::user u : data::users)
{
int usrPos = usrMenu->addOpt(u.getUserIcon(), u.getUsername());
usrMenu->optAddButtonEvent(usrPos, HidNpadButton_A, toTTL, NULL);
@ -399,7 +412,7 @@ void ui::usrInit()
usrOptPanel = new ui::slideOutPanel(410, 720, 0, ui::SLD_RIGHT, usrOptPanelDraw);
ui::registerPanel(usrOptPanel);
for(int i = 0; i < 4; i++)
for (int i = 0; i < 4; i++)
usrOptMenu->addOpt(NULL, ui::getUIString("userOptions", i));
//Dump All User Saves
@ -453,27 +466,27 @@ void ui::usrRefresh()
void ui::usrUpdate()
{
if(usrMenu->getActive())
if (usrMenu->getActive())
{
switch(ui::padKeysDown())
switch (ui::padKeysDown())
{
case HidNpadButton_Y:
ui::newThread(fs::dumpAllUsersAllSaves, NULL, fs::fileDrawFunc);
break;
case HidNpadButton_X:
{
int cachePos = usrMenu->getOptPos(ui::getUIString("saveTypeMainMenu", 2));
if (usrMenu->getSelected() <= cachePos)
{
int cachePos = usrMenu->getOptPos(ui::getUIString("saveTypeMainMenu", 2));
if(usrMenu->getSelected() <= cachePos)
{
data::user *u = data::getCurrentUser();
usrOptMenu->editOpt(0, NULL, ui::getUIString("userOptions", 0) + u->getUsername());
usrOptMenu->setActive(true);
usrMenu->setActive(false);
usrOptPanel->openPanel();
}
data::user *u = data::getCurrentUser();
usrOptMenu->editOpt(0, NULL, ui::getUIString("userOptions", 0) + u->getUsername());
usrOptMenu->setActive(true);
usrMenu->setActive(false);
usrOptPanel->openPanel();
}
break;
}
break;
}
}
usrMenu->update();
@ -486,6 +499,6 @@ void ui::usrUpdate()
void ui::usrDraw(SDL_Texture *target)
{
if(ui::mstate == USR_SEL)
if (ui::mstate == USR_SEL)
gfx::drawTextf(NULL, 18, usrHelpX, 673, &ui::txtCont, ui::getUICString("helpUser", 0));
}

View File

@ -1,40 +1,40 @@
#include <string>
#include <cstdio>
#include <ctime>
#include <sys/stat.h>
#include <json-c/json.h>
#include <string>
#include <sys/stat.h>
#include "file.h"
#include "data.h"
#include "gfx.h"
#include "util.h"
#include "ui.h"
#include "curlfuncs.h"
#include "type.h"
#include "cfg.h"
#include "curlfuncs.h"
#include "data.h"
#include "file.h"
#include "gfx.h"
#include "type.h"
#include "ui.h"
#include "util.h"
static const uint32_t verboten[] = { L',', L'/', L'\\', L'<', L'>', L':', L'"', L'|', L'?', L'*', L'', L'©', L'®'};
static const uint32_t verboten[] = {L',', L'/', L'\\', L'<', L'>', L':', L'"', L'|', L'?', L'*', L'', L'©', L'®'};
static bool isVerboten(const uint32_t& t)
static bool isVerboten(const uint32_t &t)
{
for(unsigned i = 0; i < 13; i++)
for (unsigned i = 0; i < 13; i++)
{
if(t == verboten[i])
if (t == verboten[i])
return true;
}
return false;
}
void util::replaceStr(std::string& _str, const std::string& _find, const std::string& _rep)
void util::replaceStr(std::string &_str, const std::string &_find, const std::string &_rep)
{
size_t pos = 0;
while((pos = _str.find(_find)) != _str.npos)
while ((pos = _str.find(_find)) != _str.npos)
_str.replace(pos, _find.length(), _rep);
}
//Used to split version tag git
static void getVersionFromTag(const std::string& tag, unsigned& _year, unsigned& _month, unsigned& _day)
static void getVersionFromTag(const std::string &tag, unsigned &_year, unsigned &_month, unsigned &_day)
{
_month = strtoul(tag.substr(0, 2).c_str(), NULL, 10);
_day = strtoul(tag.substr(3, 5).c_str(), NULL, 10);
@ -45,13 +45,13 @@ static void getVersionFromTag(const std::string& tag, unsigned& _year, unsigned&
typedef enum
{
SwkbdPosStart = 0,
SwkbdPosEnd = 1
SwkbdPosEnd = 1
} SwkbdInitPos;
typedef struct
{
uint16_t read[0x32 / sizeof(uint16_t)];
uint16_t word[0x32 / sizeof(uint16_t)];
uint16_t read[0x32 / sizeof(uint16_t)];
uint16_t word[0x32 / sizeof(uint16_t)];
} dictWord;
void swkbdDictWordCreate(dictWord *w, const char *read, const char *word)
@ -64,7 +64,7 @@ void swkbdDictWordCreate(dictWord *w, const char *read, const char *word)
uint32_t replaceChar(uint32_t c)
{
switch(c)
switch (c)
{
case L'é':
return 'e';
@ -77,9 +77,9 @@ uint32_t replaceChar(uint32_t c)
static inline void replaceCharCStr(char *_s, char _find, char _rep)
{
size_t strLength = strlen(_s);
for(unsigned i = 0; i < strLength; i++)
for (unsigned i = 0; i < strLength; i++)
{
if(_s[i] == _find)
if (_s[i] == _find)
_s[i] = _rep;
}
}
@ -92,14 +92,28 @@ std::string util::getDateTime(int fmt)
time(&raw);
tm *Time = localtime(&raw);
switch(fmt)
switch (fmt)
{
case DATE_FMT_YMD:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec);
sprintf(ret,
"%04d.%02d.%02d @ %02d.%02d.%02d",
Time->tm_year + 1900,
Time->tm_mon + 1,
Time->tm_mday,
Time->tm_hour,
Time->tm_min,
Time->tm_sec);
break;
case DATE_FMT_YDM:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mday, Time->tm_mon + 1, Time->tm_hour, Time->tm_min, Time->tm_sec);
sprintf(ret,
"%04d.%02d.%02d @ %02d.%02d.%02d",
Time->tm_year + 1900,
Time->tm_mday,
Time->tm_mon + 1,
Time->tm_hour,
Time->tm_min,
Time->tm_sec);
break;
case DATE_FMT_HOYSTE:
@ -107,7 +121,13 @@ std::string util::getDateTime(int fmt)
break;
case DATE_FMT_JHK:
sprintf(ret, "%04d%02d%02d_%02d%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min);
sprintf(ret,
"%04d%02d%02d_%02d%02d",
Time->tm_year + 1900,
Time->tm_mon + 1,
Time->tm_mday,
Time->tm_hour,
Time->tm_min);
break;
case DATE_FMT_ASC:
@ -120,47 +140,47 @@ std::string util::getDateTime(int fmt)
return std::string(ret);
}
void util::copyDirListToMenu(const fs::dirList& d, ui::menu& m)
void util::copyDirListToMenu(const fs::dirList &d, ui::menu &m)
{
m.reset();
m.addOpt(NULL, ".");
m.addOpt(NULL, "..");
for(unsigned i = 0; i < d.getCount(); i++)
for (unsigned i = 0; i < d.getCount(); i++)
{
if(d.isDir(i))
if (d.isDir(i))
m.addOpt(NULL, "D " + d.getItem(i));
else
m.addOpt(NULL, "F " + d.getItem(i));
}
}
void util::removeLastFolderFromString(std::string& _path)
void util::removeLastFolderFromString(std::string &_path)
{
unsigned last = _path.find_last_of('/', _path.length() - 2);
_path.erase(last + 1, _path.length());
}
size_t util::getTotalPlacesInPath(const std::string& _path)
size_t util::getTotalPlacesInPath(const std::string &_path)
{
//Skip device
size_t pos = _path.find_first_of('/'), ret = 0;
while((pos = _path.find_first_of('/', ++pos)) != _path.npos)
while ((pos = _path.find_first_of('/', ++pos)) != _path.npos)
++ret;
return ret;
}
void util::trimPath(std::string& _path, uint8_t _places)
void util::trimPath(std::string &_path, uint8_t _places)
{
size_t pos = _path.find_first_of('/');
for(int i = 0; i < _places; i++)
for (int i = 0; i < _places; i++)
pos = _path.find_first_of('/', ++pos);
_path = _path.substr(++pos, _path.npos);
}
std::string util::safeString(const std::string& s)
std::string util::safeString(const std::string &s)
{
std::string ret = "";
for(unsigned i = 0; i < s.length(); )
for (unsigned i = 0; i < s.length();)
{
uint32_t tmpChr = 0;
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&s.data()[i]);
@ -169,29 +189,34 @@ std::string util::safeString(const std::string& s)
tmpChr = replaceChar(tmpChr);
if(isVerboten(tmpChr))
if (isVerboten(tmpChr))
ret += ' ';
else if(!isASCII(tmpChr))
else if (!isASCII(tmpChr))
return ""; //return empty string so titledata::init defaults to titleID
else
ret += (char)tmpChr;
}
//Check for spaces at end
while(ret[ret.length() - 1] == ' ' || ret[ret.length() - 1] == '.')
while (ret[ret.length() - 1] == ' ' || ret[ret.length() - 1] == '.')
ret.erase(ret.length() - 1, 1);
return ret;
}
static inline std::string getTimeString(const uint32_t& _h, const uint32_t& _m)
static inline std::string getTimeString(const uint32_t &_h, const uint32_t &_m)
{
char tmp[32];
sprintf(tmp, "%02d:%02d", _h, _m);
return std::string(tmp);
}
std::string util::getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[])
std::string util::getStringInput(SwkbdType _type,
const std::string &def,
const std::string &head,
size_t maxLength,
unsigned dictCnt,
const std::string dictWords[])
{
SwkbdConfig swkbd;
swkbdCreate(&swkbd, dictCnt);
@ -205,10 +230,10 @@ std::string util::getStringInput(SwkbdType _type, const std::string& def, const
swkbdConfigSetKeySetDisableBitmask(&swkbd, SwkbdKeyDisableBitmask_Backslash | SwkbdKeyDisableBitmask_Percent);
swkbdConfigSetDicFlag(&swkbd, 1);
if(dictCnt > 0)
if (dictCnt > 0)
{
dictWord words[dictCnt];
for(unsigned i = 0; i < dictCnt; i++)
for (unsigned i = 0; i < dictCnt; i++)
swkbdDictWordCreate(&words[i], dictWords[i].c_str(), dictWords[i].c_str());
swkbdConfigSetDictionary(&swkbd, (SwkbdDictWord *)words, dictCnt);
@ -222,25 +247,25 @@ std::string util::getStringInput(SwkbdType _type, const std::string& def, const
return std::string(out);
}
std::string util::getExtensionFromString(const std::string& get)
std::string util::getExtensionFromString(const std::string &get)
{
size_t ext = get.find_last_of('.');
if(ext != get.npos)
if (ext != get.npos)
return get.substr(ext + 1, get.npos);
else
return "";
}
std::string util::getFilenameFromPath(const std::string& get)
std::string util::getFilenameFromPath(const std::string &get)
{
size_t nameStart = get.find_last_of('/');
if(nameStart != get.npos)
if (nameStart != get.npos)
return get.substr(nameStart + 1, get.npos);
else
return "";
}
std::string util::generateAbbrev(const uint64_t& tid)
std::string util::generateAbbrev(uint64_t tid)
{
data::titleInfo *tmp = data::getTitleInfoByTID(tid);
size_t titleLength = tmp->safeTitle.length();
@ -251,23 +276,23 @@ std::string util::generateAbbrev(const uint64_t& tid)
std::string ret;
char *tok = strtok(temp, " ");
while(tok)
while (tok)
{
if(isASCII(tok[0]))
if (isASCII(tok[0]))
ret += tok[0];
tok = strtok(NULL, " ");
}
return ret;
}
void util::stripChar(char _c, std::string& _s)
void util::stripChar(char _c, std::string &_s)
{
size_t pos = 0;
while((pos = _s.find(_c)) != _s.npos)
while ((pos = _s.find(_c)) != _s.npos)
_s.erase(pos, 1);
}
void util::replaceButtonsInString(std::string& rep)
void util::replaceButtonsInString(std::string &rep)
{
replaceStr(rep, "[A]", "\ue0e0");
replaceStr(rep, "[B]", "\ue0e1");
@ -292,7 +317,7 @@ SDL_Texture *util::createIconGeneric(const char *txt, int fontSize, bool clearBa
{
SDL_Texture *ret = gfx::texMgr->textureCreate(256, 256);
SDL_SetRenderTarget(gfx::render, ret);
if(clearBack)
if (clearBack)
{
SDL_SetRenderDrawColor(gfx::render, ui::rectLt.r, ui::rectLt.g, ui::rectLt.b, ui::rectLt.a);
SDL_RenderClear(gfx::render);
@ -310,7 +335,7 @@ SDL_Texture *util::createIconGeneric(const char *txt, int fontSize, bool clearBa
void util::sysBoost()
{
if(R_FAILED(clkrstInitialize()))
if (R_FAILED(clkrstInitialize()))
return;
ClkrstSession cpu, gpu, ram;
@ -330,7 +355,7 @@ void util::sysBoost()
void util::sysNormal()
{
if(R_FAILED(clkrstInitialize()))
if (R_FAILED(clkrstInitialize()))
return;
ClkrstSession cpu, gpu, ram;
@ -338,7 +363,7 @@ void util::sysNormal()
clkrstOpenSession(&gpu, PcvModuleId_GPU, 3);
clkrstOpenSession(&ram, PcvModuleId_EMC, 3);
if(cfg::config["ovrClk"])
if (cfg::config["ovrClk"])
clkrstSetClockRate(&cpu, util::CPU_SPEED_1224MHz);
else
clkrstSetClockRate(&cpu, util::CPU_SPEED_1020MHz);
@ -349,7 +374,6 @@ void util::sysNormal()
clkrstCloseSession(&gpu);
clkrstCloseSession(&ram);
clkrstExit();
}
void util::checkForUpdate(void *a)
@ -357,7 +381,7 @@ void util::checkForUpdate(void *a)
threadInfo *t = (threadInfo *)a;
t->status->setStatus(ui::getUICString("threadStatusCheckingForUpdate", 0));
std::string gitJson = curlFuncs::getJSONURL(NULL, "https://api.github.com/repos/J-D-K/JKSV/releases/latest");
if(gitJson.empty())
if (gitJson.empty())
{
ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("onlineErrorConnecting", 0));
t->finished = true;
@ -371,7 +395,7 @@ void util::checkForUpdate(void *a)
tagStr = json_object_get_string(tag);
getVersionFromTag(tagStr, year, month, day);
//This can throw false positives as is. need to fix sometime
if(year > BLD_YEAR || month > BLD_MON || month > BLD_DAY)
if (year > BLD_YEAR || month > BLD_MON || month > BLD_DAY)
{
t->status->setStatus(ui::getUICString("threadStatusDownloadingUpdate", 0));
//dunno about NSP yet...
@ -394,27 +418,16 @@ void util::checkForUpdate(void *a)
t->finished = true;
}
std::string util::getSizeString(const uint64_t& _size)
std::string util::getSizeString(uint64_t _size)
{
char sizeStr[32];
if(_size >= 0x40000000)
if (_size >= 0x40000000)
sprintf(sizeStr, "%.2fGB", (float)_size / 1024.0f / 1024.0f / 1024.0f);
else if(_size >= 0x100000)
else if (_size >= 0x100000)
sprintf(sizeStr, "%.2fMB", (float)_size / 1024.0f / 1024.0f);
else if(_size >= 0x400)
else if (_size >= 0x400)
sprintf(sizeStr, "%.2fKB", (float)_size / 1024.0f);
else
sprintf(sizeStr, "%lu Bytes", _size);
return std::string(sizeStr);
}
Result util::accountDeleteUser(AccountUid *uid)
{
Service *account = accountGetServiceSession();
struct
{
AccountUid uid;
} in = {*uid};
return serviceDispatchIn(account, 203, in);
}