Remove namespace from source files, add more text to translation text, add place holder files for translations, make folder menus share functions

This commit is contained in:
J-D-K 2020-05-22 22:17:33 -04:00
parent 2dc96be0b8
commit bdd1a1d88d
35 changed files with 3040 additions and 2982 deletions

View File

@ -38,7 +38,7 @@ INCLUDES := inc
EXEFS_SRC := exefs_src
APP_TITLE := JKSV
APP_AUTHOR := JK
APP_VERSION := 05.20.2020
APP_VERSION := 05.22.2020
ROMFS := romfs
ICON := romfs/icon.jpg

View File

@ -90,11 +90,19 @@ namespace fs
bool isOpen() { return opened; }
//Gets next good line. Returns empty string if no more.
std::string getNextLine();
bool readNextLine(bool proc);
//Finds where variable name ends. When a '(' or '=' is hit. Strips spaces
void procLine();
std::string getLine() { return line; }
std::string getName() { return name; }
//Reads until ';', ',', or '\n' is hit and returns as string.
std::string getNextValueStr();
int getNextValueInt();
private:
FILE *f;
std::string line, name;
size_t lPos = 0;
bool opened = false;
};

View File

@ -23,6 +23,9 @@ typedef struct
int fsremove(const char *_p);
Result fsDelDirRec(const char *_p);
char *getDeviceFromPath(char *dev, size_t _max, const char *path);
char *getFilePath(char *pathOut, size_t _max, const char *path);
/*Opens file. Device is fetched from path. Libnx romfs doesn't work with this.
Mode needs to be:
FsOpenMode_Read

View File

@ -3,22 +3,6 @@
#include "gfx.h"
enum buttonEvents
{
BUTTON_NOTHING,
BUTTON_PRESSED,
BUTTON_RELEASED
};
enum trackEvents
{
TRACK_NOTHING,
TRACK_SWIPE_UP,
TRACK_SWIPE_DOWN,
TRACK_SWIPE_LEFT,
TRACK_SWIPE_RIGHT
};
#define POP_FRAME_DEFAULT 130
//For smaller classes that aren't easy to get lost in and general functions

View File

@ -40,10 +40,17 @@ namespace ui
//Both UI modes need access to this
extern std::string folderMenuInfo;
//Strings since translation support soonish
//Strings since translation support
extern std::string userHelp, titleHelp, folderHelp, optHelp, \
confBlackList, confOverwrite, confRestore, confDel, confCopy, \
confEraseNand, confEraseFolder, yt, nt;
confBlacklist, confOverwrite, confRestore, confDel, confCopy, \
confEraseNand, confEraseFolder, yt, nt, on, off;
//Strings for file mode menu
extern std::string advMenuStr[6];
//Strings for extras menu
extern std::string exMenuStr[10];
//Strings for options menu
extern std::string optMenuStr[12];
/*Colors
clearClr = color to clear buffer
@ -81,6 +88,12 @@ namespace ui
//switch case so we don't have problems with multiple main loops like 3DS
void runApp(const uint64_t& down, const uint64_t& held);
//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);
}
#endif

View File

@ -34,8 +34,8 @@ namespace util
std::string generateAbbrev(data::titledata& dat);
//removes newline '\n' chars from string
void stripNL(std::string& _s);
//removes char from C++ string
void stripChar(char _c, std::string& _s);
//For future external translation support. Replaces [button] with button chars
void replaceButtonsInString(std::string& rep);

2
romfs/lang/de.txt Normal file
View File

@ -0,0 +1,2 @@
#Deutsch translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/en-GB.txt Normal file
View File

@ -0,0 +1,2 @@
#British English translation file
#Copy en-US.txt here and add a bunch of u's where they don't belong.

View File

@ -1,45 +1,86 @@
#This file's strings must be kept in this order. Lines starting with '#' will be ignored.
#Not sure yet if the whole thing needs to be translated or just important things
#Button strings [X] are replaced by JKSV at boot.
#string = set string to this.
#Translation author. Displayed in UI. NULL is ignored and not displayed.
NULL
author = NULL
#Help/Guide strings on bottom
#User Select
[A] Select [Y] Dump All [X] UI Mode [-] Options [ZR] Extras
userHelp = [A] Select [Y] Dump All [X] UI Mode [-] Options [ZR] Extras
#Title Select
[A] Select [L][R] Change User [Y] Dump All [-] Favorite [X] BlackList [ZR] Erase [B] Back
titleHelp = [A] Select [L][R] Change User [Y] Dump All [X] Favorite [-] BlackList [ZR] Erase [B] Back
#Folder Select
[-] File Mode [L][R] Auto [A] Backup [Y] Restore [X] Delete Folder [ZR] Erase [B] Back
folderHelp = [-] File Mode [L][R] Auto [A] Backup [Y] Restore [X] Delete Folder [ZR] Erase [B] Back
#Options Menu
[A] Toggle [B] Back
optHelp = [A] Toggle [B] Back
#Button prompts.
Yes [A]
No [B]
yt = Yes [A]
nt = No [B]
#On/Off for options. '>' is used to change color to green.
on = >On>
off = Off
#Strings for messages/confirmation. '*' and '#' are used in strings to change color. %s is replaced with titles and names.
#Confirm blacklist.
Are you sure you want to add #%s# to your blacklist?
confirmBlacklist = Are you sure you want to add #%s# to your blacklist?
#Confirm overwriting folder
Are you sure you want to overwrite #%s#?
confirmOverwrite = Are you sure you want to overwrite #%s#?
#Confirm restoring save
Are you sure you want to restore #%s#?
confirmRestore = Are you sure you want to restore #%s#?
#Confirm deleting.
Are you sure you want to delete #%s#? *This is permanent*!
confirmDelete = Are you sure you want to delete #%s#? *This is permanent*!
#Confirm file copy in file mode
Are you sure you want to copy #%s# to #%s#?
confirmCopy = Are you sure you want to copy #%s# to #%s#?
#Warning for erasing save data from system in title menu
*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?
confirmEraseNand = *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?
#Warning for deleting save data in folder menu
*WARNING*: This *will* delete the current save data for #%s# *from your system*! Are you sure you want to continue?
confirmEraseFolder = *WARNING*: This *will* delete the current save data for #%s# *from your system*! Are you sure you want to continue?
#Menu options are held in arrays of strings.
#The number is the option to set, string is what to set to.
#Only the string after the comma needs to be edited.
#Adv/file mode menu
#'Copy to ' NEEDS a trailing space
advMenu = 0, Copy to
advMenu = 1, Delete
advMenu = 2, Rename
advMenu = 3, Make Dir
advMenu = 4, Properties
advMenu = 5, Close
#Extras Menu
extMenu = 0, SD to SD Browser
extMenu = 1, BIS: PRODINFOF
extMenu = 2, BIS: SAFE
extMenu = 3, BIS: SYSTEM
extMenu = 4, BIS: USER
extMenu = 5, Remove Update
extMenu = 6, Terminate Process
extMenu = 7, Mount System Save
extMenu = 8, Rescan Titles
extMenu = 9, Process RomFS
#Options menu
#This is always last and all need a trailing space. It is the most likely to have things added to it.
optMenu = 0, Include Dev Sv:
optMenu = 1, AutoBackup:
optMenu = 2, Overclock:
optMenu = 3, Hold to Delete:
optMenu = 4, Hold to Restore:
optMenu = 5, Hold to Overwrite:
optMenu = 6, Force Mount:
optMenu = 7, Account Sys. Saves:
optMenu = 8, Write to Sys. Saves:
optMenu = 9, Text UI Mode:
optMenu = 10, Direct FS Cmd:
optMenu = 11, Skip User Select:

2
romfs/lang/es-419.txt Normal file
View File

@ -0,0 +1,2 @@
#Latin American Spanish translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/es.txt Normal file
View File

@ -0,0 +1,2 @@
#Spanish(Spain) translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/fr-CA.txt Normal file
View File

@ -0,0 +1,2 @@
#Canadian French translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/fr.txt Normal file
View File

@ -0,0 +1,2 @@
#French(France) French translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/it.txt Normal file
View File

@ -0,0 +1,2 @@
#Italian translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/ja.txt Normal file
View File

@ -0,0 +1,2 @@
#Japanese translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/ko.txt Normal file
View File

@ -0,0 +1,2 @@
#Korean translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/nl.txt Normal file
View File

@ -0,0 +1,2 @@
#Dutch translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/pt.txt Normal file
View File

@ -0,0 +1,2 @@
#Portugeuse translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/ru.txt Normal file
View File

@ -0,0 +1,2 @@
#Russian translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/zh-CN.txt Normal file
View File

@ -0,0 +1,2 @@
#Chinese translation file
#Copy en-US.txt here and use as a guide.

2
romfs/lang/zh-TW.txt Normal file
View File

@ -0,0 +1,2 @@
#Taiwanese translation file
#Copy en-US.txt here and use as a guide.

File diff suppressed because it is too large Load Diff

View File

@ -184,443 +184,466 @@ static void mkdirRec(const std::string& _p)
}
}
namespace fs
void fs::init()
{
void init()
{
if(fs::fileExists("sdmc:/switch/jksv_dir.txt"))
{
char tmp[256];
FILE *getDir = fopen("sdmc:/switch/jksv_dir.txt", "r");
fgets(tmp, 256, getDir);
fclose(getDir);
wd = tmp;
util::stripNL(wd);
mkdirRec(wd);
}
else
{
mkdir("sdmc:/JKSV", 777);
wd = "sdmc:/JKSV/";
}
fs::logOpen();
}
void exit()
{
fs::logClose();
}
bool mountSave(data::user& usr, data::titledata& open)
{
Result svOpen;
FsFileSystem sv;
switch(open.getType())
{
case FsSaveDataType_System:
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, open.getID(), usr.getUID128() == 1 ? (AccountUid) { 0 } : usr.getUID());
break;
case FsSaveDataType_Account:
svOpen = fsOpen_SaveData(&sv, open.getID(), usr.getUID());
break;
case FsSaveDataType_Bcat:
svOpen = fsOpen_BcatSaveData(&sv, open.getID());
break;
case FsSaveDataType_Device:
svOpen = fsOpen_DeviceSaveData(&sv, open.getID());
break;
case FsSaveDataType_Temporary:
svOpen = fsOpen_TemporaryStorage(&sv);
break;
case FsSaveDataType_Cache:
svOpen = fsOpen_CacheStorage(&sv, open.getID(), open.getSaveIndex());
break;
case FsSaveDataType_SystemBcat:
svOpen = fsOpen_SystemBcatSaveData(&sv, open.getID());
break;
default:
svOpen = 1;
break;
}
return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1;
}
dirItem::dirItem(const std::string& pathTo, const std::string& sItem)
{
itm = sItem;
std::string fullPath = pathTo + sItem;
struct stat s;
if(stat(fullPath.c_str(), &s) == 0 && S_ISDIR(s.st_mode))
dir = true;
}
dirList::dirList(const std::string& _path)
{
path = _path;
d = opendir(path.c_str());
while((ent = readdir(d)))
{
dirItem add(path, ent->d_name);
item.push_back(add);
}
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
void dirList::reassign(const std::string& _path)
{
path = _path;
d = opendir(path.c_str());
item.clear();
while((ent = readdir(d)))
{
dirItem add(path, ent->d_name);
item.push_back(add);
}
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
void dirList::rescan()
{
item.clear();
d = opendir(path.c_str());
while((ent = readdir(d)))
{
dirItem add(path, ent->d_name);
item.push_back(add);
}
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
dataFile::dataFile(const std::string& _path)
{
f = fopen(_path.c_str(), "r");
if(f != NULL)
opened = true;
}
dataFile::~dataFile()
{
fclose(f);
}
std::string dataFile::getNextLine()
{
std::string ret = "";
char tmp[1024];
while(fgets(tmp, 1024, f))
{
if(tmp[0] != '#' && tmp[0] != '\n')
{
ret = tmp;
break;
}
}
util::stripNL(ret);
return ret;
}
void copyFile(const std::string& from, const std::string& to)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, "", &gProg);
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfile_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, "Copying File...");
gfxEndFrame();
}
threadClose(&cpyThread);
delete thr;
}
void copyFileCommit(const std::string& from, const std::string& to, const std::string& dev)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, dev, &gProg);
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileCommitFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfileCommit_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, "Copying File...");
gfxEndFrame();
}
threadClose(&cpyThread);
delete thr;
}
void copyDirToDir(const std::string& from, const std::string& to)
{
dirList list(from);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newFrom = from + list.getItem(i) + "/";
std::string newTo = to + list.getItem(i);
mkdir(newTo.c_str(), 0777);
newTo += "/";
copyDirToDir(newFrom, newTo);
}
else
{
std::string fullFrom = from + list.getItem(i);
std::string fullTo = to + list.getItem(i);
if(hasFreeSpace(fullTo, fsize(fullFrom)))
copyFile(fullFrom, fullTo);
else
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
}
}
}
void copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev)
{
dirList list(from);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newFrom = from + list.getItem(i) + "/";
std::string newTo = to + list.getItem(i);
mkdir(newTo.c_str(), 0777);
newTo += "/";
copyDirToDirCommit(newFrom, newTo, dev);
}
else
{
std::string fullFrom = from + list.getItem(i);
std::string fullTo = to + list.getItem(i);
if(hasFreeSpace(fullTo, fsize(fullFrom)))
copyFileCommit(fullFrom, fullTo, dev);
else
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
}
}
}
void delfile(const std::string& path)
{
if(data::directFsCmd)
fsremove(path.c_str());
else
remove(path.c_str());
}
void delDir(const std::string& path)
{
dirList list(path);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newPath = path + list.getItem(i) + "/";
delDir(newPath);
std::string delPath = path + list.getItem(i);
rmdir(delPath.c_str());
}
else
{
std::string delPath = path + list.getItem(i);
std::remove(delPath.c_str());
}
}
rmdir(path.c_str());
}
bool dumpAllUserSaves(data::user& u)
{
for(unsigned i = 0; i < u.titles.size(); i++)
{
hidScanInput();
if(hidKeysHeld(CONTROLLER_P1_AUTO) & KEY_B)
return false;
if(fs::mountSave(u, u.titles[i]))
{
u.titles[i].createDir();
//sdmc:/JKSV/[title]/[user] - [date]/
std::string outPath = u.titles[i].getPath() + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(outPath.c_str(), 777);
outPath += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, outPath);
fsdevUnmountDevice("sv");
}
}
return true;//?
}
std::string getFileProps(const std::string& _path)
{
std::string ret = "";
FILE *get = fopen(_path.c_str(), "rb");
if(get != NULL)
{
//Size
fseek(get, 0, SEEK_END);
unsigned fileSize = ftell(get);
fseek(get, 0, SEEK_SET);
fclose(get);
//Probably add more later
char tmp[256];
std::sprintf(tmp, "Path: \"%s\"\nSize: %u", _path.c_str(), fileSize);
ret = tmp;
}
return ret;
}
void getDirProps(const std::string& _path, uint32_t& dirCount, uint32_t& fileCount, uint64_t& totalSize)
{
fs::dirList list(_path);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
dirCount++;
std::string newPath = _path + list.getItem(i) + "/";
uint32_t dirAdd = 0, fileAdd = 0;
uint64_t sizeAdd = 0;
getDirProps(newPath, dirAdd, fileAdd, sizeAdd);
dirCount += dirAdd;
fileCount += fileAdd;
totalSize += sizeAdd;
}
else
{
fileCount++;
std::string filePath = _path + list.getItem(i);
FILE *gSize = fopen(filePath.c_str(), "rb");
fseek(gSize, 0, SEEK_END);
size_t fSize = ftell(gSize);
fclose(gSize);
totalSize += fSize;
}
}
}
bool fileExists(const std::string& path)
{
FILE *test = fopen(path.c_str(), "rb");
if(test != NULL)
{
fclose(test);
return true;
}
return false;
}
size_t fsize(const std::string& _f)
{
size_t ret = 0;
FILE *get = fopen(_f.c_str(), "rb");
if(get != NULL)
{
fseek(get, 0, SEEK_END);
ret = ftell(get);
fseek(get, 0, SEEK_SET);
}
fclose(get);
return ret;
}
bool hasFreeSpace(const std::string& _f, int needed)
{
s64 free = 0;
//grab device from _f
size_t endDevPos = _f.find(':', 0);
std::string dev;
dev.assign(_f.begin(), _f.begin() + endDevPos);
fsFsGetFreeSpace(fsdevGetDeviceFileSystem(dev.c_str()), "/", &free);
return free > needed;
}
std::string getWorkDir() { return wd; }
bool isDir(const std::string& _path)
{
struct stat s;
return stat(_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
}
void logOpen()
{
std::string logPath = wd + "log.txt";
remove(logPath.c_str());
log = fsfopen(logPath.c_str(), FsOpenMode_Write);
}
void logWrite(const char *fmt, ...)
if(fs::fileExists("sdmc:/switch/jksv_dir.txt"))
{
char tmp[256];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
fsfwrite(tmp, 1, strlen(tmp), log);
FILE *getDir = fopen("sdmc:/switch/jksv_dir.txt", "r");
fgets(tmp, 256, getDir);
fclose(getDir);
wd = tmp;
util::stripChar('\n', wd);
util::stripChar('\r', wd);
mkdirRec(wd);
}
void logClose()
else
{
fsfclose(log);
mkdir("sdmc:/JKSV", 777);
wd = "sdmc:/JKSV/";
}
fs::logOpen();
}
void fs::exit()
{
fs::logClose();
}
bool fs::mountSave(data::user& usr, data::titledata& open)
{
Result svOpen;
FsFileSystem sv;
switch(open.getType())
{
case FsSaveDataType_System:
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, open.getID(), usr.getUID128() == 1 ? (AccountUid) { 0 } : usr.getUID());
break;
case FsSaveDataType_Account:
svOpen = fsOpen_SaveData(&sv, open.getID(), usr.getUID());
break;
case FsSaveDataType_Bcat:
svOpen = fsOpen_BcatSaveData(&sv, open.getID());
break;
case FsSaveDataType_Device:
svOpen = fsOpen_DeviceSaveData(&sv, open.getID());
break;
case FsSaveDataType_Temporary:
svOpen = fsOpen_TemporaryStorage(&sv);
break;
case FsSaveDataType_Cache:
svOpen = fsOpen_CacheStorage(&sv, open.getID(), open.getSaveIndex());
break;
case FsSaveDataType_SystemBcat:
svOpen = fsOpen_SystemBcatSaveData(&sv, open.getID());
break;
default:
svOpen = 1;
break;
}
return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1;
}
fs::dirItem::dirItem(const std::string& pathTo, const std::string& sItem)
{
itm = sItem;
std::string fullPath = pathTo + sItem;
struct stat s;
if(stat(fullPath.c_str(), &s) == 0 && S_ISDIR(s.st_mode))
dir = true;
}
fs::dirList::dirList(const std::string& _path)
{
path = _path;
d = opendir(path.c_str());
while((ent = readdir(d)))
item.push_back(dirItem(path, ent->d_name));
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
void fs::dirList::reassign(const std::string& _path)
{
path = _path;
d = opendir(path.c_str());
item.clear();
while((ent = readdir(d)))
item.push_back(dirItem(path, ent->d_name));
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
void fs::dirList::rescan()
{
item.clear();
d = opendir(path.c_str());
while((ent = readdir(d)))
item.push_back(dirItem(path, ent->d_name));
closedir(d);
std::sort(item.begin(), item.end(), sortDirList);
}
fs::dataFile::dataFile(const std::string& _path)
{
f = fopen(_path.c_str(), "r");
if(f != NULL)
opened = true;
}
fs::dataFile::~dataFile()
{
fclose(f);
}
bool fs::dataFile::readNextLine(bool proc)
{
bool ret = false;
char tmp[1024];
while(fgets(tmp, 1024, f))
{
if(tmp[0] != '#' && tmp[0] != '\n')
{
line = tmp;
ret = true;
break;
}
}
util::stripChar('\n', line);
util::stripChar('\r', line);
if(proc)
procLine();
return ret;
}
void fs::dataFile::procLine()
{
if((lPos = line.find_first_of('(')) != line.npos || (lPos = line.find_first_of('=')) != line.npos)
name.assign(line.begin(), line.begin() + lPos);
else
name = "NULL";
util::stripChar(' ', name);
++lPos;
}
std::string fs::dataFile::getNextValueStr()
{
//Skip all spaces until we hit actual text
size_t pos1 = line.find_first_not_of(' ', lPos);
//Set lPos to end of string we want. This should just set lPos to the end of the line if it fails, which is ok
lPos = line.find_first_of(",;\n", pos1);
return std::string(line.substr(pos1, lPos++));
}
int fs::dataFile::getNextValueInt()
{
return strtol(getNextValueStr().c_str(), 0, 10);
}
void fs::copyFile(const std::string& from, const std::string& to)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, "", &gProg);
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfile_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, "Copying File...");
gfxEndFrame();
}
threadClose(&cpyThread);
delete thr;
}
void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, dev, &gProg);
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileCommitFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfileCommit_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, "Copying File...");
gfxEndFrame();
}
threadClose(&cpyThread);
delete thr;
}
void fs::copyDirToDir(const std::string& from, const std::string& to)
{
dirList list(from);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newFrom = from + list.getItem(i) + "/";
std::string newTo = to + list.getItem(i);
mkdir(newTo.c_str(), 0777);
newTo += "/";
copyDirToDir(newFrom, newTo);
}
else
{
std::string fullFrom = from + list.getItem(i);
std::string fullTo = to + list.getItem(i);
if(hasFreeSpace(fullTo, fsize(fullFrom)))
copyFile(fullFrom, fullTo);
else
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
}
}
}
void fs::copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev)
{
dirList list(from);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newFrom = from + list.getItem(i) + "/";
std::string newTo = to + list.getItem(i);
mkdir(newTo.c_str(), 0777);
newTo += "/";
copyDirToDirCommit(newFrom, newTo, dev);
}
else
{
std::string fullFrom = from + list.getItem(i);
std::string fullTo = to + list.getItem(i);
if(hasFreeSpace(fullTo, fsize(fullFrom)))
copyFileCommit(fullFrom, fullTo, dev);
else
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
}
}
}
void fs::delfile(const std::string& path)
{
if(data::directFsCmd)
fsremove(path.c_str());
else
remove(path.c_str());
}
void fs::delDir(const std::string& path)
{
dirList list(path);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
std::string newPath = path + list.getItem(i) + "/";
delDir(newPath);
std::string delPath = path + list.getItem(i);
rmdir(delPath.c_str());
}
else
{
std::string delPath = path + list.getItem(i);
std::remove(delPath.c_str());
}
}
rmdir(path.c_str());
}
bool fs::dumpAllUserSaves(data::user& u)
{
for(unsigned i = 0; i < u.titles.size(); i++)
{
hidScanInput();
if(hidKeysHeld(CONTROLLER_P1_AUTO) & KEY_B)
return false;
if(fs::mountSave(u, u.titles[i]))
{
u.titles[i].createDir();
//sdmc:/JKSV/[title]/[user] - [date]/
std::string outPath = u.titles[i].getPath() + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(outPath.c_str(), 777);
outPath += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, outPath);
fsdevUnmountDevice("sv");
}
}
return true;//?
}
std::string fs::getFileProps(const std::string& _path)
{
std::string ret = "";
FILE *get = fopen(_path.c_str(), "rb");
if(get != NULL)
{
//Size
fseek(get, 0, SEEK_END);
unsigned fileSize = ftell(get);
fseek(get, 0, SEEK_SET);
fclose(get);
//Probably add more later
char tmp[256];
std::sprintf(tmp, "Path: \"%s\"\nSize: %u", _path.c_str(), fileSize);
ret = tmp;
}
return ret;
}
void fs::getDirProps(const std::string& _path, uint32_t& dirCount, uint32_t& fileCount, uint64_t& totalSize)
{
fs::dirList list(_path);
for(unsigned i = 0; i < list.getCount(); i++)
{
if(list.isDir(i))
{
dirCount++;
std::string newPath = _path + list.getItem(i) + "/";
uint32_t dirAdd = 0, fileAdd = 0;
uint64_t sizeAdd = 0;
getDirProps(newPath, dirAdd, fileAdd, sizeAdd);
dirCount += dirAdd;
fileCount += fileAdd;
totalSize += sizeAdd;
}
else
{
fileCount++;
std::string filePath = _path + list.getItem(i);
FILE *gSize = fopen(filePath.c_str(), "rb");
fseek(gSize, 0, SEEK_END);
size_t fSize = ftell(gSize);
fclose(gSize);
totalSize += fSize;
}
}
}
bool fs::fileExists(const std::string& path)
{
FILE *test = fopen(path.c_str(), "rb");
if(test != NULL)
{
fclose(test);
return true;
}
return false;
}
size_t fs::fsize(const std::string& _f)
{
size_t ret = 0;
FILE *get = fopen(_f.c_str(), "rb");
if(get != NULL)
{
fseek(get, 0, SEEK_END);
ret = ftell(get);
fseek(get, 0, SEEK_SET);
}
fclose(get);
return ret;
}
bool fs::hasFreeSpace(const std::string& _f, int needed)
{
s64 free = 0;
//grab device from _f
size_t endDevPos = _f.find(':', 0);
std::string dev;
dev.assign(_f.begin(), _f.begin() + endDevPos);
fsFsGetFreeSpace(fsdevGetDeviceFileSystem(dev.c_str()), "/", &free);
return free > needed;
}
std::string fs::getWorkDir() { return wd; }
bool fs::isDir(const std::string& _path)
{
struct stat s;
return stat(_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
}
void fs::logOpen()
{
std::string logPath = wd + "log.txt";
remove(logPath.c_str());
log = fsfopen(logPath.c_str(), FsOpenMode_Write);
}
void fs::logWrite(const char *fmt, ...)
{
char tmp[256];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
fsfwrite(tmp, 1, strlen(tmp), log);
}
void fs::logClose()
{
fsfclose(log);
}

View File

@ -5,7 +5,7 @@
#include "fsfile.h"
static char *getDeviceFromPath(char *dev, size_t _max, const char *path)
char *getDeviceFromPath(char *dev, size_t _max, const char *path)
{
memset(dev, 0, _max);
char *c = strchr(path, ':');
@ -18,7 +18,7 @@ static char *getDeviceFromPath(char *dev, size_t _max, const char *path)
return dev;
}
static char *getFilePath(char *pathOut, size_t _max, const char *path)
char *getFilePath(char *pathOut, size_t _max, const char *path)
{
memset(pathOut, 0, _max);
char *c = strchr(path, '/');

View File

@ -188,7 +188,6 @@ void drawText(const char *str, tex *target, const font *f, int x, int y, int sz,
continue;
break;
case '"':
case '#':
if(clrGetColor(textClr) == 0xFFEE9900)
textClr = c;
@ -204,6 +203,22 @@ void drawText(const char *str, tex *target, const font *f, int x, int y, int sz,
textClr = clrCreateU32(0xFF0000FF);
continue;
break;
case '<':
if(clrGetColor(textClr) == 0xFF00FCF8)
textClr = c;
else
textClr = clrCreateU32(0xFF00FCF8);
continue;
break;
case '>':
if(clrGetColor(textClr) == 0xFF00FF00)
textClr = c;
else
textClr = clrCreateU32(0xFF00FF00);
continue;
break;
}
FT_GlyphSlot slot = loadGlyph(tmpChr, f, FT_LOAD_RENDER);
@ -259,7 +274,6 @@ void drawTextWrap(const char *str, tex *target, const font *f, int x, int y, int
continue;
break;
case '"':
case '#':
if(clrGetColor(textClr) == 0xFFEE9900)
textClr = c;
@ -275,6 +289,22 @@ void drawTextWrap(const char *str, tex *target, const font *f, int x, int y, int
textClr = clrCreateU32(0xFF0000FF);
continue;
break;
case '<':
if(clrGetColor(textClr) == 0xFF00FCF8)
textClr = c;
else
textClr = clrCreateU32(0xFF00FCF8);
continue;
break;
case '>':
if(clrGetColor(textClr) == 0xFF00FF00)
textClr = c;
else
textClr = clrCreateU32(0xFF00FF00);
continue;
break;
}
FT_GlyphSlot slot = loadGlyph(tmpChr, f, FT_LOAD_RENDER);
@ -503,23 +533,23 @@ tex *texLoadJPEGMem(const uint8_t *jpegData, size_t jpegSize)
jpeg_start_decompress(&jpegInfo);
JSAMPARRAY row = malloc(sizeof(JSAMPROW));
for(unsigned i = 0; i < ret->height; i++)
row[0] = malloc(sizeof(JSAMPLE) * ret->width * 3);
for(unsigned i = 0; i < ret->height; i++)
row[0] = malloc(sizeof(JSAMPLE) * ret->width * 3);
uint32_t *dataPtr = &ret->data[0];
for(int y = 0; y < ret->height; y++)
{
jpeg_read_scanlines(&jpegInfo, row, 1);
uint8_t *jpegPtr = row[0];
for(int x = 0; x < ret->width; x++, jpegPtr += 3)
*dataPtr++ = (0xFF << 24 | jpegPtr[2] << 16 | jpegPtr[1] << 8 | jpegPtr[0]);
}
uint32_t *dataPtr = &ret->data[0];
for(int y = 0; y < ret->height; y++)
{
jpeg_read_scanlines(&jpegInfo, row, 1);
uint8_t *jpegPtr = row[0];
for(int x = 0; x < ret->width; x++, jpegPtr += 3)
*dataPtr++ = (0xFF << 24 | jpegPtr[2] << 16 | jpegPtr[1] << 8 | jpegPtr[0]);
}
jpeg_finish_decompress(&jpegInfo);
jpeg_destroy_decompress(&jpegInfo);
jpeg_finish_decompress(&jpegInfo);
jpeg_destroy_decompress(&jpegInfo);
free(row[0]);
free(row);
free(row[0]);
free(row);
return ret;
}

View File

@ -39,16 +39,12 @@ extern "C"
int main(int argc, const char *argv[])
{
//Max cpu to speed up boot. Doesn't take long.
util::setCPU(1785000000);
fs::init();
graphicsInit(1280, 720);
ui::initTheme();
ui::showLoadScreen();
data::init();
ui::init();
//Reset cpu
util::setCPU(data::ovrClk ? 1224000000 : 1020000000);
while(appletMainLoop())
{
@ -65,10 +61,6 @@ int main(int argc, const char *argv[])
gfxEndFrame();
}
//reset cpu on exit
if(data::ovrClk)
util::setCPU(1020000000);
ui::exit();
data::exit();
graphicsExit();

View File

@ -10,24 +10,74 @@
#include "util.h"
#include "file.h"
#define VER_STRING "v. 05.20.2020"
#define VER_STRING "v. 05.22.2020"
//text mode
bool ui::textMode = false;
//Current menu state
int ui::mstate = USR_SEL, ui::prevState = USR_SEL;
//Theme id
ColorSetId ui::thmID;
//Info printed on folder menu
std::string ui::folderMenuInfo;
//UI colors
clr ui::clearClr, ui::txtCont, ui::txtDiag, ui::rectLt, ui::rectSh, ui::tboxClr, divClr;
//textbox pieces
//I was going to flip them when I draw them, but then laziness kicked in.
tex *ui::cornerTopLeft, *ui::cornerTopRight, *ui::cornerBottomLeft, *ui::cornerBottomRight;
//Progress bar covers + dialog box predrawn
tex *ui::progCovLeft, *ui::progCovRight, *ui::diaBox;
//Menu box pieces
tex *mnuTopLeft, *mnuTopRight, *mnuBotLeft, *mnuBotRight;
//Select box + top left icon
tex *ui::sideBar;
//Shared font
font *ui::shared;
//Don't waste time drawing top and bottom over and over
//guide graphics are to save cpu drawing that over and over with alpha
static tex *top, *bot, *usrGuide, *ttlGuide, *fldrGuide, *optGuide;
//Ui text strings
std::string author, ui::userHelp, ui::titleHelp, ui::folderHelp, ui::optHelp, \
ui::confBlackList, ui::confOverwrite, ui::confRestore, ui::confDel, ui::confCopy, \
ui::confEraseNand, ui::confEraseFolder, ui::yt, ui::nt;
//UI text strings
//Freedom English stored by default
std::string author;
std::string ui::userHelp = "[A] Select [Y] Dump All [X] UI Mode [-] 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::folderHelp = "[-] File Mode [L][R] Auto [A] Backup [Y] Restore [X] Delete Folder [ZR] Erase [B] Back";
std::string ui::optHelp = "[A] Toggle [B] Back";
std::string ui::yt = "Yes [A]", ui::nt = "No [B]";
std::string ui::on = ">On>", ui::off = "Off";
std::string ui::confBlacklist = "Are you sure you want to add #%s# to your blacklist?";
std::string ui::confOverwrite = "Are you sure you want to overwrite #%s#?";
std::string ui::confRestore = "Are you sure you want to restore #%s#?";
std::string ui::confDel = "Are you sure you want to delete #%s#? *This is permanent*!";
std::string ui::confCopy = "Are you sure you want to copy #%s# to #%s#?";
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::advMenuStr[6] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close" };
std::string ui::exMenuStr[10] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS" };
std::string ui::optMenuStr[12] = { "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: " };
//X position of help texts. Calculated to make editing quicker/easier
static unsigned userHelpX, titleHelpX, folderHelpX, optHelpX;
static void 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(fs::fileExists(fs::getWorkDir() + "trans.txt"))
if(transFile)
file = fs::getWorkDir() + "trans.txt";
else
{
@ -41,372 +91,376 @@ static void loadTrans()
}
fs::dataFile lang(file);
author = lang.getNextLine();
if(author == "NULL")
author = "";
ui::userHelp = lang.getNextLine();
ui::titleHelp = lang.getNextLine();
ui::folderHelp = lang.getNextLine();
ui::optHelp = lang.getNextLine();
ui::yt = lang.getNextLine();
ui::nt = lang.getNextLine();
ui::confBlackList = lang.getNextLine();
ui::confOverwrite = lang.getNextLine();
ui::confRestore = lang.getNextLine();
ui::confDel = lang.getNextLine();
ui::confCopy = lang.getNextLine();
ui::confEraseNand = lang.getNextLine();
ui::confEraseFolder = lang.getNextLine();
while(lang.readNextLine(true))
{
//Holy shit this'll be fun
if(lang.getName() == "author")
author = lang.getNextValueStr();
else if(lang.getName() == "userHelp")
ui::userHelp = lang.getNextValueStr();
else if(lang.getName() == "titleHelp")
ui::titleHelp = lang.getNextValueStr();
else if(lang.getName() == "folderHelp")
ui::folderHelp = lang.getNextValueStr();
else if(lang.getName() == "optHelp")
ui::optHelp = lang.getNextValueStr();
else if(lang.getName() == "yt")
ui::yt = lang.getNextValueStr();
else if(lang.getName() == "nt")
ui::nt = lang.getNextValueStr();
else if(lang.getName() == "on")
ui::on = lang.getNextValueStr();
else if(lang.getName() == "off")
ui::off = lang.getNextValueStr();
else if(lang.getName() == "confirmBlacklist")
ui::confBlacklist = lang.getNextValueStr();
else if(lang.getName() == "confirmOverwrite")
ui::confOverwrite = lang.getNextValueStr();
else if(lang.getName() == "confirmRestore")
ui::confRestore = lang.getNextValueStr();
else if(lang.getName() == "confirmDelete")
ui::confDel = lang.getNextValueStr();
else if(lang.getName() == "confirmCopy")
ui::confCopy = lang.getNextValueStr();
else if(lang.getName() == "confirmEraseNand")
ui::confEraseNand = lang.getNextValueStr();
else if(lang.getName() == "confirmEraseFolder")
ui::confEraseFolder = lang.getNextValueStr();
else if(lang.getName() == "advMenu")
{
int ind = lang.getNextValueInt();
ui::advMenuStr[ind] = lang.getNextValueStr();
}
else if(lang.getName() == "extMenu")
{
int ind = lang.getNextValueInt();
ui::exMenuStr[ind] = lang.getNextValueStr();
}
else if(lang.getName() == "optMenu")
{
int ind = lang.getNextValueInt();
ui::optMenuStr[ind] = lang.getNextValueStr();
}
}
}
namespace ui
void ui::initTheme()
{
//text mode
bool textMode = false;
if(fs::fileExists(fs::getWorkDir() + "font.ttf"))
shared = fontLoadTTF(std::string(fs::getWorkDir() + "font.ttf").c_str());
else
shared = fontLoadSharedFonts();
//Current menu state
int mstate = USR_SEL, prevState = USR_SEL;
setsysGetColorSetId(&thmID);
//Theme id
ColorSetId thmID;
//Info printed on folder menu
std::string folderMenuInfo;
//UI colors
clr clearClr, txtCont, txtDiag, rectLt, rectSh, tboxClr, divClr;
//textbox pieces
//I was going to flip them when I draw them, but then laziness kicked in.
tex *cornerTopLeft, *cornerTopRight, *cornerBottomLeft, *cornerBottomRight;
tex *progCovLeft, *progCovRight, *diaBox;
//Menu box pieces
tex *mnuTopLeft, *mnuTopRight, *mnuBotLeft, *mnuBotRight;
//Select box + top left icon
tex *icn, *sideBar;
//Shared font
font *shared;
void initTheme()
switch(thmID)
{
if(fs::fileExists(fs::getWorkDir() + "font.ttf"))
shared = fontLoadTTF(std::string(fs::getWorkDir() + "font.ttf").c_str());
else
shared = fontLoadSharedFonts();
case ColorSetId_Light:
clearClr = clrCreateU32(0xFFEBEBEB);
txtCont = clrCreateU32(0xFF000000);
txtDiag = clrCreateU32(0xFFFFFFFF);
rectLt = clrCreateU32(0xFFDFDFDF);
rectSh = clrCreateU32(0xFFCACACA);
tboxClr = clrCreateU32(0xFF505050);
divClr = clrCreateU32(0xFF000000);
break;
setsysGetColorSetId(&thmID);
switch(thmID)
{
case ColorSetId_Light:
clearClr = clrCreateU32(0xFFEBEBEB);
txtCont = clrCreateU32(0xFF000000);
txtDiag = clrCreateU32(0xFFFFFFFF);
rectLt = clrCreateU32(0xFFDFDFDF);
rectSh = clrCreateU32(0xFFCACACA);
tboxClr = clrCreateU32(0xFF505050);
divClr = clrCreateU32(0xFF000000);
break;
default:
case ColorSetId_Dark:
//jic
thmID = ColorSetId_Dark;
clearClr = clrCreateU32(0xFF2D2D2D);
txtCont = clrCreateU32(0xFFFFFFFF);
txtDiag = clrCreateU32(0xFF000000);
rectLt = clrCreateU32(0xFF505050);
rectSh = clrCreateU32(0xFF202020);
tboxClr = clrCreateU32(0xFFEBEBEB);
divClr = clrCreateU32(0xFFFFFFFF);
break;
}
}
void init()
{
mnuTopLeft = texLoadPNGFile("romfs:/img/fb/menuTopLeft.png");
mnuTopRight = texLoadPNGFile("romfs:/img/fb/menuTopRight.png");
mnuBotLeft = texLoadPNGFile("romfs:/img/fb/menuBotLeft.png");
mnuBotRight = texLoadPNGFile("romfs:/img/fb/menuBotRight.png");
switch(ui::thmID)
{
case ColorSetId_Light:
//Dark corners
cornerTopLeft = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png");
cornerTopRight = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerTopRight.png");
cornerBottomLeft = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png");
cornerBottomRight = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerBotRight.png");
progCovLeft = texLoadPNGFile("romfs:/img/tboxDrk/progBarCoverLeftDrk.png");
progCovRight = texLoadPNGFile("romfs:/img/tboxDrk/progBarCoverRightDrk.png");
icn = texLoadPNGFile("romfs:/img/icn/icnDrk.png");
sideBar = texLoadPNGFile("romfs:/img/fb/lLight.png");
break;
default:
//Light corners
cornerTopLeft = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerTopLeft.png");
cornerTopRight = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerTopRight.png");
cornerBottomLeft = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerBotLeft.png");
cornerBottomRight = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerBotRight.png");
progCovLeft = texLoadPNGFile("romfs:/img/tboxLght/progBarCoverLeftLight.png");
progCovRight = texLoadPNGFile("romfs:/img/tboxLght/progBarCoverRightLight.png");
icn = texLoadPNGFile("romfs:/img/icn/icnLght.png");
sideBar = texLoadPNGFile("romfs:/img/fb/lDark.png");
break;
}
top = texCreate(1280, 88);
bot = texCreate(1280, 72);
diaBox = texCreate(640, 420);
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;
loadTrans();
textUserPrep();
//Setup top and bottom gfx
texClearColor(top, clearClr);
texDraw(icn, top, 66, 27);
drawText("JKSV", top, shared, 130, 38, 24, ui::txtCont);
drawRect(top, 30, 87, 1220, 1, ui::txtCont);
texClearColor(bot, clearClr);
drawRect(bot, 30, 0, 1220, 1, ui::txtCont);
drawText(VER_STRING, bot, shared, 8, author.empty() ? 56 : 38, 12, ui::txtCont);
if(!author.empty())
drawText(std::string("Translation: " + author).c_str(), bot, ui::shared, 8, 56, 12, ui::txtCont);
//Not needed anymore
texDestroy(icn);
//Setup dialog box
drawTextbox(diaBox, 0, 0, 640, 420);
drawRect(diaBox, 0, 56, 640, 2, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFF6D6D6D) : clrCreateU32(0xFFCCCCCC));
util::replaceButtonsInString(ui::userHelp);
util::replaceButtonsInString(ui::titleHelp);
util::replaceButtonsInString(ui::folderHelp);
util::replaceButtonsInString(ui::optHelp);
util::replaceButtonsInString(ui::yt);
util::replaceButtonsInString(ui::nt);
//Create graphics to hold guides
usrGuide = texCreate(textGetWidth(userHelp.c_str(), ui::shared, 18), 28);
ttlGuide = texCreate(textGetWidth(titleHelp.c_str(), ui::shared, 18), 28);
fldrGuide = texCreate(textGetWidth(folderHelp.c_str(), ui::shared, 18), 28);
optGuide = texCreate(textGetWidth(optHelp.c_str(), ui::shared, 18), 28);
//Clear with bg color
texClearColor(usrGuide, ui::clearClr);
texClearColor(ttlGuide, ui::clearClr);
texClearColor(fldrGuide, ui::clearClr);
texClearColor(optGuide, ui::clearClr);
//Draw text to them
drawText(userHelp.c_str(), usrGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(titleHelp.c_str(), ttlGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(folderHelp.c_str(), fldrGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(optHelp.c_str(), optGuide, ui::shared, 0, 3, 18, ui::txtCont);
//Calculate x position of help text
userHelpX = 1220 - usrGuide->width;
titleHelpX = 1220 - ttlGuide->width;
folderHelpX = 1220 - fldrGuide->width;
optHelpX = 1220 - optGuide->width;
advCopyMenuPrep();
ui::exMenuPrep();
ui::optMenuInit();
}
void exit()
{
texDestroy(cornerTopLeft);
texDestroy(cornerTopRight);
texDestroy(cornerBottomLeft);
texDestroy(cornerBottomRight);
texDestroy(progCovLeft);
texDestroy(progCovRight);
texDestroy(mnuTopLeft);
texDestroy(mnuTopRight);
texDestroy(mnuBotLeft);
texDestroy(mnuBotRight);
texDestroy(usrGuide);
texDestroy(ttlGuide);
texDestroy(fldrGuide);
texDestroy(optGuide);
texDestroy(top);
texDestroy(bot);
texDestroy(diaBox);
fontDestroy(shared);
}
void showLoadScreen()
{
tex *icn = texLoadJPEGFile("romfs:/icon.jpg");
gfxBeginFrame();
texClearColor(frameBuffer, clrCreateU32(0xFF2D2D2D));
texDrawNoAlpha(icn, frameBuffer, 512, 232);
drawText("Loading...", frameBuffer, ui::shared, 1100, 673, 16, clrCreateU32(0xFFFFFFFF));
gfxEndFrame();
texDestroy(icn);
}
void drawUI()
{
texClearColor(frameBuffer, clearClr);
texDrawNoAlpha(top, frameBuffer, 0, 0);
texDrawNoAlpha(bot, frameBuffer, 0, 648);
switch(mstate)
{
case USR_SEL:
texDrawNoAlpha(usrGuide, frameBuffer, userHelpX, 673);
break;
case TTL_SEL:
texDrawNoAlpha(ttlGuide, frameBuffer, titleHelpX, 673);
break;
case FLD_SEL:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(fldrGuide, frameBuffer, folderHelpX, 673);
break;
case TXT_USR:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(usrGuide, frameBuffer, userHelpX, 673);
break;
case TXT_TTL:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(ttlGuide, frameBuffer, titleHelpX, 673);
break;
case TXT_FLD:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(fldrGuide, frameBuffer, folderHelpX, 673);
break;
case EX_MNU:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
break;
case OPT_MNU:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(optGuide, frameBuffer, optHelpX, 673);
break;
case ADV_MDE:
drawRect(frameBuffer, 640, 88, 1, 559, ui::txtCont);
break;
}
}
void drawBoundBox(int x, int y, int w, int h, int clrSh)
{
clr rectClr = clrCreateRGBA(0x00, 0x88 + clrSh, 0xC5 + (clrSh / 2), 0xFF);
texSwapColors(mnuTopLeft, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuTopRight, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuBotLeft, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuBotRight, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
switch(ui::thmID)
{
case ColorSetId_Light:
drawRect(frameBuffer, x + 4, y + 4, w - 8, h - 8, clrCreateU32(0xFFFDFDFD));
break;
default:
case ColorSetId_Dark:
drawRect(frameBuffer, x + 4, y + 4, w - 8, h - 8, clrCreateU32(0xFF212221));
break;
}
//top
texDraw(mnuTopLeft, frameBuffer, x, y);
drawRect(frameBuffer, x + 4, y, w - 8, 4, rectClr);
texDraw(mnuTopRight, frameBuffer, (x + w) - 4, y);
//mid
drawRect(frameBuffer, x, y + 4, 4, h - 8, rectClr);
drawRect(frameBuffer, (x + w) - 4, y + 4, 4, h - 8, rectClr);
//bottom
texDraw(mnuBotLeft, frameBuffer, x, (y + h) - 4);
drawRect(frameBuffer, x + 4, (y + h) - 4, w - 8, 4, rectClr);
texDraw(mnuBotRight, frameBuffer, (x + w) - 4, (y + h) - 4);
texSwapColors(mnuTopLeft, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuTopRight, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuBotLeft, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuBotRight, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
}
void runApp(const uint64_t& down, const uint64_t& held)
{
//Draw first. Shouldn't, but it simplifies the showX functions
drawUI();
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);
break;
case EX_MNU:
updateExMenu(down, held);
break;
case OPT_MNU:
updateOptMenu(down, held);
break;
}
drawPopup(down);
default:
case ColorSetId_Dark:
//jic
thmID = ColorSetId_Dark;
clearClr = clrCreateU32(0xFF2D2D2D);
txtCont = clrCreateU32(0xFFFFFFFF);
txtDiag = clrCreateU32(0xFF000000);
rectLt = clrCreateU32(0xFF505050);
rectSh = clrCreateU32(0xFF202020);
tboxClr = clrCreateU32(0xFFEBEBEB);
divClr = clrCreateU32(0xFFFFFFFF);
break;
}
}
void ui::init()
{
tex *icn;
mnuTopLeft = texLoadPNGFile("romfs:/img/fb/menuTopLeft.png");
mnuTopRight = texLoadPNGFile("romfs:/img/fb/menuTopRight.png");
mnuBotLeft = texLoadPNGFile("romfs:/img/fb/menuBotLeft.png");
mnuBotRight = texLoadPNGFile("romfs:/img/fb/menuBotRight.png");
switch(ui::thmID)
{
case ColorSetId_Light:
//Dark corners
cornerTopLeft = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerTopLeft.png");
cornerTopRight = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerTopRight.png");
cornerBottomLeft = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerBotLeft.png");
cornerBottomRight = texLoadPNGFile("romfs:/img/tboxDrk/tboxCornerBotRight.png");
progCovLeft = texLoadPNGFile("romfs:/img/tboxDrk/progBarCoverLeftDrk.png");
progCovRight = texLoadPNGFile("romfs:/img/tboxDrk/progBarCoverRightDrk.png");
icn = texLoadPNGFile("romfs:/img/icn/icnDrk.png");
sideBar = texLoadPNGFile("romfs:/img/fb/lLight.png");
break;
default:
//Light corners
cornerTopLeft = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerTopLeft.png");
cornerTopRight = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerTopRight.png");
cornerBottomLeft = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerBotLeft.png");
cornerBottomRight = texLoadPNGFile("romfs:/img/tboxLght/tboxCornerBotRight.png");
progCovLeft = texLoadPNGFile("romfs:/img/tboxLght/progBarCoverLeftLight.png");
progCovRight = texLoadPNGFile("romfs:/img/tboxLght/progBarCoverRightLight.png");
icn = texLoadPNGFile("romfs:/img/icn/icnLght.png");
sideBar = texLoadPNGFile("romfs:/img/fb/lDark.png");
break;
}
top = texCreate(1280, 88);
bot = texCreate(1280, 72);
diaBox = texCreate(640, 420);
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;
loadTrans();
textUserPrep();
//Replace the button [x] in strings that need it. Needs to be outside loadTrans so even defaults will get replaced
util::replaceButtonsInString(ui::userHelp);
util::replaceButtonsInString(ui::titleHelp);
util::replaceButtonsInString(ui::folderHelp);
util::replaceButtonsInString(ui::optHelp);
util::replaceButtonsInString(ui::yt);
util::replaceButtonsInString(ui::nt);
//Setup top and bottom gfx
texClearColor(top, clearClr);
texDraw(icn, top, 66, 27);
drawText("JKSV", top, shared, 130, 38, 24, ui::txtCont);
drawRect(top, 30, 87, 1220, 1, ui::txtCont);
texClearColor(bot, clearClr);
drawRect(bot, 30, 0, 1220, 1, ui::txtCont);
drawText(VER_STRING, bot, shared, 8, author == "NULL" ? 56 : 38, 12, ui::txtCont);
if(author != "NULL")
drawText(std::string("Translation: " + author).c_str(), bot, ui::shared, 8, 56, 12, ui::txtCont);
//Not needed anymore
texDestroy(icn);
//Setup dialog box
drawTextbox(diaBox, 0, 0, 640, 420);
drawRect(diaBox, 0, 56, 640, 2, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFF6D6D6D) : clrCreateU32(0xFFCCCCCC));
//Create graphics to hold guides
usrGuide = texCreate(textGetWidth(userHelp.c_str(), ui::shared, 18), 28);
ttlGuide = texCreate(textGetWidth(titleHelp.c_str(), ui::shared, 18), 28);
fldrGuide = texCreate(textGetWidth(folderHelp.c_str(), ui::shared, 18), 28);
optGuide = texCreate(textGetWidth(optHelp.c_str(), ui::shared, 18), 28);
//Clear with bg color
texClearColor(usrGuide, ui::clearClr);
texClearColor(ttlGuide, ui::clearClr);
texClearColor(fldrGuide, ui::clearClr);
texClearColor(optGuide, ui::clearClr);
//Draw text to them
drawText(userHelp.c_str(), usrGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(titleHelp.c_str(), ttlGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(folderHelp.c_str(), fldrGuide, ui::shared, 0, 3, 18, ui::txtCont);
drawText(optHelp.c_str(), optGuide, ui::shared, 0, 3, 18, ui::txtCont);
//Calculate x position of help text
userHelpX = 1220 - usrGuide->width;
titleHelpX = 1220 - ttlGuide->width;
folderHelpX = 1220 - fldrGuide->width;
optHelpX = 1220 - optGuide->width;
advCopyMenuPrep();
ui::exMenuPrep();
ui::optMenuInit();
}
void ui::exit()
{
texDestroy(cornerTopLeft);
texDestroy(cornerTopRight);
texDestroy(cornerBottomLeft);
texDestroy(cornerBottomRight);
texDestroy(progCovLeft);
texDestroy(progCovRight);
texDestroy(mnuTopLeft);
texDestroy(mnuTopRight);
texDestroy(mnuBotLeft);
texDestroy(mnuBotRight);
texDestroy(usrGuide);
texDestroy(ttlGuide);
texDestroy(fldrGuide);
texDestroy(optGuide);
texDestroy(top);
texDestroy(bot);
texDestroy(diaBox);
fontDestroy(shared);
}
void ui::showLoadScreen()
{
tex *icn = texLoadJPEGFile("romfs:/icon.jpg");
gfxBeginFrame();
texClearColor(frameBuffer, clrCreateU32(0xFF2D2D2D));
texDrawNoAlpha(icn, frameBuffer, 512, 232);
drawText("Loading...", frameBuffer, ui::shared, 1100, 673, 16, clrCreateU32(0xFFFFFFFF));
gfxEndFrame();
texDestroy(icn);
}
void ui::drawUI()
{
texClearColor(frameBuffer, clearClr);
texDrawNoAlpha(top, frameBuffer, 0, 0);
texDrawNoAlpha(bot, frameBuffer, 0, 648);
switch(mstate)
{
case USR_SEL:
texDrawNoAlpha(usrGuide, frameBuffer, userHelpX, 673);
break;
case TTL_SEL:
texDrawNoAlpha(ttlGuide, frameBuffer, titleHelpX, 673);
break;
case FLD_SEL:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(fldrGuide, frameBuffer, folderHelpX, 673);
break;
case TXT_USR:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(usrGuide, frameBuffer, userHelpX, 673);
break;
case TXT_TTL:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(ttlGuide, frameBuffer, titleHelpX, 673);
break;
case TXT_FLD:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(fldrGuide, frameBuffer, folderHelpX, 673);
break;
case EX_MNU:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
break;
case OPT_MNU:
texDrawNoAlpha(sideBar, frameBuffer, 0, 88);
texDrawNoAlpha(optGuide, frameBuffer, optHelpX, 673);
break;
case ADV_MDE:
drawRect(frameBuffer, 640, 88, 1, 559, ui::txtCont);
break;
}
}
void ui::drawBoundBox(int x, int y, int w, int h, int clrSh)
{
clr rectClr = clrCreateRGBA(0x00, 0x88 + clrSh, 0xC5 + (clrSh / 2), 0xFF);
texSwapColors(mnuTopLeft, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuTopRight, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuBotLeft, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
texSwapColors(mnuBotRight, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF), rectClr);
switch(ui::thmID)
{
case ColorSetId_Light:
drawRect(frameBuffer, x + 4, y + 4, w - 8, h - 8, clrCreateU32(0xFFFDFDFD));
break;
default:
case ColorSetId_Dark:
drawRect(frameBuffer, x + 4, y + 4, w - 8, h - 8, clrCreateU32(0xFF212221));
break;
}
//top
texDraw(mnuTopLeft, frameBuffer, x, y);
drawRect(frameBuffer, x + 4, y, w - 8, 4, rectClr);
texDraw(mnuTopRight, frameBuffer, (x + w) - 4, y);
//mid
drawRect(frameBuffer, x, y + 4, 4, h - 8, rectClr);
drawRect(frameBuffer, (x + w) - 4, y + 4, 4, h - 8, rectClr);
//bottom
texDraw(mnuBotLeft, frameBuffer, x, (y + h) - 4);
drawRect(frameBuffer, x + 4, (y + h) - 4, w - 8, 4, rectClr);
texDraw(mnuBotRight, frameBuffer, (x + w) - 4, (y + h) - 4);
texSwapColors(mnuTopLeft, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuTopRight, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuBotLeft, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
texSwapColors(mnuBotRight, rectClr, clrCreateRGBA(0x00, 0x88, 0xC5, 0xFF));
}
void ui::runApp(const uint64_t& down, const uint64_t& held)
{
//Draw first. Shouldn't, but it simplifies the showX functions
drawUI();
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);
break;
case EX_MNU:
updateExMenu(down, held);
break;
case OPT_MNU:
updateOptMenu(down, held);
break;
}
drawPopup(down);
}

View File

@ -341,189 +341,184 @@ void performCopyMenuOps()
util::copyDirListToMenu(saveList, saveMenu);
}
namespace ui
void ui::advCopyMenuPrep()
{
void advCopyMenuPrep()
for(unsigned i = 0; i < 6; i++)
copyMenu.addOpt(ui::advMenuStr[i]);
}
void ui::advModePrep(const std::string& svDev, bool commitOnWrite)
{
commit = commitOnWrite;
saveMenu.setParams(30, 98, 602);
sdMenu.setParams(648, 98, 602);
copyMenu.setParams(472, 278, 304);
savePath = svDev, dev = svDev;
sdPath = "sdmc:/";
saveList.reassign(savePath);
sdList.reassign(sdPath);
util::copyDirListToMenu(saveList, saveMenu);
util::copyDirListToMenu(sdList, sdMenu);
advMenuCtrl = 0;
}
void ui::updateAdvMode(const uint64_t& down, const uint64_t& held)
{
//0 = save; 1 = sd; 2 = cpy
switch(advMenuCtrl)
{
copyMenu.addOpt("Copy From");
copyMenu.addOpt("Delete");
copyMenu.addOpt("Rename");
copyMenu.addOpt("Make Dir");
copyMenu.addOpt("Properties");
copyMenu.addOpt("Back");
case 0:
saveMenu.handleInput(down, held);
break;
case 1:
sdMenu.handleInput(down, held);
break;
case 2:
copyMenu.handleInput(down, held);
break;
}
void advModePrep(const std::string& svDev, bool commitOnWrite)
saveMenu.draw(ui::txtCont);
sdMenu.draw(ui::txtCont);
drawTextWrap(savePath.c_str(), frameBuffer, ui::shared, 30, 654, 14, ui::txtCont, 600);
drawTextWrap(sdPath.c_str(), frameBuffer, ui::shared, 640, 654, 14, ui::txtCont, 600);
//OH BOY HERE WE GO
if(down & KEY_A)
{
commit = commitOnWrite;
saveMenu.setParams(30, 98, 602);
sdMenu.setParams(648, 98, 602);
copyMenu.setParams(472, 278, 304);
savePath = svDev, dev = svDev;
sdPath = "sdmc:/";
saveList.reassign(savePath);
sdList.reassign(sdPath);
util::copyDirListToMenu(saveList, saveMenu);
util::copyDirListToMenu(sdList, sdMenu);
advMenuCtrl = 0;
}
void updateAdvMode(const uint64_t& down, const uint64_t& held)
{
//0 = save; 1 = sd; 2 = cpy
switch(advMenuCtrl)
{
//save
case 0:
saveMenu.handleInput(down, held);
{
int saveSel = saveMenu.getSelected();
if(saveSel == 1 && savePath != dev)
{
util::removeLastFolderFromString(savePath);
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
else if(saveSel > 1 && saveList.isDir(saveSel - 2))
{
savePath += saveList.getItem(saveSel - 2) + "/";
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
}
break;
//sd
case 1:
{
int sdSel = sdMenu.getSelected();
if(sdSel == 1 && sdPath != "sdmc:/")
{
util::removeLastFolderFromString(sdPath);
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
else if(sdSel > 1 && sdList.isDir(sdSel - 2))
{
sdPath += sdList.getItem(sdSel - 2) + "/";
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
}
break;
//advanced mode
case 2:
performCopyMenuOps();
break;
}
}
else if(down & KEY_B)
{
//save
if(advMenuCtrl == 0 && savePath != dev)
{
util::removeLastFolderFromString(savePath);
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
//sd
else if(advMenuCtrl == 1 && sdPath != "sdmc:/")
{
util::removeLastFolderFromString(sdPath);
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
else if(advMenuCtrl == 2)
advMenuCtrl = advPrev;
}
else if(down & KEY_X)
{
if(advMenuCtrl == 2)
{
advMenuCtrl = advPrev;
}
else
{
advPrev = advMenuCtrl;
advMenuCtrl = 2;
}
}
else if(down & KEY_ZL || down & KEY_ZR)
{
if(advMenuCtrl == 0 || advMenuCtrl == 1)
{
if(advMenuCtrl == 0)
advMenuCtrl = 1;
else
advMenuCtrl = 0;
}
}
else if(down & KEY_MINUS)
{
if(prevState == EX_MNU)
mstate = EX_MNU;
else if(prevState == TTL_SEL)
mstate = TTL_SEL;
else if(ui::textMode)
mstate = TXT_FLD;
else
mstate = FLD_SEL;
}
//draw copy menu if it's supposed to be up
if(advMenuCtrl == 2)
{
switch(advPrev)
{
case 0:
copyMenu.setParams(176, 278, 304);
copyMenu.editOpt(0, advMenuStr[0] + "sdmc");
ui::drawTextbox(frameBuffer, 168, 236, 320, 268);
drawText("SAVE", frameBuffer, ui::shared, 176, 250, 18, ui::txtDiag);
break;
case 1:
sdMenu.handleInput(down, held);
break;
case 2:
copyMenu.handleInput(down, held);
copyMenu.setParams(816, 278, 304);
copyMenu.editOpt(0, advMenuStr[0] + dev);
ui::drawTextbox(frameBuffer, 808, 236, 320, 268);
drawText("SDMC", frameBuffer, ui::shared, 816, 250, 18, ui::txtDiag);
break;
}
saveMenu.draw(ui::txtCont);
sdMenu.draw(ui::txtCont);
drawTextWrap(savePath.c_str(), frameBuffer, ui::shared, 30, 654, 14, ui::txtCont, 600);
drawTextWrap(sdPath.c_str(), frameBuffer, ui::shared, 640, 654, 14, ui::txtCont, 600);
//OH BOY HERE WE GO
if(down & KEY_A)
{
switch(advMenuCtrl)
{
//save
case 0:
{
int saveSel = saveMenu.getSelected();
if(saveSel == 1 && savePath != dev)
{
util::removeLastFolderFromString(savePath);
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
else if(saveSel > 1 && saveList.isDir(saveSel - 2))
{
savePath += saveList.getItem(saveSel - 2) + "/";
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
}
break;
//sd
case 1:
{
int sdSel = sdMenu.getSelected();
if(sdSel == 1 && sdPath != "sdmc:/")
{
util::removeLastFolderFromString(sdPath);
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
else if(sdSel > 1 && sdList.isDir(sdSel - 2))
{
sdPath += sdList.getItem(sdSel - 2) + "/";
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
}
break;
//advanced mode
case 2:
performCopyMenuOps();
break;
}
}
else if(down & KEY_B)
{
//save
if(advMenuCtrl == 0 && savePath != dev)
{
util::removeLastFolderFromString(savePath);
saveList.reassign(savePath);
util::copyDirListToMenu(saveList, saveMenu);
}
//sd
else if(advMenuCtrl == 1 && sdPath != "sdmc:/")
{
util::removeLastFolderFromString(sdPath);
sdList.reassign(sdPath);
util::copyDirListToMenu(sdList, sdMenu);
}
else if(advMenuCtrl == 2)
advMenuCtrl = advPrev;
}
else if(down & KEY_X)
{
if(advMenuCtrl == 2)
{
advMenuCtrl = advPrev;
}
else
{
advPrev = advMenuCtrl;
advMenuCtrl = 2;
}
}
else if(down & KEY_ZL || down & KEY_ZR)
{
if(advMenuCtrl == 0 || advMenuCtrl == 1)
{
if(advMenuCtrl == 0)
advMenuCtrl = 1;
else
advMenuCtrl = 0;
}
}
else if(down & KEY_MINUS)
{
if(prevState == EX_MNU)
mstate = EX_MNU;
else if(prevState == TTL_SEL)
mstate = TTL_SEL;
else if(ui::textMode)
mstate = TXT_FLD;
else
mstate = FLD_SEL;
}
//draw copy menu if it's supposed to be up
if(advMenuCtrl == 2)
{
switch(advPrev)
{
case 0:
copyMenu.setParams(176, 278, 304);
copyMenu.editOpt(0, "Copy to SD");
ui::drawTextbox(frameBuffer, 168, 236, 320, 268);
drawText("SAVE", frameBuffer, ui::shared, 176, 250, 18, ui::txtDiag);
break;
case 1:
copyMenu.setParams(816, 278, 304);
copyMenu.editOpt(0, "Copy to Save");
ui::drawTextbox(frameBuffer, 808, 236, 320, 268);
drawText("SDMC", frameBuffer, ui::shared, 816, 250, 18, ui::txtDiag);
break;
}
copyMenu.draw(ui::txtDiag);
}
copyMenu.draw(ui::txtDiag);
}
}

View File

@ -8,153 +8,159 @@
ui::menu folderMenu;
namespace ui
void ui::folderMenuPrepare(data::user& usr, data::titledata& dat)
{
void folderMenuPrepare(data::user& usr, data::titledata& dat)
folderMenu.setParams(466, 98, 730);
folderMenu.reset();
dat.createDir();
fs::dirList list(dat.getPath());
folderMenu.addOpt("New");
for(unsigned i = 0; i < list.getCount(); i++)
folderMenu.addOpt(list.getItem(i));
folderMenu.adjust();
}
void ui::createNewBackup(const uint64_t& held)
{
std::string folder;
if(held & KEY_R)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
else if(held & KEY_L)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
else if(held & KEY_ZL)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE);
else
{
folderMenu.setParams(466, 98, 730);
folderMenu.reset();
dat.createDir();
fs::dirList list(dat.getPath());
folderMenu.addOpt("New");
for(unsigned i = 0; i < list.getCount(); i++)
folderMenu.addOpt(list.getItem(i));
folderMenu.adjust();
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().c_str(),
data::curData.getTitle().length() < 24 ? data::curData.getTitleSafe() : util::generateAbbrev(data::curData)
};
folder = util::getStringInput("", "Enter a folder name", 64, 7, dict);
}
void updateFolderMenu(const uint64_t& down, const uint64_t& held)
if(!folder.empty())
{
folderMenu.handleInput(down, held);
std::string path = data::curData.getPath() + "/" + folder;
mkdir(path.c_str(), 777);
path += "/";
fs::copyDirToDir("sv:/", path);
//Draw folder menu
folderMenu.draw(ui::txtCont);
folderMenuPrepare(data::curUser, data::curData);
}
}
data::curData.icon.draw(96, 98);
drawTextWrap(folderMenuInfo.c_str(), frameBuffer, ui::shared, 60, 370, 16, ui::txtCont, 360);
void ui::overwriteBackup(unsigned ind)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(ind);
if(confirm(data::holdOver, ui::confOverwrite.c_str(), folderName.c_str()))
{
std::string toPath = data::curData.getPath() + folderName + "/";
//Delete and recreate
fs::delDir(toPath);
mkdir(toPath.c_str(), 777);
if(down & KEY_A)
std::string root = "sv:/";
fs::copyDirToDir(root, toPath);
}
}
void ui::restoreBackup(unsigned ind)
{
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(ind);
if(confirm(data::holdRest, ui::confRestore.c_str(), folderName.c_str()))
{
if(folderMenu.getSelected() == 0)
if(data::autoBack)
{
std::string folder;
//Add back 3DS shortcut thing
if(held & KEY_R)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
else if(held & KEY_L)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
else if(held & KEY_ZL)
folder = 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().c_str(),
data::curData.getTitle().length() < 24 ? data::curData.getTitleSafe() : util::generateAbbrev(data::curData)
};
folder = util::getStringInput("", "Enter a folder name", 64, 7, dict);
}
if(!folder.empty())
{
std::string path = data::curData.getPath() + "/" + folder;
mkdir(path.c_str(), 777);
path += "/";
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(autoFolder.c_str(), 777);
autoFolder += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, path);
folderMenuPrepare(data::curUser, data::curData);
}
std::string root = "sv:/";
fs::copyDirToDir(root, autoFolder);
}
else
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(confirm(data::holdOver, ui::confOverwrite.c_str(), folderName.c_str()))
{
std::string toPath = data::curData.getPath() + folderName + "/";
//Delete and recreate
fs::delDir(toPath);
mkdir(toPath.c_str(), 777);
std::string fromPath = data::curData.getPath() + folderName + "/";
std::string root = "sv:/";
std::string root = "sv:/";
fs::copyDirToDir(root, toPath);
}
}
}
else if(down & KEY_Y)
{
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(confirm(data::holdRest, ui::confRestore.c_str(), folderName.c_str()))
{
if(data::autoBack)
{
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(autoFolder.c_str(), 777);
autoFolder += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, autoFolder);
}
std::string fromPath = data::curData.getPath() + folderName + "/";
std::string root = "sv:/";
fs::delDir(root);
fsdevCommitDevice("sv");
fs::copyDirToDirCommit(fromPath, root, "sv");
//Rescan init folder menu if autobak to show changes
if(data::autoBack)
folderMenuPrepare(data::curUser, data::curData);
}
}
}
else if(down & KEY_X)
{
if(folderMenu.getSelected() > 0)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(ui::confirmDelete(folderName))
{
std::string delPath = data::curData.getPath() + folderName + "/";
fs::delDir(delPath);
}
folderMenuPrepare(data::curUser, data::curData);
}
}
else if(down & KEY_MINUS)
{
advModePrep("sv:/", true);
mstate = ADV_MDE;
}
else if(down & KEY_ZR && data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
{
fs::delDir("sv:/");
fs::delDir(root);
fsdevCommitDevice("sv");
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
mstate = TTL_SEL;
fs::copyDirToDirCommit(fromPath, root, "sv");
//Rescan init folder menu if autobak to show changes
if(data::autoBack)
folderMenuPrepare(data::curUser, data::curData);
}
}
}
void ui::deleteBackup(unsigned ind)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(ui::confirmDelete(folderName))
{
std::string delPath = data::curData.getPath() + folderName + "/";
fs::delDir(delPath);
}
folderMenuPrepare(data::curUser, data::curData);
}
void ui::updateFolderMenu(const uint64_t& down, const uint64_t& held)
{
folderMenu.handleInput(down, held);
//Draw folder menu
folderMenu.draw(ui::txtCont);
data::curData.icon.draw(96, 98);
drawTextWrap(folderMenuInfo.c_str(), frameBuffer, ui::shared, 60, 370, 16, ui::txtCont, 360);
if(down & KEY_A)
{
if(folderMenu.getSelected() == 0)
ui::createNewBackup(held);
else
ui::overwriteBackup(folderMenu.getSelected() - 1);
}
else if(down & KEY_Y)
ui::restoreBackup(folderMenu.getSelected() - 1);
else if(down & KEY_X && folderMenu.getSelected() > 0)
ui::deleteBackup(folderMenu.getSelected() - 1);
else if(down & KEY_MINUS)
{
advModePrep("sv:/", true);
mstate = ADV_MDE;
}
else if(down & KEY_ZR && data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
{
fs::delDir("sv:/");
fsdevCommitDevice("sv");
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
mstate = TTL_SEL;
}
}

View File

@ -8,154 +8,153 @@
static const clr menuColorLight = clrCreateU32(0xFFF05032), menuColorDark = clrCreateU32(0xFFC5FF00);
namespace ui
void ui::menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW)
{
void menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW)
{
x = _x;
y = _y;
rW = _rW;
rY = _y;
}
x = _x;
y = _y;
rW = _rW;
rY = _y;
}
void menu::addOpt(const std::string& add)
void ui::menu::addOpt(const std::string& add)
{
if(textGetWidth(add.c_str(), ui::shared, 18) < rW - 32 || rW == 0)
opt.push_back(add);
else
{
if(textGetWidth(add.c_str(), ui::shared, 18) < rW - 32 || rW == 0)
opt.push_back(add);
else
std::string tmp;
for(unsigned i = 0; i < add.length(); )
{
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]);
uint32_t tmpChr = 0;
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&add.c_str()[i]);
tmp += add.substr(i, untCnt);
i += untCnt;
if(textGetWidth(tmp.c_str(), ui::shared, 18) >= rW - 32)
{
opt.push_back(tmp);
break;
}
tmp += add.substr(i, untCnt);
i += untCnt;
if(textGetWidth(tmp.c_str(), ui::shared, 18) >= rW - 32)
{
opt.push_back(tmp);
break;
}
}
}
void menu::editOpt(int ind, const std::string& ch)
{
opt[ind] = ch;
}
menu::~menu()
{
opt.clear();
}
void menu::handleInput(const uint64_t& down, const uint64_t& held)
{
if( (held & KEY_UP) || (held & KEY_DOWN))
fc++;
else
fc = 0;
if(fc > 10)
fc = 0;
int size = opt.size() - 1;
if((down & KEY_UP) || ((held & KEY_UP) && fc == 10))
{
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 & KEY_DOWN) || ((held & KEY_DOWN) && fc == 10))
{
selected++;
if(selected > size)
selected = 0;
if((selected > (start + 14)) && ((start + 14) < size))
start++;
if(selected == 0)
start = 0;
}
else if(down & KEY_RIGHT)
{
selected += 7;
if(selected > size)
selected = size;
if((selected - 14) > start)
start = selected - 14;
}
else if(down & KEY_LEFT)
{
selected -= 7;
if(selected < 0)
selected = 0;
if(selected < start)
start = selected;
}
}
void menu::draw(const clr& 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)
{
drawBoundBox(x, y + ((i - start) * 36), rW, 36, clrSh);
drawText(opt[i].c_str(), frameBuffer, shared, x + 8, (y + 8) + ((i - start) * 36), 18, ui::thmID == ColorSetId_Light ? menuColorLight : menuColorDark);
}
else
drawText(opt[i].c_str(), frameBuffer, shared, x + 8, (y + 8) + ((i - start) * 36), 18, textClr);
}
}
void menu::reset()
{
opt.clear();
start = 0;
selected = 0;
fc = 0;
}
void 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;
}
}
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 & KEY_UP) || (held & KEY_DOWN))
fc++;
else
fc = 0;
if(fc > 10)
fc = 0;
int size = opt.size() - 1;
if((down & KEY_UP) || ((held & KEY_UP) && fc == 10))
{
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 & KEY_DOWN) || ((held & KEY_DOWN) && fc == 10))
{
selected++;
if(selected > size)
selected = 0;
if((selected > (start + 14)) && ((start + 14) < size))
start++;
if(selected == 0)
start = 0;
}
else if(down & KEY_RIGHT)
{
selected += 7;
if(selected > size)
selected = size;
if((selected - 14) > start)
start = selected - 14;
}
else if(down & KEY_LEFT)
{
selected -= 7;
if(selected < 0)
selected = 0;
if(selected < start)
start = selected;
}
}
void ui::menu::draw(const clr& 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)
{
drawBoundBox(x, y + ((i - start) * 36), rW, 36, clrSh);
drawText(opt[i].c_str(), frameBuffer, shared, x + 8, (y + 8) + ((i - start) * 36), 18, ui::thmID == ColorSetId_Light ? menuColorLight : menuColorDark);
}
else
drawText(opt[i].c_str(), frameBuffer, shared, x + 8, (y + 8) + ((i - start) * 36), 18, textClr);
}
}
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;
}

View File

@ -26,243 +26,242 @@ static const std::string loadGlyphArray[] =
"\ue024", "\ue025", "\ue026", "\ue027"
};
namespace ui
void ui::progBar::update(const uint64_t& _prog)
{
void progBar::update(const uint64_t& _prog)
prog = _prog;
width = (float)(((float)prog / (float)max) * 576);
}
void ui::progBar::draw(const std::string& text, const std::string& head)
{
size_t headWidth = textGetWidth(head.c_str(), ui::shared, 20);
unsigned headX = (1280 / 2) - (headWidth / 2);
texDraw(diaBox, frameBuffer, 320, 150);
drawRect(frameBuffer, 320, 206, 640, 2, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFF6D6D6D) : clrCreateU32(0xFFCCCCCC));
drawRect(frameBuffer, 352, 530, 576, 12, clrCreateU32(0xFF666666));
drawRect(frameBuffer, 352, 530, (unsigned)width, 12, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFFC5FF00) : clrCreateU32(0xFFF05032));
texDraw(ui::progCovLeft, frameBuffer, 352, 530);
texDraw(ui::progCovRight, frameBuffer, 920, 530);
drawText(head.c_str(), frameBuffer, ui::shared, headX, 168, 20, ui::txtDiag);
drawTextWrap(text.c_str(), frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
}
void ui::showMessage(const char *head, const char *fmt, ...)
{
//fake focus
drawRectAlpha(frameBuffer, 0, 0, 1280, 720, clrCreateU32(0xAA0D0D0D));
char tmp[1024];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
unsigned headX = (640 / 2) - (textGetWidth(head, ui::shared, 20) / 2);
unsigned okX = (640 / 2) - (textGetWidth(okt, ui::shared, 20) / 2);
while(true)
{
prog = _prog;
hidScanInput();
width = (float)(((float)prog / (float)max) * 576);
}
uint64_t down = hidKeysDown(CONTROLLER_P1_AUTO);
void progBar::draw(const std::string& text, const std::string& head)
{
size_t headWidth = textGetWidth(head.c_str(), ui::shared, 20);
unsigned headX = (1280 / 2) - (headWidth / 2);
if(down)
break;
gfxBeginFrame();
texDraw(diaBox, frameBuffer, 320, 150);
drawRect(frameBuffer, 320, 206, 640, 2, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFF6D6D6D) : clrCreateU32(0xFFCCCCCC));
drawRect(frameBuffer, 352, 530, 576, 12, clrCreateU32(0xFF666666));
drawRect(frameBuffer, 352, 530, (unsigned)width, 12, ui::thmID == ColorSetId_Light ? clrCreateU32(0xFFC5FF00) : clrCreateU32(0xFFF05032));
texDraw(ui::progCovLeft, frameBuffer, 352, 530);
texDraw(ui::progCovRight, frameBuffer, 920, 530);
drawText(head.c_str(), frameBuffer, ui::shared, headX, 168, 20, ui::txtDiag);
drawTextWrap(text.c_str(), frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
drawText(head, frameBuffer, ui::shared, 320 + headX, 168, 20, ui::txtDiag);
drawTextWrap(tmp, frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
drawText(okt, frameBuffer, ui::shared, 320 + okX, 530, 20, ui::txtDiag);
gfxEndFrame();
}
}
void showMessage(const char *head, const char *fmt, ...)
bool ui::confirm(bool hold, const char *fmt, ...)
{
//fake focus
drawRectAlpha(frameBuffer, 0, 0, 1280, 720, clrCreateU32(0xAA0D0D0D));
char tmp[1024];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
bool ret = false, heldDown = false;
unsigned loadFrame = 0, holdCount = 0;
uint8_t holdClrDiff = 0;
clr holdClr = ui::txtDiag;
unsigned headX = (640 / 2) - (textGetWidth("Confirm", ui::shared, 20) / 2);
unsigned yesX = 160 - (textGetWidth(ui::yt.c_str(), ui::shared, 20) / 2);
unsigned noX = 160 - (textGetWidth(ui::nt.c_str(), ui::shared, 20) / 2);
std::string yesText = yt;
while(true)
{
//fake focus
drawRectAlpha(frameBuffer, 0, 0, 1280, 720, clrCreateU32(0xAA0D0D0D));
hidScanInput();
char tmp[1024];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
uint64_t down = hidKeysDown(CONTROLLER_P1_AUTO);
uint64_t held = hidKeysHeld(CONTROLLER_P1_AUTO);
unsigned headX = (640 / 2) - (textGetWidth(head, ui::shared, 20) / 2);
unsigned okX = (640 / 2) - (textGetWidth(okt, ui::shared, 20) / 2);
while(true)
if(hold && held & KEY_A)
{
hidScanInput();
uint64_t down = hidKeysDown(CONTROLLER_P1_AUTO);
if(down)
break;
gfxBeginFrame();
texDraw(diaBox, frameBuffer, 320, 150);
drawText(head, frameBuffer, ui::shared, 320 + headX, 168, 20, ui::txtDiag);
drawTextWrap(tmp, frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
drawText(okt, frameBuffer, ui::shared, 320 + okX, 530, 20, ui::txtDiag);
gfxEndFrame();
}
}
bool confirm(bool hold, const char *fmt, ...)
{
//fake focus
drawRectAlpha(frameBuffer, 0, 0, 1280, 720, clrCreateU32(0xAA0D0D0D));
char tmp[1024];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
bool ret = false, heldDown = false;
unsigned loadFrame = 0, holdCount = 0;
uint8_t holdClrDiff = 0;
clr holdClr = ui::txtDiag;
unsigned headX = (640 / 2) - (textGetWidth("Confirm", ui::shared, 20) / 2);
unsigned yesX = 160 - (textGetWidth(ui::yt.c_str(), ui::shared, 20) / 2);
unsigned noX = 160 - (textGetWidth(ui::nt.c_str(), ui::shared, 20) / 2);
std::string yesText = yt;
while(true)
{
hidScanInput();
uint64_t down = hidKeysDown(CONTROLLER_P1_AUTO);
uint64_t held = hidKeysHeld(CONTROLLER_P1_AUTO);
if(hold && held & KEY_A)
heldDown = true;
holdCount++, holdClrDiff++;
if(holdCount % 4 == 0)
{
heldDown = true;
holdCount++, holdClrDiff++;
if(holdCount % 4 == 0)
{
loadFrame++;
if(loadFrame > 7)
loadFrame = 0;
}
if(holdCount >= 120)
{
ret = true;
break;
}
if(holdCount <= 40)
yesText = "(Hold) ";
else if(holdCount <= 80)
yesText = "(Keep Holding) ";
else if(holdCount < 120)
yesText = "(Almost There!) ";
yesText += loadGlyphArray[loadFrame];
yesX = 160 - (textGetWidth(yesText.c_str(), ui::shared, 20) / 2);
loadFrame++;
if(loadFrame > 7)
loadFrame = 0;
}
else if(hold && heldDown)
{
//Reset everything
heldDown= false;
holdCount = 0, loadFrame = 0, holdClrDiff = 0;
yesX = 160 - (textGetWidth(ui::yt.c_str(), ui::shared, 20) / 2);
yesText = ui::yt;
holdClr = ui::txtDiag;
}
else if(down & KEY_A)
if(holdCount >= 120)
{
ret = true;
break;
}
else if(down & KEY_B)
{
ret = false;
break;
}
if(hold && heldDown)
{
if(ui::thmID == ColorSetId_Light)
holdClr = clrCreateRGBA(0xFF, 0xFF - holdClrDiff, 0xFF - holdClrDiff, 0xFF);
else
holdClr = clrCreateRGBA(0x25 + holdClrDiff, 0x00, 0x00, 0xFF);
}
if(holdCount <= 40)
yesText = "(Hold) ";
else if(holdCount <= 80)
yesText = "(Keep Holding) ";
else if(holdCount < 120)
yesText = "(Almost There!) ";
gfxBeginFrame();
texDraw(diaBox, frameBuffer, 320, 150);
drawText("Confirm", frameBuffer, ui::shared, 320 + headX, 168, 20, ui::txtDiag);
drawText(yesText.c_str(), frameBuffer, ui::shared, 320 + yesX, 530, 20, holdClr);
drawText(ui::nt.c_str(), frameBuffer, ui::shared, 860 - noX, 530, 20, ui::txtDiag);
drawTextWrap(tmp, frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
gfxEndFrame();
yesText += loadGlyphArray[loadFrame];
yesX = 160 - (textGetWidth(yesText.c_str(), ui::shared, 20) / 2);
}
return ret;
}
bool confirmTransfer(const std::string& f, const std::string& t)
{
return confirm(false, ui::confCopy.c_str(), f.c_str(), t.c_str());
}
bool confirmDelete(const std::string& p)
{
return confirm(data::holdDel, ui::confDel.c_str(), p.c_str());
}
void drawTextbox(tex *target, int x, int y, int w, int h)
{
//Top
texDraw(ui::cornerTopLeft, target, x, y);
drawRect(target, x + 32, y, w - 64, 32, ui::tboxClr);
texDraw(ui::cornerTopRight, target, (x + w) - 32, y);
//middle
drawRect(target, x, y + 32, w, h - 64, tboxClr);
//bottom
texDraw(ui::cornerBottomLeft, target, x, (y + h) - 32);
drawRect(target, x + 32, (y + h) - 32, w - 64, 32, tboxClr);
texDraw(ui::cornerBottomRight, target, (x + w) - 32, (y + h) - 32);
}
void drawTextboxInvert(tex *target, int x, int y, int w, int h)
{
clr temp = ui::tboxClr;
clrInvert(&temp);
//Top
texDrawInvert(ui::cornerTopLeft, target, x, y);
drawRect(target, x + 32, y, w - 64, 32, temp);
texDrawInvert(ui::cornerTopRight, target, (x + w) - 32, y);
//middle
drawRect(target, x, y + 32, w, h - 64, temp);
//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);
}
void showPopup(const std::string& mess, unsigned frames)
{
frameCount = 0;
frameHold = frames;
popWidth = textGetWidth(mess.c_str(), ui::shared, 24) + 32;
popX = 640 - (popWidth / 2);
popText = mess;
popY = 721;
popState = popRise;
popDraw = true;
}
void drawPopup(const uint64_t& down)
{
if(!popDraw)
return;
switch(popState)
else if(hold && heldDown)
{
case popRise:
if(popY > 560)
popY -= 24;
else
popState = popShow;
break;
case popShow:
if(frameCount++ >= frameHold || down)
popState = popFall;
break;
case popFall:
if(popY < 721)
popY += 24;
else
popDraw = false;
break;
//Reset everything
heldDown= false;
holdCount = 0, loadFrame = 0, holdClrDiff = 0;
yesX = 160 - (textGetWidth(ui::yt.c_str(), ui::shared, 20) / 2);
yesText = ui::yt;
holdClr = ui::txtDiag;
}
else if(down & KEY_A)
{
ret = true;
break;
}
else if(down & KEY_B)
{
ret = false;
break;
}
drawTextbox(frameBuffer, popX, popY, popWidth, 64);
drawText(popText.c_str(), frameBuffer, ui::shared, popX + 16, popY + 20, 24, ui::txtDiag);
if(hold && heldDown)
{
if(ui::thmID == ColorSetId_Light)
holdClr = clrCreateRGBA(0xFF, 0xFF - holdClrDiff, 0xFF - holdClrDiff, 0xFF);
else
holdClr = clrCreateRGBA(0x25 + holdClrDiff, 0x00, 0x00, 0xFF);
}
gfxBeginFrame();
texDraw(diaBox, frameBuffer, 320, 150);
drawText("Confirm", frameBuffer, ui::shared, 320 + headX, 168, 20, ui::txtDiag);
drawText(yesText.c_str(), frameBuffer, ui::shared, 320 + yesX, 530, 20, holdClr);
drawText(ui::nt.c_str(), frameBuffer, ui::shared, 860 - noX, 530, 20, ui::txtDiag);
drawTextWrap(tmp, frameBuffer, ui::shared, 352, 230, 16, ui::txtDiag, 576);
gfxEndFrame();
}
return ret;
}
bool ui::confirmTransfer(const std::string& f, const std::string& t)
{
return confirm(false, ui::confCopy.c_str(), f.c_str(), t.c_str());
}
bool ui::confirmDelete(const std::string& p)
{
return confirm(data::holdDel, ui::confDel.c_str(), p.c_str());
}
void ui::drawTextbox(tex *target, int x, int y, int w, int h)
{
//Top
texDraw(ui::cornerTopLeft, target, x, y);
drawRect(target, x + 32, y, w - 64, 32, ui::tboxClr);
texDraw(ui::cornerTopRight, target, (x + w) - 32, y);
//middle
drawRect(target, x, y + 32, w, h - 64, tboxClr);
//bottom
texDraw(ui::cornerBottomLeft, target, x, (y + h) - 32);
drawRect(target, x + 32, (y + h) - 32, w - 64, 32, tboxClr);
texDraw(ui::cornerBottomRight, target, (x + w) - 32, (y + h) - 32);
}
void ui::drawTextboxInvert(tex *target, int x, int y, int w, int h)
{
clr temp = ui::tboxClr;
clrInvert(&temp);
//Top
texDrawInvert(ui::cornerTopLeft, target, x, y);
drawRect(target, x + 32, y, w - 64, 32, temp);
texDrawInvert(ui::cornerTopRight, target, (x + w) - 32, y);
//middle
drawRect(target, x, y + 32, w, h - 64, temp);
//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);
}
void ui::showPopup(const std::string& mess, unsigned frames)
{
frameCount = 0;
frameHold = frames;
popWidth = textGetWidth(mess.c_str(), ui::shared, 24) + 32;
popX = 640 - (popWidth / 2);
popText = mess;
popY = 721;
popState = popRise;
popDraw = true;
}
void ui::drawPopup(const uint64_t& down)
{
if(!popDraw)
return;
switch(popState)
{
case popRise:
if(popY > 560)
popY -= 24;
else
popState = popShow;
break;
case popShow:
if(frameCount++ >= frameHold || down)
popState = popFall;
break;
case popFall:
if(popY < 721)
popY += 24;
else
popDraw = false;
break;
}
drawTextbox(frameBuffer, popX, popY, popWidth, 64);
drawText(popText.c_str(), frameBuffer, ui::shared, popX + 16, popY + 20, 24, ui::txtDiag);
}

View File

@ -7,181 +7,180 @@
#include "util.h"
#include "ex.h"
namespace ui
void ui::updateTitleMenu(const uint64_t& down, const uint64_t& held)
{
void updateTitleMenu(const uint64_t& down, const uint64_t& held)
//Static vars so they don't change on every loop
//Where to start in titles, selected title
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;
if(clrAdd)
{
//Static vars so they don't change on every loop
//Where to start in titles, selected title
static int start = 0;
clrShft += 6;
if(clrShft >= 0x72)
clrAdd = false;
}
else
{
clrShft -= 3;
if(clrShft <= 0)
clrAdd = true;
}
//Color shift for rect
static uint8_t clrShft = 0;
//Whether or not we're adding or subtracting from clrShft
static bool clrAdd = true;
unsigned x = 70, y = 98;
//Selected rectangle X and Y.
static unsigned selRectX = 66, selRectY = 94;
unsigned endTitle = start + 32;
if(start + 32 > (int)data::curUser.titles.size())
endTitle = data::curUser.titles.size();
if(clrAdd)
//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)
{
clrShft += 6;
if(clrShft >= 0x72)
clrAdd = false;
}
else
{
clrShft -= 3;
if(clrShft <= 0)
clrAdd = true;
}
if(i == endTitle)
break;
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((int)i == data::selData)
{
if(i == endTitle)
break;
selRectX = tX - 6;
selRectY = y - 6;
if((int)i == data::selData)
{
selRectX = tX - 6;
selRectY = y - 6;
std::string title = data::curUser.titles[data::selData].getTitle();
unsigned titleWidth = textGetWidth(title.c_str(), ui::shared, 18);
int rectWidth = titleWidth + 32, rectX = (tX + 64) - (rectWidth / 2);
if(rectX < 16)
rectX = 16;
else if(rectX + rectWidth > 1264)
rectX = 1264 - rectWidth;
std::string title = data::curUser.titles[data::selData].getTitle();
unsigned titleWidth = textGetWidth(title.c_str(), ui::shared, 18);
int rectWidth = titleWidth + 32, rectX = (tX + 64) - (rectWidth / 2);
if(rectX < 16)
rectX = 16;
else if(rectX + rectWidth > 1264)
rectX = 1264 - rectWidth;
drawTextbox(frameBuffer, rectX, y - 50, rectWidth, 38);
drawText(title.c_str(), frameBuffer, ui::shared, rectX + 16, y - 40, 18, ui::txtDiag);
}
if(data::curUser.titles[i].getFav())
data::curUser.titles[i].icon.drawFavHalf(tX, y);
else
data::curUser.titles[i].icon.drawHalf(tX, y);
drawTextbox(frameBuffer, rectX, y - 50, rectWidth, 38);
drawText(title.c_str(), frameBuffer, ui::shared, rectX + 16, y - 40, 18, ui::txtDiag);
}
}
if(down & KEY_RIGHT)
{
if(data::selData < (int)data::curUser.titles.size() - 1)
data::selData++;
if(data::selData >= (int)start + 32)
start += 8;
}
else if(down & KEY_LEFT)
{
if(data::selData > 0)
data::selData--;
if(data::selData < (int)start)
start -= 8;
}
else if(down & KEY_UP)
{
data::selData -= 8;
if(data::selData < 0)
data::selData = 0;
if(data::selData < start)
start -= 8;
}
else if(down & KEY_DOWN)
{
data::selData += 8;
if(data::selData > (int)data::curUser.titles.size() - 1)
data::selData = data::curUser.titles.size() - 1;
if(data::selData - start >= 32)
start += 8;
}
else if(down & KEY_A)
{
data::curData = data::curUser.titles[data::selData];
if(fs::mountSave(data::curUser, data::curData))
{
folderMenuPrepare(data::curUser, data::curData);
//Wanna change this sometime
ui::folderMenuInfo = util::getInfoString(data::curUser, data::curData);
mstate = FLD_SEL;
}
}
else if(down & KEY_Y)
fs::dumpAllUserSaves(data::curUser);
else if(down & KEY_X)
{
if(ui::confirm(false, ui::confBlackList.c_str(), data::curUser.titles[data::selData].getTitle().c_str()))
data::blacklistAdd(data::curUser, data::curUser.titles[data::selData]);
}
else if(down & KEY_B)
{
start = 0;
data::selData = 0;
selRectX = 64;
selRectY = 90;
mstate = USR_SEL;
return;
}
else if(down & KEY_L)
{
if(--data::selUser < 0)
data::selUser = data::users.size() - 1;
start = 0;
data::selData = 0;
selRectX = 64, selRectY = 90;
data::curUser = data::users[data::selUser];
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_R)
{
if(++data::selUser > (int)data::users.size() - 1)
data::selUser = 0;
start = 0;
data::selData = 0;
selRectX = 64, selRectY = 90;
data::curUser = data::users[data::selUser];
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_ZR)
{
data::titledata tempData = data::curUser.titles[data::selData];
if(tempData.getType() == FsSaveDataType_System)
ui::showMessage("*NO*", "Deleting system save archives is disabled.");
else if(confirm(true, ui::confEraseNand.c_str(), tempData.getTitle().c_str()))
{
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tempData.getSaveID());
data::rescanTitles();
data::curUser = data::users[data::selUser];
data::selData = 0;
}
}
else if(down & KEY_MINUS)
{
if(!data::curUser.titles[data::selData].getFav())
data::favoriteAdd(data::curUser, data::curUser.titles[data::selData]);
if(data::curUser.titles[i].getFav())
data::curUser.titles[i].icon.drawFavHalf(tX, y);
else
data::favoriteRemove(data::curUser, data::curUser.titles[data::selData]);
data::curUser.titles[i].icon.drawHalf(tX, y);
}
}
if(down & KEY_RIGHT)
{
if(data::selData < (int)data::curUser.titles.size() - 1)
data::selData++;
if(data::selData >= (int)start + 32)
start += 8;
}
else if(down & KEY_LEFT)
{
if(data::selData > 0)
data::selData--;
if(data::selData < (int)start)
start -= 8;
}
else if(down & KEY_UP)
{
data::selData -= 8;
if(data::selData < 0)
data::selData = 0;
if(data::selData < start)
start -= 8;
}
else if(down & KEY_DOWN)
{
data::selData += 8;
if(data::selData > (int)data::curUser.titles.size() - 1)
data::selData = data::curUser.titles.size() - 1;
if(data::selData - start >= 32)
start += 8;
}
else if(down & KEY_A)
{
data::curData = data::curUser.titles[data::selData];
if(fs::mountSave(data::curUser, data::curData))
{
folderMenuPrepare(data::curUser, data::curData);
//Wanna change this sometime
ui::folderMenuInfo = util::getInfoString(data::curUser, data::curData);
mstate = FLD_SEL;
}
}
else if(down & KEY_Y)
fs::dumpAllUserSaves(data::curUser);
else if(down & KEY_MINUS)
{
if(ui::confirm(false, ui::confBlacklist.c_str(), data::curUser.titles[data::selData].getTitle().c_str()))
data::blacklistAdd(data::curUser, data::curUser.titles[data::selData]);
}
else if(down & KEY_B)
{
start = 0;
data::selData = 0;
selRectX = 64;
selRectY = 90;
mstate = USR_SEL;
return;
}
else if(down & KEY_L)
{
if(--data::selUser < 0)
data::selUser = data::users.size() - 1;
start = 0;
data::selData = 0;
selRectX = 64, selRectY = 90;
data::curUser = data::users[data::selUser];
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_R)
{
if(++data::selUser > (int)data::users.size() - 1)
data::selUser = 0;
start = 0;
data::selData = 0;
selRectX = 64, selRectY = 90;
data::curUser = data::users[data::selUser];
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_ZR)
{
data::titledata tempData = data::curUser.titles[data::selData];
if(tempData.getType() == FsSaveDataType_System)
ui::showMessage("*NO*", "Deleting system save archives is disabled.");
else if(confirm(true, ui::confEraseNand.c_str(), tempData.getTitle().c_str()))
{
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tempData.getSaveID());
data::rescanTitles();
data::curUser = data::users[data::selUser];
data::selData = 0;
}
}
else if(down & KEY_X)
{
if(!data::curUser.titles[data::selData].getFav())
data::favoriteAdd(data::curUser, data::curUser.titles[data::selData]);
else
data::favoriteRemove(data::curUser, data::curUser.titles[data::selData]);
}
}

View File

@ -37,534 +37,421 @@ static inline void switchBool(bool& sw)
static inline std::string getBoolText(bool b)
{
return b ? "On" : "Off";
return b ? ui::on : ui::off;
}
namespace ui
void textFolderPrep(data::user& usr, data::titledata& dat)
{
void textUserPrep()
folderMenu.setParams(466, 98, 730);
folderMenu.reset();
dat.createDir();
fs::dirList list(dat.getPath());
folderMenu.addOpt("New");
for(unsigned i = 0; i < list.getCount(); i++)
folderMenu.addOpt(list.getItem(i));
folderMenu.adjust();
}
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++)
{
userMenu.reset();
userMenu.setParams(76, 98, 310);
for(unsigned i = 0; i < data::users.size(); i++)
userMenu.addOpt(data::users[i].getUsername());
if(u.titles[i].getFav())
titleMenu.addOpt("" + u.titles[i].getTitle());
else
titleMenu.addOpt(u.titles[i].getTitle());
}
}
void textTitlePrep(data::user& u)
void ui::textUserMenuUpdate(const uint64_t& down, const uint64_t& held)
{
userMenu.handleInput(down, held);
userMenu.draw(ui::txtCont);
if(down & KEY_A)
{
titleMenu.reset();
titleMenu.setParams(76, 98, 310);
for(unsigned i = 0; i < u.titles.size(); i++)
if(data::users[userMenu.getSelected()].titles.size() > 0)
{
if(u.titles[i].getFav())
titleMenu.addOpt("" + u.titles[i].getTitle());
else
titleMenu.addOpt(u.titles[i].getTitle());
}
}
void textFolderPrep(data::user& usr, data::titledata& dat)
{
folderMenu.setParams(466, 98, 730);
folderMenu.reset();
dat.createDir();
fs::dirList list(dat.getPath());
folderMenu.addOpt("New");
for(unsigned i = 0; i < list.getCount(); i++)
folderMenu.addOpt(list.getItem(i));
folderMenu.adjust();
}
void textUserMenuUpdate(const uint64_t& down, const uint64_t& held)
{
userMenu.handleInput(down, held);
userMenu.draw(ui::txtCont);
if(down & KEY_A)
{
if(data::users[userMenu.getSelected()].titles.size() > 0)
{
data::curUser = data::users[userMenu.getSelected()];
textTitlePrep(data::curUser);
mstate = TXT_TTL;
}
else
ui::showPopup("No saves available for " + data::users[userMenu.getSelected()].getUsername() + ".", POP_FRAME_DEFAULT);
}
else if(down & KEY_Y)
{
for(unsigned i = 0; i < data::users.size(); i++)
fs::dumpAllUserSaves(data::users[i]);
}
else if(down & KEY_X)
{
ui::textMode = false;
mstate = USR_SEL;
}
else if(down & KEY_ZR)
{
fs::unmountSave();
ui::exMenuPrep();
ui::mstate = EX_MNU;
}
else if(down & KEY_MINUS)
ui::mstate = OPT_MNU;
}
void textTitleMenuUpdate(const uint64_t& down, const uint64_t& held)
{
titleMenu.handleInput(down, held);
titleMenu.draw(ui::txtCont);
if(down & KEY_A)
{
data::curData = data::curUser.titles[titleMenu.getSelected()];
if(fs::mountSave(data::curUser, data::curData))
{
textFolderPrep(data::curUser, data::curData);
mstate = TXT_FLD;
}
}
else if(down & KEY_Y)
{
fs::dumpAllUserSaves(data::curUser);
}
else if(down & KEY_X)
{
if(ui::confirm(false, ui::confBlackList.c_str(), data::curUser.titles[titleMenu.getSelected()].getTitle().c_str()))
data::blacklistAdd(data::curUser, data::curUser.titles[titleMenu.getSelected()]);
data::curUser = data::users[userMenu.getSelected()];
textTitlePrep(data::curUser);
}
else if(down & KEY_L)
{
if(--data::selUser < 0)
data::selUser = data::users.size() - 1;
data::curUser = data::users[data::selUser];
textTitlePrep(data::curUser);
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_R)
{
if(++data::selUser > (int)data::users.size() - 1)
data::selUser = 0;
data::curUser = data::users[data::selUser];
textTitlePrep(data::curUser);
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_MINUS)
{
unsigned sel = titleMenu.getSelected();
if(!data::curUser.titles[sel].getFav())
data::favoriteAdd(data::curUser, data::curUser.titles[sel]);
else
data::favoriteRemove(data::curUser, data::curUser.titles[sel]);
textTitlePrep(data::curUser);
}
else if(down & KEY_ZR)
{
data::titledata tempData = data::curUser.titles[titleMenu.getSelected()];
if(tempData.getType() == FsSaveDataType_System)
ui::showMessage("*NO*", "Deleting system save archives is disabled.");
else if(confirm(true, ui::confEraseNand.c_str(), tempData.getTitle().c_str()))
{
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tempData.getSaveID());
data::rescanTitles();
data::curUser = data::users[data::selUser];
ui::textTitlePrep(data::curUser);
}
}
else if(down & KEY_B)
mstate = TXT_USR;
}
void textFolderMenuUpdate(const uint64_t& down, const uint64_t& held)
{
titleMenu.draw(ui::txtCont);
folderMenu.handleInput(down, held);
folderMenu.draw(ui::txtCont);
if(down & KEY_A)
{
if(folderMenu.getSelected() == 0)
{
std::string folder;
//Add back 3DS shortcut thing
if(held & KEY_R)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
else if(held & KEY_L)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
else if(held & KEY_ZL)
folder = 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().c_str(),
data::curData.getTitle().length() < 24 ? data::curData.getTitleSafe() : util::generateAbbrev(data::curData)
};
folder = util::getStringInput("", "New Folder", 64, 7, dict);
}
if(!folder.empty())
{
std::string path = data::curData.getPath() + folder;
mkdir(path.c_str(), 777);
path += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, path);
textFolderPrep(data::curUser, data::curData);
}
}
else
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(confirm(data::holdOver, ui::confOverwrite.c_str(), folderName.c_str()))
{
std::string toPath = data::curData.getPath() + folderName + "/";
//Delete and recreate
fs::delDir(toPath);
mkdir(toPath.c_str(), 777);
std::string root = "sv:/";
fs::copyDirToDir(root, toPath);
}
}
}
else if(down & KEY_Y)
{
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(confirm(data::holdRest, ui::confRestore.c_str(), folderName.c_str()))
{
if(data::autoBack)
{
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(autoFolder.c_str(), 777);
autoFolder += "/";
std::string root = "sv:/";
fs::copyDirToDir(root, autoFolder);
}
std::string fromPath = data::curData.getPath() + folderName + "/";
std::string root = "sv:/";
fs::delDir(root);
fsdevCommitDevice("sv");
fs::copyDirToDirCommit(fromPath, root, "sv");
if(data::autoBack)
folderMenuPrepare(data::curUser, data::curData);
}
}
}
else if(down & KEY_X)
{
if(folderMenu.getSelected() > 0)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(ui::confirmDelete(folderName))
{
std::string delPath = data::curData.getPath() + folderName + "/";
fs::delDir(delPath);
}
textFolderPrep(data::curUser, data::curData);
}
}
else if(down & KEY_MINUS)
{
advModePrep("sv:/", true);
mstate = ADV_MDE;
}
else if(down & KEY_ZR && data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
{
fs::delDir("sv:/");
fsdevCommitDevice("sv");
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
mstate = TXT_TTL;
}
else
ui::showPopup("No saves available for " + data::users[userMenu.getSelected()].getUsername() + ".", POP_FRAME_DEFAULT);
}
void exMenuPrep()
else if(down & KEY_Y)
{
exMenu.reset();
exMenu.setParams(76, 98, 310);
exMenu.addOpt("SD to SD Browser");
exMenu.addOpt("Bis: PRODINFOF");
exMenu.addOpt("Bis: SAFE");
exMenu.addOpt("Bis: SYSTEM");
exMenu.addOpt("Bis: USER");
exMenu.addOpt("Remove Downloaded Update");
exMenu.addOpt("Terminate Process ID");
exMenu.addOpt("Mount System Save ID");
exMenu.addOpt("Rescan Titles");
exMenu.addOpt("Mount Process RomFS");
for(unsigned i = 0; i < data::users.size(); i++)
fs::dumpAllUserSaves(data::users[i]);
}
void updateExMenu(const uint64_t& down, const uint64_t& held)
else if(down & KEY_X)
{
exMenu.handleInput(down, held);
ui::textMode = false;
mstate = USR_SEL;
}
else if(down & KEY_ZR)
{
fs::unmountSave();
ui::exMenuPrep();
ui::mstate = EX_MNU;
}
else if(down & KEY_MINUS)
ui::mstate = OPT_MNU;
}
if(down & KEY_A)
void ui::textTitleMenuUpdate(const uint64_t& down, const uint64_t& held)
{
titleMenu.handleInput(down, held);
titleMenu.draw(ui::txtCont);
if(down & KEY_A)
{
data::curData = data::curUser.titles[titleMenu.getSelected()];
if(fs::mountSave(data::curUser, data::curData))
{
fsdevUnmountDevice("sv");
FsFileSystem sv;
data::curData.setType(FsSaveDataType_System);
switch(exMenu.getSelected())
{
case 0:
data::curData.setType(FsSaveDataType_Bcat);
advModePrep("sdmc:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 1:
fsdevUnmountDevice("sv");
fsOpenBisFileSystem(&sv, FsBisPartitionId_CalibrationFile, "");
fsdevMountDevice("prodInfo-f", sv);
advModePrep("profInfo-f:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 2:
fsOpenBisFileSystem(&sv, FsBisPartitionId_SafeMode, "");
fsdevMountDevice("safe", sv);
advModePrep("safe:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 3:
fsOpenBisFileSystem(&sv, FsBisPartitionId_System, "");
fsdevMountDevice("sys", sv);
advModePrep("sys:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 4:
fsOpenBisFileSystem(&sv, FsBisPartitionId_User, "");
fsdevMountDevice("user", sv);
advModePrep("user:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
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:/", true);
data::curData.setType(FsSaveDataType_SystemBcat);
prevState = EX_MNU;
mstate = ADV_MDE;
}
}
break;
case 8:
data::rescanTitles();
break;
case 9:
{
FsFileSystem tromfs;
Result res = fsOpenDataFileSystemByCurrentProcess(&tromfs);
//Result res = romfsMountFromCurrentProcess("tromfs"); << Works too, but is kinda weird
if(R_SUCCEEDED(res))
{
fsdevMountDevice("tromfs", tromfs);
advModePrep("tromfs:/", false);
data::curData.setType(FsSaveDataType_System);
ui::mstate = ADV_MDE;
ui::prevState = EX_MNU;
}
}
break;
}
textFolderPrep(data::curUser, data::curData);
mstate = TXT_FLD;
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
if(ui::textMode)
mstate = TXT_USR;
else
mstate = USR_SEL;
prevState = USR_SEL;
}
exMenu.draw(ui::txtCont);
}
void optMenuInit()
else if(down & KEY_Y)
{
optMenu.setParams(76, 98, 310);
optMenu.addOpt("Inc. Dev Sv");
optMenu.addOpt("Auto Backup");
optMenu.addOpt("OverClock");
optMenu.addOpt("Hold to Delete");
optMenu.addOpt("Hold to Restore");
optMenu.addOpt("Hold to Overwrite");
optMenu.addOpt("Force Mount");
optMenu.addOpt("Account Sys Saves");
optMenu.addOpt("Write to Sys Saves");
optMenu.addOpt("Text UI Mode");
optMenu.addOpt("Direct FS");
optMenu.addOpt("Skip User");
fs::dumpAllUserSaves(data::curUser);
}
void updateOptMenu(const uint64_t& down, const uint64_t& held)
else if(down & KEY_MINUS)
{
optMenu.handleInput(down, held);
if(ui::confirm(false, ui::confBlacklist.c_str(), data::curUser.titles[titleMenu.getSelected()].getTitle().c_str()))
data::blacklistAdd(data::curUser, data::curUser.titles[titleMenu.getSelected()]);
//Update Menu Options to reflect changes
optMenu.editOpt(0, "Include Dev Sv: " + getBoolText(data::incDev));
optMenu.editOpt(1, "Auto Backup: " + getBoolText(data::autoBack));
optMenu.editOpt(2, "Overclock: " + getBoolText(data::ovrClk));
optMenu.editOpt(3, "Hold to Delete: " + getBoolText(data::holdDel));
optMenu.editOpt(4, "Hold to Restore: " + getBoolText(data::holdRest));
optMenu.editOpt(5, "Hold to Overwrite: " + getBoolText(data::holdOver));
optMenu.editOpt(6, "Force Mount: " + getBoolText(data::forceMount));
optMenu.editOpt(7, "Account Sys. Saves: " + getBoolText(data::accSysSave));
optMenu.editOpt(8, "Write To Sys. Saves: " + getBoolText(data::sysSaveWrite));
optMenu.editOpt(9, "Text UI Mode: " + getBoolText(ui::textMode));
optMenu.editOpt(10, "Direct FS Cmd: " + getBoolText(data::directFsCmd));
optMenu.editOpt(11, "Skip User Menu: " + getBoolText(data::skipUser));
textTitlePrep(data::curUser);
}
else if(down & KEY_L)
{
if(--data::selUser < 0)
data::selUser = data::users.size() - 1;
if(down & KEY_A)
data::curUser = data::users[data::selUser];
textTitlePrep(data::curUser);
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_R)
{
if(++data::selUser > (int)data::users.size() - 1)
data::selUser = 0;
data::curUser = data::users[data::selUser];
textTitlePrep(data::curUser);
ui::showPopup(data::curUser.getUsername(), POP_FRAME_DEFAULT);
}
else if(down & KEY_X)
{
unsigned sel = titleMenu.getSelected();
if(!data::curUser.titles[sel].getFav())
data::favoriteAdd(data::curUser, data::curUser.titles[sel]);
else
data::favoriteRemove(data::curUser, data::curUser.titles[sel]);
textTitlePrep(data::curUser);
}
else if(down & KEY_ZR)
{
data::titledata tempData = data::curUser.titles[titleMenu.getSelected()];
if(tempData.getType() == FsSaveDataType_System)
ui::showMessage("*NO*", "Deleting system save archives is disabled.");
else if(confirm(true, ui::confEraseNand.c_str(), tempData.getTitle().c_str()))
{
switch(optMenu.getSelected())
{
case 0:
switchBool(data::incDev);
break;
fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tempData.getSaveID());
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;
}
data::rescanTitles();
data::curUser = data::users[data::selUser];
ui::textTitlePrep(data::curUser);
}
else if(down & KEY_B)
ui::mstate = ui::textMode ? TXT_USR : USR_SEL;
}
else if(down & KEY_B)
mstate = TXT_USR;
}
optMenu.draw(ui::txtCont);
drawTextWrap(optHelpStrings[optMenu.getSelected()].c_str(), frameBuffer, ui::shared, 466, 98, 18, ui::txtCont, 730);
void ui::textFolderMenuUpdate(const uint64_t& down, const uint64_t& held)
{
titleMenu.draw(ui::txtCont);
folderMenu.handleInput(down, held);
folderMenu.draw(ui::txtCont);
if(down & KEY_A)
{
if(folderMenu.getSelected() == 0)
createNewBackup(held);
else
overwriteBackup(folderMenu.getSelected() - 1);
}
else if(down & KEY_Y)
restoreBackup(folderMenu.getSelected() - 1);
else if(down & KEY_X)
deleteBackup(folderMenu.getSelected() - 1);
else if(down & KEY_MINUS)
{
advModePrep("sv:/", true);
mstate = ADV_MDE;
}
else if(down & KEY_ZR && data::curData.getType() != FsSaveDataType_System && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
{
fs::delDir("sv:/");
fsdevCommitDevice("sv");
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
mstate = TXT_TTL;
}
}
void ui::exMenuPrep()
{
exMenu.reset();
exMenu.setParams(76, 98, 310);
for(unsigned i = 0; i < 10; i++)
exMenu.addOpt(ui::exMenuStr[i]);
}
void ui::updateExMenu(const uint64_t& down, const uint64_t& held)
{
exMenu.handleInput(down, held);
if(down & KEY_A)
{
fsdevUnmountDevice("sv");
FsFileSystem sv;
data::curData.setType(FsSaveDataType_System);
switch(exMenu.getSelected())
{
case 0:
data::curData.setType(FsSaveDataType_Bcat);
advModePrep("sdmc:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 1:
fsdevUnmountDevice("sv");
fsOpenBisFileSystem(&sv, FsBisPartitionId_CalibrationFile, "");
fsdevMountDevice("prodInfo-f", sv);
advModePrep("profInfo-f:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 2:
fsOpenBisFileSystem(&sv, FsBisPartitionId_SafeMode, "");
fsdevMountDevice("safe", sv);
advModePrep("safe:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 3:
fsOpenBisFileSystem(&sv, FsBisPartitionId_System, "");
fsdevMountDevice("sys", sv);
advModePrep("sys:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
break;
case 4:
fsOpenBisFileSystem(&sv, FsBisPartitionId_User, "");
fsdevMountDevice("user", sv);
advModePrep("user:/", false);
mstate = ADV_MDE;
prevState = EX_MNU;
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:/", true);
data::curData.setType(FsSaveDataType_SystemBcat);
prevState = EX_MNU;
mstate = ADV_MDE;
}
}
break;
case 8:
data::rescanTitles();
break;
case 9:
{
FsFileSystem tromfs;
Result res = fsOpenDataFileSystemByCurrentProcess(&tromfs);
//Result res = romfsMountFromCurrentProcess("tromfs"); << Works too, but is kinda weird
if(R_SUCCEEDED(res))
{
fsdevMountDevice("tromfs", tromfs);
advModePrep("tromfs:/", false);
data::curData.setType(FsSaveDataType_System);
ui::mstate = ADV_MDE;
ui::prevState = EX_MNU;
}
}
break;
}
}
else if(down & KEY_B)
{
fsdevUnmountDevice("sv");
if(ui::textMode)
mstate = TXT_USR;
else
mstate = USR_SEL;
prevState = USR_SEL;
}
exMenu.draw(ui::txtCont);
}
void ui::optMenuInit()
{
optMenu.setParams(76, 98, 310);
for(unsigned i = 0; i < 12; 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));
if(down & KEY_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;
}
}
else if(down & KEY_B)
ui::mstate = ui::textMode ? TXT_USR : USR_SEL;
optMenu.draw(ui::txtCont);
drawTextWrap(optHelpStrings[optMenu.getSelected()].c_str(), frameBuffer, ui::shared, 466, 98, 18, ui::txtCont, 730);
}

View File

@ -7,112 +7,111 @@
#include "uiupdate.h"
#include "file.h"
namespace ui
void ui::updateUserMenu(const uint64_t& down, const uint64_t& held)
{
void updateUserMenu(const uint64_t& down, const uint64_t& held)
//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 = 364, selRectY = 160;
if(clrAdd)
{
//Static so they don't get reset every loop
static int start = 0;
clrShft += 6;
if(clrShft >= 0x72)
clrAdd = false;
}
else
{
clrShft -= 3;
if(clrShft <= 0)
clrAdd = true;
}
static uint8_t clrShft = 0;
static bool clrAdd = true;
unsigned x = 368, y = 164;
unsigned endUser = data::users.size();
static unsigned selRectX = 364, selRectY = 160;
drawBoundBox(selRectX, selRectY, 140, 140, clrShft);
if(clrAdd)
for(unsigned i = start; i < endUser; y += 136)
{
unsigned endRow = i + 4;
for(unsigned tX = x; i < endRow; i++, tX += 144)
{
clrShft += 6;
if(clrShft >= 0x72)
clrAdd = false;
}
else
{
clrShft -= 3;
if(clrShft <= 0)
clrAdd = true;
}
if(i == endUser)
break;
unsigned x = 368, y = 164;
unsigned endUser = data::users.size();
drawBoundBox(selRectX, selRectY, 140, 140, clrShft);
for(unsigned i = start; i < endUser; y += 136)
{
unsigned endRow = i + 4;
for(unsigned tX = x; i < endRow; i++, tX += 144)
if((int)i == data::selUser)
{
if(i == endUser)
break;
selRectX = tX - 6;
selRectY = y - 6;
if((int)i == data::selUser)
{
selRectX = tX - 6;
selRectY = y - 6;
std::string username = data::users[data::selUser].getUsername();
unsigned userWidth = textGetWidth(username.c_str(), ui::shared, 18);
int userRectWidth = userWidth + 32, userRectX = (tX + 64) - (userRectWidth / 2);
if(userRectX < 16)
userRectX = 16;
else if(userRectX + userRectWidth > 1264)
userRectX = 1264 - userRectWidth;
std::string username = data::users[data::selUser].getUsername();
unsigned userWidth = textGetWidth(username.c_str(), ui::shared, 18);
int userRectWidth = userWidth + 32, userRectX = (tX + 64) - (userRectWidth / 2);
if(userRectX < 16)
userRectX = 16;
else if(userRectX + userRectWidth > 1264)
userRectX = 1264 - userRectWidth;
drawTextbox(frameBuffer, userRectX, y - 50, userRectWidth, 38);
drawText(username.c_str(), frameBuffer, ui::shared, userRectX + 16, y - 40, 18, ui::txtDiag);
}
data::users[i].drawIconHalf(tX, y);
drawTextbox(frameBuffer, userRectX, y - 50, userRectWidth, 38);
drawText(username.c_str(), frameBuffer, ui::shared, userRectX + 16, y - 40, 18, ui::txtDiag);
}
}
if(down & KEY_RIGHT && data::selUser < (int)data::users.size() - 1)
data::selUser++;
else if(down & KEY_LEFT && data::selUser > 0)
data::selUser--;
else if(down & KEY_UP)
{
data::selUser -= 4;
if(data::selUser < 0)
data::selUser = 0;
}
else if(down & KEY_DOWN)
{
data::selUser += 4;
if(data::selUser > (int)data::users.size() - 1)
data::selUser = data::users.size() - 1;
}
else if(down & KEY_A)
{
if(data::users[data::selUser].titles.size() > 0)
{
data::curUser = data::users[data::selUser];
mstate = TTL_SEL;
}
else
ui::showPopup("No Saves available for " + data::users[data::selUser].getUsername() + ".", POP_FRAME_DEFAULT);
}
else if(down & KEY_Y)
{
bool cont = true;
for(unsigned i = 0; i < data::users.size() - 2; i++)
{
if(cont)
cont = fs::dumpAllUserSaves(data::users[i]);
}
}
else if(down & KEY_X)
{
ui::textMode = true;
mstate = TXT_USR;
}
else if(down & KEY_ZR)
{
fs::unmountSave();
ui::mstate = EX_MNU;
}
else if(down & KEY_MINUS)
{
ui::mstate = OPT_MNU;
data::users[i].drawIconHalf(tX, y);
}
}
if(down & KEY_RIGHT && data::selUser < (int)data::users.size() - 1)
data::selUser++;
else if(down & KEY_LEFT && data::selUser > 0)
data::selUser--;
else if(down & KEY_UP)
{
data::selUser -= 4;
if(data::selUser < 0)
data::selUser = 0;
}
else if(down & KEY_DOWN)
{
data::selUser += 4;
if(data::selUser > (int)data::users.size() - 1)
data::selUser = data::users.size() - 1;
}
else if(down & KEY_A)
{
if(data::users[data::selUser].titles.size() > 0)
{
data::curUser = data::users[data::selUser];
mstate = TTL_SEL;
}
else
ui::showPopup("No Saves available for " + data::users[data::selUser].getUsername() + ".", POP_FRAME_DEFAULT);
}
else if(down & KEY_Y)
{
bool cont = true;
for(unsigned i = 0; i < data::users.size() - 2; i++)
{
if(cont)
cont = fs::dumpAllUserSaves(data::users[i]);
}
}
else if(down & KEY_X)
{
ui::textMode = true;
mstate = TXT_USR;
}
else if(down & KEY_ZR)
{
fs::unmountSave();
ui::mstate = EX_MNU;
}
else if(down & KEY_MINUS)
{
ui::mstate = OPT_MNU;
}
}

View File

@ -79,236 +79,232 @@ static inline void replaceCharCStr(char *_s, char _find, char _rep)
}
}
namespace util
std::string util::getDateTime(int fmt)
{
std::string getDateTime(int fmt)
char ret[128];
time_t raw;
time(&raw);
tm *Time = localtime(&raw);
switch(fmt)
{
char ret[128];
case DATE_FMT_YMD:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec);
break;
time_t raw;
time(&raw);
tm *Time = localtime(&raw);
case DATE_FMT_YDM:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mday, Time->tm_mon + 1, Time->tm_hour, Time->tm_min, Time->tm_sec);
break;
switch(fmt)
{
case DATE_FMT_YMD:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min, Time->tm_sec);
break;
case DATE_FMT_HOYSTE:
sprintf(ret, "%02d.%02d.%04d", Time->tm_mday, Time->tm_mon + 1, Time->tm_year + 1900);
break;
case DATE_FMT_YDM:
sprintf(ret, "%04d.%02d.%02d @ %02d.%02d.%02d", Time->tm_year + 1900, Time->tm_mday, Time->tm_mon + 1, Time->tm_hour, Time->tm_min, Time->tm_sec);
break;
case DATE_FMT_JHK:
sprintf(ret, "%04d%02d%02d_%02d%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min);
break;
case DATE_FMT_HOYSTE:
sprintf(ret, "%02d.%02d.%04d", Time->tm_mday, Time->tm_mon + 1, Time->tm_year + 1900);
break;
case DATE_FMT_JHK:
sprintf(ret, "%04d%02d%02d_%02d%02d", Time->tm_year + 1900, Time->tm_mon + 1, Time->tm_mday, Time->tm_hour, Time->tm_min);
break;
case DATE_FMT_ASC:
strcpy(ret, asctime(Time));
replaceCharCStr(ret, ':', '_');
replaceCharCStr(ret, '\n', 0x00);
break;
}
return std::string(ret);
case DATE_FMT_ASC:
strcpy(ret, asctime(Time));
replaceCharCStr(ret, ':', '_');
replaceCharCStr(ret, '\n', 0x00);
break;
}
void copyDirListToMenu(fs::dirList& d, ui::menu& m)
{
m.reset();
m.addOpt(".");
m.addOpt("..");
for(unsigned i = 0; i < d.getCount(); i++)
{
if(d.isDir(i))
m.addOpt("D " + d.getItem(i));
else
m.addOpt("F " + d.getItem(i));
}
m.adjust();
}
void removeLastFolderFromString(std::string& _path)
{
unsigned last = _path.find_last_of('/', _path.length() - 2);
_path.erase(last + 1, _path.length());
}
std::string safeString(const std::string& s)
{
std::string ret = "";
for(unsigned i = 0; i < s.length(); )
{
uint32_t tmpChr = 0;
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&s.data()[i]);
i += untCnt;
tmpChr = replaceChar(tmpChr);
if(isVerboten(tmpChr))
ret += ' ';
else if(tmpChr < 31 || tmpChr > 126)
return ""; //return empty string so titledata::init defaults to titleID
else
ret += (char)tmpChr;
}
//Check for spaces at end
while(ret[ret.length() - 1] == ' ')
ret.erase(ret.length() - 1, 1);
return ret;
}
std::string getInfoString(data::user& u, data::titledata& d)
{
std::string ret = d.getTitle() + "\n\n";
ret += "TID: " + d.getTIDStr() + "\n\n";
ret += "SID: " + d.getSaveIDStr() + "\n\n";
switch(d.getType())
{
case FsSaveDataType_System:
ret += "System Save\n\n";
break;
case FsSaveDataType_Account:
ret += "Save Data\n\n";
break;
case FsSaveDataType_Bcat:
ret += "BCAT\n\n";
break;
case FsSaveDataType_Device:
ret += "Device Save\n\n";
break;
case FsSaveDataType_Temporary:
ret += "Temp Storage\n\n";
break;
case FsSaveDataType_Cache:
ret += "Cache Storage\n\n";
break;
case FsSaveDataType_SystemBcat:
ret += "System BCAT\n\n";
break;
}
ret += u.getUsername();
return ret;
}
std::string getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[])
{
SwkbdConfig swkbd;
swkbdCreate(&swkbd, dictCnt);
swkbdConfigSetBlurBackground(&swkbd, true);
swkbdConfigSetInitialText(&swkbd, def.c_str());
swkbdConfigSetHeaderText(&swkbd, head.c_str());
swkbdConfigSetGuideText(&swkbd, head.c_str());
swkbdConfigSetInitialCursorPos(&swkbd, SwkbdPosEnd);
swkbdConfigSetType(&swkbd, SwkbdType_QWERTY);
swkbdConfigSetStringLenMax(&swkbd, maxLength);
swkbdConfigSetKeySetDisableBitmask(&swkbd, SwkbdKeyDisableBitmask_Backslash | SwkbdKeyDisableBitmask_ForwardSlash | SwkbdKeyDisableBitmask_Percent);
swkbdConfigSetDicFlag(&swkbd, 1);
if(dictCnt > 0)
{
dictWord words[dictCnt];
for(unsigned i = 0; i < dictCnt; i++)
swkbdDictWordCreate(&words[i], dictWords[i].c_str(), dictWords[i].c_str());
swkbdConfigSetDictionary(&swkbd, (SwkbdDictWord *)words, dictCnt);
}
char out[maxLength];
memset(out, 0, maxLength);
swkbdShow(&swkbd, out, maxLength);
swkbdClose(&swkbd);
return std::string(out);
}
std::string generateAbbrev(data::titledata& dat)
{
size_t titleLength = dat.getTitle().length();
char temp[titleLength + 1];
memset(temp, 0, titleLength + 1);
memcpy(temp, dat.getTitle().c_str(), titleLength);
std::string ret;
char *tok = strtok(temp, " ");
while(tok)
{
ret += tok[0];
tok = strtok(NULL, " ");
}
return ret;
}
void stripNL(std::string& _s)
{
size_t pos = 0;
while((pos = _s.find('\n')) != _s.npos)
_s.erase(pos, 1);
while((pos = _s.find('\r')) != _s.npos)
_s.erase(pos, 1);
}
void replaceButtonsInString(std::string& rep)
{
replaceStr(rep, "[A]", "\ue0e0");
replaceStr(rep, "[B]", "\ue0e1");
replaceStr(rep, "[X]", "\ue0e2");
replaceStr(rep, "[Y]", "\ue0e3");
replaceStr(rep, "[L]", "\ue0e4");
replaceStr(rep, "[R]", "\ue0e5");
replaceStr(rep, "[ZL]", "\ue0e6");
replaceStr(rep, "[ZR]", "\ue0e7");
replaceStr(rep, "[SL]", "\ue0e8");
replaceStr(rep, "[SR]", "\ue0e9");
replaceStr(rep, "[DPAD]", "\ue0ea");
replaceStr(rep, "[DUP]", "\ue0eb");
replaceStr(rep, "[DDOWN]", "\ue0ec");
replaceStr(rep, "[DLEFT]", "\ue0ed");
replaceStr(rep, "[DRIGHT]", "\ue0ee");
replaceStr(rep, "[+]", "\ue0ef");
replaceStr(rep, "[-]", "\ue0f0");
}
tex *createIconGeneric(const char *txt)
{
tex *ret = texCreate(256, 256);
texClearColor(ret, ui::rectLt);
unsigned int x = 128 - (textGetWidth(txt, ui::shared, 32) / 2);
drawText(txt, ret, ui::shared, x, 112, 32, ui::txtCont);
return ret;
}
void setCPU(uint32_t hz)
{
if(R_FAILED(clkrstInitialize()))
return;
ClkrstSession cpu;
clkrstOpenSession(&cpu, PcvModuleId_CpuBus, 3);
clkrstSetClockRate(&cpu, hz);
clkrstCloseSession(&cpu);
clkrstExit();
}
return std::string(ret);
}
void util::copyDirListToMenu(fs::dirList& d, ui::menu& m)
{
m.reset();
m.addOpt(".");
m.addOpt("..");
for(unsigned i = 0; i < d.getCount(); i++)
{
if(d.isDir(i))
m.addOpt("D " + d.getItem(i));
else
m.addOpt("F " + d.getItem(i));
}
m.adjust();
}
void util::removeLastFolderFromString(std::string& _path)
{
unsigned last = _path.find_last_of('/', _path.length() - 2);
_path.erase(last + 1, _path.length());
}
std::string util::safeString(const std::string& s)
{
std::string ret = "";
for(unsigned i = 0; i < s.length(); )
{
uint32_t tmpChr = 0;
ssize_t untCnt = decode_utf8(&tmpChr, (uint8_t *)&s.data()[i]);
i += untCnt;
tmpChr = replaceChar(tmpChr);
if(isVerboten(tmpChr))
ret += ' ';
else if(tmpChr < 31 || tmpChr > 126)
return ""; //return empty string so titledata::init defaults to titleID
else
ret += (char)tmpChr;
}
//Check for spaces at end
while(ret[ret.length() - 1] == ' ')
ret.erase(ret.length() - 1, 1);
return ret;
}
std::string util::getInfoString(data::user& u, data::titledata& d)
{
std::string ret = d.getTitle() + "\n\n";
ret += "TID: " + d.getTIDStr() + "\n\n";
ret += "SID: " + d.getSaveIDStr() + "\n\n";
switch(d.getType())
{
case FsSaveDataType_System:
ret += "System Save\n\n";
break;
case FsSaveDataType_Account:
ret += "Save Data\n\n";
break;
case FsSaveDataType_Bcat:
ret += "BCAT\n\n";
break;
case FsSaveDataType_Device:
ret += "Device Save\n\n";
break;
case FsSaveDataType_Temporary:
ret += "Temp Storage\n\n";
break;
case FsSaveDataType_Cache:
ret += "Cache Storage\n\n";
break;
case FsSaveDataType_SystemBcat:
ret += "System BCAT\n\n";
break;
}
ret += u.getUsername();
return ret;
}
std::string util::getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[])
{
SwkbdConfig swkbd;
swkbdCreate(&swkbd, dictCnt);
swkbdConfigSetBlurBackground(&swkbd, true);
swkbdConfigSetInitialText(&swkbd, def.c_str());
swkbdConfigSetHeaderText(&swkbd, head.c_str());
swkbdConfigSetGuideText(&swkbd, head.c_str());
swkbdConfigSetInitialCursorPos(&swkbd, SwkbdPosEnd);
swkbdConfigSetType(&swkbd, SwkbdType_QWERTY);
swkbdConfigSetStringLenMax(&swkbd, maxLength);
swkbdConfigSetKeySetDisableBitmask(&swkbd, SwkbdKeyDisableBitmask_Backslash | SwkbdKeyDisableBitmask_ForwardSlash | SwkbdKeyDisableBitmask_Percent);
swkbdConfigSetDicFlag(&swkbd, 1);
if(dictCnt > 0)
{
dictWord words[dictCnt];
for(unsigned i = 0; i < dictCnt; i++)
swkbdDictWordCreate(&words[i], dictWords[i].c_str(), dictWords[i].c_str());
swkbdConfigSetDictionary(&swkbd, (SwkbdDictWord *)words, dictCnt);
}
char out[maxLength];
memset(out, 0, maxLength);
swkbdShow(&swkbd, out, maxLength);
swkbdClose(&swkbd);
return std::string(out);
}
std::string util::generateAbbrev(data::titledata& dat)
{
size_t titleLength = dat.getTitle().length();
char temp[titleLength + 1];
memset(temp, 0, titleLength + 1);
memcpy(temp, dat.getTitle().c_str(), titleLength);
std::string ret;
char *tok = strtok(temp, " ");
while(tok)
{
ret += tok[0];
tok = strtok(NULL, " ");
}
return ret;
}
void util::stripChar(char _c, std::string& _s)
{
size_t pos = 0;
while((pos = _s.find(_c)) != _s.npos)
_s.erase(pos, 1);
}
void util::replaceButtonsInString(std::string& rep)
{
replaceStr(rep, "[A]", "\ue0e0");
replaceStr(rep, "[B]", "\ue0e1");
replaceStr(rep, "[X]", "\ue0e2");
replaceStr(rep, "[Y]", "\ue0e3");
replaceStr(rep, "[L]", "\ue0e4");
replaceStr(rep, "[R]", "\ue0e5");
replaceStr(rep, "[ZL]", "\ue0e6");
replaceStr(rep, "[ZR]", "\ue0e7");
replaceStr(rep, "[SL]", "\ue0e8");
replaceStr(rep, "[SR]", "\ue0e9");
replaceStr(rep, "[DPAD]", "\ue0ea");
replaceStr(rep, "[DUP]", "\ue0eb");
replaceStr(rep, "[DDOWN]", "\ue0ec");
replaceStr(rep, "[DLEFT]", "\ue0ed");
replaceStr(rep, "[DRIGHT]", "\ue0ee");
replaceStr(rep, "[+]", "\ue0ef");
replaceStr(rep, "[-]", "\ue0f0");
}
tex *util::createIconGeneric(const char *txt)
{
tex *ret = texCreate(256, 256);
texClearColor(ret, ui::rectLt);
unsigned int x = 128 - (textGetWidth(txt, ui::shared, 32) / 2);
drawText(txt, ret, ui::shared, x, 112, 32, ui::txtCont);
return ret;
}
void util::setCPU(uint32_t hz)
{
if(R_FAILED(clkrstInitialize()))
return;
ClkrstSession cpu;
clkrstOpenSession(&cpu, PcvModuleId_CpuBus, 3);
clkrstSetClockRate(&cpu, hz);
clkrstCloseSession(&cpu);
clkrstExit();
}