mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-08-27 13:04:11 -05:00
WIP UI Update
This commit is contained in:
2
Makefile
2
Makefile
@@ -38,7 +38,7 @@ INCLUDES := inc
|
||||
EXEFS_SRC := exefs_src
|
||||
APP_TITLE := JKSV
|
||||
APP_AUTHOR := JK
|
||||
APP_VERSION := 06.14.2021
|
||||
APP_VERSION := 07.09.2021
|
||||
ROMFS := romfs
|
||||
ICON := icon.jpg
|
||||
|
||||
|
||||
31
README.MD
31
README.MD
@@ -70,40 +70,17 @@ JKSV on Switch started as a small project/port to test some things and get famil
|
||||
* Rescan Titles reloads save data information. This can be used to reload after a process is terminated or when options are changed.
|
||||
* Mount Process RomFS opens the title's romfs that is taken over to launch the homebrew menu. This only works as an NRO. The NSP will only open JKSV's own RomFS.
|
||||
* Backup JKSV folder writes the entire JKSV folder to a ZIP archive and places it in your JKSV folder.
|
||||
|
||||
6. Options
|
||||
* Include Dev Sv will add Device Save games such as Animal Crossing to your user account saves for easier access.
|
||||
* AutoBackup will create a backup of your current save before restoring just in case.
|
||||
* Overclock will clock your Switch's CPU to 1224MHz on boot.
|
||||
* Hold to [X] will disable needing to hold down A to confirm an action
|
||||
* Force Mount will only allow JKSV to list titles it can open. Disabling will give a complete list of all saves on your system
|
||||
* Account Sys. Saves will allow you to see and open system saves associated with user accounts
|
||||
* Write to Sys. Saves will allow you to write data to system save archives. This can be dangerous.
|
||||
* Text UI mode enables a simplified UI that only uses text menus
|
||||
* Direct FS Commands uses a simple wrapper instead of libnx's stdio.
|
||||
* Skip User Select jumps directly to the first user found instead of requiring a user to be selected.
|
||||
* Export to ZIP uses minizip to compress your save data to a ZIP archive instead of a folder full of files. This saves space and makes moving saves more convienient.
|
||||
* Sort changes the way titles are sorted. Alphabetically, Most time played, or by last title played.
|
||||
|
||||
**IMPORTANT**: Press Plus to Exit JKSV. JKSV saves all config, favorites, and the blacklist when exited. Pressing the home button and closing that way will not allow this to take place.
|
||||
|
||||
**NOTE**: Press Plus to Exit JKSV. JKSV saves all config, favorites, and the blacklist when exited. Pressing the home button and closing that way will not allow this to take place.
|
||||
|
||||
## Building:
|
||||
1. Requires [devkitPro](https://devkitpro.org/) and [libnx](https://github.com/switchbrew/libnx)
|
||||
2. Requires switch-
|
||||
* freetype
|
||||
* libpng
|
||||
* zlib
|
||||
* libjpeg-turbo
|
||||
* curl
|
||||
* libjson-c
|
||||
* sdl2
|
||||
* sdl2_image
|
||||
* libwebp
|
||||
|
||||
2. Requires switch-freetype, libpng, zlib, libjpeg-turbo, lib-curl, and lib-json-c
|
||||
|
||||
## Credits and Thanks:
|
||||
* [shared-font](https://github.com/switchbrew/switch-portlibs-examples) example by yellows8
|
||||
* Authors of switch-examples for account and save mounting code.
|
||||
* [Iguniisu](https://github.com/igniscitrinus) for the icon.
|
||||
* Uses graphics from [Twemoji](https://github.com/twitter/twemoji) covered by the [Creative Commons License](https://creativecommons.org/licenses/by/4.0/legalcode)
|
||||
* [Leo](https://github.com/qazrfv1234) For the Traditional Chinese translation
|
||||
* [JamePeng](https://github.com/JamePeng) For the Simplified Chinese translation.
|
||||
|
||||
117
inc/data.h
117
inc/data.h
@@ -1,6 +1,4 @@
|
||||
#ifndef DATA_H
|
||||
#define DATA_H
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include <vector>
|
||||
@@ -10,14 +8,16 @@
|
||||
#include "gfx.h"
|
||||
|
||||
#define curUser users[data::selUser]
|
||||
#define curData users[data::selUser].titles[data::selData]
|
||||
#define curData users[data::selUser].titleInfo[data::selData]
|
||||
|
||||
#define BLD_MON 06
|
||||
#define BLD_DAY 14
|
||||
#define BLD_MON 7
|
||||
#define BLD_DAY 9
|
||||
#define BLD_YEAR 2021
|
||||
|
||||
namespace data
|
||||
{
|
||||
extern bool forceMount;
|
||||
|
||||
//Loads user + title info
|
||||
void init();
|
||||
void exit();
|
||||
@@ -29,61 +29,27 @@ namespace data
|
||||
void loadFav();
|
||||
void saveFav();
|
||||
void loadDefs();
|
||||
void exportIcons();
|
||||
|
||||
//Draws some stats to the upper left corner
|
||||
void dispStats();
|
||||
|
||||
//Class to store title info
|
||||
class titledata
|
||||
//Global stuff for all titles/saves
|
||||
typedef struct
|
||||
{
|
||||
public:
|
||||
titledata() = default;
|
||||
//Attempts to read title's info
|
||||
titledata(const FsSaveDataInfo& inf, NsApplicationControlData *dat);
|
||||
NacpStruct nacp;
|
||||
std::string title, safeTitle, author;//Shortcuts sorta.
|
||||
SDL_Texture *icon;
|
||||
bool fav;
|
||||
} titleInfo;
|
||||
|
||||
//Returns title + title without forbidden chars
|
||||
std::string getTitle() const { return title;}
|
||||
std::string getTitleSafe() const { return titleSafe; }
|
||||
std::string getAuthor() const { return author; }
|
||||
|
||||
//Creates title folder
|
||||
void createDir() const;
|
||||
//Returns folder path
|
||||
std::string getPath() const;
|
||||
|
||||
//returns save_data_id string. only used for helping identify nand files
|
||||
std::string getTIDStr() const;
|
||||
std::string getSaveIDStr() const;
|
||||
|
||||
uint64_t getID() const { return id; }
|
||||
uint64_t getSaveID() const { return saveID; }
|
||||
uint16_t getSaveIndex() const { return saveIndex; }
|
||||
FsSaveDataType getType() const { return (FsSaveDataType)saveDataType; }
|
||||
void setID(const uint64_t& _id){ id = _id; }
|
||||
void setIndex(const uint16_t& _ind){ saveIndex = _ind; }
|
||||
void setType(FsSaveDataType type) { saveDataType = type; }
|
||||
void setFav(bool setFav) { favorite = setFav; }
|
||||
bool getFav() const { return favorite; }
|
||||
void assignIcon();
|
||||
void drawIcon(bool full, unsigned x, unsigned y);
|
||||
void drawIconFav(bool full, unsigned x, unsigned y);
|
||||
void setPlayTime(const uint32_t& _p){ playMins = _p; }
|
||||
uint32_t getPlayTime() const { return playMins; }
|
||||
void setLastTimeStamp(const uint32_t& _ts){ lastTimeStamp = _ts; }
|
||||
uint32_t getLastTimeStamp() const { return lastTimeStamp; }
|
||||
void setLaunchCount(const uint32_t& _lc) { launchCount = _lc; }
|
||||
uint32_t getLaunchCount() const { return launchCount; }
|
||||
|
||||
private:
|
||||
SDL_Texture *icon;
|
||||
uint8_t saveDataType;
|
||||
std::string title, titleSafe, author;
|
||||
uint64_t id, saveID;
|
||||
uint16_t saveIndex;
|
||||
uint32_t playMins, lastTimeStamp, launchCount;
|
||||
bool favorite = false;
|
||||
};
|
||||
//Holds stuff specific to user's titles/saves
|
||||
typedef struct
|
||||
{
|
||||
//Makes it easier to grab id
|
||||
uint64_t saveID;
|
||||
FsSaveDataInfo saveInfo;
|
||||
PdmPlayStatistics playStats;
|
||||
} userTitleInfo;
|
||||
|
||||
//Class to store user info + titles
|
||||
class user
|
||||
@@ -107,13 +73,11 @@ namespace data
|
||||
std::string getUsername() const { return username; }
|
||||
std::string getUsernameSafe() const { return userSafe; }
|
||||
|
||||
//Vector for storing save data info for user
|
||||
std::vector<titledata> titles;
|
||||
void loadPlayTimes();
|
||||
SDL_Texture *getUserIcon(){ return userIcon; }
|
||||
void delIcon(){ SDL_DestroyTexture(userIcon); }
|
||||
|
||||
void drawIcon(int x, int y) { gfx::texDraw(userIcon, x, y); }
|
||||
void drawIconHalf(int x, int y) { gfx::texDrawStretch(userIcon, x, y, 128, 128); }
|
||||
void delIcon() { SDL_DestroyTexture(userIcon); }
|
||||
std::vector<data::userTitleInfo> titleInfo;
|
||||
void addUserTitleInfo(const uint64_t& _tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats);
|
||||
|
||||
private:
|
||||
AccountUid userID;
|
||||
@@ -123,17 +87,34 @@ namespace data
|
||||
SDL_Texture *userIcon;
|
||||
};
|
||||
|
||||
//Gets total count of save containers
|
||||
unsigned getTotalSaves();
|
||||
|
||||
//Adds title to blacklist
|
||||
void blacklistAdd(data::titledata& t);
|
||||
void blacklistAdd(const uint64_t& tid);
|
||||
//Adds title to favorite list
|
||||
void favoriteTitle(data::titledata& t);
|
||||
void favoriteTitle(const uint64_t& tid);
|
||||
|
||||
bool isFavorite(const uint64_t& tid);
|
||||
|
||||
//User vector
|
||||
extern std::vector<user> users;
|
||||
extern std::unordered_map<uint64_t, SDL_Texture *> icons;
|
||||
//Title data/info map
|
||||
extern std::unordered_map<uint64_t, data::titleInfo> titles;
|
||||
|
||||
//Gets pointer to info
|
||||
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);
|
||||
inline int getTitleIndexInUser(const data::user& u, const uint64_t& sid)
|
||||
{
|
||||
for(unsigned i = 0; i < u.titleInfo.size(); i++)
|
||||
{
|
||||
if(u.titleInfo[i].saveID == sid)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Options and info
|
||||
//Restores config to default
|
||||
@@ -143,5 +124,3 @@ namespace data
|
||||
extern bool incDev, autoBack, ovrClk, holdDel, holdRest, holdOver, forceMount, accSysSave, sysSaveWrite, directFsCmd, skipUser, zip, langOverride;
|
||||
extern uint8_t sortType;
|
||||
}
|
||||
|
||||
#endif // DATA_H
|
||||
|
||||
20
inc/file.h
20
inc/file.h
@@ -1,5 +1,4 @@
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
@@ -11,6 +10,7 @@
|
||||
|
||||
#include "fsfile.h"
|
||||
#include "data.h"
|
||||
#include "miscui.h"
|
||||
|
||||
namespace fs
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace fs
|
||||
void exit();
|
||||
|
||||
//Mounts usr's save data for open. Returns false it fails
|
||||
bool mountSave(const data::user& usr, const data::titledata& open);
|
||||
bool mountSave(const FsSaveDataInfo& _m);
|
||||
inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; }
|
||||
|
||||
void copyFile(const std::string& from, const std::string& to);
|
||||
@@ -127,9 +127,19 @@ namespace fs
|
||||
bool opened = false;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ui::menu *m;
|
||||
fs::dirList *d;
|
||||
} backupArgs;
|
||||
|
||||
//Take a pointer to backupArgs^
|
||||
void createNewBackup(void *a);
|
||||
void overwriteBackup(void *a);
|
||||
void restoreBackup(void *a);
|
||||
void deleteBackup(void *a);
|
||||
|
||||
void logOpen();
|
||||
void logWrite(const char *fmt, ...);
|
||||
void logClose();
|
||||
}
|
||||
|
||||
#endif // FILE_H
|
||||
|
||||
9
inc/fld.h
Normal file
9
inc/fld.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace ui
|
||||
{
|
||||
void fldInit();
|
||||
void fldExit();
|
||||
void fldUpdate();
|
||||
void fldDraw();
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
#ifndef FSFILE_H
|
||||
#define FSFILE_H
|
||||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include <stdint.h>
|
||||
@@ -97,5 +96,3 @@ inline void fsfputc(int ch, FSFILE *_f) { fsfwrite(&ch, 1, 1, _f); }
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
49
inc/gfx.h
49
inc/gfx.h
@@ -1,5 +1,4 @@
|
||||
#ifndef GFX_H
|
||||
#define GFX_H
|
||||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
@@ -9,51 +8,67 @@ namespace gfx
|
||||
|
||||
void init();
|
||||
void exit();
|
||||
void clear(const SDL_Color *c);
|
||||
void present();
|
||||
|
||||
SDL_Texture *loadJPEGMem(const void *jpegData, size_t jpegSize);
|
||||
SDL_Texture *loadImageFile(const char *file);
|
||||
|
||||
void drawTextf(int fontSize, int x, int y, const SDL_Color *c, const char *fmt, ...);
|
||||
void drawTextfWrap(int fontSize, int x, int y, int maxWidth, const SDL_Color* c, const char *fmt, ...);
|
||||
void drawTextf(SDL_Texture *target, int fontSize, int x, int y, const SDL_Color *c, const char *fmt, ...);
|
||||
void drawTextfWrap(SDL_Texture *target, int fontSize, int x, int y, int maxWidth, const SDL_Color* c, const char *fmt, ...);
|
||||
size_t getTextWidth(const char *str, int fontSize);
|
||||
|
||||
//Shortcuts for drawing
|
||||
inline void texDraw(SDL_Texture *tex, int x, int y)
|
||||
inline void texDraw(SDL_Texture *target, SDL_Texture *tex, int x, int y)
|
||||
{
|
||||
int tW = 0, tH = 0;
|
||||
if(SDL_QueryTexture(tex, NULL, NULL, &tW, &tH) == 0)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_Rect src = {0, 0, tW, tH};
|
||||
SDL_Rect pos = {x, y, tW, tH};
|
||||
SDL_RenderCopy(render, tex, &src, &pos);
|
||||
SDL_RenderCopy(gfx::render, tex, &src, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
inline void texDrawStretch(SDL_Texture *tex, int x, int y, int w, int h)
|
||||
inline void texDrawStretch(SDL_Texture *target, SDL_Texture *tex, int x, int y, int w, int h)
|
||||
{
|
||||
int tW = 0, tH = 0;
|
||||
if(SDL_QueryTexture(tex, NULL, NULL, &tW, &tH) == 0)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_Rect src = {0, 0, tW, tH};
|
||||
SDL_Rect pos = {x, y, w, h};
|
||||
SDL_RenderCopy(render, tex, &src, &pos);
|
||||
SDL_RenderCopy(gfx::render, tex, &src, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
inline void drawLine(const SDL_Color *c, int x1, int y1, int x2, int y2)
|
||||
inline void texDrawPart(SDL_Texture *target, SDL_Texture *tex, int srcX, int srcY, int srcW, int srcH, int dstX, int dstY)
|
||||
{
|
||||
SDL_SetRenderDrawColor(render, c->r, c->g, c->b, c->a);
|
||||
SDL_RenderDrawLine(render, x1, y1, x2, y2);
|
||||
SDL_Rect src = {srcX, srcY, srcW, srcH};
|
||||
SDL_Rect dst = {dstX, dstY, srcW, srcH};
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_RenderCopy(gfx::render, tex, &src, &dst);
|
||||
}
|
||||
|
||||
inline void drawRect(const SDL_Color *c, int x, int y, int w, int h)
|
||||
inline void drawLine(SDL_Texture *target, const SDL_Color *c, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
SDL_SetRenderDrawColor(render, c->r, c->g, c->b, c->a);
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_SetRenderDrawColor(gfx::render, c->r, c->g, c->b, c->a);
|
||||
SDL_RenderDrawLine(gfx::render, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
inline void drawRect(SDL_Texture *target, const SDL_Color *c, int x, int y, int w, int h)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_SetRenderDrawColor(gfx::render, c->r, c->g, c->b, c->a);
|
||||
SDL_Rect rect = {x, y, w, h};
|
||||
SDL_RenderFillRect(render, &rect);
|
||||
SDL_RenderFillRect(gfx::render, &rect);
|
||||
}
|
||||
|
||||
inline void clearTarget(SDL_Texture *target, const SDL_Color *clear)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_SetRenderDrawColor(gfx::render, clear->r, clear->g, clear->b, clear->a);
|
||||
SDL_RenderClear(gfx::render);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GFX_H
|
||||
|
||||
54
inc/menu.h
54
inc/menu.h
@@ -1,54 +0,0 @@
|
||||
#ifndef MENU_H
|
||||
#define MENU_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gfx.h"
|
||||
#include "miscui.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class menu
|
||||
{
|
||||
public:
|
||||
void setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW);
|
||||
//Adds option
|
||||
void addOpt(const std::string& add);
|
||||
//Changes opt text
|
||||
void editOpt(int ind, const std::string& ch);
|
||||
//Clears menu stuff
|
||||
~menu();
|
||||
|
||||
//Handles controller input
|
||||
void handleInput(const uint64_t& down, const uint64_t& held);
|
||||
|
||||
//Returns selected option
|
||||
int getSelected() { return selected; }
|
||||
|
||||
//Draws the menu at x and y. rectWidth is the width of the rectangle drawn under the selected
|
||||
void draw(const SDL_Color *textClr);
|
||||
|
||||
//Clears and resets menu
|
||||
void reset();
|
||||
|
||||
//Resets selected + start
|
||||
void resetSel() { selected = 0; start = 0; }
|
||||
|
||||
//Adjusts things after changes are made
|
||||
void adjust();
|
||||
|
||||
private:
|
||||
//drawing x and y + rectangle width
|
||||
unsigned x = 0, y = 0, rW = 0, rY = 0;
|
||||
//Options vector
|
||||
std::vector<std::string> opt;
|
||||
//Selected + frame counting for auto-scroll
|
||||
int selected = 0, fc = 0, start = 0;
|
||||
//How much we shift the color of the rectangle
|
||||
uint8_t clrSh = 0;
|
||||
bool clrAdd = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
133
inc/miscui.h
133
inc/miscui.h
@@ -1,39 +1,139 @@
|
||||
#ifndef MISCUI_H
|
||||
#define MISCUI_H
|
||||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "type.h"
|
||||
#include "gfx.h"
|
||||
|
||||
#define PROG_MAX_WIDTH_DEFAULT 576
|
||||
#define POP_FRAME_DEFAULT 130
|
||||
|
||||
#define MENU_FONT_SIZE_DEFAULT 18
|
||||
#define MENU_MAX_SCROLL_DEFAULT 15
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FUNC_A,
|
||||
FUNC_B,
|
||||
FUNC_X,
|
||||
FUNC_Y,
|
||||
} funcBtn;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MENU_X,
|
||||
MENU_Y,
|
||||
MENU_RECT_WIDTH,
|
||||
MENU_FONT_SIZE,
|
||||
MENU_MAX_SCROLL
|
||||
} menuParams;
|
||||
|
||||
//For smaller classes that aren't easy to get lost in and general functions
|
||||
namespace ui
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
SDL_Texture *icn = NULL;
|
||||
std::string txt;
|
||||
funcPtr func[4] = {NULL};
|
||||
void *argPtr[4] = {NULL};
|
||||
} menuOpt;
|
||||
|
||||
class menu
|
||||
{
|
||||
public:
|
||||
menu() = default;
|
||||
|
||||
//X, Y, Rect width/Max length, Font size, max to show
|
||||
void setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW, const unsigned& _fS, const unsigned& _mL);
|
||||
void editParam(int _param, unsigned newVal);
|
||||
|
||||
//Gets executed when menu changes at all
|
||||
void setOnChangeFunc(funcPtr func){ onChange = func; }
|
||||
|
||||
//executed when .update() is called.
|
||||
void setCallback(funcPtr _callback, void *args) { callback = _callback; callbackArgs = args; }
|
||||
|
||||
//Adds option.
|
||||
void addOpt(SDL_Texture *_icn, const std::string& add);
|
||||
//Changes opt text
|
||||
void editOpt(int ind, SDL_Texture *_icn, const std::string& ch);
|
||||
|
||||
void setOptFunc(unsigned _ind, unsigned _funcbtn, funcPtr _func, void *args);
|
||||
void updateOptArgs(unsigned _ind, unsigned _funcbtn, void *args){ opt[_ind].argPtr[_funcbtn] = args; }
|
||||
|
||||
int getOptPos(const std::string& txt);
|
||||
|
||||
//Clears menu stuff
|
||||
~menu();
|
||||
|
||||
//Handles controller input and executes functions for buttons if they're set
|
||||
void update();
|
||||
|
||||
//Returns selected option
|
||||
int getSelected() { return selected; }
|
||||
|
||||
//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);
|
||||
|
||||
//Clears and resets menu
|
||||
void reset();
|
||||
|
||||
//Resets selected + start
|
||||
void resetSel() { selected = 0; start = 0; }
|
||||
|
||||
//Enables control/disables drawing select box
|
||||
void setActive(bool _set);
|
||||
bool getActive() { return isActive; }
|
||||
|
||||
private:
|
||||
//drawing x and y + rectangle width/height. Height is calc'd with font size
|
||||
int x = 0, y = 0, rW = 0, rY = 0, fSize = 0, rH = 0, mL = 0;
|
||||
//Options vector
|
||||
std::vector<ui::menuOpt> opt;
|
||||
//Selected + frame counting for auto-scroll
|
||||
int selected = 0, fc = 0, start = 0;
|
||||
//How much we shift the color of the rectangle
|
||||
uint8_t clrSh = 0;
|
||||
bool clrAdd = true, isActive = true;
|
||||
funcPtr onChange = NULL, callback = NULL;
|
||||
void *callbackArgs, *funcArgs;
|
||||
};
|
||||
|
||||
//Progress bar for showing loading. Mostly so people know it didn't freeze
|
||||
class progBar
|
||||
{
|
||||
public:
|
||||
progBar() = default;
|
||||
|
||||
//Constructor. _max is the maximum value
|
||||
progBar(const uint64_t& _max, const uint64_t& _maxWidth) { max = _max; maxWidth = _maxWidth; }
|
||||
|
||||
void setMax(const uint64_t& _max, const uint64_t& _maxWidth){ max = _max; maxWidth = _maxWidth; }
|
||||
progBar(const uint64_t& _max) { max = _max; }
|
||||
|
||||
//Updates progress
|
||||
void update(const uint64_t& _prog);
|
||||
|
||||
void incProgress(unsigned inc){ prog += inc; }
|
||||
|
||||
//Draws with text at top
|
||||
void draw(const std::string& text, const std::string& head);
|
||||
|
||||
//Draws without dialog box
|
||||
void drawNoDialog(int x, int y);
|
||||
private:
|
||||
uint64_t max, prog;
|
||||
float width;
|
||||
};
|
||||
|
||||
//_draw is called and passed the panel texture/target when this.draw() is called.
|
||||
class slideOutPanel
|
||||
{
|
||||
public:
|
||||
slideOutPanel(int _w, int _h, int _y, funcPtr _draw);
|
||||
~slideOutPanel();
|
||||
|
||||
void openPanel() { open = true; }
|
||||
void closePanel() { open = false; }
|
||||
bool isOpen() { return open; }
|
||||
void draw(const SDL_Color *backCol);
|
||||
|
||||
private:
|
||||
uint64_t max, prog, maxWidth;
|
||||
float width;
|
||||
int w, h, x = 1280, y, slideSpd = 0;
|
||||
bool open = false;
|
||||
SDL_Texture *panel;
|
||||
funcPtr drawFunc;
|
||||
};
|
||||
|
||||
//General use
|
||||
@@ -41,11 +141,10 @@ namespace ui
|
||||
bool confirm(bool hold, const char *fmt, ...);
|
||||
bool confirmTransfer(const std::string& f, const std::string& t);
|
||||
bool confirmDelete(const std::string& p);
|
||||
void drawTextbox(int x, int y, int w, int h);
|
||||
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);
|
||||
|
||||
//Popup from freebird
|
||||
void showPopup(unsigned frames, const char *fmt, ...);
|
||||
void drawPopup(const uint64_t& down);
|
||||
}
|
||||
|
||||
#endif // MISCUI_H
|
||||
|
||||
13
inc/ttl.h
Normal file
13
inc/ttl.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace ui
|
||||
{
|
||||
void ttlInit();
|
||||
void ttlExit();
|
||||
|
||||
//JIC for func ptr
|
||||
void setupTiles(void *);
|
||||
void ttlReset();
|
||||
void ttlUpdate();
|
||||
void ttlDraw(SDL_Texture *target);
|
||||
}
|
||||
31
inc/txtui.h
31
inc/txtui.h
@@ -1,31 +0,0 @@
|
||||
#ifndef TXTUI_H
|
||||
#define TXTUI_H
|
||||
|
||||
#include "data.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
void textUserPrep();
|
||||
void textTitlePrep(data::user& u);
|
||||
|
||||
void textUserMenuUpdate(const uint64_t& down, const uint64_t& held);
|
||||
void drawTextUserMenu();
|
||||
|
||||
void textTitleMenuUpdate(const uint64_t& down, const uint64_t& held);
|
||||
void drawTextTitleMenu();
|
||||
|
||||
void textFolderMenuUpdate(const uint64_t& down, const uint64_t& held);
|
||||
void drawTextFolderMenu();
|
||||
|
||||
void updateExMenu(const uint64_t& down, const uint64_t& held);
|
||||
void drawExMenu();
|
||||
|
||||
void exMenuPrep();
|
||||
|
||||
//Options
|
||||
void optMenuInit();
|
||||
void updateOptMenu(const uint64_t& down, const uint64_t& held);
|
||||
void drawOptMenu();
|
||||
}
|
||||
|
||||
#endif
|
||||
4
inc/type.h
Normal file
4
inc/type.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
//Misc stuff for new menu code
|
||||
typedef void (*funcPtr)(void *);
|
||||
46
inc/ui.h
46
inc/ui.h
@@ -1,19 +1,18 @@
|
||||
#ifndef UI_H
|
||||
#define UI_H
|
||||
#pragma once
|
||||
|
||||
#include <switch.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "data.h"
|
||||
#include "uistr.h"
|
||||
#include "gfx.h"
|
||||
|
||||
//ui headers - split up to keep a bit more organized
|
||||
#include "menu.h"
|
||||
#include "miscui.h"
|
||||
#include "txtui.h"
|
||||
#include "uiupdate.h"
|
||||
#include "uistr.h"
|
||||
#include "usr.h"
|
||||
#include "ttl.h"
|
||||
#include "fld.h"
|
||||
|
||||
enum menuState
|
||||
{
|
||||
@@ -38,10 +37,12 @@ namespace ui
|
||||
|
||||
//pad data cause i don't know where else to put it
|
||||
extern PadState pad;
|
||||
static inline void updatePad() { padUpdate(&pad); }
|
||||
extern HidTouchScreenState touchState;
|
||||
static inline void updateInput() { touchState = {0}; padUpdate(&pad); hidGetTouchScreenStates(&touchState, 1); }
|
||||
inline uint64_t padKeysDown() { return padGetButtonsDown(&pad); }
|
||||
inline uint64_t padKeysHeld() { return padGetButtons(&pad); }
|
||||
inline uint64_t padKeysUp() { return padGetButtonsUp(&pad); }
|
||||
inline void touchGetXY(uint32_t *x, uint32_t *y) { *x = touchState.touches[0].x; *y = touchState.touches[0].y; }
|
||||
|
||||
inline void changeState(int newState)
|
||||
{
|
||||
@@ -52,7 +53,7 @@ namespace ui
|
||||
//Holds theme set id
|
||||
extern ColorSetId thmID;
|
||||
|
||||
//Both UI modes need access to thi
|
||||
//Both UI modes need access to this
|
||||
extern std::string folderMenuInfo;
|
||||
|
||||
/*Colors
|
||||
@@ -60,10 +61,13 @@ namespace ui
|
||||
txtCont = text that contrasts clearClr
|
||||
txtDiag = text color for dialogs
|
||||
*/
|
||||
extern SDL_Color clearClr, txtCont, txtDiag, rectLt, rectSh, tboxClr, sideRect;
|
||||
extern SDL_Color clearClr, transparent, txtCont, txtDiag, rectLt, rectSh, tboxClr, sideRect, divClr, heartColor, slidePanelColor;
|
||||
|
||||
//Textbox graphics
|
||||
extern SDL_Texture *cornerTopLeft, *cornerTopRight, *cornerBottomLeft, *cornerBottomRight;
|
||||
//Menu bounding
|
||||
extern SDL_Texture *mnuTopLeft, *mnuTopRight, *mnuBotLeft, *mnuBotRight;
|
||||
|
||||
//Covers left and right of progress bar to fake being not a rectangle.
|
||||
extern SDL_Texture *progCovLeft, *progCovRight, *diaBox;
|
||||
|
||||
@@ -77,22 +81,26 @@ namespace ui
|
||||
void init();
|
||||
void exit();
|
||||
|
||||
//Adds a panel pointer to a vector since they need to be drawn over everything else
|
||||
void addPanel(slideOutPanel *sop);
|
||||
|
||||
//Just draws a screen and flips JIC boot takes long.
|
||||
void showLoadScreen();
|
||||
|
||||
//Clears and draws general stuff used by multiple screens
|
||||
void drawUI();
|
||||
|
||||
//Draws selection box
|
||||
void drawBoundBox(int x, int y, int w, int h, int clrSh);
|
||||
|
||||
//switch case so we don't have problems with multiple main loops like 3DS
|
||||
void runApp(const uint64_t& down, const uint64_t& held);
|
||||
bool runApp();
|
||||
|
||||
//These are shared by both folder menus
|
||||
void createNewBackup(const uint64_t& held);
|
||||
void overwriteBackup(unsigned ind);
|
||||
void restoreBackup(unsigned ind);
|
||||
void deleteBackup(unsigned ind);
|
||||
}
|
||||
//Expects a uint64_t passed for held buttons
|
||||
void createNewBackup(void *a);
|
||||
//all exepect an unsigned int containing menu's selected
|
||||
void overwriteBackup(void *a);
|
||||
void restoreBackup(void *a);
|
||||
void deleteBackup(void *a);
|
||||
|
||||
#endif
|
||||
//Used for multiple menu functions/callback
|
||||
void toTTL(void *);
|
||||
}
|
||||
|
||||
16
inc/uistr.h
16
inc/uistr.h
@@ -1,15 +1,15 @@
|
||||
#ifndef UISTR_H
|
||||
#define UISTR_H
|
||||
#pragma once
|
||||
|
||||
//Strings since translation support
|
||||
namespace ui
|
||||
{
|
||||
extern const std::string loadGlyphArray[8];
|
||||
void loadTrans();
|
||||
|
||||
extern std::string author, userHelp, titleHelp, folderHelp, optHelp, \
|
||||
confBlacklist, confOverwrite, confRestore, confDel, confCopy, \
|
||||
confEraseNand, confEraseFolder, yt, nt, on, off, confirmHead, \
|
||||
copyHead, noSavesFound, errorConnecting, noUpdate;
|
||||
copyHead, noSavesFound, errorConnecting, noUpdate, saveCreated, saveCreateFailed, \
|
||||
saveDataReset, saveDataResetSuccess, saveDataDeleteSuccess;
|
||||
|
||||
//Strings for file mode menu
|
||||
extern std::string advMenuStr[6];
|
||||
@@ -17,12 +17,12 @@ namespace ui
|
||||
extern std::string exMenuStr[11];
|
||||
//Strings for options menu
|
||||
extern std::string optMenuStr[15];
|
||||
//Strings for options explanations
|
||||
extern std::string optMenuExp[15];
|
||||
//Strings for the holding thing
|
||||
extern std::string holdingText[3];
|
||||
//Strings for sort type
|
||||
extern std::string sortString[3];
|
||||
//Strings for user options
|
||||
extern std::string usrOptString[1];
|
||||
//Strings for title options
|
||||
extern std::string titleOptString[4];
|
||||
}
|
||||
|
||||
#endif // UISTR_H
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef UIUPDATE_H
|
||||
#define UIUPDATE_H
|
||||
|
||||
//Contains declarations of ui updating functions
|
||||
|
||||
namespace ui
|
||||
{
|
||||
void updateUserMenu(const uint64_t& down, const uint64_t& held);
|
||||
void drawUserMenu();
|
||||
|
||||
void updateTitleMenu(const uint64_t& down, const uint64_t& held);
|
||||
void drawTitleMenu();
|
||||
|
||||
void updateFolderMenu(const uint64_t& down, const uint64_t& held);
|
||||
void drawFolderMenu();
|
||||
|
||||
void updateAdvMode(const uint64_t& down, const uint64_t& held);
|
||||
void drawAdvMode();
|
||||
|
||||
//needed here since it uses static menu
|
||||
void folderMenuPrepare(data::user& usr, data::titledata& dat);
|
||||
void advCopyMenuPrep();
|
||||
void advModePrep(const std::string& svDev, const FsSaveDataType& _type, bool commitOnWrite);
|
||||
}
|
||||
|
||||
#endif
|
||||
10
inc/usr.h
Normal file
10
inc/usr.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace ui
|
||||
{
|
||||
void usrInit();
|
||||
void usrExit();
|
||||
void usrMenuSetActive(bool _set);
|
||||
void usrUpdate();
|
||||
void usrDraw(SDL_Texture *target);
|
||||
}
|
||||
31
inc/util.h
31
inc/util.h
@@ -28,11 +28,11 @@ namespace util
|
||||
|
||||
std::string safeString(const std::string& s);
|
||||
|
||||
std::string getInfoString(const data::user& u, const data::titledata& d);
|
||||
std::string getInfoString(data::user& u, const uint64_t& tid);
|
||||
|
||||
std::string getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
|
||||
|
||||
std::string generateAbbrev(const data::titledata& dat);
|
||||
std::string generateAbbrev(const uint64_t& tid);
|
||||
|
||||
//removes char from C++ string
|
||||
void stripChar(char _c, std::string& _s);
|
||||
@@ -56,6 +56,33 @@ namespace util
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string getIDStr(const uint64_t& _id)
|
||||
{
|
||||
char tmp[18];
|
||||
sprintf(tmp, "%016lX", _id);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
inline std::string getIDStrLower(const uint64_t& _id)
|
||||
{
|
||||
char tmp[18];
|
||||
sprintf(tmp, "%08X", (uint32_t)_id);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
inline std::string generatePathByTID(const uint64_t& tid)
|
||||
{
|
||||
return fs::getWorkDir() + data::getTitleSafeNameByTID(tid) + "/";
|
||||
}
|
||||
|
||||
inline void createTitleDirectoryByTID(const uint64_t& tid)
|
||||
{
|
||||
std::string makePath = fs::getWorkDir() + data::getTitleSafeNameByTID(tid);
|
||||
mkdir(makePath.c_str(), 777);
|
||||
}
|
||||
|
||||
Result accountDeleteUser(AccountUid *uid);
|
||||
|
||||
void setCPU(uint32_t hz);
|
||||
void checkForUpdate();
|
||||
}
|
||||
|
||||
403
src/data.cpp
403
src/data.cpp
@@ -11,14 +11,8 @@
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
//Color for favorite hearts
|
||||
const SDL_Color heartColor = {0xFF, 0x44, 0x44, 0xFF};
|
||||
|
||||
//FsSaveDataSpaceId_All doesn't work for SD
|
||||
static const unsigned saveOrder [] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 100, 101
|
||||
};
|
||||
static const unsigned saveOrder [] = { 0, 1, 2, 3, 4, 100, 101 };
|
||||
|
||||
int data::selUser = 0, data::selData = 0;
|
||||
|
||||
@@ -30,8 +24,8 @@ SetLanguage data::sysLang;
|
||||
|
||||
//Options
|
||||
bool data::incDev = false, data::autoBack = true, data::ovrClk = false, data::holdDel = true, data::holdRest = true, data::holdOver = true;
|
||||
bool data::forceMount = true, data::accSysSave = false, data::sysSaveWrite = false, data::directFsCmd = false, data::skipUser = false, data::zip = false;
|
||||
bool data::langOverride = false;
|
||||
bool data::forceMount = true, data::accSysSave = false, data::sysSaveWrite = false, data::directFsCmd = false, data::skipUser = false, data::zip = false, data::langOverride = false;
|
||||
|
||||
uint8_t data::sortType = 0;
|
||||
|
||||
//For other save types
|
||||
@@ -40,25 +34,29 @@ static bool sysBCATPushed = false, cachePushed = false, tempPushed = false;
|
||||
static std::vector<uint64_t> blacklist;
|
||||
static std::vector<uint64_t> favorites;
|
||||
static std::unordered_map<uint64_t, std::string> pathDefs;
|
||||
std::unordered_map<uint64_t, SDL_Texture *> data::icons;
|
||||
std::unordered_map<uint64_t, data::titleInfo> data::titles;
|
||||
|
||||
static SDL_Texture *iconMask;
|
||||
|
||||
//Sorts titles by sortType
|
||||
static struct
|
||||
{
|
||||
bool operator()(const data::titledata& a, const data::titledata& b)
|
||||
bool operator()(const data::userTitleInfo& a, const data::userTitleInfo& b)
|
||||
{
|
||||
//Favorites override EVERYTHING
|
||||
if(a.getFav() != b.getFav()) return a.getFav();
|
||||
if(data::isFavorite(a.saveID) != data::isFavorite(b.saveID)) return data::isFavorite(a.saveID);
|
||||
|
||||
switch(data::sortType)
|
||||
{
|
||||
case 0://Alpha
|
||||
{
|
||||
std::string titleA = data::getTitleNameByTID(a.saveID);
|
||||
std::string titleB = data::getTitleNameByTID(b.saveID);
|
||||
uint32_t tmpA, tmpB;
|
||||
for(unsigned i = 0; i < a.getTitle().length(); )
|
||||
for(unsigned i = 0; i < titleA.length(); )
|
||||
{
|
||||
ssize_t uCnt = decode_utf8(&tmpA, (const uint8_t *)&a.getTitle().data()[i]);
|
||||
decode_utf8(&tmpB, (const uint8_t *)&b.getTitle().data()[i]);
|
||||
ssize_t uCnt = decode_utf8(&tmpA, (const uint8_t *)&titleA.data()[i]);
|
||||
decode_utf8(&tmpB, (const uint8_t *)&titleB.data()[i]);
|
||||
tmpA = tolower(tmpA), tmpB = tolower(tmpB);
|
||||
if(tmpA != tmpB)
|
||||
return tmpA < tmpB;
|
||||
@@ -69,11 +67,11 @@ static struct
|
||||
break;
|
||||
|
||||
case 1://Most played
|
||||
return a.getPlayTime() > b.getPlayTime();
|
||||
return a.playStats.playtimeMinutes > b.playStats.playtimeMinutes;
|
||||
break;
|
||||
|
||||
case 2://Last Played
|
||||
return a.getLastTimeStamp() > b.getLastTimeStamp();
|
||||
return a.playStats.last_timestampUser > b.playStats.last_timestampUser;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@@ -98,7 +96,7 @@ static bool blacklisted(const uint64_t& tid)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isFavorite(const uint64_t& tid)
|
||||
bool data::isFavorite(const uint64_t& tid)
|
||||
{
|
||||
for(uint64_t& fid : favorites)
|
||||
if(tid == fid) return true;
|
||||
@@ -114,31 +112,6 @@ static bool isDefined(const uint64_t& id)
|
||||
return false;
|
||||
}
|
||||
|
||||
static SDL_Texture *createDeviceIcon()
|
||||
{
|
||||
return util::createIconGeneric("\ue121", 192);
|
||||
}
|
||||
|
||||
static inline void loadCreateIcon(const uint64_t& _id, size_t _sz, const NsApplicationControlData *_d)
|
||||
{
|
||||
data::icons[_id] = gfx::loadJPEGMem(_d->icon, _sz);
|
||||
}
|
||||
|
||||
static void loadCreateSystemIcon(const uint64_t& _id)
|
||||
{
|
||||
char tmp[16];
|
||||
sprintf(tmp, "%08X", (uint32_t)_id);
|
||||
|
||||
data::icons[_id] = util::createIconGeneric(tmp, 32);
|
||||
}
|
||||
|
||||
static inline std::string getIDStr(const uint64_t& _id)
|
||||
{
|
||||
char tmp[18];
|
||||
sprintf(tmp, "%016lX", _id);
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
static inline bool accountSystemSaveCheck(const FsSaveDataInfo& _inf)
|
||||
{
|
||||
if(_inf.save_data_type == FsSaveDataType_System && util::accountUIDToU128(_inf.uid) != 0 && !data::accSysSave)
|
||||
@@ -150,30 +123,92 @@ static inline bool accountSystemSaveCheck(const FsSaveDataInfo& _inf)
|
||||
//Minimal init/test to avoid loading and creating things I don't need
|
||||
static bool testMount(const FsSaveDataInfo& _inf)
|
||||
{
|
||||
bool ret = false;
|
||||
if(!data::forceMount)
|
||||
return true;
|
||||
|
||||
bool ret = false;
|
||||
uint64_t id;
|
||||
data::user tmpusr;
|
||||
data::titledata tmpdat;
|
||||
|
||||
if(_inf.save_data_type == FsSaveDataType_System || _inf.save_data_type == FsSaveDataType_SystemBcat)
|
||||
id = _inf.system_save_data_id;
|
||||
else
|
||||
id = _inf.application_id;
|
||||
|
||||
tmpusr.setUID(_inf.uid);
|
||||
tmpdat.setID(id);
|
||||
tmpdat.setIndex(_inf.save_data_index);
|
||||
tmpdat.setType((FsSaveDataType)_inf.save_data_type);
|
||||
|
||||
if((ret = fs::mountSave(tmpusr, tmpdat)))
|
||||
if((ret = fs::mountSave(_inf)))
|
||||
fs::unmountSave();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void addTitleToList(const uint64_t& tid)
|
||||
{
|
||||
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);
|
||||
|
||||
if(R_SUCCEEDED(ctrlRes) && !(outSize < sizeof(ctrlData->nacp)) && R_SUCCEEDED(nacpRes) && iconSize > 0)
|
||||
{
|
||||
//Copy nacp
|
||||
memcpy(&data::titles[tid].nacp, &ctrlData->nacp, sizeof(NacpStruct));
|
||||
|
||||
//Setup 'shortcuts' to strings
|
||||
NacpLanguageEntry *ent;
|
||||
nacpGetLanguageEntry(&data::titles[tid].nacp, &ent);
|
||||
data::titles[tid].title = ent->name;
|
||||
data::titles[tid].author = ent->author;
|
||||
if(isDefined(tid))
|
||||
data::titles[tid].safeTitle = pathDefs[tid];
|
||||
else if((data::titles[tid].safeTitle = util::safeString(ent->name)) == "")
|
||||
data::titles[tid].safeTitle = util::getIDStr(tid);
|
||||
|
||||
if(data::isFavorite(tid))
|
||||
data::titles[tid].fav = true;
|
||||
|
||||
data::titles[tid].icon = gfx::loadJPEGMem(ctrlData->icon, iconSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&data::titles[tid].nacp, 0, sizeof(NacpStruct));
|
||||
data::titles[tid].title = util::getIDStr(tid);
|
||||
data::titles[tid].author = "Someone?";
|
||||
if(isDefined(tid))
|
||||
data::titles[tid].safeTitle = pathDefs[tid];
|
||||
else
|
||||
data::titles[tid].safeTitle = util::getIDStr(tid);
|
||||
|
||||
data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32);
|
||||
}
|
||||
|
||||
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)))
|
||||
{
|
||||
for(int i = 0; i < total; i++)
|
||||
data::users.emplace_back(uids[i], "");
|
||||
}
|
||||
delete[] uids;
|
||||
}
|
||||
|
||||
//This can load titles installed without having save data
|
||||
static void loadTitlesFromRecords()
|
||||
{
|
||||
NsApplicationRecord nsRecord;
|
||||
int32_t entryCount = 0, recordOffset = 0;
|
||||
while(R_SUCCEEDED(nsListApplicationRecord(&nsRecord, 1, recordOffset++, &entryCount)) && entryCount > 0)
|
||||
{
|
||||
if(!titleIsLoaded(nsRecord.application_id))
|
||||
addTitleToList(nsRecord.application_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool data::loadUsersTitles(bool clearUsers)
|
||||
{
|
||||
static unsigned systemUserCount = 3;
|
||||
@@ -181,25 +216,28 @@ bool data::loadUsersTitles(bool clearUsers)
|
||||
FsSaveDataInfo info;
|
||||
s64 total = 0;
|
||||
|
||||
loadTitlesFromRecords();
|
||||
|
||||
//Clear titles
|
||||
for(data::user& u : data::users)
|
||||
u.titles.clear();
|
||||
u.titleInfo.clear();
|
||||
if(clearUsers)
|
||||
{
|
||||
systemUserCount = 3;
|
||||
systemUserCount = 4;
|
||||
for(data::user& u : data::users)
|
||||
u.delIcon();
|
||||
|
||||
data::users.clear();
|
||||
|
||||
loadUserAccounts();
|
||||
sysBCATPushed = false;
|
||||
cachePushed = false;
|
||||
tempPushed = false;
|
||||
users.emplace_back(util::u128ToAccountUID(3), "Device Saves", createDeviceIcon());
|
||||
users.emplace_back(util::u128ToAccountUID(3), "Device");
|
||||
users.emplace_back(util::u128ToAccountUID(2), "BCAT");
|
||||
users.emplace_back(util::u128ToAccountUID(5), "Cache");
|
||||
users.emplace_back(util::u128ToAccountUID(0), "System");
|
||||
}
|
||||
|
||||
NsApplicationControlData *dat = new NsApplicationControlData;
|
||||
for(unsigned i = 0; i < 7; i++)
|
||||
{
|
||||
if(R_FAILED(fsOpenSaveDataInfoReader(&it, (FsSaveDataSpaceId)saveOrder[i])))
|
||||
@@ -207,8 +245,14 @@ bool data::loadUsersTitles(bool clearUsers)
|
||||
|
||||
while(R_SUCCEEDED(fsSaveDataInfoReaderRead(&it, &info, 1, &total)) && total != 0)
|
||||
{
|
||||
uint64_t saveID = 0;
|
||||
if(info.save_data_type == FsSaveDataType_System || info.save_data_type == FsSaveDataType_SystemBcat)
|
||||
saveID = info.system_save_data_id;
|
||||
else
|
||||
saveID = info.application_id;
|
||||
|
||||
//Don't bother with this stuff
|
||||
if(blacklisted(info.application_id) || blacklisted(info.save_data_id) || !accountSystemSaveCheck(info) || !testMount(info))
|
||||
if(blacklisted(saveID) || !accountSystemSaveCheck(info) || !testMount(info))
|
||||
continue;
|
||||
|
||||
switch(info.save_data_type)
|
||||
@@ -252,35 +296,41 @@ bool data::loadUsersTitles(bool clearUsers)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!titleIsLoaded(saveID))
|
||||
addTitleToList(saveID);
|
||||
|
||||
int u = getUserIndex(info.uid);
|
||||
if(u == -1)
|
||||
{
|
||||
users.emplace(data::users.end() - systemUserCount, info.uid, "");
|
||||
u = getUserIndex(info.uid);
|
||||
}
|
||||
users[u].titles.emplace_back(info, dat);
|
||||
|
||||
PdmPlayStatistics 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(saveID, &info, &playStats);
|
||||
}
|
||||
fsSaveDataInfoReaderClose(&it);
|
||||
}
|
||||
delete dat;
|
||||
|
||||
if(data::incDev)
|
||||
/*if(data::incDev)
|
||||
{
|
||||
//Get reference to device save user
|
||||
data::user& dev = data::users[data::users.size() - 3];
|
||||
for(unsigned i = 0; i < users.size() - 3; i++)
|
||||
data::user& dev = data::users[data::users.size() - 4];
|
||||
for(unsigned i = 0; i < users.size() - 4; i++)
|
||||
{
|
||||
//Not needed but makes this easier to read
|
||||
data::user& u = data::users[i];
|
||||
u.titles.insert(u.titles.end(), dev.titles.begin(), dev.titles.end());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for(data::user& u : data::users)
|
||||
{
|
||||
u.loadPlayTimes();
|
||||
std::sort(u.titles.begin(), u.titles.end(), sortTitles);
|
||||
}
|
||||
std::sort(u.titleInfo.begin(), u.titleInfo.end(), sortTitles);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -305,11 +355,10 @@ void data::init()
|
||||
void data::exit()
|
||||
{
|
||||
for(data::user& u : data::users) u.delIcon();
|
||||
for(auto& icn : icons)
|
||||
{
|
||||
if(icn.second)
|
||||
SDL_DestroyTexture(icn.second);
|
||||
}
|
||||
for(auto& tinfo : titles)
|
||||
SDL_DestroyTexture(tinfo.second.icon);
|
||||
|
||||
SDL_DestroyTexture(iconMask);
|
||||
|
||||
saveFav();
|
||||
saveCfg();
|
||||
@@ -317,95 +366,24 @@ void data::exit()
|
||||
util::setCPU(1020000000);
|
||||
}
|
||||
|
||||
data::titledata::titledata(const FsSaveDataInfo& inf, NsApplicationControlData *dat)
|
||||
data::titleInfo *data::getTitleInfoByTID(const uint64_t& tid)
|
||||
{
|
||||
size_t outSz = 0;
|
||||
NacpLanguageEntry *ent = NULL;
|
||||
memset(dat, 0, sizeof(NsApplicationControlData));
|
||||
|
||||
if(inf.save_data_type == FsSaveDataType_System || inf.save_data_type == FsSaveDataType_SystemBcat)
|
||||
id = inf.system_save_data_id;
|
||||
else
|
||||
id = inf.application_id;
|
||||
|
||||
saveID = inf.save_data_id;
|
||||
saveIndex = inf.save_data_index;
|
||||
saveDataType = inf.save_data_type;
|
||||
|
||||
Result ctrlDataRes = nsGetApplicationControlData(NsApplicationControlSource_Storage, id, dat, sizeof(NsApplicationControlData), &outSz);
|
||||
Result nacpRes = nacpGetLanguageEntry(&dat->nacp, &ent);
|
||||
size_t icnSize = outSz - sizeof(dat->nacp);
|
||||
auto icnInd = icons.find(id);
|
||||
if(R_SUCCEEDED(ctrlDataRes) && !(outSz < sizeof(dat->nacp)) && R_SUCCEEDED(nacpRes) && ent != NULL && icnSize > 0)
|
||||
{
|
||||
title.assign(ent->name);
|
||||
author.assign(ent->author);
|
||||
if(isDefined(id))
|
||||
titleSafe = util::safeString(pathDefs[id]);
|
||||
else if((titleSafe = util::safeString(title)) == "")
|
||||
titleSafe = getIDStr(id);
|
||||
|
||||
if(icnInd == icons.end())
|
||||
loadCreateIcon(id, icnSize, dat);
|
||||
|
||||
assignIcon();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(icnInd == icons.end())
|
||||
loadCreateSystemIcon(id);
|
||||
title = getIDStr(id);
|
||||
titleSafe = getIDStr(id);
|
||||
assignIcon();
|
||||
}
|
||||
favorite = isFavorite(id);
|
||||
return &titles[tid];
|
||||
}
|
||||
|
||||
void data::titledata::createDir() const
|
||||
std::string data::getTitleNameByTID(const uint64_t& tid)
|
||||
{
|
||||
mkdir(std::string(fs::getWorkDir() + titleSafe).c_str(), 777);
|
||||
return titles[tid].title;
|
||||
}
|
||||
|
||||
std::string data::titledata::getPath() const
|
||||
std::string data::getTitleSafeNameByTID(const uint64_t& tid)
|
||||
{
|
||||
return std::string(fs::getWorkDir() + titleSafe + "/");
|
||||
return titles[tid].safeTitle;
|
||||
}
|
||||
|
||||
std::string data::titledata::getTIDStr() const
|
||||
SDL_Texture *data::getTitleIconByTID(const uint64_t& tid)
|
||||
{
|
||||
return getIDStr(id);
|
||||
}
|
||||
|
||||
std::string data::titledata::getSaveIDStr() const
|
||||
{
|
||||
return getIDStr(saveID);
|
||||
}
|
||||
|
||||
void data::titledata::assignIcon()
|
||||
{
|
||||
icon = icons[id];
|
||||
}
|
||||
|
||||
void data::titledata::drawIcon(bool full, unsigned x, unsigned y)
|
||||
{
|
||||
if(full)
|
||||
gfx::texDraw(icon, x, y);
|
||||
else
|
||||
gfx::texDrawStretch(icon, x, y, 128, 128);
|
||||
}
|
||||
|
||||
void data::titledata::drawIconFav(bool full, unsigned x, unsigned y)
|
||||
{
|
||||
if(full)
|
||||
{
|
||||
gfx::texDraw(icon, x, y);
|
||||
gfx::drawTextf(48, x + 16, y + 16, &heartColor, "♥");
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx::texDrawStretch(icon, x, y, 128, 128);
|
||||
gfx::drawTextf(24, x + 8, y + 8, &heartColor, "♥");
|
||||
}
|
||||
return titles[tid].icon;
|
||||
}
|
||||
|
||||
data::user::user(const AccountUid& _id, const std::string& _backupName)
|
||||
@@ -438,17 +416,18 @@ data::user::user(const AccountUid& _id, const std::string& _backupName)
|
||||
}
|
||||
else
|
||||
{
|
||||
username = _backupName.empty() ? getIDStr((uint64_t)uID128) : _backupName;
|
||||
userSafe = _backupName.empty() ? getIDStr((uint64_t)uID128) : _backupName;
|
||||
userIcon = util::createIconGeneric(_backupName.c_str(), 32);
|
||||
username = _backupName.empty() ? util::getIDStr((uint64_t)uID128) : _backupName;
|
||||
userSafe = _backupName.empty() ? util::getIDStr((uint64_t)uID128) : _backupName;
|
||||
userIcon = util::createIconGeneric(_backupName.c_str(), 40);
|
||||
}
|
||||
titles.reserve(32);
|
||||
titles.reserve(64);
|
||||
}
|
||||
|
||||
data::user::user(const AccountUid& _id, const std::string& _backupName, SDL_Texture *img) : user(_id, _backupName)
|
||||
{
|
||||
delIcon();
|
||||
userIcon = img;
|
||||
titles.reserve(64);
|
||||
}
|
||||
|
||||
void data::user::setUID(const AccountUid& _id)
|
||||
@@ -457,52 +436,13 @@ void data::user::setUID(const AccountUid& _id)
|
||||
uID128 = util::accountUIDToU128(_id);
|
||||
}
|
||||
|
||||
void data::user::loadPlayTimes()
|
||||
void data::user::addUserTitleInfo(const uint64_t& tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats)
|
||||
{
|
||||
PdmPlayStatistics stats;
|
||||
for(data::titledata& _d : titles)
|
||||
{
|
||||
switch(_d.getType())
|
||||
{
|
||||
case FsSaveDataType_Account:
|
||||
pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(_d.getID(), userID, false, &stats);
|
||||
_d.setPlayTime(stats.playtimeMinutes);
|
||||
_d.setLastTimeStamp(stats.last_timestampUser);
|
||||
_d.setLaunchCount(stats.totalLaunches);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Device:
|
||||
pdmqryQueryPlayStatisticsByApplicationId(_d.getID(), false, &stats);
|
||||
_d.setPlayTime(stats.playtimeMinutes);
|
||||
_d.setLastTimeStamp(stats.last_timestampNetwork);
|
||||
_d.setLaunchCount(stats.totalLaunches);
|
||||
break;
|
||||
|
||||
default:
|
||||
_d.setPlayTime(0);
|
||||
_d.setLastTimeStamp(0);
|
||||
_d.setLaunchCount(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned data::getTotalSaves()
|
||||
{
|
||||
unsigned ret = 0;
|
||||
FsSaveDataInfoReader read;
|
||||
FsSaveDataInfo tmp;
|
||||
int64_t out = 0;
|
||||
for(unsigned i = 0; i < 7; i++)
|
||||
{
|
||||
if(R_FAILED(fsOpenSaveDataInfoReader(&read, (FsSaveDataSpaceId)saveOrder[i])))
|
||||
continue;
|
||||
|
||||
while(R_SUCCEEDED(fsSaveDataInfoReaderRead(&read, &tmp, 1, &out)) && out != 0)
|
||||
++ret;
|
||||
}
|
||||
fsSaveDataInfoReaderClose(&read);
|
||||
return ret;
|
||||
data::userTitleInfo newInfo;
|
||||
newInfo.saveID = tid;
|
||||
memcpy(&newInfo.saveInfo, _saveInfo, sizeof(FsSaveDataInfo));
|
||||
memcpy(&newInfo.playStats, _stats, sizeof(PdmPlayStatistics));
|
||||
titleInfo.emplace_back(newInfo);
|
||||
}
|
||||
|
||||
void data::loadBlacklist()
|
||||
@@ -519,49 +459,38 @@ void data::saveBlackList()
|
||||
{
|
||||
std::string blPath = fs::getWorkDir() + "blacklist.txt";
|
||||
FILE *bl = fopen(blPath.c_str(), "w");
|
||||
for(uint64_t& id : blacklist)
|
||||
fprintf(bl, "0x%016lX\n", id);
|
||||
for(uint64_t id : blacklist)
|
||||
fprintf(bl, "#%s\n0x%016lX\n", data::getTitleNameByTID(id).c_str(), id);
|
||||
|
||||
fclose(bl);
|
||||
}
|
||||
|
||||
void data::blacklistAdd(titledata& t)
|
||||
void data::blacklistAdd(const uint64_t& tid)
|
||||
{
|
||||
uint64_t tid = t.getID();
|
||||
for(data::user& _u : data::users)
|
||||
{
|
||||
for(unsigned i = 0; i < _u.titles.size(); i++)
|
||||
if(_u.titles[i].getID() == tid) _u.titles.erase(_u.titles.begin() + i);
|
||||
for(unsigned i = 0; i < _u.titleInfo.size(); i++)
|
||||
if(_u.titleInfo[i].saveID == tid) _u.titleInfo.erase(_u.titleInfo.begin() + i);
|
||||
}
|
||||
blacklist.push_back(tid);
|
||||
}
|
||||
|
||||
void data::favoriteTitle(titledata& t)
|
||||
void data::favoriteTitle(const uint64_t& tid)
|
||||
{
|
||||
uint64_t tid = t.getID();
|
||||
if(!t.getFav())
|
||||
if(!isFavorite(tid))
|
||||
{
|
||||
for(data::user& _u : data::users)
|
||||
{
|
||||
for(unsigned i = 0; i < _u.titles.size(); i++)
|
||||
if(_u.titles[i].getID() == tid) _u.titles[i].setFav(true);
|
||||
|
||||
std::sort(_u.titles.begin(), _u.titles.end(), sortTitles);
|
||||
}
|
||||
titles[tid].fav = true;
|
||||
favorites.push_back(tid);
|
||||
}
|
||||
else
|
||||
{
|
||||
titles[tid].fav = false;
|
||||
auto ind = std::find(favorites.begin(), favorites.end(), tid);
|
||||
favorites.erase(ind);
|
||||
for(data::user& _u : data::users)
|
||||
{
|
||||
for(unsigned i = 0; i < _u.titles.size(); i++)
|
||||
if(_u.titles[i].getID() == tid) _u.titles[i].setFav(false);
|
||||
|
||||
std::sort(_u.titles.begin(), _u.titles.end(), sortTitles);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &u : data::users)
|
||||
std::sort(u.titleInfo.begin(), u.titleInfo.end(), sortTitles);
|
||||
}
|
||||
|
||||
void data::loadCfg()
|
||||
@@ -585,7 +514,6 @@ void data::loadCfg()
|
||||
data::forceMount = cfgIn >> 57 & 1;
|
||||
data::accSysSave = cfgIn >> 56 & 1;
|
||||
data::sysSaveWrite = cfgIn >> 55 & 1;
|
||||
ui::textMode = cfgIn >> 54 & 1;
|
||||
data::directFsCmd = cfgIn >> 53 & 1;
|
||||
data::skipUser = cfgIn >> 52 & 1;
|
||||
data::zip = cfgIn >> 51 & 1;
|
||||
@@ -609,7 +537,6 @@ void data::saveCfg()
|
||||
cfgOut |= (uint64_t)data::forceMount << 57;
|
||||
cfgOut |= (uint64_t)data::accSysSave << 56;
|
||||
cfgOut |= (uint64_t)data::sysSaveWrite << 55;
|
||||
cfgOut |= (uint64_t)ui::textMode << 54;
|
||||
cfgOut |= (uint64_t)data::directFsCmd << 53;
|
||||
cfgOut |= (uint64_t)data::skipUser << 52;
|
||||
cfgOut |= (uint64_t)data::zip << 51;
|
||||
@@ -636,7 +563,6 @@ void data::restoreDefaultConfig()
|
||||
data::skipUser = false;
|
||||
data::zip = false;
|
||||
data::sortType = 0;
|
||||
data::langOverride = false;
|
||||
}
|
||||
|
||||
void data::loadFav()
|
||||
@@ -680,11 +606,10 @@ void data::dispStats()
|
||||
//Easiest/laziest way to do this
|
||||
std::string stats = "User Count: " + std::to_string(users.size()) + "\n";
|
||||
for(data::user& u : data::users)
|
||||
stats += u.getUsername() + ": " + std::to_string(u.titles.size()) + "\n";
|
||||
stats += u.getUsername() + ": " + std::to_string(u.titleInfo.size()) + "\n";
|
||||
stats += "Current User: " + data::curUser.getUsername() + "\n";
|
||||
stats += "Current Title: " + data::curData.getTitle() + "\n";
|
||||
stats += "Safe Title: " + data::curData.getTitleSafe() + "\n";
|
||||
stats += "Icon count: " + std::to_string(icons.size()) + "\n";
|
||||
stats += "Current Title: " + data::getTitleNameByTID(data::curData.saveID) + "\n";
|
||||
stats += "Safe Title: " + data::getTitleSafeNameByTID(data::curData.saveID) + "\n";
|
||||
stats += "Sort Type: " + std::to_string(data::sortType) + "\n";
|
||||
gfx::drawTextf(16, 8, 8, &green, stats.c_str());
|
||||
gfx::drawTextf(NULL, 16, 2, 2, &green, stats.c_str());
|
||||
}
|
||||
|
||||
217
src/file.cpp
217
src/file.cpp
@@ -131,25 +131,25 @@ void fs::exit()
|
||||
fs::logClose();
|
||||
}
|
||||
|
||||
bool fs::mountSave(const data::user& usr, const data::titledata& open)
|
||||
bool fs::mountSave(const FsSaveDataInfo& _m)
|
||||
{
|
||||
Result svOpen;
|
||||
switch(open.getType())
|
||||
switch(_m.save_data_type)
|
||||
{
|
||||
case FsSaveDataType_System:
|
||||
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, open.getID(), usr.getUID());
|
||||
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, _m.save_data_id, _m.uid);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Account:
|
||||
svOpen = fsOpen_SaveData(&sv, open.getID(), usr.getUID());
|
||||
svOpen = fsOpen_SaveData(&sv, _m.application_id, _m.uid);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Bcat:
|
||||
svOpen = fsOpen_BcatSaveData(&sv, open.getID());
|
||||
svOpen = fsOpen_BcatSaveData(&sv, _m.application_id);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Device:
|
||||
svOpen = fsOpen_DeviceSaveData(&sv, open.getID());
|
||||
svOpen = fsOpen_DeviceSaveData(&sv, _m.application_id);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Temporary:
|
||||
@@ -157,11 +157,11 @@ bool fs::mountSave(const data::user& usr, const data::titledata& open)
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Cache:
|
||||
svOpen = fsOpen_CacheStorage(&sv, open.getID(), open.getSaveIndex());
|
||||
svOpen = fsOpen_CacheStorage(&sv, _m.application_id, _m.save_data_rank);
|
||||
break;
|
||||
|
||||
case FsSaveDataType_SystemBcat:
|
||||
svOpen = fsOpen_SystemBcatSaveData(&sv, open.getID());
|
||||
svOpen = fsOpen_SystemBcatSaveData(&sv, _m.application_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -371,7 +371,7 @@ void fs::copyFile(const std::string& from, const std::string& to)
|
||||
copyArgs *send = copyArgsCreate(from, to, "", NULL, &progress);
|
||||
|
||||
//Setup progress bar. This thread updates screen, other handles copying
|
||||
ui::progBar prog(fsize(from), PROG_MAX_WIDTH_DEFAULT);
|
||||
ui::progBar prog(fsize(from));
|
||||
|
||||
Thread cpyThread;
|
||||
threadCreate(&cpyThread, copyfile_t, send, NULL, 0x4000, 0x2B, 1);
|
||||
@@ -448,7 +448,7 @@ void copyFileCommit_t(void *a)
|
||||
void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev)
|
||||
{
|
||||
uint64_t offset = 0;
|
||||
ui::progBar prog(fsize(from), PROG_MAX_WIDTH_DEFAULT);
|
||||
ui::progBar prog(fsize(from));
|
||||
copyArgs *send = copyArgsCreate(from, to, dev, NULL, &offset);
|
||||
|
||||
Thread cpyThread;
|
||||
@@ -501,7 +501,7 @@ void copyFileToZip_t(void *a)
|
||||
{
|
||||
if(zipWriteInFileInZip(*args->z, inBuff, readIn) != 0)
|
||||
{
|
||||
fs::logWrite("zipWriteInFileInZip failed -> \"%s\"\n", args->from.c_str());
|
||||
fs::logWrite("Failed", "zipWriteInFileInZip -> \"%s\"\n", args->from.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ void copyFileToZip_t(void *a)
|
||||
|
||||
void copyFileToZip(const std::string& from, zipFile *z)
|
||||
{
|
||||
ui::progBar prog(fs::fsize(from), PROG_MAX_WIDTH_DEFAULT);
|
||||
ui::progBar prog(fs::fsize(from));
|
||||
uint64_t progress = 0;
|
||||
copyArgs *send = copyArgsCreate(from, "", "", z, &progress);
|
||||
|
||||
@@ -571,7 +571,7 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de
|
||||
{
|
||||
std::string path = to + filename;
|
||||
mkdirRec(path.substr(0, path.find_last_of('/') + 1));
|
||||
ui::progBar prog(info.uncompressed_size, PROG_MAX_WIDTH_DEFAULT);
|
||||
ui::progBar prog(info.uncompressed_size);
|
||||
size_t done = 0;
|
||||
|
||||
//Create new empty file using FS
|
||||
@@ -584,6 +584,7 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de
|
||||
done += readIn;
|
||||
fwriteCommit(path, buff, readIn, dev);
|
||||
prog.update(done);
|
||||
|
||||
prog.draw(filename, ui::copyHead);
|
||||
gfx::present();
|
||||
}
|
||||
@@ -595,6 +596,7 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de
|
||||
done += readIn;
|
||||
fwriteCommit(path, buff, readIn, dev);
|
||||
prog.update(done);
|
||||
|
||||
prog.draw(filename, ui::copyHead);
|
||||
gfx::present();
|
||||
}
|
||||
@@ -697,23 +699,22 @@ void fs::freePathFilters()
|
||||
|
||||
bool fs::dumpAllUserSaves(const data::user& u)
|
||||
{
|
||||
for(unsigned i = 0; i < u.titles.size(); i++)
|
||||
for(unsigned i = 0; i < u.titleInfo.size(); i++)
|
||||
{
|
||||
ui::updatePad();
|
||||
ui::updateInput();
|
||||
|
||||
if(ui::padKeysDown() & HidNpadButton_B)
|
||||
return false;
|
||||
|
||||
if(fs::mountSave(u, u.titles[i]))
|
||||
if(fs::mountSave(u.titleInfo[i].saveInfo))
|
||||
{
|
||||
u.titles[i].createDir();
|
||||
std::string filtersPath = u.titles[i].getPath() + "pathFilters.txt";
|
||||
fs::loadPathFilters(filtersPath);
|
||||
util::createTitleDirectoryByTID(u.titleInfo[i].saveID);
|
||||
std::string basePath = util::generatePathByTID(u.titleInfo[i].saveID);
|
||||
switch(data::zip)
|
||||
{
|
||||
case true:
|
||||
{
|
||||
std::string outPath = u.titles[i].getPath() + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
|
||||
std::string outPath = basePath + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
|
||||
zipFile zip = zipOpen(outPath.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
@@ -722,16 +723,18 @@ bool fs::dumpAllUserSaves(const data::user& u)
|
||||
|
||||
case false:
|
||||
{
|
||||
std::string outPath = u.titles[i].getPath() + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
|
||||
std::string outPath = basePath + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
|
||||
mkdir(outPath.substr(0, outPath.length() - 1).c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", outPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
fsdevUnmountDevice("sv");
|
||||
fs::freePathFilters();
|
||||
}
|
||||
}
|
||||
|
||||
ui::updateInput();
|
||||
|
||||
return true;//?
|
||||
}
|
||||
|
||||
@@ -825,6 +828,176 @@ bool fs::isDir(const std::string& _path)
|
||||
return stat(_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
|
||||
}
|
||||
|
||||
void fs::createNewBackup(void *a)
|
||||
{
|
||||
uint64_t held = ui::padKeysHeld();
|
||||
|
||||
std::string out;
|
||||
|
||||
if(held & HidNpadButton_R)
|
||||
out = data::users[data::selUser].getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
|
||||
else if(held & HidNpadButton_L)
|
||||
out = data::users[data::selUser].getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
|
||||
else if(held & HidNpadButton_ZL)
|
||||
out = data::users[data::selUser].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),
|
||||
data::users[data::selUser].getUsernameSafe(),
|
||||
data::getTitleInfoByTID(data::curData.saveID)->safeTitle,
|
||||
util::generateAbbrev(data::curData.saveID)
|
||||
};
|
||||
out = util::getStringInput("", "Enter a name", 64, 8, dict);
|
||||
}
|
||||
|
||||
if(!out.empty())
|
||||
{
|
||||
std::string path = util::generatePathByTID(data::curData.saveID) + out;
|
||||
switch(data::zip)
|
||||
{
|
||||
case true:
|
||||
{
|
||||
path += ".zip";
|
||||
zipFile zip = zipOpen(path.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case false:
|
||||
{
|
||||
mkdir(path.c_str(), 777);
|
||||
path += "/";
|
||||
fs::copyDirToDir("sv:/", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ui::fldInit();
|
||||
}
|
||||
}
|
||||
|
||||
void fs::overwriteBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;;//Skip new
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if(ui::confirm(data::holdOver, ui::confOverwrite.c_str(), itemName.c_str()))
|
||||
{
|
||||
if(d->isDir(ind))
|
||||
{
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
//Delete and recreate
|
||||
fs::delDir(toPath);
|
||||
mkdir(toPath.c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", toPath);
|
||||
}
|
||||
else if(!d->isDir(ind) && d->getItemExt(ind) == "zip")
|
||||
{
|
||||
std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(toPath);
|
||||
zipFile zip = zipOpen(toPath.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fs::restoreBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if((data::curData.saveInfo.save_data_type != FsSaveDataType_System || data::sysSaveWrite) && m->getSelected() > 0 && ui::confirm(data::holdRest, ui::confRestore.c_str(), itemName.c_str()))
|
||||
{
|
||||
if(data::autoBack)
|
||||
{
|
||||
switch(data::zip)
|
||||
{
|
||||
case true:
|
||||
{
|
||||
std::string autoZip = util::generatePathByTID(data::curData.saveID) + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
|
||||
zipFile zip = zipOpen(autoZip.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case false:
|
||||
{
|
||||
std::string autoFolder = util::generatePathByTID(data::curData.saveID) + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
|
||||
mkdir(autoFolder.substr(0, autoFolder.length() - 1).c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", autoFolder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(d->isDir(ind))
|
||||
{
|
||||
fs::wipeSave();
|
||||
std::string fromPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
fs::copyDirToDirCommit(fromPath, "sv:/", "sv");
|
||||
}
|
||||
else if(!d->isDir(ind) && d->getItemExt(ind) == "zip")
|
||||
{
|
||||
fs::wipeSave();
|
||||
std::string path = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
unzFile unz = unzOpen(path.c_str());
|
||||
fs::copyZipToDir(&unz, "sv:/", "sv");
|
||||
unzClose(unz);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Just copy file over
|
||||
std::string fromPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
std::string toPath = "sv:/" + itemName;
|
||||
fs::copyFileCommit(fromPath, toPath, "sv");
|
||||
}
|
||||
}
|
||||
|
||||
if(data::autoBack)
|
||||
ui::fldInit();
|
||||
}
|
||||
|
||||
void fs::deleteBackup(void *a)
|
||||
{
|
||||
fs::backupArgs *in = (fs::backupArgs *)a;
|
||||
ui::menu *m = in->m;
|
||||
fs::dirList *d = in->d;
|
||||
|
||||
unsigned ind = m->getSelected() - 1;
|
||||
|
||||
std::string itemName = d->getItem(ind);
|
||||
if(ui::confirmDelete(itemName))
|
||||
{
|
||||
if(d->isDir(ind))
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName + "/";
|
||||
fs::delDir(delPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName;
|
||||
fs::delfile(delPath);
|
||||
}
|
||||
ui::fldInit();
|
||||
}
|
||||
}
|
||||
|
||||
void fs::logOpen()
|
||||
{
|
||||
std::string logPath = wd + "log.txt";
|
||||
|
||||
36
src/gfx.cpp
36
src/gfx.cpp
@@ -9,6 +9,7 @@
|
||||
#define VA_SIZE 1024
|
||||
|
||||
#include "gfx.h"
|
||||
#include "file.h"
|
||||
|
||||
static SDL_Window *wind;
|
||||
SDL_Renderer *gfx::render;
|
||||
@@ -29,6 +30,8 @@ static const uint32_t greenMask = 0x00FF0000;
|
||||
static const uint32_t blueMask = 0x0000FF00;
|
||||
static const uint32_t alphaMask = 0x000000FF;
|
||||
|
||||
static uint8_t *alphaMod;
|
||||
|
||||
static inline bool compClr(const SDL_Color *c1, const SDL_Color *c2)
|
||||
{
|
||||
return (c1->r == c2->r) && (c1->b == c2->b) && (c1->g == c2->g) && (c1->a == c2->a);
|
||||
@@ -97,6 +100,15 @@ void gfx::init()
|
||||
|
||||
wind = SDL_CreateWindow("JKSV", 0, 0, 1280, 720, SDL_WINDOW_SHOWN);
|
||||
render = SDL_CreateRenderer(wind, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
|
||||
|
||||
//Load the alpha mod to round icon corners
|
||||
alphaMod = (uint8_t *)malloc(256 * 256);
|
||||
FILE *modLoad = fopen("romfs:/img/icn/icon.msk", "rb");
|
||||
fread(alphaMod, 1, 256 * 256, modLoad);
|
||||
fclose(modLoad);
|
||||
|
||||
loadSystemFont();
|
||||
}
|
||||
|
||||
@@ -106,16 +118,12 @@ void gfx::exit()
|
||||
SDL_Quit();
|
||||
freeSystemFont();
|
||||
|
||||
free(alphaMod);
|
||||
|
||||
for(auto c : glyphCache)
|
||||
SDL_DestroyTexture(c.second.tex);
|
||||
}
|
||||
|
||||
void gfx::clear(const SDL_Color *c)
|
||||
{
|
||||
SDL_SetRenderDrawColor(render, c->r, c->g, c->b, c->a);
|
||||
SDL_RenderClear(render);
|
||||
}
|
||||
|
||||
void gfx::present()
|
||||
{
|
||||
SDL_RenderPresent(render);
|
||||
@@ -131,6 +139,9 @@ SDL_Texture *gfx::loadJPEGMem(const void *jpegData, size_t jpegsize)
|
||||
|
||||
SDL_FreeSurface(tmpSurf);
|
||||
SDL_RWclose(jpeg);
|
||||
|
||||
SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -142,6 +153,9 @@ SDL_Texture *gfx::loadImageFile(const char *file)
|
||||
ret = SDL_CreateTextureFromSurface(render, tmpSurf);
|
||||
|
||||
SDL_FreeSurface(tmpSurf);
|
||||
|
||||
SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -245,8 +259,9 @@ static inline bool specialChar(const uint32_t *p, const int *fontSize, const SDL
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gfx::drawTextf(int fontSize, int x, int y, const SDL_Color *c, const char *fmt, ...)
|
||||
void gfx::drawTextf(SDL_Texture *target, int fontSize, int x, int y, const SDL_Color *c, const char *fmt, ...)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
char tmp[VA_SIZE];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -283,10 +298,12 @@ void gfx::drawTextf(int fontSize, int x, int y, const SDL_Color *c, const char *
|
||||
tmpX += g->advX;
|
||||
}
|
||||
}
|
||||
SDL_SetRenderTarget(gfx::render, NULL);
|
||||
}
|
||||
|
||||
void gfx::drawTextfWrap(int fontSize, int x, int y, int maxWidth, const SDL_Color *c, const char *fmt, ...)
|
||||
void gfx::drawTextfWrap(SDL_Texture *target, int fontSize, int x, int y, int maxWidth, const SDL_Color *c, const char *fmt, ...)
|
||||
{
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
char tmp[VA_SIZE], wordBuff[128];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -307,7 +324,7 @@ void gfx::drawTextfWrap(int fontSize, int x, int y, int maxWidth, const SDL_Colo
|
||||
|
||||
size_t width = gfx::getTextWidth(wordBuff, fontSize);
|
||||
|
||||
if(tmpX + width >= x + maxWidth)
|
||||
if((int)(tmpX + width) >= (int)(x + maxWidth))
|
||||
{
|
||||
tmpX = x;
|
||||
y += fontSize + 8;
|
||||
@@ -339,6 +356,7 @@ void gfx::drawTextfWrap(int fontSize, int x, int y, int maxWidth, const SDL_Colo
|
||||
}
|
||||
i += wordLength;
|
||||
}
|
||||
SDL_SetRenderTarget(gfx::render, NULL);
|
||||
}
|
||||
|
||||
size_t gfx::getTextWidth(const char *str, int fontSize)
|
||||
|
||||
28
src/main.cpp
28
src/main.cpp
@@ -1,13 +1,9 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <switch.h>
|
||||
|
||||
#include "gfx.h"
|
||||
#include "file.h"
|
||||
#include "data.h"
|
||||
#include "ui.h"
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
extern "C"
|
||||
@@ -19,7 +15,7 @@ extern "C"
|
||||
nsInitialize();
|
||||
setsysInitialize();
|
||||
setInitialize();
|
||||
accountInitialize(AccountServiceType_System);
|
||||
accountInitialize(AccountServiceType_Administrator);
|
||||
pmshellInitialize();
|
||||
socketInitializeDefault();
|
||||
pdmqryInitialize();
|
||||
@@ -39,8 +35,6 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
bool debDataStats = false;
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
romfsInit();
|
||||
@@ -52,23 +46,7 @@ int main(int argc, const char *argv[])
|
||||
ui::init();
|
||||
romfsExit();
|
||||
|
||||
while(appletMainLoop())
|
||||
{
|
||||
ui::updatePad();
|
||||
|
||||
uint64_t down = ui::padKeysDown(), held = ui::padKeysHeld();
|
||||
|
||||
if(held & HidNpadButton_StickL && held & HidNpadButton_StickR)
|
||||
debDataStats = true;
|
||||
else if(down & HidNpadButton_Plus)
|
||||
break;
|
||||
|
||||
ui::runApp(down, held);
|
||||
|
||||
if(debDataStats)
|
||||
data::dispStats();
|
||||
gfx::present();
|
||||
}
|
||||
while(ui::runApp()){ }
|
||||
|
||||
ui::exit();
|
||||
data::exit();
|
||||
|
||||
433
src/ui.cpp
433
src/ui.cpp
@@ -2,22 +2,21 @@
|
||||
#include <unordered_map>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include <switch.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "ui.h"
|
||||
#include "gfx.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
|
||||
//text mode
|
||||
bool ui::textMode = false;
|
||||
|
||||
//Current menu state
|
||||
int ui::mstate = USR_SEL, ui::prevState = USR_SEL;
|
||||
|
||||
//pad data?
|
||||
PadState ui::pad;
|
||||
HidTouchScreenState ui::touchState;
|
||||
|
||||
//Theme id
|
||||
ColorSetId ui::thmID;
|
||||
@@ -26,7 +25,8 @@ ColorSetId ui::thmID;
|
||||
std::string ui::folderMenuInfo;
|
||||
|
||||
//UI colors
|
||||
SDL_Color ui::clearClr, ui::txtCont, ui::txtDiag, ui::rectLt, ui::rectSh, ui::tboxClr, divClr;
|
||||
SDL_Color ui::clearClr, ui::txtCont, ui::txtDiag, ui::rectLt, ui::rectSh, ui::tboxClr, ui::divClr, ui::slidePanelColor;
|
||||
SDL_Color ui::transparent = {0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
//textbox pieces
|
||||
//I was going to flip them when I draw them, but then laziness kicked in.
|
||||
@@ -36,194 +36,23 @@ SDL_Texture *ui::cornerTopLeft, *ui::cornerTopRight, *ui::cornerBottomLeft, *ui:
|
||||
SDL_Texture *ui::progCovLeft, *ui::progCovRight, *ui::diaBox;
|
||||
|
||||
//Menu box pieces
|
||||
SDL_Texture *mnuTopLeft, *mnuTopRight, *mnuBotLeft, *mnuBotRight;
|
||||
SDL_Texture *ui::mnuTopLeft, *ui::mnuTopRight, *ui::mnuBotLeft, *ui::mnuBotRight;
|
||||
|
||||
//Select box + top left icon
|
||||
SDL_Texture *ui::sideBar;
|
||||
|
||||
static SDL_Texture *icn;
|
||||
static SDL_Texture *icn, *leftPanel, *rightPanel;
|
||||
static SDL_Color rectTop = {0x36, 0x36, 0x36, 0xFF};
|
||||
SDL_Color ui::heartColor = {0xFF, 0x44, 0x44, 0xFF};
|
||||
|
||||
//X position of help texts. Calculated to make editing quicker/easier
|
||||
static unsigned userHelpX, titleHelpX, folderHelpX, optHelpX;
|
||||
|
||||
//Map to associate external string names to unsigned ints for switch case.
|
||||
static std::unordered_map<std::string, unsigned> uistrdef =
|
||||
{
|
||||
{"author", 0}, {"userHelp", 1}, {"titleHelp", 2}, {"folderHelp", 3}, {"optHelp", 4},
|
||||
{"yt", 5}, {"nt", 6}, {"on", 7}, {"off", 8}, {"confirmBlacklist", 9}, {"confirmOverwrite", 10},
|
||||
{"confirmRestore", 11}, {"confirmDelete", 12}, {"confirmCopy", 13}, {"confirmEraseNand", 14},
|
||||
{"confirmEraseFolder", 15}, {"confirmHead", 16}, {"copyHead", 17}, {"noSavesFound", 18},
|
||||
{"advMenu", 19}, {"extMenu", 20}, {"optMenu", 21}, {"optMenuExp", 22}, {"holdingText", 23},
|
||||
{"errorConnecting", 24}, {"noUpdate", 25}, {"sortType", 26}
|
||||
};
|
||||
//For shrinking left panel
|
||||
unsigned leftWidth = 410;
|
||||
|
||||
static void loadTrans()
|
||||
{
|
||||
bool transFile = fs::fileExists(fs::getWorkDir() + "trans.txt");
|
||||
if(!transFile && (data::sysLang == SetLanguage_ENUS || data::langOverride))
|
||||
return;//Don't bother loading from file. It serves as a translation guide
|
||||
|
||||
std::string file;
|
||||
if(transFile)
|
||||
file = fs::getWorkDir() + "trans.txt";
|
||||
else
|
||||
{
|
||||
file = "romfs:/lang/";
|
||||
switch(data::sysLang)
|
||||
{
|
||||
case SetLanguage_ZHCN:
|
||||
case SetLanguage_ZHHANS:
|
||||
file += "zh-CN.txt";
|
||||
break;
|
||||
|
||||
case SetLanguage_ZHTW:
|
||||
case SetLanguage_ZHHANT:
|
||||
file += "zh-TW.txt";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fs::dataFile lang(file);
|
||||
while(lang.readNextLine(true))
|
||||
{
|
||||
switch(uistrdef[lang.getName()])
|
||||
{
|
||||
case 0:
|
||||
ui::author = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ui::userHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ui::titleHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ui::folderHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ui::optHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ui::yt = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ui::nt = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
ui::on = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ui::off = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ui::confBlacklist = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 10:
|
||||
ui::confOverwrite = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 11:
|
||||
ui::confRestore = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ui::confDel = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 13:
|
||||
ui::confCopy = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 14:
|
||||
ui::confEraseNand = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ui::confEraseFolder = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ui::confirmHead = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 17:
|
||||
ui::copyHead = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 18:
|
||||
ui::noSavesFound = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 19:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::advMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 20:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::exMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 21:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::optMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 22:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::optMenuExp[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 23:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::holdingText[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 24:
|
||||
ui::errorConnecting = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 25:
|
||||
ui::noUpdate = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 26:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::sortString[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ui::showMessage("*Translation File Error:*", "On Line: %s\n*%s* is not a known or valid string name.", lang.getLine(), lang.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Vector of pointers to slideOutPanels. Is looped and drawn last so they are always on top
|
||||
std::vector<ui::slideOutPanel *> panels;
|
||||
|
||||
void ui::initTheme()
|
||||
{
|
||||
@@ -239,6 +68,7 @@ void ui::initTheme()
|
||||
rectSh = {0xCA, 0xCA, 0xCA, 0xFF};
|
||||
tboxClr = {0x50, 0x50, 0x50, 0xFF};
|
||||
divClr = {0x00, 0x00, 0x00, 0xFF};
|
||||
slidePanelColor = {0xEE, 0xEE, 0xEE, 0xDD};
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -253,6 +83,7 @@ void ui::initTheme()
|
||||
rectSh = {0x20, 0x20, 0x20, 0xFF};
|
||||
tboxClr = {0xEB, 0xEB, 0xEB, 0xFF};
|
||||
divClr = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||
slidePanelColor = {0x2F, 0x2F, 0x2F, 0xDD};
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -263,6 +94,12 @@ void ui::init()
|
||||
mnuTopRight = gfx::loadImageFile("romfs:/img/fb/menuTopRight.png");
|
||||
mnuBotLeft = gfx::loadImageFile("romfs:/img/fb/menuBotLeft.png");
|
||||
mnuBotRight = gfx::loadImageFile("romfs:/img/fb/menuBotRight.png");
|
||||
|
||||
leftPanel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET | SDL_TEXTUREACCESS_STATIC, 200, 559);
|
||||
rightPanel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET | SDL_TEXTUREACCESS_STATIC, 1080, 559);
|
||||
SDL_SetTextureBlendMode(leftPanel, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureBlendMode(rightPanel, SDL_BLENDMODE_BLEND);
|
||||
|
||||
switch(ui::thmID)
|
||||
{
|
||||
case ColorSetId_Light:
|
||||
@@ -290,17 +127,6 @@ void ui::init()
|
||||
break;
|
||||
}
|
||||
|
||||
if(ui::textMode && data::skipUser)
|
||||
{
|
||||
ui::textTitlePrep(data::curUser);
|
||||
mstate = TXT_TTL;
|
||||
}
|
||||
else if(ui::textMode)
|
||||
mstate = TXT_USR;
|
||||
else if(data::skipUser)
|
||||
mstate = TTL_SEL;
|
||||
|
||||
textUserPrep();
|
||||
loadTrans();
|
||||
|
||||
//Replace the button [x] in strings that need it. Needs to be outside loadTrans so even defaults will get replaced
|
||||
@@ -310,9 +136,6 @@ void ui::init()
|
||||
util::replaceButtonsInString(ui::optHelp);
|
||||
util::replaceButtonsInString(ui::yt);
|
||||
util::replaceButtonsInString(ui::nt);
|
||||
util::replaceButtonsInString(ui::optMenuExp[3]);
|
||||
util::replaceButtonsInString(ui::optMenuExp[4]);
|
||||
util::replaceButtonsInString(ui::optMenuExp[5]);
|
||||
|
||||
//Calculate x position of help text
|
||||
userHelpX = 1220 - gfx::getTextWidth(ui::userHelp.c_str(), 18);
|
||||
@@ -324,13 +147,20 @@ void ui::init()
|
||||
padConfigureInput(1, HidNpadStyleSet_NpadStandard);
|
||||
padInitializeDefault(&ui::pad);
|
||||
|
||||
advCopyMenuPrep();
|
||||
ui::exMenuPrep();
|
||||
ui::optMenuInit();
|
||||
//Setup touch
|
||||
hidInitializeTouchScreen();
|
||||
|
||||
//advCopyMenuPrep();
|
||||
ui::usrInit();
|
||||
ui::ttlInit();
|
||||
}
|
||||
|
||||
void ui::exit()
|
||||
{
|
||||
ui::usrExit();
|
||||
ui::ttlExit();
|
||||
ui::fldExit();
|
||||
|
||||
SDL_DestroyTexture(cornerTopLeft);
|
||||
SDL_DestroyTexture(cornerTopRight);
|
||||
SDL_DestroyTexture(cornerBottomLeft);
|
||||
@@ -343,158 +173,117 @@ void ui::exit()
|
||||
SDL_DestroyTexture(mnuBotLeft);
|
||||
SDL_DestroyTexture(mnuBotRight);
|
||||
|
||||
SDL_DestroyTexture(leftPanel);
|
||||
SDL_DestroyTexture(rightPanel);
|
||||
|
||||
SDL_DestroyTexture(icn);
|
||||
}
|
||||
|
||||
void ui::addPanel(slideOutPanel *sop)
|
||||
{
|
||||
panels.push_back(sop);
|
||||
}
|
||||
|
||||
void ui::showLoadScreen()
|
||||
{
|
||||
SDL_Texture *icon = gfx::loadImageFile("romfs:/icon.png");
|
||||
gfx::clear(&ui::clearClr);
|
||||
gfx::texDraw(icon, 512, 226);
|
||||
gfx::drawTextf(18, 1100, 673, &ui::txtCont, "Loading...");
|
||||
gfx::clearTarget(NULL, &ui::clearClr);
|
||||
gfx::texDraw(NULL, icon, 512, 232);
|
||||
gfx::drawTextf(NULL, 16, 1100, 673, &ui::txtCont, "Loading...");
|
||||
gfx::present();
|
||||
SDL_DestroyTexture(icon);
|
||||
}
|
||||
|
||||
void ui::drawUI()
|
||||
{
|
||||
gfx::clear(&ui::clearClr);
|
||||
gfx::texDraw(icn, 66, 27);
|
||||
gfx::drawTextf(24, 130, 38, &ui::txtCont, "JKSV");
|
||||
gfx::drawLine(&divClr, 30, 88, 1250, 88);
|
||||
gfx::drawLine(&divClr, 30, 648, 1250, 648);
|
||||
gfx::clearTarget(NULL, &ui::clearClr);
|
||||
gfx::clearTarget(leftPanel, &transparent);
|
||||
gfx::clearTarget(rightPanel, &transparent);
|
||||
|
||||
gfx::drawLine(NULL, &divClr, 30, 88, 1250, 88);
|
||||
gfx::drawLine(NULL, &divClr, 30, 648, 1250, 648);
|
||||
gfx::texDraw(NULL, icn, 66, 27);
|
||||
gfx::drawTextf(NULL, 24, 130, 38, &ui::txtCont, "JKSV");
|
||||
|
||||
//Version / translation author
|
||||
gfx::drawTextf(12, 8, 700, &ui::txtCont, "v. %02d.%02d.%04d", BLD_MON, BLD_DAY, BLD_YEAR);
|
||||
gfx::drawTextf(NULL, 12, 8, 700, &ui::txtCont, "v. %02d.%02d.%04d", BLD_MON, BLD_DAY, BLD_YEAR);
|
||||
if(author != "NULL")
|
||||
gfx::drawTextf(12, 8, 682, &ui::txtCont, "Translation: %s", author.c_str());
|
||||
gfx::drawTextf(NULL, 12, 8, 682, &ui::txtCont, "Translation: %s", author.c_str());
|
||||
|
||||
switch(mstate)
|
||||
gfx::texDraw(leftPanel, sideBar, 0, 89);
|
||||
ui::usrDraw(leftPanel);
|
||||
ui::ttlDraw(rightPanel);
|
||||
gfx::texDraw(NULL, rightPanel, 200, 89);
|
||||
gfx::texDraw(NULL, leftPanel, 0, 89);
|
||||
ui::fldDraw();
|
||||
for(slideOutPanel *s : panels)
|
||||
s->draw(&ui::slidePanelColor);
|
||||
}
|
||||
|
||||
static bool debugDisp = false;
|
||||
|
||||
bool ui::runApp()
|
||||
{
|
||||
ui::updateInput();
|
||||
uint64_t down = ui::padKeysDown();
|
||||
|
||||
if(down & HidNpadButton_StickL && down & HidNpadButton_StickR)
|
||||
debugDisp = true;
|
||||
else if(down & HidNpadButton_Plus)
|
||||
return false;
|
||||
|
||||
switch(ui::mstate)
|
||||
{
|
||||
case USR_SEL:
|
||||
gfx::drawTextf(18, userHelpX, 673, &ui::txtCont, userHelp.c_str());
|
||||
ui::drawUserMenu();
|
||||
usrUpdate();
|
||||
break;
|
||||
|
||||
case TTL_SEL:
|
||||
gfx::drawTextf(18, titleHelpX, 673, &ui::txtCont, titleHelp.c_str());
|
||||
ui::drawTitleMenu();
|
||||
ttlUpdate();
|
||||
break;
|
||||
|
||||
case FLD_SEL:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
gfx::drawTextf(18, folderHelpX, 673, &ui::txtCont, folderHelp.c_str());
|
||||
ui::drawFolderMenu();
|
||||
break;
|
||||
|
||||
case TXT_USR:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
gfx::drawTextf(18, userHelpX, 673, &ui::txtCont, userHelp.c_str());
|
||||
ui::drawTextUserMenu();
|
||||
break;
|
||||
|
||||
case TXT_TTL:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
gfx::drawTextf(18, titleHelpX, 673, &ui::txtCont, titleHelp.c_str());
|
||||
ui::drawTextTitleMenu();
|
||||
break;
|
||||
|
||||
case TXT_FLD:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
gfx::drawTextf(18, folderHelpX, 673, &ui::txtCont, folderHelp.c_str());
|
||||
ui::drawTextFolderMenu();
|
||||
break;
|
||||
|
||||
case EX_MNU:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
ui::drawExMenu();
|
||||
fldUpdate();
|
||||
break;
|
||||
|
||||
case OPT_MNU:
|
||||
gfx::texDraw(sideBar, 0, 89);
|
||||
ui::drawOptMenu();
|
||||
break;
|
||||
|
||||
case ADV_MDE:
|
||||
gfx::drawRect(&ui::txtCont, 640, 88, 1, 559);
|
||||
drawAdvMode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::drawBoundBox(int x, int y, int w, int h, int clrSh)
|
||||
{
|
||||
SDL_Color rectClr;
|
||||
|
||||
if(ui::thmID == ColorSetId_Light)
|
||||
rectClr = {0xFD, 0xFD, 0xFD, 0xFF};
|
||||
else
|
||||
rectClr = {0x21, 0x22, 0x21, 0xFF};
|
||||
|
||||
gfx::drawRect(&rectClr, x + 4, y + 4, w - 8, h - 8);
|
||||
|
||||
rectClr = {0x00,(uint8_t)(0x88 + clrSh), (uint8_t)(0xC5 + (clrSh / 2)), 0xFF};
|
||||
|
||||
SDL_SetTextureColorMod(mnuTopLeft, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuTopRight, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuBotLeft, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuBotRight, rectClr.r, rectClr.g, rectClr.b);
|
||||
|
||||
//top
|
||||
gfx::texDraw(mnuTopLeft, x, y);
|
||||
gfx::drawRect(&rectClr, x + 4, y, w - 8, 4);
|
||||
gfx::texDraw(mnuTopRight, (x + w) - 4, y);
|
||||
|
||||
//mid
|
||||
gfx::drawRect(&rectClr, x, y + 4, 4, h - 8);
|
||||
gfx::drawRect(&rectClr, (x + w) - 4, y + 4, 4, h - 8);
|
||||
|
||||
//bottom
|
||||
gfx::texDraw(mnuBotLeft, x, (y + h) - 4);
|
||||
gfx::drawRect(&rectClr, x + 4, (y + h) - 4, w - 8, 4);
|
||||
gfx::texDraw(mnuBotRight, (x + w) - 4, (y + h) - 4);
|
||||
}
|
||||
|
||||
void ui::runApp(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
switch(mstate)
|
||||
{
|
||||
case USR_SEL:
|
||||
updateUserMenu(down, held);
|
||||
break;
|
||||
|
||||
case TTL_SEL:
|
||||
updateTitleMenu(down, held);
|
||||
break;
|
||||
|
||||
case FLD_SEL:
|
||||
updateFolderMenu(down, held);
|
||||
break;
|
||||
|
||||
case ADV_MDE:
|
||||
updateAdvMode(down, held);
|
||||
break;
|
||||
|
||||
case TXT_USR:
|
||||
textUserMenuUpdate(down, held);
|
||||
break;
|
||||
|
||||
case TXT_TTL:
|
||||
textTitleMenuUpdate(down, held);
|
||||
break;
|
||||
|
||||
case TXT_FLD:
|
||||
textFolderMenuUpdate(down, held);
|
||||
/*optMenu.update();
|
||||
if(down & HidNpadButton_B)
|
||||
{
|
||||
ui::changeState(USR_SEL);
|
||||
mainMenu.setActive(true);
|
||||
optMenu.setActive(false);
|
||||
}*/
|
||||
break;
|
||||
|
||||
case EX_MNU:
|
||||
updateExMenu(down, held);
|
||||
break;
|
||||
|
||||
case OPT_MNU:
|
||||
updateOptMenu(down, held);
|
||||
/*extMenu.update();
|
||||
if(down & HidNpadButton_B)
|
||||
{
|
||||
ui::changeState(USR_SEL);
|
||||
mainMenu.setActive(true);
|
||||
extMenu.setActive(false);
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
|
||||
drawUI();
|
||||
drawPopup(down);
|
||||
drawPopup(ui::padKeysDown());
|
||||
if(debugDisp)
|
||||
data::dispStats();
|
||||
|
||||
gfx::present();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ui::toTTL(void *a)
|
||||
{
|
||||
if(data::curUser.titleInfo.size() > 0)
|
||||
{
|
||||
ui::changeState(TTL_SEL);
|
||||
ui::usrMenuSetActive(false);
|
||||
}
|
||||
else
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::noSavesFound.c_str(), data::curUser.getUsername().c_str());
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "ui.h"
|
||||
#include "miscui.h"
|
||||
#include "uiupdate.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
|
||||
//Text menus
|
||||
static ui::menu saveMenu, sdMenu, copyMenu;
|
||||
@@ -342,20 +341,20 @@ void performCopyMenuOps()
|
||||
}
|
||||
|
||||
|
||||
void ui::advCopyMenuPrep()
|
||||
void advCopyMenuPrep()
|
||||
{
|
||||
for(unsigned i = 0; i < 6; i++)
|
||||
copyMenu.addOpt(ui::advMenuStr[i]);
|
||||
copyMenu.addOpt(NULL, ui::advMenuStr[i]);
|
||||
}
|
||||
|
||||
void ui::advModePrep(const std::string& svDev, const FsSaveDataType& _type, bool commitOnWrite)
|
||||
void advModePrep(const std::string& svDev, const FsSaveDataType& _type, bool commitOnWrite)
|
||||
{
|
||||
commit = commitOnWrite;
|
||||
type = _type;
|
||||
|
||||
saveMenu.setParams(30, 98, 602);
|
||||
sdMenu.setParams(648, 98, 602);
|
||||
copyMenu.setParams(472, 278, 304);
|
||||
saveMenu.setParams(30, 98, 602, MENU_FONT_SIZE_DEFAULT, MENU_MAX_SCROLL_DEFAULT);
|
||||
sdMenu.setParams(648, 98, 602, MENU_FONT_SIZE_DEFAULT, MENU_MAX_SCROLL_DEFAULT);
|
||||
copyMenu.setParams(472, 278, 304, MENU_FONT_SIZE_DEFAULT, MENU_MAX_SCROLL_DEFAULT);
|
||||
|
||||
savePath = svDev, dev = svDev;
|
||||
sdPath = "sdmc:/";
|
||||
@@ -369,13 +368,13 @@ void ui::advModePrep(const std::string& svDev, const FsSaveDataType& _type, bool
|
||||
advMenuCtrl = 0;
|
||||
}
|
||||
|
||||
void ui::drawAdvMode()
|
||||
void drawAdvMode()
|
||||
{
|
||||
saveMenu.draw(&ui::txtCont);
|
||||
sdMenu.draw(&ui::txtCont);
|
||||
saveMenu.draw(NULL, &ui::txtCont, true);
|
||||
sdMenu.draw(NULL, &ui::txtCont, true);
|
||||
|
||||
gfx::drawTextfWrap(14, 30, 654, 600, &ui::txtCont, savePath.c_str());
|
||||
gfx::drawTextfWrap(14, 640, 654, 600, &ui::txtCont, sdPath.c_str());
|
||||
gfx::drawTextfWrap(NULL, 14, 30, 654, 600, &ui::txtCont, savePath.c_str());
|
||||
gfx::drawTextfWrap(NULL, 14, 640, 654, 600, &ui::txtCont, sdPath.c_str());
|
||||
|
||||
//draw copy menu if it's supposed to be up
|
||||
if(advMenuCtrl == 2)
|
||||
@@ -383,38 +382,38 @@ void ui::drawAdvMode()
|
||||
switch(advPrev)
|
||||
{
|
||||
case 0:
|
||||
copyMenu.setParams(176, 278, 304);
|
||||
copyMenu.editOpt(0, advMenuStr[0] + "sdmc");
|
||||
ui::drawTextbox(168, 236, 320, 268);
|
||||
gfx::drawTextf(18, 176, 250, &ui::txtDiag, dev.c_str());
|
||||
copyMenu.setParams(176, 278, 304, MENU_FONT_SIZE_DEFAULT, MENU_MAX_SCROLL_DEFAULT);
|
||||
copyMenu.editOpt(0, NULL, ui::advMenuStr[0] + "sdmc");
|
||||
ui::drawTextbox(NULL, 168, 236, 320, 268);
|
||||
gfx::drawTextf(NULL, 18, 176, 250, &ui::txtDiag, dev.c_str());
|
||||
break;
|
||||
|
||||
case 1:
|
||||
copyMenu.setParams(816, 278, 304);
|
||||
copyMenu.editOpt(0, advMenuStr[0] + dev);
|
||||
ui::drawTextbox(808, 236, 320, 268);
|
||||
gfx::drawTextf(18, 816, 250, &ui::txtDiag, "SDMC");
|
||||
copyMenu.setParams(816, 278, 304, MENU_FONT_SIZE_DEFAULT, MENU_MAX_SCROLL_DEFAULT);
|
||||
copyMenu.editOpt(0, NULL, ui::advMenuStr[0] + dev);
|
||||
ui::drawTextbox(NULL, 808, 236, 320, 268);
|
||||
gfx::drawTextf(NULL, 18, 816, 250, &ui::txtDiag, "SDMC");
|
||||
break;
|
||||
}
|
||||
copyMenu.draw(&ui::txtDiag);
|
||||
copyMenu.draw(NULL, &ui::txtDiag, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ui::updateAdvMode(const uint64_t& down, const uint64_t& held)
|
||||
void updateAdvMode(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
//0 = save; 1 = sd; 2 = cpy
|
||||
switch(advMenuCtrl)
|
||||
{
|
||||
case 0:
|
||||
saveMenu.handleInput(down, held);
|
||||
saveMenu.update();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
sdMenu.handleInput(down, held);
|
||||
sdMenu.update();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
copyMenu.handleInput(down, held);
|
||||
copyMenu.update();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -511,18 +510,18 @@ void ui::updateAdvMode(const uint64_t& down, const uint64_t& held)
|
||||
}
|
||||
else if(down & HidNpadButton_Minus)
|
||||
{
|
||||
switch(prevState)
|
||||
switch(ui::prevState)
|
||||
{
|
||||
case EX_MNU:
|
||||
mstate = EX_MNU;
|
||||
ui::mstate = EX_MNU;
|
||||
break;
|
||||
|
||||
case TTL_SEL:
|
||||
mstate = TTL_SEL;
|
||||
ui::mstate = TTL_SEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
mstate = ui::textMode ? TXT_FLD : FLD_SEL;
|
||||
ui::mstate = ui::textMode ? TXT_FLD : FLD_SEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
82
src/ui/fld.cpp
Normal file
82
src/ui/fld.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "fld.h"
|
||||
#include "ui.h"
|
||||
#include "file.h"
|
||||
#include "data.h"
|
||||
#include "util.h"
|
||||
|
||||
static ui::slideOutPanel *fldSlide = NULL;
|
||||
static ui::menu fldMenu;
|
||||
static fs::dirList fldList;
|
||||
static fs::backupArgs backargs;
|
||||
|
||||
static void fldCallback(void *a)
|
||||
{
|
||||
if(ui::padKeysDown() & HidNpadButton_B)
|
||||
{
|
||||
fs::unmountSave();
|
||||
fldSlide->closePanel();
|
||||
ui::changeState(TTL_SEL);
|
||||
}
|
||||
}
|
||||
|
||||
static void slideDrawFunc(void *a)
|
||||
{
|
||||
//Slide panel passes texture/target to draw func
|
||||
SDL_Texture *panel = (SDL_Texture *)a;
|
||||
fldMenu.draw(panel, &ui::txtCont, true);
|
||||
}
|
||||
|
||||
void ui::fldInit()
|
||||
{
|
||||
//Only allocate new if null
|
||||
if(!fldSlide)
|
||||
{
|
||||
fldSlide = new ui::slideOutPanel(410, 720, 0, slideDrawFunc);
|
||||
ui::addPanel(fldSlide);
|
||||
}
|
||||
|
||||
fldMenu.reset();
|
||||
fldMenu.setParams(12, 32, 390, MENU_FONT_SIZE_DEFAULT, 8);
|
||||
fldMenu.setCallback(fldCallback, NULL);
|
||||
|
||||
util::createTitleDirectoryByTID(data::curUser.titleInfo[data::selData].saveID);
|
||||
std::string folderPath = util::generatePathByTID(data::curUser.titleInfo[data::selData].saveID);
|
||||
|
||||
fldList.reassign(folderPath);
|
||||
fs::loadPathFilters(folderPath + "pathFilters.txt");
|
||||
|
||||
backargs = {&fldMenu, &fldList};
|
||||
|
||||
fldMenu.addOpt(NULL, "New");
|
||||
fldMenu.setOptFunc(0, FUNC_A, fs::createNewBackup, &backargs);
|
||||
|
||||
//Same as above, args updated at press
|
||||
for(unsigned i = 0; i < fldList.getCount(); i++)
|
||||
{
|
||||
fldMenu.addOpt(NULL, fldList.getItem(i));
|
||||
|
||||
//Pass the menu to the functions so selected can be grabbed
|
||||
//offset i by 1 since new is always first option
|
||||
fldMenu.setOptFunc(i + 1, FUNC_A, fs::overwriteBackup, &backargs);
|
||||
fldMenu.setOptFunc(i + 1, FUNC_X, fs::deleteBackup, &backargs);
|
||||
fldMenu.setOptFunc(i + 1, FUNC_Y, fs::restoreBackup, &backargs);
|
||||
}
|
||||
fldSlide->openPanel();
|
||||
}
|
||||
|
||||
void ui::fldExit()
|
||||
{
|
||||
if(fldSlide)
|
||||
delete fldSlide;
|
||||
}
|
||||
|
||||
void ui::fldUpdate()
|
||||
{
|
||||
fldMenu.update();
|
||||
}
|
||||
|
||||
void ui::fldDraw()
|
||||
{
|
||||
/*if(fldSlide)
|
||||
fldSlide->draw(&slidePanelColor);*/
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "uiupdate.h"
|
||||
#include "util.h"
|
||||
|
||||
ui::menu folderMenu;
|
||||
static fs::dirList fldList;
|
||||
|
||||
void ui::folderMenuPrepare(data::user& usr, data::titledata& dat)
|
||||
{
|
||||
folderMenu.setParams(466, 98, 730);
|
||||
folderMenu.reset();
|
||||
|
||||
dat.createDir();
|
||||
|
||||
fldList.reassign(dat.getPath());
|
||||
fs::loadPathFilters(dat.getPath() + "pathFilters.txt");
|
||||
folderMenu.addOpt("New");
|
||||
for(unsigned i = 0; i < fldList.getCount(); i++)
|
||||
folderMenu.addOpt(fldList.getItem(i));
|
||||
|
||||
folderMenu.adjust();
|
||||
}
|
||||
|
||||
void ui::createNewBackup(const uint64_t& held)
|
||||
{
|
||||
std::string out;
|
||||
|
||||
if(held & HidNpadButton_R)
|
||||
out = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
|
||||
else if(held & HidNpadButton_L)
|
||||
out = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
|
||||
else if(held & HidNpadButton_ZL)
|
||||
out = data::curUser.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),
|
||||
data::curUser.getUsernameSafe(),
|
||||
data::curData.getTitleSafe(),
|
||||
util::generateAbbrev(data::curData)
|
||||
};
|
||||
out = util::getStringInput("", "Enter a name", 64, 8, dict);
|
||||
}
|
||||
|
||||
if(!out.empty())
|
||||
{
|
||||
std::string path = data::curData.getPath() + "/" + out;
|
||||
switch(data::zip)
|
||||
{
|
||||
case true:
|
||||
{
|
||||
path += ".zip";
|
||||
zipFile zip = zipOpen(path.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case false:
|
||||
{
|
||||
mkdir(path.c_str(), 777);
|
||||
path += "/";
|
||||
fs::copyDirToDir("sv:/", path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
folderMenuPrepare(data::curUser, data::curData);
|
||||
}
|
||||
}
|
||||
|
||||
void ui::overwriteBackup(unsigned ind)
|
||||
{
|
||||
std::string itemName = fldList.getItem(ind);
|
||||
if(confirm(data::holdOver, ui::confOverwrite.c_str(), itemName.c_str()))
|
||||
{
|
||||
if(fldList.isDir(ind))
|
||||
{
|
||||
std::string toPath = data::curData.getPath() + itemName + "/";
|
||||
//Delete and recreate
|
||||
fs::delDir(toPath);
|
||||
mkdir(toPath.c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", toPath);
|
||||
}
|
||||
else if(!fldList.isDir(ind) && fldList.getItemExt(ind) == "zip")
|
||||
{
|
||||
std::string toPath = data::curData.getPath() + itemName;
|
||||
fs::delfile(toPath);
|
||||
zipFile zip = zipOpen(toPath.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::restoreBackup(unsigned ind)
|
||||
{
|
||||
std::string itemName = fldList.getItem(ind);
|
||||
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0 && confirm(data::holdRest, ui::confRestore.c_str(), itemName.c_str()))
|
||||
{
|
||||
if(data::autoBack)
|
||||
{
|
||||
switch(data::zip)
|
||||
{
|
||||
case true:
|
||||
{
|
||||
std::string autoZip = data::curData.getPath() + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
|
||||
zipFile zip = zipOpen(autoZip.c_str(), 0);
|
||||
fs::copyDirToZip("sv:/", &zip);
|
||||
zipClose(zip, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case false:
|
||||
{
|
||||
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/";
|
||||
mkdir(autoFolder.substr(0, autoFolder.length() - 1).c_str(), 777);
|
||||
fs::copyDirToDir("sv:/", autoFolder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(fldList.isDir(ind))
|
||||
{
|
||||
fs::wipeSave();
|
||||
std::string fromPath = data::curData.getPath() + itemName + "/";
|
||||
fs::copyDirToDirCommit(fromPath, "sv:/", "sv");
|
||||
}
|
||||
else if(!fldList.isDir(ind) && fldList.getItemExt(ind) == "zip")
|
||||
{
|
||||
fs::wipeSave();
|
||||
std::string path = data::curData.getPath() + itemName;
|
||||
unzFile unz = unzOpen(path.c_str());
|
||||
fs::copyZipToDir(&unz, "sv:/", "sv");
|
||||
unzClose(unz);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Just copy file over
|
||||
std::string fromPath = data::curData.getPath() + itemName;
|
||||
std::string toPath = "sv:/" + itemName;
|
||||
fs::copyFileCommit(fromPath, toPath, "sv");
|
||||
}
|
||||
}
|
||||
if(data::autoBack)
|
||||
folderMenuPrepare(data::curUser, data::curData);
|
||||
}
|
||||
|
||||
void ui::deleteBackup(unsigned ind)
|
||||
{
|
||||
std::string itemName = fldList.getItem(folderMenu.getSelected() - 1);
|
||||
if(ui::confirmDelete(itemName))
|
||||
{
|
||||
if(fldList.isDir(ind))
|
||||
{
|
||||
std::string delPath = data::curData.getPath() + itemName + "/";
|
||||
fs::delDir(delPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string delPath = data::curData.getPath() + itemName;
|
||||
fs::delfile(delPath);
|
||||
}
|
||||
}
|
||||
folderMenuPrepare(data::curUser, data::curData);
|
||||
}
|
||||
|
||||
void ui::drawFolderMenu()
|
||||
{
|
||||
data::curData.drawIcon(true, 96, 98);
|
||||
gfx::drawTextfWrap(16, 60, 370, 360, &ui::txtCont, folderMenuInfo.c_str());
|
||||
folderMenu.draw(&ui::txtCont);
|
||||
}
|
||||
|
||||
void ui::updateFolderMenu(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
folderMenu.handleInput(down, held);
|
||||
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(folderMenu.getSelected() == 0)
|
||||
ui::createNewBackup(held);
|
||||
else
|
||||
ui::overwriteBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
fs::unmountSave();
|
||||
fs::freePathFilters();
|
||||
ui::changeState(TTL_SEL);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
if(folderMenu.getSelected() > 0)
|
||||
ui::deleteBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
if(folderMenu.getSelected() > 0)
|
||||
ui::restoreBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
if(data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
|
||||
{
|
||||
fs::delDir("sv:/");
|
||||
fsdevCommitDevice("sv");
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
advModePrep("sv:/", data::curData.getType(), true);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
162
src/ui/menu.cpp
162
src/ui/menu.cpp
@@ -1,162 +0,0 @@
|
||||
#include <string>
|
||||
#include <switch.h>
|
||||
|
||||
#include "gfx.h"
|
||||
#include "menu.h"
|
||||
#include "ui.h"
|
||||
#include "miscui.h"
|
||||
|
||||
static const SDL_Color menuColorLight = {0x32, 0x50, 0xF0, 0xFF};
|
||||
static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF};
|
||||
|
||||
#define HOLD_FC 10
|
||||
|
||||
void ui::menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
rW = _rW;
|
||||
rY = _y;
|
||||
}
|
||||
|
||||
void ui::menu::addOpt(const std::string& add)
|
||||
{
|
||||
if(gfx::getTextWidth(add.c_str(), 18) < rW - 32 || rW == 0)
|
||||
opt.push_back(add);
|
||||
else
|
||||
{
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < add.length(); )
|
||||
{
|
||||
uint32_t tmpChr = 0;
|
||||
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&add.c_str()[i]);
|
||||
|
||||
tmp += add.substr(i, untCnt);
|
||||
i += untCnt;
|
||||
if(gfx::getTextWidth(tmp.c_str(), 18) >= rW - 32)
|
||||
{
|
||||
opt.push_back(tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::menu::editOpt(int ind, const std::string& ch)
|
||||
{
|
||||
opt[ind] = ch;
|
||||
}
|
||||
|
||||
ui::menu::~menu()
|
||||
{
|
||||
opt.clear();
|
||||
}
|
||||
|
||||
void ui::menu::handleInput(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
if( (held & HidNpadButton_Up) || (held & HidNpadButton_Down))
|
||||
fc++;
|
||||
else
|
||||
fc = 0;
|
||||
if(fc > 10)
|
||||
fc = 0;
|
||||
|
||||
int size = opt.size() - 1;
|
||||
if((down & HidNpadButton_Up) || ((held & HidNpadButton_Up) && fc == HOLD_FC))
|
||||
{
|
||||
selected--;
|
||||
if(selected < 0)
|
||||
selected = size;
|
||||
|
||||
if((start > selected) && (start > 0))
|
||||
start--;
|
||||
if(size < 15)
|
||||
start = 0;
|
||||
if((selected - 14) > start)
|
||||
start = selected - 14;
|
||||
}
|
||||
else if((down & HidNpadButton_Down) || ((held & HidNpadButton_Down) && fc == HOLD_FC))
|
||||
{
|
||||
selected++;
|
||||
if(selected > size)
|
||||
selected = 0;
|
||||
|
||||
if((selected > (start + 14)) && ((start + 14) < size))
|
||||
start++;
|
||||
if(selected == 0)
|
||||
start = 0;
|
||||
}
|
||||
else if(down & HidNpadButton_Right)
|
||||
{
|
||||
selected += 7;
|
||||
if(selected > size)
|
||||
selected = size;
|
||||
if((selected - 14) > start)
|
||||
start = selected - 14;
|
||||
}
|
||||
else if(down & HidNpadButton_Left)
|
||||
{
|
||||
selected -= 7;
|
||||
if(selected < 0)
|
||||
selected = 0;
|
||||
if(selected < start)
|
||||
start = selected;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::menu::draw(const SDL_Color *textClr)
|
||||
{
|
||||
if(opt.size() < 1)
|
||||
return;
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrSh += 6;
|
||||
if(clrSh >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrSh -= 3;
|
||||
if(clrSh <= 0x00)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
if((opt.size() - 1) < 15)
|
||||
length = opt.size();
|
||||
else
|
||||
length = start + 15;
|
||||
|
||||
for(int i = start; i < length; i++)
|
||||
{
|
||||
if(i == selected)
|
||||
{
|
||||
ui::drawBoundBox(x, y + ((i - start) * 36), rW, 36, clrSh);
|
||||
gfx::drawTextf(18, x + 8, (y + 8) + ((i - start) * 36), ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].c_str());
|
||||
}
|
||||
else
|
||||
gfx::drawTextf(18, x + 8, (y + 8) + ((i - start) * 36), textClr, opt[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ui::menu::reset()
|
||||
{
|
||||
opt.clear();
|
||||
start = 0;
|
||||
selected = 0;
|
||||
|
||||
fc = 0;
|
||||
}
|
||||
|
||||
void ui::menu::adjust()
|
||||
{
|
||||
if(selected > (int)opt.size() - 1)
|
||||
selected = opt.size() - 1;
|
||||
|
||||
if(opt.size() < 14)
|
||||
start = 0;
|
||||
else if(opt.size() > 14 && start + 14 > (int)opt.size() - 1)
|
||||
start = opt.size() - 15;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ static const SDL_Color fillBack = {0x66, 0x66, 0x66, 0xFF};
|
||||
static const SDL_Color fillLight = {0x00, 0xFF, 0xC5, 0xFF};
|
||||
static const SDL_Color fillDark = {0x32, 0x50, 0xF0, 0xFF};
|
||||
|
||||
static const SDL_Color menuColorLight = {0x32, 0x50, 0xF0, 0xFF};
|
||||
static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF};
|
||||
|
||||
enum popStates
|
||||
{
|
||||
popRise,
|
||||
@@ -27,11 +30,264 @@ enum popStates
|
||||
popFall
|
||||
};
|
||||
|
||||
//8
|
||||
static const std::string loadGlyphArray[] =
|
||||
{
|
||||
"\ue020", "\ue021", "\ue022", "\ue023",
|
||||
"\ue024", "\ue025", "\ue026", "\ue027"
|
||||
};
|
||||
|
||||
void ui::menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW, const unsigned& _fS, const unsigned& _mL)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
rW = _rW;
|
||||
rY = _y;
|
||||
fSize = _fS;
|
||||
mL = _mL;
|
||||
rH = _fS + 24;
|
||||
}
|
||||
|
||||
void ui::menu::editParam(int _param, unsigned newVal)
|
||||
{
|
||||
switch(_param)
|
||||
{
|
||||
case MENU_X:
|
||||
x = newVal;
|
||||
break;
|
||||
|
||||
case MENU_Y:
|
||||
y = newVal;
|
||||
break;
|
||||
|
||||
case MENU_RECT_WIDTH:
|
||||
rW = newVal;
|
||||
break;
|
||||
|
||||
case MENU_FONT_SIZE:
|
||||
fSize = newVal;
|
||||
break;
|
||||
|
||||
case MENU_MAX_SCROLL:
|
||||
mL = newVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::menu::addOpt(SDL_Texture *_icn, const std::string& add)
|
||||
{
|
||||
ui::menuOpt newOpt;
|
||||
if((int)gfx::getTextWidth(add.c_str(), fSize) < rW - 56 || rW == 0)
|
||||
newOpt.txt = add;
|
||||
else
|
||||
{
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < add.length(); )
|
||||
{
|
||||
uint32_t tmpChr = 0;
|
||||
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&add.c_str()[i]);
|
||||
|
||||
tmp += add.substr(i, untCnt);
|
||||
i += untCnt;
|
||||
if((int)gfx::getTextWidth(tmp.c_str(), fSize) >= rW - 48)
|
||||
{
|
||||
newOpt.txt = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
newOpt.icn = _icn;
|
||||
opt.push_back(newOpt);
|
||||
}
|
||||
|
||||
void ui::menu::editOpt(int ind, SDL_Texture *_icn, const std::string& ch)
|
||||
{
|
||||
if(!opt[ind].icn && _icn)
|
||||
opt[ind].icn = _icn;
|
||||
|
||||
opt[ind].txt = ch;
|
||||
}
|
||||
|
||||
void ui::menu::setOptFunc(unsigned _ind, unsigned _funcbtn, funcPtr _func, void *args)
|
||||
{
|
||||
opt[_ind].func[_funcbtn] = _func;
|
||||
opt[_ind].argPtr[_funcbtn] = args;
|
||||
}
|
||||
|
||||
int ui::menu::getOptPos(const std::string& txt)
|
||||
{
|
||||
for(unsigned i = 0; i < opt.size(); i++)
|
||||
{
|
||||
if(opt[i].txt == txt)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ui::menu::~menu()
|
||||
{
|
||||
opt.clear();
|
||||
}
|
||||
|
||||
void ui::menu::update()
|
||||
{
|
||||
if(!isActive)
|
||||
return;
|
||||
|
||||
uint64_t down = ui::padKeysDown();
|
||||
uint64_t held = ui::padKeysHeld();
|
||||
|
||||
if(held & HidNpadButton_AnyUp || held & HidNpadButton_AnyDown)
|
||||
++fc;
|
||||
else
|
||||
fc = 0;
|
||||
|
||||
if(fc > 10)
|
||||
fc = 0;
|
||||
|
||||
int oldSel = selected;
|
||||
int mSize = opt.size() - 1, scrL = mL - 1;
|
||||
if( (down & HidNpadButton_AnyUp) || ((held & HidNpadButton_AnyUp) && fc == 10) )
|
||||
{
|
||||
--selected;
|
||||
if(selected < 0)
|
||||
selected = mSize;
|
||||
|
||||
if(mSize > (int)mL)
|
||||
{
|
||||
if(start > selected)
|
||||
--start;
|
||||
else if(selected - scrL > start)
|
||||
start = selected - scrL;
|
||||
}
|
||||
}
|
||||
else if( (down & HidNpadButton_AnyDown) || ((held & HidNpadButton_AnyDown) && fc == 10))
|
||||
{
|
||||
++selected;
|
||||
if(selected > mSize)
|
||||
selected = 0;
|
||||
|
||||
if(selected > (start + scrL) && (start + scrL) < mSize)
|
||||
++start;
|
||||
if(selected == 0)
|
||||
start = 0;
|
||||
}
|
||||
else if(down & HidNpadButton_AnyLeft)
|
||||
{
|
||||
selected -= scrL / 2;
|
||||
if(selected < 0)
|
||||
selected = 0;
|
||||
if(selected < start)
|
||||
start = selected;
|
||||
}
|
||||
else if(down & HidNpadButton_AnyRight)
|
||||
{
|
||||
selected += scrL / 2;
|
||||
if(selected > mSize)
|
||||
selected = mSize;
|
||||
if(selected - scrL > start)
|
||||
start = selected - scrL;
|
||||
}
|
||||
|
||||
//func exec
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(opt[selected].func[FUNC_A])
|
||||
(*opt[selected].func[FUNC_A])(opt[selected].argPtr[FUNC_A]);
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
if(opt[selected].func[FUNC_B])
|
||||
(*opt[selected].func[FUNC_B])(opt[selected].argPtr[FUNC_B]);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
if(opt[selected].func[FUNC_X])
|
||||
(*opt[selected].func[FUNC_X])(opt[selected].argPtr[FUNC_X]);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
if(opt[selected].func[FUNC_Y])
|
||||
(*opt[selected].func[FUNC_Y])(opt[selected].argPtr[FUNC_Y]);
|
||||
break;
|
||||
}
|
||||
|
||||
if(selected != oldSel && onChange)
|
||||
(*onChange)(NULL);
|
||||
|
||||
if(callback)
|
||||
(*callback)(callbackArgs);
|
||||
}
|
||||
|
||||
void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText)
|
||||
{
|
||||
if(opt.size() < 1)
|
||||
return;
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrSh += 6;
|
||||
if(clrSh >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrSh -= 3;
|
||||
if(clrSh <= 0x00)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
for(int i = start; i < (int)opt.size(); i++)
|
||||
{
|
||||
if(i == selected)
|
||||
{
|
||||
if(isActive)
|
||||
ui::drawBoundBox(target, x, y + ((i - start) * rH), rW, rH, clrSh);
|
||||
|
||||
gfx::drawRect(target, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, x + 10, ((y + (rH / 2 - fSize / 2)) + ((i - start) * rH)) - 2, 4, fSize + 4);
|
||||
if(drawText)
|
||||
gfx::drawTextf(target, fSize, x + 20, (y + (rH / 2 - fSize / 2)) + ((i - start) * rH), ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(drawText)
|
||||
gfx::drawTextf(target, fSize, x + 20, (y + (rH / 2 - fSize / 2)) + ((i - start) * rH), textClr, opt[i].txt.c_str());
|
||||
}
|
||||
|
||||
int w, h;
|
||||
if(opt[i].icn && SDL_QueryTexture(opt[i].icn, NULL, NULL, &w, &h) == 0)
|
||||
{
|
||||
float scale = (float)fSize / (float)h;
|
||||
int dW = scale * w;
|
||||
int dH = scale * h;
|
||||
|
||||
gfx::texDrawStretch(target, opt[i].icn, x + 20, (y + (rH / 2 - fSize / 2)) + ((i - start) * rH), dW, dH);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ui::menu::reset()
|
||||
{
|
||||
opt.clear();
|
||||
start = 0;
|
||||
selected = 0;
|
||||
|
||||
fc = 0;
|
||||
}
|
||||
|
||||
void ui::menu::setActive(bool _set)
|
||||
{
|
||||
isActive = _set;
|
||||
}
|
||||
|
||||
void ui::progBar::update(const uint64_t& _prog)
|
||||
{
|
||||
prog = _prog;
|
||||
|
||||
width = (float)(((float)prog / (float)max) * (float)maxWidth);
|
||||
width = (float)(((float)prog / (float)max) * 576);
|
||||
}
|
||||
|
||||
void ui::progBar::draw(const std::string& text, const std::string& head)
|
||||
@@ -39,24 +295,55 @@ void ui::progBar::draw(const std::string& text, const std::string& head)
|
||||
size_t headWidth = gfx::getTextWidth(head.c_str(), 20);
|
||||
unsigned headX = (1280 / 2) - (headWidth / 2);
|
||||
|
||||
ui::drawTextbox(320, 150, 640, 420);
|
||||
gfx::drawLine(ui::thmID == ColorSetId_Light ? &divLight : &divDark, 320, 206, 959, 206);
|
||||
gfx::drawRect(&fillBack, 352, 530, 576, 12);
|
||||
gfx::drawRect(ui::thmID == ColorSetId_Light ? &fillLight : &fillDark, 352, 530, (int)width, 12);
|
||||
gfx::texDraw(ui::progCovLeft, 352, 530);
|
||||
gfx::texDraw(ui::progCovRight, 920, 530);
|
||||
ui::drawTextbox(NULL, 320, 150, 640, 420);
|
||||
gfx::drawLine(NULL, ui::thmID == ColorSetId_Light ? &divLight : &divDark, 320, 206, 959, 206);
|
||||
gfx::drawRect(NULL, &fillBack, 352, 530, 576, 12);
|
||||
gfx::drawRect(NULL, ui::thmID == ColorSetId_Light ? &fillLight : &fillDark, 352, 530, (int)width, 12);
|
||||
gfx::texDraw(NULL, ui::progCovLeft, 352, 530);
|
||||
gfx::texDraw(NULL, ui::progCovRight, 920, 530);
|
||||
|
||||
|
||||
gfx::drawTextf(20, headX, 160, &ui::txtDiag, head.c_str());
|
||||
gfx::drawTextfWrap(16, 352, 230, 576, &ui::txtDiag, text.c_str());
|
||||
gfx::drawTextf(NULL, 20, headX, 168, &ui::txtDiag, head.c_str());
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 230, 576, &ui::txtDiag, text.c_str());
|
||||
}
|
||||
|
||||
void ui::progBar::drawNoDialog(int x, int y)
|
||||
ui::slideOutPanel::slideOutPanel(int _w, int _h, int _y, funcPtr _draw)
|
||||
{
|
||||
gfx::drawRect(&fillBack, x, y, maxWidth, 12);
|
||||
gfx::drawRect(ui::thmID == ColorSetId_Light ? &fillLight : &fillDark, x, y, width, 12);
|
||||
gfx::texDraw(ui::progCovLeft, x, y);
|
||||
gfx::texDraw(ui::progCovRight, x + maxWidth - 8, y);
|
||||
w = _w;
|
||||
h = _h;
|
||||
y = _y;
|
||||
drawFunc = _draw;
|
||||
panel = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
SDL_SetTextureBlendMode(panel, SDL_BLENDMODE_BLEND);
|
||||
|
||||
int getDiv = 99;
|
||||
while(w % getDiv != 0){ getDiv--; }
|
||||
slideSpd = getDiv;
|
||||
}
|
||||
|
||||
ui::slideOutPanel::~slideOutPanel()
|
||||
{
|
||||
SDL_DestroyTexture(panel);
|
||||
}
|
||||
|
||||
void ui::slideOutPanel::draw(const SDL_Color *backCol)
|
||||
{
|
||||
gfx::clearTarget(panel, backCol);
|
||||
|
||||
if(open && x > 1280 - w)
|
||||
{
|
||||
x -= slideSpd;
|
||||
}
|
||||
else if(!open && x < 1280)
|
||||
{
|
||||
x += slideSpd;
|
||||
}
|
||||
|
||||
//don't waste time drawing if you can't even see it.
|
||||
if(x < 1280)
|
||||
{
|
||||
(*drawFunc)(panel);
|
||||
gfx::texDraw(NULL, panel, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void ui::showMessage(const char *head, const char *fmt, ...)
|
||||
@@ -72,17 +359,18 @@ void ui::showMessage(const char *head, const char *fmt, ...)
|
||||
|
||||
while(true)
|
||||
{
|
||||
ui::updatePad();
|
||||
ui::updateInput();
|
||||
|
||||
if(ui::padKeysDown())
|
||||
break;
|
||||
|
||||
ui::drawTextbox(320, 150, 640, 420);
|
||||
gfx::drawTextf(20, 320 + headX, 168, &ui::txtDiag, head);
|
||||
gfx::drawTextfWrap(16, 352, 230, 576, &ui::txtDiag, tmp);
|
||||
gfx::drawTextf(20, 320 + okX, 522, &ui::txtDiag, okt);
|
||||
ui::drawTextbox(NULL, 320, 150, 640, 420);
|
||||
gfx::drawTextf(NULL, 20, 320 + headX, 168, &ui::txtDiag, head);
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 230, 576, &ui::txtDiag, tmp);
|
||||
gfx::drawTextf(NULL, 20, 320 + okX, 522, &ui::txtDiag, okt);
|
||||
gfx::present();
|
||||
}
|
||||
ui::updateInput();
|
||||
}
|
||||
|
||||
bool ui::confirm(bool hold, const char *fmt, ...)
|
||||
@@ -106,7 +394,7 @@ bool ui::confirm(bool hold, const char *fmt, ...)
|
||||
|
||||
while(true)
|
||||
{
|
||||
ui::updatePad();
|
||||
ui::updateInput();
|
||||
|
||||
uint64_t down = ui::padKeysDown();
|
||||
uint64_t held = ui::padKeysHeld();
|
||||
@@ -161,18 +449,21 @@ bool ui::confirm(bool hold, const char *fmt, ...)
|
||||
if(hold && heldDown)
|
||||
{
|
||||
if(ui::thmID == ColorSetId_Light)
|
||||
holdClr = {0xFF, 0xFF - holdClrDiff, 0xFF - holdClrDiff, 0xFF};
|
||||
holdClr = {0xFF, (uint8_t)(0xFF - holdClrDiff), (uint8_t)(0xFF - holdClrDiff), 0xFF};
|
||||
else
|
||||
holdClr = {0x25 + holdClrDiff, 0x00, 0x00, 0xFF};
|
||||
holdClr = {(uint8_t)(0x25 + holdClrDiff), 0x00, 0x00, 0xFF};
|
||||
}
|
||||
|
||||
ui::drawTextbox(320, 150, 640, 420);
|
||||
gfx::drawTextf(20, 320 + headX, 168, &ui::txtDiag, ui::confirmHead.c_str());
|
||||
gfx::drawTextf(20, 320 + yesX, 522, &holdClr, yesText.c_str());
|
||||
gfx::drawTextf(20, 640 + noX, 522, &ui::txtDiag, ui::nt.c_str());
|
||||
gfx::drawTextfWrap(16, 352, 230, 576, &ui::txtDiag, tmp);
|
||||
ui::drawTextbox(NULL, 320, 150, 640, 420);
|
||||
gfx::drawTextf(NULL, 20, 320 + headX, 168, &ui::txtDiag, ui::confirmHead.c_str());
|
||||
gfx::drawTextf(NULL, 20, 320 + yesX, 522, &holdClr, yesText.c_str());
|
||||
gfx::drawTextf(NULL, 20, 640 + noX, 522, &ui::txtDiag, ui::nt.c_str());
|
||||
gfx::drawTextfWrap(NULL, 16, 352, 230, 576, &ui::txtDiag, tmp);
|
||||
gfx::present();
|
||||
}
|
||||
|
||||
ui::updateInput();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -186,40 +477,55 @@ bool ui::confirmDelete(const std::string& p)
|
||||
return confirm(data::holdDel, ui::confDel.c_str(), p.c_str());
|
||||
}
|
||||
|
||||
void ui::drawTextbox(int x, int y, int w, int h)
|
||||
void ui::drawTextbox(SDL_Texture *target, int x, int y, int w, int h)
|
||||
{
|
||||
//Top
|
||||
gfx::texDraw(ui::cornerTopLeft, x, y);
|
||||
gfx::drawRect(&ui::tboxClr, x + 32, y, w - 64, 32);
|
||||
gfx::texDraw(ui::cornerTopRight, (x + w) - 32, y);
|
||||
gfx::texDraw(target, ui::cornerTopLeft, x, y);
|
||||
gfx::drawRect(target, &ui::tboxClr, x + 32, y, w - 64, 32);
|
||||
gfx::texDraw(target, ui::cornerTopRight, (x + w) - 32, y);
|
||||
|
||||
//middle
|
||||
gfx::drawRect(&ui::tboxClr, x, y + 32, w, h - 64);
|
||||
gfx::drawRect(target, &ui::tboxClr, x, y + 32, w, h - 64);
|
||||
|
||||
//bottom
|
||||
gfx::texDraw(ui::cornerBottomLeft, x, (y + h) - 32);
|
||||
gfx::drawRect(&ui::tboxClr, x + 32, (y + h) - 32, w - 64, 32);
|
||||
gfx::texDraw(ui::cornerBottomRight, (x + w) - 32, (y + h) - 32);
|
||||
gfx::texDraw(target, ui::cornerBottomLeft, x, (y + h) - 32);
|
||||
gfx::drawRect(target, &ui::tboxClr, x + 32, (y + h) - 32, w - 64, 32);
|
||||
gfx::texDraw(target, ui::cornerBottomRight, (x + w) - 32, (y + h) - 32);
|
||||
}
|
||||
|
||||
/*void ui::drawTextboxInvert(tex *target, int x, int y, int w, int h)
|
||||
void ui::drawBoundBox(SDL_Texture *target, int x, int y, int w, int h, uint8_t clrSh)
|
||||
{
|
||||
clr temp = ui::tboxClr;
|
||||
clrInvert(&temp);
|
||||
SDL_SetRenderTarget(gfx::render, target);
|
||||
SDL_Color rectClr;
|
||||
|
||||
//Top
|
||||
texDrawInvert(ui::cornerTopLeft, target, x, y);
|
||||
drawRect(target, x + 32, y, w - 64, 32, temp);
|
||||
texDrawInvert(ui::cornerTopRight, target, (x + w) - 32, y);
|
||||
if(ui::thmID == ColorSetId_Light)
|
||||
rectClr = {0xFD, 0xFD, 0xFD, 0xFF};
|
||||
else
|
||||
rectClr = {0x21, 0x22, 0x21, 0xFF};
|
||||
|
||||
//middle
|
||||
drawRect(target, x, y + 32, w, h - 64, temp);
|
||||
gfx::drawRect(target, &rectClr, x + 4, y + 4, w - 8, h - 8);
|
||||
|
||||
rectClr = {0x00,(uint8_t)(0x88 + clrSh), (uint8_t)(0xC5 + (clrSh / 2)), 0xFF};
|
||||
|
||||
SDL_SetTextureColorMod(mnuTopLeft, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuTopRight, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuBotLeft, rectClr.r, rectClr.g, rectClr.b);
|
||||
SDL_SetTextureColorMod(mnuBotRight, rectClr.r, rectClr.g, rectClr.b);
|
||||
|
||||
//top
|
||||
gfx::texDraw(target, mnuTopLeft, x, y);
|
||||
gfx::drawRect(target, &rectClr, x + 4, y, w - 8, 4);
|
||||
gfx::texDraw(target, mnuTopRight, (x + w) - 4, y);
|
||||
|
||||
//mid
|
||||
gfx::drawRect(target, &rectClr, x, y + 4, 4, h - 8);
|
||||
gfx::drawRect(target, &rectClr, (x + w) - 4, y + 4, 4, h - 8);
|
||||
|
||||
//bottom
|
||||
texDrawInvert(ui::cornerBottomLeft, target, x, (y + h) - 32);
|
||||
drawRect(target, x + 32, (y + h) - 32, w - 64, 32, temp);
|
||||
texDrawInvert(ui::cornerBottomRight, target, (x + w) - 32, (y + h) - 32);
|
||||
}*/
|
||||
gfx::texDraw(target, mnuBotLeft, x, (y + h) - 4);
|
||||
gfx::drawRect(target, &rectClr, x + 4, (y + h) - 4, w - 8, 4);
|
||||
gfx::texDraw(target, mnuBotRight, (x + w) - 4, (y + h) - 4);
|
||||
}
|
||||
|
||||
void ui::showPopup(unsigned frames, const char *fmt, ...)
|
||||
{
|
||||
@@ -267,7 +573,7 @@ void ui::drawPopup(const uint64_t& down)
|
||||
break;
|
||||
}
|
||||
|
||||
drawTextbox(popX, popY, popWidth, 64);
|
||||
gfx::drawTextf(24, popX + 16, popY + 20, &ui::txtDiag, popText.c_str());
|
||||
drawTextbox(NULL, popX, popY, popWidth, 64);
|
||||
gfx::drawTextf(NULL, 24, popX + 16, popY + 20, &ui::txtDiag, popText.c_str());
|
||||
}
|
||||
|
||||
|
||||
347
src/ui/ttl.cpp
Normal file
347
src/ui/ttl.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
#include "ui.h"
|
||||
#include "ttl.h"
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
class titleTile
|
||||
{
|
||||
public:
|
||||
titleTile(unsigned _w, unsigned _h, bool _fav, SDL_Texture *_icon)
|
||||
{
|
||||
w = _w;
|
||||
h = _h;
|
||||
wS = _w;
|
||||
hS = _h;
|
||||
fav = _fav;
|
||||
icon = _icon;
|
||||
}
|
||||
|
||||
void draw(SDL_Texture *target, int x, int y, bool sel);
|
||||
|
||||
private:
|
||||
unsigned w, h, wS, hS;
|
||||
bool fav = false;
|
||||
SDL_Texture *icon;
|
||||
};
|
||||
|
||||
static uint8_t clrShft = 0;
|
||||
static bool clrAdd = true;
|
||||
static int selRectX = 38, selRectY = 38;
|
||||
static int x = 34, y = 69, ttlHelpX = 0;
|
||||
static std::vector<titleTile> titleList;
|
||||
static ui::menu *ttlOpts;
|
||||
static ui::slideOutPanel *ttlOptsPanel, *infoPanel;
|
||||
static std::string infoPanelString;
|
||||
|
||||
static void ttlOptsCallback(void *a)
|
||||
{
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_B:
|
||||
ttlOpts->setActive(false);
|
||||
ttlOptsPanel->closePanel();
|
||||
ui::updateInput();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ttlOptsPanelDraw(void *a)
|
||||
{
|
||||
SDL_Texture *panel = (SDL_Texture *)a;
|
||||
ttlOpts->draw(panel, &ui::txtCont, true);
|
||||
}
|
||||
|
||||
static void ttlOptsShowInfoPanel(void *a)
|
||||
{
|
||||
ttlOpts->setActive(false);
|
||||
ttlOptsPanel->closePanel();
|
||||
infoPanelString = util::getInfoString(data::curUser, data::curData.saveID);
|
||||
infoPanel->openPanel();
|
||||
}
|
||||
|
||||
static void ttlOptsBlacklistTitle(void *a)
|
||||
{
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(false, ui::confBlacklist.c_str(), title.c_str()))
|
||||
{
|
||||
data::blacklistAdd(data::curData.saveID);
|
||||
ui::setupTiles(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ttlOptsResetSaveData(void *a)
|
||||
{
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(data::holdDel, ui::saveDataReset.c_str(), title.c_str()) && fs::mountSave(data::curData.saveInfo))
|
||||
{
|
||||
fs::delDir("sv:/");
|
||||
fsdevCommitDevice("sv:/");
|
||||
fs::unmountSave();
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::saveDataResetSuccess.c_str(), title.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static void ttlOptsDeleteSaveData(void *a)
|
||||
{
|
||||
FsSaveDataAttribute attr;
|
||||
attr.application_id = data::curData.saveID;
|
||||
attr.uid = data::curUser.getUID();
|
||||
attr.system_save_data_id = 0;
|
||||
attr.save_data_type = data::curData.saveInfo.save_data_type;
|
||||
attr.save_data_rank = data::curData.saveInfo.save_data_rank;
|
||||
attr.save_data_index = data::curData.saveInfo.save_data_index;
|
||||
|
||||
std::string title = data::getTitleNameByTID(data::curData.saveID);
|
||||
if(ui::confirm(data::holdDel, ui::confEraseNand.c_str(), title.c_str()) && R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataAttribute(FsSaveDataSpaceId_User, &attr)))
|
||||
{
|
||||
data::loadUsersTitles(false);
|
||||
if(data::curUser.titleInfo.size() == 0)
|
||||
{
|
||||
//Kick back to user
|
||||
ttlOptsPanel->closePanel();//JIC
|
||||
ui::usrMenuSetActive(true);
|
||||
ui::changeState(USR_SEL);
|
||||
}
|
||||
else if(data::selData > (int)data::curUser.titleInfo.size() - 1)
|
||||
data::selData = data::curUser.titleInfo.size() - 1;
|
||||
|
||||
ui::setupTiles(NULL);
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::saveDataDeleteSuccess.c_str(), title.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static void infoPanelDraw(void *a)
|
||||
{
|
||||
SDL_Texture *panel = (SDL_Texture *)a;
|
||||
gfx::texDraw(panel, data::getTitleIconByTID(data::curData.saveID), 77, 32);
|
||||
gfx::drawTextfWrap(panel, 18, 32, 320, 362, &ui::txtCont, infoPanelString.c_str());
|
||||
}
|
||||
|
||||
void ui::ttlInit()
|
||||
{
|
||||
ttlHelpX = 1220 - gfx::getTextWidth(ui::titleHelp.c_str(), 18);
|
||||
|
||||
ttlOpts = new ui::menu;
|
||||
ttlOpts->setParams(10, 32, 390, 18, 8);
|
||||
|
||||
ttlOptsPanel = new ui::slideOutPanel(410, 720, 0, ttlOptsPanelDraw);
|
||||
ttlOpts->setCallback(ttlOptsCallback, NULL);
|
||||
ui::addPanel(ttlOptsPanel);
|
||||
|
||||
infoPanel = new ui::slideOutPanel(410, 720, 0, infoPanelDraw);
|
||||
ui::addPanel(infoPanel);
|
||||
|
||||
ttlOpts->setActive(false);
|
||||
ttlOpts->addOpt(NULL, ui::titleOptString[0]);
|
||||
ttlOpts->setOptFunc(0, FUNC_A, ttlOptsShowInfoPanel, NULL);
|
||||
ttlOpts->addOpt(NULL, ui::titleOptString[1]);
|
||||
ttlOpts->setOptFunc(1, FUNC_A, ttlOptsBlacklistTitle, NULL);
|
||||
ttlOpts->addOpt(NULL, ui::titleOptString[2]);
|
||||
ttlOpts->setOptFunc(2, FUNC_A, ttlOptsResetSaveData, NULL);
|
||||
ttlOpts->addOpt(NULL, ui::titleOptString[3]);
|
||||
ttlOpts->setOptFunc(3, FUNC_A, ttlOptsDeleteSaveData, NULL);
|
||||
}
|
||||
|
||||
void ui::ttlExit()
|
||||
{
|
||||
delete ttlOptsPanel;
|
||||
delete ttlOpts;
|
||||
delete infoPanel;
|
||||
}
|
||||
|
||||
void ui::setupTiles(void *)
|
||||
{
|
||||
titleList.clear();
|
||||
int infoSize = data::curUser.titleInfo.size();
|
||||
for(int i = 0; i < infoSize; i++)
|
||||
{
|
||||
uint64_t sid = data::curUser.titleInfo[i].saveID;
|
||||
SDL_Texture *iconPtr = data::getTitleIconByTID(sid);
|
||||
bool fav = data::isFavorite(sid);
|
||||
titleList.emplace_back(128, 128, fav, iconPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void ui::ttlReset()
|
||||
{
|
||||
clrShft = 0;
|
||||
clrAdd = true;
|
||||
selRectX = 38;
|
||||
selRectY = 38;
|
||||
x = 34;
|
||||
y = 69;
|
||||
//Reset data
|
||||
data::selData = 0;
|
||||
}
|
||||
|
||||
static inline void updateTitleScroll()
|
||||
{
|
||||
if(selRectY > 264)
|
||||
y -= 48;
|
||||
else if(selRectY > 144)
|
||||
y -= 24;
|
||||
else if(selRectY < -82)
|
||||
y += 48;
|
||||
else if(selRectY < 38)
|
||||
y += 24;
|
||||
}
|
||||
|
||||
void ui::ttlUpdate()
|
||||
{
|
||||
ttlOpts->update();
|
||||
|
||||
if(ttlOptsPanel->isOpen() || infoPanel->isOpen())
|
||||
return;
|
||||
|
||||
uint64_t down = ui::padKeysDown();
|
||||
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(fs::mountSave(data::curData.saveInfo))
|
||||
{
|
||||
fldInit();
|
||||
ui::changeState(FLD_SEL);
|
||||
}
|
||||
else
|
||||
ui::showPopup(POP_FRAME_DEFAULT, "Failed to Mount save!");
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
ui::usrMenuSetActive(true);
|
||||
ui::changeState(USR_SEL);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
ttlOpts->setActive(true);
|
||||
ttlOptsPanel->openPanel();
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
{
|
||||
uint64_t sid = data::curData.saveID;
|
||||
data::favoriteTitle(sid);
|
||||
setupTiles(NULL);
|
||||
if(data::isFavorite(sid))
|
||||
data::selData = data::getTitleIndexInUser(data::curUser, sid);
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLUp:
|
||||
case HidNpadButton_Up:
|
||||
data::selData -= 7;
|
||||
if(data::selData < 0)
|
||||
data::selData = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLDown:
|
||||
case HidNpadButton_Down:
|
||||
data::selData += 7;
|
||||
if(data::selData > (int)data::curUser.titleInfo.size() - 1)
|
||||
data::selData = data::curUser.titleInfo.size() - 1;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLLeft:
|
||||
case HidNpadButton_Left:
|
||||
if(data::selData > 0)
|
||||
--data::selData;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLRight:
|
||||
case HidNpadButton_Right:
|
||||
if(data::selData < (int)data::curUser.titleInfo.size() - 1)
|
||||
++data::selData;
|
||||
break;
|
||||
|
||||
case HidNpadButton_L:
|
||||
if(data::selData - 21 > 0)
|
||||
data::selData -= 21;
|
||||
else
|
||||
data::selData = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
if(data::selData + 21 < (int)data::curUser.titleInfo.size())
|
||||
data::selData += 21;
|
||||
else
|
||||
data::selData = data::curUser.titleInfo.size() - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::ttlDraw(SDL_Texture *target)
|
||||
{
|
||||
updateTitleScroll();
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrShft += 6;
|
||||
if(clrShft >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrShft -= 3;
|
||||
if(clrShft <= 0)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
int totalTiles = titleList.size();
|
||||
int selX = 0, selY = 0;
|
||||
for(int tY = y, i = 0; i < totalTiles; tY += 144)
|
||||
{
|
||||
int endRow = i + 7;
|
||||
for(int tX = x; i < endRow; tX += 144, i++)
|
||||
{
|
||||
if(i >= totalTiles)
|
||||
break;
|
||||
|
||||
if(i == data::selData && (ui::mstate == TTL_SEL|| ui::mstate == FLD_SEL))
|
||||
{
|
||||
//save x and y for selected for later so it's drawn on top.
|
||||
//I can't find anyway to change the Z for SDL.
|
||||
selX = tX;
|
||||
selY = tY;
|
||||
selRectX = tX - 24;
|
||||
selRectY = tY - 24;
|
||||
}
|
||||
else
|
||||
titleList[i].draw(target, tX, tY, false);
|
||||
}
|
||||
}
|
||||
|
||||
if(ui::mstate == TTL_SEL || ui::mstate == FLD_SEL)
|
||||
{
|
||||
//Draw selected after so it's on top
|
||||
ui::drawBoundBox(target, selRectX, selRectY, 176, 176, clrShft);
|
||||
titleList[data::selData].draw(target, selX, selY, true);
|
||||
if(ui::mstate == TTL_SEL)
|
||||
gfx::drawTextf(NULL, 18, ttlHelpX, 673, &ui::txtCont, ui::titleHelp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//Todo make less hardcoded
|
||||
void titleTile::draw(SDL_Texture *target, int x, int y, bool sel)
|
||||
{
|
||||
if(sel)
|
||||
{
|
||||
unsigned xScale = w * 1.28, yScale = w * 1.28;
|
||||
if(wS < xScale)
|
||||
wS += 18;
|
||||
if(hS < yScale)
|
||||
hS += 18;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(wS > w)
|
||||
wS -= 18;
|
||||
if(hS > h)
|
||||
hS -= 18;
|
||||
}
|
||||
|
||||
int dX = x - ((wS - w) / 2);
|
||||
int dY = y - ((hS - h) / 2);
|
||||
gfx::texDrawStretch(target, icon, dX, dY, wS, hS);
|
||||
if(fav)
|
||||
gfx::drawTextf(target, 20, dX + 8, dY + 8, &ui::heartColor, "♥");
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "data.h"
|
||||
#include "ui.h"
|
||||
#include "uiupdate.h"
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
//Where to start in titles
|
||||
static int start = 0;
|
||||
|
||||
//Color shift for rect
|
||||
static uint8_t clrShft = 0;
|
||||
//Whether or not we're adding or subtracting from clrShft
|
||||
static bool clrAdd = true;
|
||||
|
||||
//Selected rectangle X and Y.
|
||||
static unsigned selRectX = 66, selRectY = 94;
|
||||
|
||||
static inline void reset()
|
||||
{
|
||||
start = 0;
|
||||
selRectX = 66;
|
||||
selRectY = 94;
|
||||
data::selData = 0;
|
||||
}
|
||||
|
||||
void ui::drawTitleMenu()
|
||||
{
|
||||
if(clrAdd)
|
||||
{
|
||||
clrShft += 6;
|
||||
if(clrShft >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrShft -= 3;
|
||||
if(clrShft <= 0)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
unsigned x = 70, y = 98;
|
||||
|
||||
unsigned endTitle = start + 32;
|
||||
if(start + 32 > (int)data::curUser.titles.size())
|
||||
endTitle = data::curUser.titles.size();
|
||||
|
||||
//draw Rect so it's always behind icons
|
||||
drawBoundBox(selRectX, selRectY, 140, 140, clrShft);
|
||||
|
||||
for(unsigned i = start; i < endTitle; y += 136)
|
||||
{
|
||||
unsigned endRow = i + 8;
|
||||
for(unsigned tX = x; i < endRow; i++, tX += 144)
|
||||
{
|
||||
if(i == endTitle)
|
||||
break;
|
||||
|
||||
if((int)i == data::selData)
|
||||
{
|
||||
selRectX = tX - 6;
|
||||
selRectY = y - 6;
|
||||
|
||||
unsigned titleWidth = gfx::getTextWidth(data::curData.getTitle().c_str(), 18);
|
||||
int rectWidth = titleWidth + 32, rectX = (tX + 64) - (rectWidth / 2);
|
||||
if(rectX < 16)
|
||||
rectX = 16;
|
||||
else if(rectX + rectWidth > 1264)
|
||||
rectX = 1264 - rectWidth;
|
||||
|
||||
ui::drawTextbox(rectX, y - 50, rectWidth, 38);
|
||||
gfx::drawTextf(18, rectX + 16, y - 40, &ui::txtDiag, data::curData.getTitle().c_str());
|
||||
}
|
||||
if(data::curUser.titles[i].getFav())
|
||||
data::curUser.titles[i].drawIconFav(false, tX, y);
|
||||
else
|
||||
data::curUser.titles[i].drawIcon(false, tX, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::updateTitleMenu(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(fs::mountSave(data::curUser, data::curData))
|
||||
{
|
||||
folderMenuPrepare(data::curUser, data::curData);
|
||||
ui::folderMenuInfo = util::getInfoString(data::curUser, data::curData);
|
||||
ui::changeState(FLD_SEL);
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
reset();
|
||||
ui::changeState(USR_SEL);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
data::favoriteTitle(data::curData);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
fs::dumpAllUserSaves(data::curUser);
|
||||
break;
|
||||
|
||||
case HidNpadButton_L:
|
||||
if(--data::selUser < 0)
|
||||
data::selUser = data::users.size() - 1;
|
||||
reset();
|
||||
ui::showPopup(POP_FRAME_DEFAULT, data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
if(++data::selUser == (int)data::users.size())
|
||||
data::selUser = 0;
|
||||
reset();
|
||||
ui::showPopup(POP_FRAME_DEFAULT, data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
if(data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseNand.c_str(), data::curData.getTitle().c_str()))
|
||||
{
|
||||
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, data::curData.getSaveID());
|
||||
data::loadUsersTitles(false);
|
||||
data::selData = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
if(ui::confirm(false, ui::confBlacklist.c_str(), data::curUser.titles[data::selData].getTitle().c_str()))
|
||||
data::blacklistAdd(data::curData);
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLUp:
|
||||
case HidNpadButton_Up:
|
||||
data::selData -= 8;
|
||||
if(data::selData < 0)
|
||||
data::selData = 0;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLDown:
|
||||
case HidNpadButton_Down:
|
||||
data::selData += 8;
|
||||
if(data::selData > (int)data::curUser.titles.size() - 1)
|
||||
data::selData = data::curUser.titles.size() - 1;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLLeft:
|
||||
case HidNpadButton_Left:
|
||||
if(data::selData > 0)
|
||||
--data::selData;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLRight:
|
||||
case HidNpadButton_Right:
|
||||
if(data::selData < (int)data::curUser.titles.size() - 1)
|
||||
++data::selData;
|
||||
break;
|
||||
}
|
||||
|
||||
if(data::selData < start)
|
||||
start -= 8;
|
||||
else if(data::selData - start >= 32)
|
||||
start += 8;
|
||||
}
|
||||
|
||||
474
src/ui/txtui.cpp
474
src/ui/txtui.cpp
@@ -1,474 +0,0 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <switch.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "data.h"
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
static ui::menu userMenu, titleMenu, exMenu, optMenu;
|
||||
extern ui::menu folderMenu;
|
||||
|
||||
void ui::textUserPrep()
|
||||
{
|
||||
userMenu.reset();
|
||||
|
||||
userMenu.setParams(76, 98, 310);
|
||||
|
||||
for(unsigned i = 0; i < data::users.size(); i++)
|
||||
userMenu.addOpt(data::users[i].getUsername());
|
||||
}
|
||||
|
||||
void ui::textTitlePrep(data::user& u)
|
||||
{
|
||||
titleMenu.reset();
|
||||
titleMenu.setParams(76, 98, 310);
|
||||
|
||||
for(unsigned i = 0; i < u.titles.size(); i++)
|
||||
{
|
||||
if(u.titles[i].getFav())
|
||||
titleMenu.addOpt("♥ " + u.titles[i].getTitle());
|
||||
else
|
||||
titleMenu.addOpt(u.titles[i].getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
void ui::textUserMenuUpdate(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
userMenu.handleInput(down, held);
|
||||
|
||||
data::selUser = userMenu.getSelected();
|
||||
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(data::curUser.titles.size() > 0)
|
||||
{
|
||||
ui::textTitlePrep(data::curUser);
|
||||
ui::changeState(TXT_TTL);
|
||||
}
|
||||
else
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::noSavesFound.c_str(), data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
ui::textMode = false;
|
||||
ui::changeState(USR_SEL);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
{
|
||||
bool cont = true;
|
||||
for(unsigned i = 0; i < data::users.size() - 2; i++)
|
||||
{
|
||||
if(cont)
|
||||
cont = fs::dumpAllUserSaves(data::users[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
util::checkForUpdate();
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
ui::changeState(EX_MNU);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
ui::changeState(OPT_MNU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::drawTextUserMenu()
|
||||
{
|
||||
userMenu.draw(&ui::txtCont);
|
||||
}
|
||||
|
||||
void ui::textTitleMenuUpdate(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
titleMenu.handleInput(down, held);
|
||||
|
||||
data::selData = titleMenu.getSelected();
|
||||
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(fs::mountSave(data::curUser, data::curData))
|
||||
{
|
||||
folderMenuPrepare(data::curUser, data::curData);
|
||||
ui::folderMenuInfo = util::getInfoString(data::curUser, data::curData);
|
||||
ui::changeState(TXT_FLD);
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
ui::changeState(TXT_USR);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
data::favoriteTitle(data::curData);
|
||||
textTitlePrep(data::curUser);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
fs::dumpAllUserSaves(data::curUser);
|
||||
break;
|
||||
|
||||
case HidNpadButton_L:
|
||||
if(--data::selUser < 0)
|
||||
data::selUser = data::users.size() - 1;
|
||||
ui::textTitlePrep(data::curUser);
|
||||
ui::showPopup(POP_FRAME_DEFAULT, data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
if(++data::selUser == (int)data::users.size())
|
||||
data::selUser = 0;
|
||||
ui::textTitlePrep(data::curUser);
|
||||
ui::showPopup(POP_FRAME_DEFAULT, data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
if(data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseNand.c_str(), data::curData.getTitle().c_str()))
|
||||
{
|
||||
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, data::curData.getSaveID());
|
||||
data::loadUsersTitles(false);
|
||||
data::selData = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
if(ui::confirm(false, ui::confBlacklist.c_str(), data::curUser.titles[data::selData].getTitle().c_str()))
|
||||
data::blacklistAdd(data::curData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::drawTextTitleMenu()
|
||||
{
|
||||
titleMenu.draw(&ui::txtCont);
|
||||
}
|
||||
|
||||
void ui::textFolderMenuUpdate(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
folderMenu.handleInput(down, held);
|
||||
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(folderMenu.getSelected() == 0)
|
||||
ui::createNewBackup(held);
|
||||
else
|
||||
ui::overwriteBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_B:
|
||||
fs::unmountSave();
|
||||
fs::freePathFilters();
|
||||
ui::changeState(TXT_TTL);
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
if(folderMenu.getSelected() > 0)
|
||||
ui::deleteBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
if(folderMenu.getSelected() > 0)
|
||||
ui::restoreBackup(folderMenu.getSelected() - 1);
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
if(data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
|
||||
{
|
||||
fs::delDir("sv:/");
|
||||
fsdevCommitDevice("sv");
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
advModePrep("sv:/", data::curData.getType(), true);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::drawTextFolderMenu()
|
||||
{
|
||||
titleMenu.draw(&ui::txtCont);
|
||||
folderMenu.draw(&ui::txtCont);
|
||||
}
|
||||
|
||||
void ui::exMenuPrep()
|
||||
{
|
||||
exMenu.reset();
|
||||
exMenu.setParams(76, 98, 310);
|
||||
for(unsigned i = 0; i < 11; i++)
|
||||
exMenu.addOpt(ui::exMenuStr[i]);
|
||||
}
|
||||
|
||||
void ui::updateExMenu(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
exMenu.handleInput(down, held);
|
||||
|
||||
if(down & HidNpadButton_A)
|
||||
{
|
||||
fsdevUnmountDevice("sv");
|
||||
FsFileSystem sv;
|
||||
data::curData.setType(FsSaveDataType_System);
|
||||
switch(exMenu.getSelected())
|
||||
{
|
||||
case 0:
|
||||
data::curData.setType(FsSaveDataType_Bcat);
|
||||
advModePrep("sdmc:/", data::curData.getType(), false);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fsdevUnmountDevice("sv");
|
||||
fsOpenBisFileSystem(&sv, FsBisPartitionId_CalibrationFile, "");
|
||||
fsdevMountDevice("prodInfo-f", sv);
|
||||
advModePrep("profInfo-f:/", FsSaveDataType_System, false);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fsOpenBisFileSystem(&sv, FsBisPartitionId_SafeMode, "");
|
||||
fsdevMountDevice("safe", sv);
|
||||
advModePrep("safe:/", FsSaveDataType_System, false);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fsOpenBisFileSystem(&sv, FsBisPartitionId_System, "");
|
||||
fsdevMountDevice("sys", sv);
|
||||
advModePrep("sys:/", FsSaveDataType_System, false);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
fsOpenBisFileSystem(&sv, FsBisPartitionId_User, "");
|
||||
fsdevMountDevice("user", sv);
|
||||
advModePrep("user:/", FsSaveDataType_System, false);
|
||||
ui::changeState(ADV_MDE);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
{
|
||||
fsOpenBisFileSystem(&sv, FsBisPartitionId_System, "");
|
||||
fsdevMountDevice("sv", sv);
|
||||
std::string delPath = "sv:/Contents/placehld/";
|
||||
|
||||
fs::dirList plcHld(delPath);
|
||||
for(unsigned i = 0; i < plcHld.getCount(); i++)
|
||||
{
|
||||
std::string fullPath = delPath + plcHld.getItem(i);
|
||||
std::remove(fullPath.c_str());
|
||||
}
|
||||
fsdevUnmountDevice("sv");
|
||||
|
||||
if(ui::confirm(false, "Restart?"))
|
||||
{
|
||||
bpcInitialize();
|
||||
bpcRebootSystem();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
{
|
||||
std::string idStr = util::getStringInput("0100000000000000", "Enter Process ID", 18, 0, NULL);
|
||||
if(!idStr.empty())
|
||||
{
|
||||
uint64_t termID = std::strtoull(idStr.c_str(), NULL, 16);
|
||||
if(R_SUCCEEDED(pmshellTerminateProgram(termID)))
|
||||
ui::showMessage("Success!", "Process %s successfully shutdown.", idStr.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
{
|
||||
std::string idStr = util::getStringInput("8000000000000000", "Enter Sys Save ID", 18, 0, NULL);
|
||||
uint64_t mountID = std::strtoull(idStr.c_str(), NULL, 16);
|
||||
if(R_SUCCEEDED(fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, mountID, (AccountUid) {0})))
|
||||
{
|
||||
fsdevMountDevice("sv", sv);
|
||||
advModePrep("sv:/", data::curData.getType(), true);
|
||||
ui::changeState(ADV_MDE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
data::loadUsersTitles(true);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
{
|
||||
FsFileSystem tromfs;
|
||||
//Result res = romfsMountFromCurrentProcess("tromfs"); << Works too, but is kinda weird
|
||||
if(R_SUCCEEDED(fsOpenDataFileSystemByCurrentProcess(&tromfs)))
|
||||
{
|
||||
fsdevMountDevice("tromfs", tromfs);
|
||||
advModePrep("tromfs:/", FsSaveDataType_Account, false);
|
||||
ui::changeState(ADV_MDE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
{
|
||||
fs::logClose();
|
||||
remove(std::string(fs::getWorkDir() + "log.txt").c_str());
|
||||
std::string zipName = "JKSV - " + util::getDateTime(util::DATE_FMT_ASC) + ".zip";
|
||||
zipFile jksv = zipOpen(std::string("sdmc:/" + zipName).c_str(), 0);
|
||||
fs::copyDirToZip(fs::getWorkDir(), &jksv);
|
||||
zipClose(jksv, NULL);
|
||||
rename(std::string("sdmc:/" + zipName).c_str(), std::string(fs::getWorkDir() + zipName).c_str());
|
||||
fs::logOpen();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(down & HidNpadButton_B)
|
||||
{
|
||||
fsdevUnmountDevice("sv");
|
||||
ui::changeState(ui::textMode ? TXT_USR : USR_SEL);
|
||||
prevState = USR_SEL;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::drawExMenu()
|
||||
{
|
||||
exMenu.draw(&ui::txtCont);
|
||||
}
|
||||
|
||||
static inline void switchBool(bool& sw)
|
||||
{
|
||||
sw ? sw = false : sw = true;
|
||||
}
|
||||
|
||||
static inline std::string getBoolText(bool b)
|
||||
{
|
||||
return b ? ui::on : ui::off;
|
||||
}
|
||||
|
||||
static inline void changeSort()
|
||||
{
|
||||
if(++data::sortType > 2)
|
||||
data::sortType = 0;
|
||||
}
|
||||
|
||||
void ui::optMenuInit()
|
||||
{
|
||||
optMenu.setParams(76, 98, 310);
|
||||
for(unsigned i = 0; i < 15; i++)
|
||||
optMenu.addOpt(ui::optMenuStr[i]);
|
||||
}
|
||||
|
||||
void ui::updateOptMenu(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
optMenu.handleInput(down, held);
|
||||
|
||||
//Update Menu Options to reflect changes
|
||||
optMenu.editOpt(0, optMenuStr[0] + getBoolText(data::incDev));
|
||||
optMenu.editOpt(1, optMenuStr[1] + getBoolText(data::autoBack));
|
||||
optMenu.editOpt(2, optMenuStr[2] + getBoolText(data::ovrClk));
|
||||
optMenu.editOpt(3, optMenuStr[3] + getBoolText(data::holdDel));
|
||||
optMenu.editOpt(4, optMenuStr[4] + getBoolText(data::holdRest));
|
||||
optMenu.editOpt(5, optMenuStr[5] + getBoolText(data::holdOver));
|
||||
optMenu.editOpt(6, optMenuStr[6] + getBoolText(data::forceMount));
|
||||
optMenu.editOpt(7, optMenuStr[7] + getBoolText(data::accSysSave));
|
||||
optMenu.editOpt(8, optMenuStr[8] + getBoolText(data::sysSaveWrite));
|
||||
optMenu.editOpt(9, optMenuStr[9] + getBoolText(ui::textMode));
|
||||
optMenu.editOpt(10, optMenuStr[10] + getBoolText(data::directFsCmd));
|
||||
optMenu.editOpt(11, optMenuStr[11] + getBoolText(data::skipUser));
|
||||
optMenu.editOpt(12, optMenuStr[12] + getBoolText(data::zip));
|
||||
optMenu.editOpt(13, optMenuStr[13] + ui::sortString[data::sortType]);
|
||||
optMenu.editOpt(14, optMenuStr[14] + getBoolText(data::langOverride));
|
||||
|
||||
|
||||
if(down & HidNpadButton_A)
|
||||
{
|
||||
switch(optMenu.getSelected())
|
||||
{
|
||||
case 0:
|
||||
switchBool(data::incDev);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
switchBool(data::autoBack);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switchBool(data::ovrClk);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
switchBool(data::holdDel);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
switchBool(data::holdRest);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
switchBool(data::holdOver);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
switchBool(data::forceMount);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
switchBool(data::accSysSave);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
switchBool(data::sysSaveWrite);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
switchBool(ui::textMode);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
switchBool(data::directFsCmd);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
switchBool(data::skipUser);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
switchBool(data::zip);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
changeSort();
|
||||
data::loadUsersTitles(false);
|
||||
break;
|
||||
|
||||
case 14:
|
||||
switchBool(data::langOverride);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(down & HidNpadButton_X)
|
||||
data::restoreDefaultConfig();
|
||||
else if(down & HidNpadButton_B)
|
||||
ui::changeState(ui::textMode ? TXT_USR : USR_SEL);
|
||||
}
|
||||
|
||||
void ui::drawOptMenu()
|
||||
{
|
||||
optMenu.draw(&ui::txtCont);
|
||||
gfx::drawTextfWrap(18, 466, 98, 730, &ui::txtCont, ui::optMenuExp[optMenu.getSelected()].c_str());
|
||||
}
|
||||
|
||||
254
src/ui/uistr.cpp
254
src/ui/uistr.cpp
@@ -1,17 +1,24 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "file.h"
|
||||
#include "uistr.h"
|
||||
|
||||
//8
|
||||
const std::string ui::loadGlyphArray[8] =
|
||||
//Map to associate external string names to unsigned ints for switch case.
|
||||
static std::unordered_map<std::string, unsigned> uistrdef =
|
||||
{
|
||||
"\ue020", "\ue021", "\ue022", "\ue023",
|
||||
"\ue024", "\ue025", "\ue026", "\ue027"
|
||||
{"author", 0}, {"userHelp", 1}, {"titleHelp", 2}, {"folderHelp", 3}, {"optHelp", 4},
|
||||
{"yt", 5}, {"nt", 6}, {"on", 7}, {"off", 8}, {"confirmBlacklist", 9}, {"confirmOverwrite", 10},
|
||||
{"confirmRestore", 11}, {"confirmDelete", 12}, {"confirmCopy", 13}, {"confirmEraseNand", 14},
|
||||
{"confirmReset", 15}, {"confirmHead", 16}, {"copyHead", 17}, {"noSavesFound", 18},
|
||||
{"advMenu", 19}, {"extMenu", 20}, {"optMenu", 21}, {"optMenuExp", 22}, {"holdingText", 23},
|
||||
{"errorConnecting", 24}, {"noUpdate", 25}, {"sortType", 26}, {"saveCreated", 27}, {"saveCreateFailed", 28},
|
||||
{"saveDataResetSuccess", 29}, {"saveDataDeleteSuccess", 30}
|
||||
};
|
||||
|
||||
std::string ui::author = "NULL";
|
||||
std::string ui::userHelp = "[A] Select [Y] Dump All [X] UI Mode [R] Update [-] Options [ZR] Extras";
|
||||
std::string ui::titleHelp = "[A] Select [L][R] Change User [Y] Dump All [X] Favorite [-] BlackList [ZR] Erase [B] Back";
|
||||
std::string ui::userHelp = "[A] Select [X] User Options";
|
||||
std::string ui::titleHelp = "[A] Select [L][R] Jump [Y] Favorite [X] Title Options [B] Back";
|
||||
std::string ui::folderHelp = "[-] File Mode [L]/[R]+[A] Auto [A] Backup [Y] Restore [X] Delete Selected [ZR] Erase [B] Back";
|
||||
std::string ui::optHelp = "[A] Toggle [X] Defaults [B] Back";
|
||||
std::string ui::yt = "Yes [A]", ui::nt = "No [B]";
|
||||
@@ -24,68 +31,183 @@ std::string ui::confCopy = "Are you sure you want to copy #%s# to #%s#?";
|
||||
std::string ui::confirmHead = "Confirm";
|
||||
std::string ui::copyHead = "Copying File...";
|
||||
std::string ui::confEraseNand = "*WARNING*: This *will* erase the save data for #%s# *from your system*. This is the same as deleting it from #Data Management#! Are you sure you want to continue?";
|
||||
std::string ui::confEraseFolder = "*WARNING*: This *will* delete the current save data for #%s# *from your system*! Are you sure you want to continue?";
|
||||
std::string ui::noSavesFound = "No saves found for #%s#!";
|
||||
std::string ui::saveCreated = "Save data created for %s!";
|
||||
std::string ui::saveCreateFailed = "Save data creation failed!";
|
||||
std::string ui::saveDataReset = "Are you sure want to reset your current save data for %s?";
|
||||
std::string ui::saveDataResetSuccess = "Save for %s reset!";
|
||||
std::string ui::saveDataDeleteSuccess = "Save data for %s deleted!";
|
||||
std::string ui::errorConnecting = "Error Connecting!";
|
||||
std::string ui::noUpdate = "No updates available!";
|
||||
std::string ui::advMenuStr[6] =
|
||||
{
|
||||
"Copy to ",
|
||||
"Delete",
|
||||
"Rename",
|
||||
"Make Dir",
|
||||
"Properties",
|
||||
"Close"
|
||||
};
|
||||
std::string ui::exMenuStr[11] =
|
||||
{
|
||||
"SD to SD Browser",
|
||||
"BIS: PRODINFOF",
|
||||
"BIS: SAFE",
|
||||
"BIS: SYSTEM",
|
||||
"BIS: USER",
|
||||
"Remove Update",
|
||||
"Terminate Process",
|
||||
"Mount System Save",
|
||||
"Rescan Titles",
|
||||
"Mount Process RomFS",
|
||||
"Backup JKSV Folder"
|
||||
};
|
||||
std::string ui::optMenuStr[15] =
|
||||
{
|
||||
"Include Dev Sv: ",
|
||||
"AutoBackup: ",
|
||||
"Overclock: ",
|
||||
"Hold to Delete: ",
|
||||
"Hold to Restore: ",
|
||||
"Hold to Overwrite: ",
|
||||
"Force Mount: ",
|
||||
"Account Sys. Saves: ",
|
||||
"Write to Sys. Saves: ",
|
||||
"Text UI Mode: ",
|
||||
"Direct FS Cmd: ",
|
||||
"Skip User Select: ",
|
||||
"Export to ZIP: ",
|
||||
"Sort: ",
|
||||
"Language Override: "
|
||||
};
|
||||
std::string ui::optMenuExp[15] =
|
||||
{
|
||||
"Includes Device Save data in user accounts.",
|
||||
"Automatically creates a save backup before restoring a save.",
|
||||
"Applies a small CPU over clock to 1224Mhz at boot. This is the same speed developer units run at.",
|
||||
"Whether or not holding [A] is required when deleting folders and files.",
|
||||
"Whether or not holding [A] is required when restoring save data.",
|
||||
"Whether or not holding [A] is required when overwriting saves on SD.",
|
||||
"When enabled, JKSV will only load and show save data that can be opened. When disabled, everything found will be shown.",
|
||||
"When enabled, system save data tied to accounts will be shown.",
|
||||
"Controls whether system save data and partitions can have files and data written and deleted from them. *This can be extremely dangerous if you don't know what you're doing!*",
|
||||
"Changes the UI to be text menu based like the original JKSM for 3DS.",
|
||||
"Directly uses the Switch's FS commands to copy files instead of stdio.",
|
||||
"Skips the user selection screen and jumps directly to the first user account found.",
|
||||
"Exports saves to ZIP files.",
|
||||
"Changes the way titles are sorted and listed.",
|
||||
"Forces English to be used regardless of system language."
|
||||
};
|
||||
std::string ui::advMenuStr[6] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close" };
|
||||
std::string ui::exMenuStr[11] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS", "Backup JKSV Folder" };
|
||||
std::string ui::optMenuStr[15] = { "Include Device Saves: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Text UI Mode: ", "Direct FS Cmd: ", "Skip User Select: ", "Export to ZIP: ", "Language Override: ", "Sort: "};
|
||||
std::string ui::holdingText[3] = { "(Hold) ", "(Keep Holding) ", "(Almost there!) " };
|
||||
std::string ui::sortString[3] = { "Alphabetical", "Time Played", "Last Played" };
|
||||
std::string ui::usrOptString[1] = { "Create Save Data" };
|
||||
std::string ui::titleOptString[4] = {"Information", "Blacklist", "Reset Save Data", "Delete Save Filesystem"};
|
||||
|
||||
void ui::loadTrans()
|
||||
{
|
||||
bool transFile = fs::fileExists(fs::getWorkDir() + "trans.txt");
|
||||
if(!transFile && data::sysLang == SetLanguage_ENUS)
|
||||
return;//Don't bother loading from file. It serves as a translation guide
|
||||
|
||||
std::string file;
|
||||
if(transFile)
|
||||
file = fs::getWorkDir() + "trans.txt";
|
||||
else
|
||||
{
|
||||
file = "romfs:/lang/";
|
||||
switch(data::sysLang)
|
||||
{
|
||||
case SetLanguage_ZHCN:
|
||||
case SetLanguage_ZHHANS:
|
||||
file += "zh-CN.txt";
|
||||
break;
|
||||
|
||||
case SetLanguage_ZHTW:
|
||||
case SetLanguage_ZHHANT:
|
||||
file += "zh-TW.txt";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fs::dataFile lang(file);
|
||||
while(lang.readNextLine(true))
|
||||
{
|
||||
switch(uistrdef[lang.getName()])
|
||||
{
|
||||
case 0:
|
||||
ui::author = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ui::userHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ui::titleHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ui::folderHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ui::optHelp = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ui::yt = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ui::nt = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
ui::on = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ui::off = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ui::confBlacklist = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 10:
|
||||
ui::confOverwrite = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 11:
|
||||
ui::confRestore = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ui::confDel = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 13:
|
||||
ui::confCopy = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 14:
|
||||
ui::confEraseNand = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ui::saveDataReset = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ui::confirmHead = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 17:
|
||||
ui::copyHead = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 18:
|
||||
ui::noSavesFound = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 19:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::advMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 20:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::exMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 21:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::optMenuStr[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 22:
|
||||
break;
|
||||
|
||||
case 23:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::holdingText[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
case 24:
|
||||
ui::errorConnecting = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 25:
|
||||
ui::noUpdate = lang.getNextValueStr();
|
||||
break;
|
||||
|
||||
case 26:
|
||||
{
|
||||
int ind = lang.getNextValueInt();
|
||||
ui::sortString[ind] = lang.getNextValueStr();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ui::showMessage("*Translation File Error:*", "On Line: %s\n*%s* is not a known or valid string name.", lang.getLine(), lang.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
237
src/ui/usr.cpp
Normal file
237
src/ui/usr.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <switch.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "data.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "type.h"
|
||||
|
||||
#include "usr.h"
|
||||
#include "ttl.h"
|
||||
|
||||
//Main menu/Users + options, folder
|
||||
static ui::menu *usrMenu, *usrOptMenu, *saveCreateMenu;
|
||||
static ui::slideOutPanel *usrOptPanel, *saveCreatePanel;
|
||||
|
||||
//This stores save ids to match with saveCreateMenu
|
||||
//Probably needs/should be changed
|
||||
static std::vector<uint64_t> sids;
|
||||
|
||||
static unsigned optsPos = 0, extPos = 0, usrHelpX = 0;
|
||||
|
||||
fs::backupArgs backargs;
|
||||
|
||||
static void onMainChange(void *a)
|
||||
{
|
||||
if(usrMenu->getSelected() < (int)data::users.size())
|
||||
{
|
||||
data::selUser = usrMenu->getSelected();
|
||||
ui::ttlReset();
|
||||
ui::setupTiles(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void toOPT(void *a)
|
||||
{
|
||||
ui::changeState(OPT_MNU);
|
||||
ui::usrMenuSetActive(false);
|
||||
}
|
||||
|
||||
static void toEXT(void *a)
|
||||
{
|
||||
ui::changeState(EX_MNU);
|
||||
ui::usrMenuSetActive(false);
|
||||
}
|
||||
|
||||
static void toMAIN(void *a)
|
||||
{
|
||||
if(ui::padKeysDown() & HidNpadButton_B)
|
||||
{
|
||||
ui::changeState(USR_SEL);
|
||||
ui::usrMenuSetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void usrOptCallback(void *a)
|
||||
{
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_B:
|
||||
usrOptPanel->closePanel();
|
||||
usrMenu->setActive(true);
|
||||
usrOptMenu->setActive(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void saveCreateCallback(void *a)
|
||||
{
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_B:
|
||||
usrOptMenu->setActive(true);
|
||||
saveCreateMenu->setActive(false);
|
||||
saveCreatePanel->closePanel();
|
||||
usrOptPanel->openPanel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usrOptSaveCreate(void *a)
|
||||
{
|
||||
ui::updateInput();
|
||||
usrOptMenu->setActive(false);
|
||||
saveCreateMenu->setActive(true);
|
||||
usrOptPanel->closePanel();
|
||||
saveCreatePanel->openPanel();
|
||||
}
|
||||
|
||||
static void usrOptPanelDraw(void *a)
|
||||
{
|
||||
SDL_Texture *panel = (SDL_Texture *)a;
|
||||
usrOptMenu->draw(panel, &ui::txtCont, true);
|
||||
}
|
||||
|
||||
static void saveCreatePanelDraw(void *a)
|
||||
{
|
||||
SDL_Texture *panel = (SDL_Texture *)a;
|
||||
saveCreateMenu->draw(panel, &ui::txtCont, true);
|
||||
}
|
||||
|
||||
static void createSaveData(void *a)
|
||||
{
|
||||
ui::menu *in = (ui::menu *)a;
|
||||
uint64_t sid = sids[in->getSelected()];
|
||||
data::titleInfo *create = data::getTitleInfoByTID(sid);
|
||||
|
||||
FsSaveDataAttribute attr;
|
||||
memset(&attr, 0, sizeof(FsSaveDataAttribute));
|
||||
attr.application_id = sid;
|
||||
attr.uid = data::curUser.getUID();
|
||||
attr.system_save_data_id = 0;
|
||||
attr.save_data_type = FsSaveDataType_Account;
|
||||
attr.save_data_rank = 0;
|
||||
attr.save_data_index = 0;
|
||||
|
||||
FsSaveDataCreationInfo svCreate;
|
||||
memset(&svCreate, 0, sizeof(FsSaveDataCreationInfo));
|
||||
svCreate.save_data_size = create->nacp.user_account_save_data_size;
|
||||
svCreate.journal_size = create->nacp.user_account_save_data_journal_size;
|
||||
svCreate.available_size = create->nacp.user_account_save_data_size;
|
||||
svCreate.owner_id = create->nacp.save_data_owner_id;
|
||||
svCreate.flags = 0;
|
||||
svCreate.save_data_space_id = FsSaveDataSpaceId_User;
|
||||
|
||||
FsSaveDataMetaInfo meta;
|
||||
memset(&meta, 0, sizeof(FsSaveDataMetaInfo));
|
||||
meta.size = 0x40060;
|
||||
meta.type = FsSaveDataMetaType_Thumbnail;
|
||||
|
||||
Result res = 0;
|
||||
if(R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &svCreate, &meta)))
|
||||
{
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::saveCreated.c_str(), create->title.c_str());
|
||||
data::loadUsersTitles(false);
|
||||
ui::setupTiles(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::saveCreateFailed.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ui::usrInit()
|
||||
{
|
||||
usrMenu = new ui::menu;
|
||||
usrOptMenu = new ui::menu;
|
||||
saveCreateMenu = new ui::menu;
|
||||
|
||||
usrMenu->setParams(64, 16, 0, 96, 4);
|
||||
usrOptMenu->setParams(8, 32, 390, 18, 8);
|
||||
usrOptMenu->setCallback(usrOptCallback, NULL);
|
||||
|
||||
saveCreateMenu->setParams(8, 32, 390, 18, 8);
|
||||
saveCreateMenu->setCallback(saveCreateCallback, NULL);
|
||||
|
||||
for(data::user u : data::users)
|
||||
{
|
||||
usrMenu->addOpt(u.getUserIcon(), u.getUsername());
|
||||
unsigned ind = usrMenu->getOptPos(u.getUsername());
|
||||
usrMenu->setOptFunc(ind, FUNC_A, toTTL, NULL);
|
||||
}
|
||||
|
||||
usrMenu->addOpt(NULL, "Settings");
|
||||
optsPos = usrMenu->getOptPos("Settings");
|
||||
usrMenu->setOptFunc(optsPos, FUNC_A, toOPT, NULL);
|
||||
|
||||
usrMenu->addOpt(NULL, "Extras");
|
||||
extPos = usrMenu->getOptPos("Extras");
|
||||
usrMenu->setOptFunc(extPos, FUNC_A, toEXT, NULL);
|
||||
|
||||
usrMenu->setOnChangeFunc(onMainChange);
|
||||
|
||||
usrMenu->editParam(MENU_RECT_WIDTH, 126);
|
||||
|
||||
usrOptPanel = new ui::slideOutPanel(410, 720, 0, usrOptPanelDraw);
|
||||
ui::addPanel(usrOptPanel);
|
||||
usrOptMenu->addOpt(NULL, ui::usrOptString[0]);
|
||||
usrOptMenu->setOptFunc(0, FUNC_A, usrOptSaveCreate, NULL);
|
||||
usrOptMenu->setActive(false);
|
||||
|
||||
saveCreatePanel = new ui::slideOutPanel(410, 720, 0, saveCreatePanelDraw);
|
||||
saveCreateMenu->setActive(false);
|
||||
ui::addPanel(saveCreatePanel);
|
||||
unsigned i = 0;
|
||||
for(auto& t : data::titles)
|
||||
{
|
||||
saveCreateMenu->addOpt(NULL, t.second.title);
|
||||
saveCreateMenu->setOptFunc(i++, FUNC_A, createSaveData, saveCreateMenu);
|
||||
sids.push_back(t.first);
|
||||
}
|
||||
|
||||
setupTiles(NULL);
|
||||
|
||||
usrHelpX = 1220 - gfx::getTextWidth(ui::userHelp.c_str(), 18);
|
||||
}
|
||||
|
||||
void ui::usrExit()
|
||||
{
|
||||
delete usrOptPanel;
|
||||
delete saveCreatePanel;
|
||||
delete usrMenu;
|
||||
delete usrOptMenu;
|
||||
delete saveCreateMenu;
|
||||
}
|
||||
|
||||
void ui::usrMenuSetActive(bool _set)
|
||||
{
|
||||
usrMenu->setActive(_set);
|
||||
}
|
||||
|
||||
void ui::usrUpdate()
|
||||
{
|
||||
usrMenu->update();
|
||||
usrOptMenu->update();
|
||||
saveCreateMenu->update();
|
||||
|
||||
if(!usrOptMenu->getActive() && !saveCreateMenu->getActive())
|
||||
{
|
||||
switch(ui::padKeysDown())
|
||||
{
|
||||
case HidNpadButton_X:
|
||||
usrOptMenu->setActive(true);
|
||||
usrMenu->setActive(false);
|
||||
usrOptPanel->openPanel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::usrDraw(SDL_Texture *target)
|
||||
{
|
||||
usrMenu->draw(target, &ui::txtCont, false);
|
||||
if(ui::mstate == USR_SEL)
|
||||
gfx::drawTextf(NULL, 18, usrHelpX, 673, &ui::txtCont, ui::userHelp.c_str());
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <switch.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "ui.h"
|
||||
#include "uiupdate.h"
|
||||
#include "file.h"
|
||||
#include "util.h"
|
||||
|
||||
void ui::drawUserMenu()
|
||||
{
|
||||
//Static so they don't get reset every loop
|
||||
static int start = 0;
|
||||
|
||||
static uint8_t clrShft = 0;
|
||||
static bool clrAdd = true;
|
||||
|
||||
static unsigned selRectX = 276, selRectY = 160;
|
||||
|
||||
if(clrAdd)
|
||||
{
|
||||
clrShft += 6;
|
||||
if(clrShft >= 0x72)
|
||||
clrAdd = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
clrShft -= 3;
|
||||
if(clrShft <= 0)
|
||||
clrAdd = true;
|
||||
}
|
||||
|
||||
unsigned x = 280, y = 164;
|
||||
unsigned endUser = data::users.size();
|
||||
|
||||
drawBoundBox(selRectX, selRectY, 140, 140, clrShft);
|
||||
|
||||
for(unsigned i = start; i < endUser; y += 136)
|
||||
{
|
||||
unsigned endRow = i + 5;
|
||||
for(unsigned tX = x; i < endRow; i++, tX += 144)
|
||||
{
|
||||
if(i == endUser)
|
||||
break;
|
||||
|
||||
if((int)i == data::selUser)
|
||||
{
|
||||
selRectX = tX - 6;
|
||||
selRectY = y - 6;
|
||||
|
||||
unsigned userWidth = gfx::getTextWidth(data::curUser.getUsername().c_str(), 18);
|
||||
int userRectWidth = userWidth + 32, userRectX = (tX + 64) - (userRectWidth / 2);
|
||||
if(userRectX < 16)
|
||||
userRectX = 16;
|
||||
else if(userRectX + userRectWidth > 1264)
|
||||
userRectX = 1264 - userRectWidth;
|
||||
|
||||
drawTextbox(userRectX, y - 50, userRectWidth, 38);
|
||||
gfx::drawTextf(18, userRectX + 16, y - 40, &ui::txtDiag, data::curUser.getUsername().c_str());
|
||||
}
|
||||
data::users[i].drawIconHalf(tX, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui::updateUserMenu(const uint64_t& down, const uint64_t& held)
|
||||
{
|
||||
switch(down)
|
||||
{
|
||||
case HidNpadButton_A:
|
||||
if(data::curUser.titles.size() > 0)
|
||||
ui::changeState(TTL_SEL);
|
||||
else
|
||||
ui::showPopup(POP_FRAME_DEFAULT, ui::noSavesFound.c_str(), data::curUser.getUsername().c_str());
|
||||
break;
|
||||
|
||||
case HidNpadButton_X:
|
||||
ui::textMode = true;
|
||||
ui::changeState(TXT_USR);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Y:
|
||||
{
|
||||
bool cont = true;
|
||||
for(unsigned i = 0; i < data::users.size() - 2; i++)
|
||||
{
|
||||
if(cont)
|
||||
cont = fs::dumpAllUserSaves(data::users[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HidNpadButton_R:
|
||||
util::checkForUpdate();
|
||||
break;
|
||||
|
||||
case HidNpadButton_ZR:
|
||||
ui::changeState(EX_MNU);
|
||||
break;
|
||||
|
||||
case HidNpadButton_Minus:
|
||||
ui::changeState(OPT_MNU);
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLUp:
|
||||
case HidNpadButton_Up:
|
||||
data::selUser - 5 < 0 ? data::selUser = 0 : data::selUser -= 5;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLDown:
|
||||
case HidNpadButton_Down:
|
||||
data::selUser + 5 > (int)data::users.size() - 1 ? data::selUser = data::users.size() - 1 : data::selUser += 5;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLLeft:
|
||||
case HidNpadButton_Left:
|
||||
if(data::selUser > 0)
|
||||
--data::selUser;
|
||||
break;
|
||||
|
||||
case HidNpadButton_StickLRight:
|
||||
case HidNpadButton_Right:
|
||||
if(data::selUser < (int)data::users.size() - 1)
|
||||
++data::selUser;
|
||||
break;
|
||||
}
|
||||
}
|
||||
54
src/util.cpp
54
src/util.cpp
@@ -4,10 +4,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <json-c/json.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "data.h"
|
||||
#include "gfx.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
#include "ui.h"
|
||||
#include "curlfuncs.h"
|
||||
|
||||
@@ -133,17 +133,15 @@ std::string util::getDateTime(int fmt)
|
||||
void util::copyDirListToMenu(const fs::dirList& d, ui::menu& m)
|
||||
{
|
||||
m.reset();
|
||||
m.addOpt(".");
|
||||
m.addOpt("..");
|
||||
m.addOpt(NULL, ".");
|
||||
m.addOpt(NULL, "..");
|
||||
for(unsigned i = 0; i < d.getCount(); i++)
|
||||
{
|
||||
if(d.isDir(i))
|
||||
m.addOpt("D " + d.getItem(i));
|
||||
m.addOpt(NULL, "D " + d.getItem(i));
|
||||
else
|
||||
m.addOpt("F " + d.getItem(i));
|
||||
m.addOpt(NULL, "F " + d.getItem(i));
|
||||
}
|
||||
|
||||
m.adjust();
|
||||
}
|
||||
|
||||
void util::removeLastFolderFromString(std::string& _path)
|
||||
@@ -173,7 +171,7 @@ std::string util::safeString(const std::string& s)
|
||||
}
|
||||
|
||||
//Check for spaces at end
|
||||
while(ret[ret.length() - 1] == ' ' || ret[ret.length() - 1] == '.')
|
||||
while(ret[ret.length() - 1] == ' ')
|
||||
ret.erase(ret.length() - 1, 1);
|
||||
|
||||
return ret;
|
||||
@@ -186,21 +184,25 @@ static inline std::string getTimeString(const uint32_t& _h, const uint32_t& _m)
|
||||
return std::string(tmp);
|
||||
}
|
||||
|
||||
std::string util::getInfoString(const data::user& u, const data::titledata& d)
|
||||
std::string util::getInfoString(data::user& u, const uint64_t& tid)
|
||||
{
|
||||
std::string ret = d.getTitle() + "\n";
|
||||
data::titleInfo *tinfo = data::getTitleInfoByTID(tid);
|
||||
data::userTitleInfo *userTinfo = &u.titleInfo[data::selData];
|
||||
|
||||
ret += "TID: " + d.getTIDStr() + "\n";
|
||||
ret += "SID: " + d.getSaveIDStr() + "\n";
|
||||
std::string ret = tinfo->title + "\n";
|
||||
|
||||
ret += "TID: " + util::getIDStr(tid) + "\n";
|
||||
ret += "SID: " + util::getIDStr(userTinfo->saveInfo.save_data_id) + "\n";
|
||||
|
||||
uint32_t hours, mins;
|
||||
hours = d.getPlayTime() / 60;
|
||||
mins = d.getPlayTime() - (hours * 60);
|
||||
hours = userTinfo->playStats.playtimeMinutes / 60;
|
||||
mins = userTinfo->playStats.playtimeMinutes - (hours * 60);
|
||||
|
||||
ret += "Play Time: " + getTimeString(hours, mins) + "\n";
|
||||
ret += "Total Launches: " + std::to_string(d.getLaunchCount()) + "\n";
|
||||
ret += "Total Launches: " + std::to_string(userTinfo->playStats.totalLaunches) + "\n";
|
||||
|
||||
switch(d.getType())
|
||||
|
||||
switch(userTinfo->saveInfo.save_data_type)
|
||||
{
|
||||
case FsSaveDataType_System:
|
||||
ret += "System Save\n";
|
||||
@@ -267,13 +269,14 @@ std::string util::getStringInput(const std::string& def, const std::string& head
|
||||
return std::string(out);
|
||||
}
|
||||
|
||||
std::string util::generateAbbrev(const data::titledata& dat)
|
||||
std::string util::generateAbbrev(const uint64_t& tid)
|
||||
{
|
||||
size_t titleLength = dat.getTitle().length();
|
||||
data::titleInfo *tmp = data::getTitleInfoByTID(tid);
|
||||
size_t titleLength = tmp->safeTitle.length();
|
||||
|
||||
char temp[titleLength + 1];
|
||||
memset(temp, 0, titleLength + 1);
|
||||
memcpy(temp, dat.getTitle().c_str(), titleLength);
|
||||
memcpy(temp, tmp->safeTitle.c_str(), titleLength);
|
||||
|
||||
std::string ret;
|
||||
char *tok = strtok(temp, " ");
|
||||
@@ -322,7 +325,7 @@ SDL_Texture *util::createIconGeneric(const char *txt, int fontSize)
|
||||
SDL_RenderClear(gfx::render);
|
||||
unsigned int x = 128 - (gfx::getTextWidth(txt, fontSize) / 2);
|
||||
unsigned int y = 128 - (fontSize / 2);
|
||||
gfx::drawTextf(fontSize, x, y, &ui::txtCont, txt);
|
||||
gfx::drawTextf(ret, fontSize, x, y, &ui::txtCont, txt);
|
||||
SDL_SetRenderTarget(gfx::render, NULL);
|
||||
return ret;
|
||||
}
|
||||
@@ -375,3 +378,14 @@ void util::checkForUpdate()
|
||||
|
||||
json_object_put(jobj);
|
||||
}
|
||||
|
||||
Result util::accountDeleteUser(AccountUid *uid)
|
||||
{
|
||||
Service *account = accountGetServiceSession();
|
||||
struct
|
||||
{
|
||||
AccountUid uid;
|
||||
} in = {*uid};
|
||||
|
||||
return serviceDispatchIn(account, 203, in);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user