initial commit

This commit is contained in:
2024-07-14 20:20:03 +03:00
commit 31953464e7
95 changed files with 4688 additions and 0 deletions

BIN
include/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
#pragma once
#include <pu/Plutonium>
#include <UsersLayout.hpp>
#include <TitlesLayout.hpp>
namespace ui {
class MainApplication : public pu::ui::Application {
public:
using Application::Application;
PU_SMART_CTOR(MainApplication)
void OnLoad() override;
// Layout instance
UsersLayout::Ref usersLayout;
TitlesLayout::Ref titlesLayout;
};
}

19
include/TitlesLayout.hpp Normal file
View File

@@ -0,0 +1,19 @@
#include <pu/Plutonium>
#include <const.h>
#include <data.h>
namespace ui {
class TitlesLayout : public pu::ui::Layout {
private:
pu::ui::elm::Menu::Ref titlesMenu;
public:
void InitTitles();
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::TouchPoint Pos);
PU_SMART_CTOR(TitlesLayout)
};
}

22
include/UsersLayout.hpp Normal file
View File

@@ -0,0 +1,22 @@
#include <pu/Plutonium>
#include <const.h>
namespace ui {
class UsersLayout : public pu::ui::Layout {
private:
pu::ui::elm::Menu::Ref usersMenu;
public:
UsersLayout();
void onInput(u64 Down, u64 Up, u64 Held, pu::ui::TouchPoint Pos);
int32_t GetCurrentIndex();
PU_SMART_CTOR(UsersLayout)
};
}

2
include/const.h Normal file
View File

@@ -0,0 +1,2 @@
#define BACKGROUND_COLOR COLOR("00FFFFFF")
#define COLOR(hex) pu::ui::Color::FromHex(hex)

91
include/data.h Normal file
View File

@@ -0,0 +1,91 @@
#pragma once
#include <switch.h>
#include <vector>
#include <string>
#include <unordered_map>
#define BLD_MON 02
#define BLD_DAY 23
#define BLD_YEAR 2023
namespace data
{
//Loads user + title info
void init();
void exit();
bool loadUsersTitles(bool clearUsers);
void sortUserTitles();
//Draws some stats to the upper left corner
void dispStats();
//Global stuff for all titles/saves
typedef struct
{
NacpStruct nacp;
std::string title, safeTitle, author;//Shortcuts sorta.
bool fav;
} titleInfo;
//Holds stuff specific to user's titles/saves
typedef struct
{
//Makes it easier to grab id
uint64_t tid;
FsSaveDataInfo saveInfo;
PdmPlayStatistics playStats;
} userTitleInfo;
//Class to store user info + titles
class user
{
public:
user() = default;
user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName);
//Sets ID
void setUID(const AccountUid& _id);
//Returns user ID
AccountUid getUID() const { return userID; }
u128 getUID128() const { return uID128; }
//Returns username
std::string getUsername() const { return username; }
std::string getUsernameSafe() const { return userSafe; }
std::vector<data::userTitleInfo> titleInfo;
void addUserTitleInfo(const uint64_t& _tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats);
private:
AccountUid userID;
u128 uID128;
std::string username, userSafe;
//User icon
};
//User vector
extern std::vector<user> users;
//Title data/info map
extern std::unordered_map<uint64_t, data::titleInfo> titles;
//Sets/Retrieves current user/title
void setUserIndex(unsigned _sUser);
data::user *getCurrentUser();
unsigned getCurrentUserIndex();
void setTitleIndex(unsigned _sTitle);
data::userTitleInfo *getCurrentUserTitleInfo();
unsigned getCurrentUserTitleInfoIndex();
//Gets pointer to info that also has title + nacp
data::titleInfo *getTitleInfoByTID(const uint64_t& tid);
//More shortcut functions
std::string getTitleNameByTID(const uint64_t& tid);
std::string getTitleSafeNameByTID(const uint64_t& tid);
int getTitleIndexInUser(const data::user& u, const uint64_t& tid);
extern SetLanguage sysLang;
}

54
include/fs.h Normal file
View File

@@ -0,0 +1,54 @@
#pragma once
#include <cstring>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "fs/fstype.h"
#include "fs/file.h"
#include "fs/dir.h"
#include "fs/fsfile.h"
#include "fs/zip.h"
#define BUFF_SIZE 0x4000
#define ZIP_BUFF_SIZE 0x20000
#define TRANSFER_BUFFER_LIMIT 0xC00000
namespace fs
{
copyArgs *copyArgsCreate(const std::string& src, const std::string& dst, const std::string& dev, zipFile z, unzFile unz, bool _cleanup, bool _trimZipPath, uint8_t _trimPlaces);
void copyArgsDestroy(copyArgs *c);
void init();
bool mountSave(const FsSaveDataInfo& _m);
inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; }
bool commitToDevice(const std::string& dev);
std::string getWorkDir();
void setWorkDir(const std::string& _w);
//Loads paths to filter from backup/deletion
void loadPathFilters(const uint64_t& tid);
bool pathIsFiltered(const std::string& _path);
void freePathFilters();
void createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, threadInfo *t);
void createSaveDataThreaded(FsSaveDataType _type, uint64_t _tid, AccountUid _uid);
bool extendSaveData(const data::userTitleInfo *tinfo, uint64_t extSize, threadInfo *t);
void extendSaveDataThreaded(const data::userTitleInfo *tinfo, uint64_t extSize);
uint64_t getJournalSize(const data::userTitleInfo *tinfo);
uint64_t getJournalSizeMax(const data::userTitleInfo *tinfo);
//Always threaded
void wipeSave();
void createNewBackup(void *a);
void overwriteBackup(void *a);
void restoreBackup(void *a);
void deleteBackup(void *a);
void dumpAllUserSaves(void *a);
void dumpAllUsersAllSaves(void *a);
void logOpen();
void logWrite(const char *fmt, ...);
}

54
include/fs/dir.h Normal file
View File

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

64
include/fs/file.h Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
#include <string>
#include <cstdio>
#include <vector>
#include <switch.h>
#include <dirent.h>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "fs.h"
#include "data.h"
namespace fs
{
//Copy args are optional and only used if passed and threaded
void copyFile(const std::string& src, const std::string& dst, threadInfo *t);
void copyFileThreaded(const std::string& src, const std::string& dst);
void copyFileCommit(const std::string& src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyFileCommitThreaded(const std::string& src, const std::string& dst, const std::string& dev);
void fileDrawFunc(void *a);
//deletes file
void delfile(const std::string& _p);
//Dumps all titles for current user
void dumpAllUserSaves();
void getShowFileProps(const std::string& _path);
void getShowDirProps(const std::string& _path);
bool fileExists(const std::string& _path);
//Returns file size
size_t fsize(const std::string& _f);
class dataFile
{
public:
dataFile(const std::string& _path);
~dataFile();
void close(){ fclose(f); }
bool isOpen() const { return opened; }
bool readNextLine(bool proc);
//Finds where variable name ends. When a '(' or '=' is hit. Strips spaces
void procLine();
std::string getLine() const { return line; }
std::string getName() const { 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;
};
void logOpen();
void logWrite(const char *fmt, ...);
void logClose();
}

100
include/fs/fsfile.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <switch.h>
#include <stdint.h>
//Bare minimum wrapper around switch fs for JKSV
#define FS_SEEK_SET 0
#define FS_SEEK_CUR 1
#define FS_SEEK_END 2
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
FsFile _f;
Result error;
s64 offset, fsize;
} FSFILE;
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);
bool fsMkDir(const char *_p);
/*Opens file. Device is fetched from path. Libnx romfs doesn't work with this.
Mode needs to be:
FsOpenMode_Read
FsOpenMode_Write
FsOpenMode_Append
*/
bool fsfcreate(const char *_p, int64_t crSize);
FSFILE *fsfopen(const char *_p, uint32_t mode);
/*Same as above, but FsFileSystem _s is used. Path cannot have device in it*/
FSFILE *fsfopenWithSystem(FsFileSystem *_s, const char *_p, uint32_t mode);
//Closes _f
inline void fsfclose(FSFILE *_f)
{
if(_f != NULL)
{
fsFileClose(&_f->_f);
free(_f);
}
}
//Seeks like stdio
inline void fsfseek(FSFILE *_f, int offset, int origin)
{
switch(origin)
{
case FS_SEEK_SET:
_f->offset = offset;
break;
case FS_SEEK_CUR:
_f->offset += offset;
break;
case FS_SEEK_END:
_f->offset = offset + _f->fsize;
break;
}
}
//Returns offset
inline size_t fsftell(FSFILE *_f) { return _f->offset; }
//Writes buf to file. Automatically resizes _f to fit buf
size_t fsfwrite(const void *buf, size_t sz, size_t count, FSFILE *_f);
//Reads to buff
inline size_t fsfread(void *buf, size_t sz, size_t count, FSFILE *_f)
{
uint64_t read = 0;
_f->error = fsFileRead(&_f->_f, _f->offset, buf, sz * count, 0, &read);
_f->offset += read;
return read;
}
//Gets byte from file
inline char fsfgetc(FSFILE *_f)
{
char ret = 0;
uint64_t read = 0;
_f->error = fsFileRead(&_f->_f, _f->offset++, &ret, 1, 0, &read);
return ret;
}
//Writes byte to file
inline void fsfputc(int ch, FSFILE *_f) { fsfwrite(&ch, 1, 1, _f); }
#ifdef __cplusplus
}
#endif

46
include/fs/fstype.h Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include "data.h"
#include "type.h"
#include "ldn.h"
namespace fs
{
typedef struct
{
std::string src, dst, dev;
zipFile z;
unzFile unz;
LDN::LDNCommunicate *comm;
bool cleanup = false, trimZipPath = false;
uint8_t trimZipPlaces = 0;
uint64_t offset = 0;
threadStatus *thrdStatus;
Mutex arglck = 0;
void argLock() { mutexLock(&arglck); }
void argUnlock() { mutexUnlock(&arglck); }
} copyArgs;
typedef struct
{
FsSaveDataType type;
uint64_t tid;
AccountUid account;
uint16_t index;
} svCreateArgs;
typedef struct
{
const data::userTitleInfo *tinfo;
uint64_t extSize;
} svExtendArgs;
typedef struct
{
std::string path;
bool origin = false;
unsigned dirCount = 0;
unsigned fileCount = 0;
uint64_t totalSize = 0;
} dirCountArgs;
}

94
include/fs/ldn.h Normal file
View File

@@ -0,0 +1,94 @@
#pragma once
#include <switch.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string>
#include <vector>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4frame_static.h>
#include <mutex>
#include "type.h"
#define SAVE_DATA_SERVER_PORT 25789
#define SOCKET_BUFFER_SIZE 4096
#define LENGTH_OF_LISTEN_QUEUE 20
enum LDN_COMMUNICATE_TYPE {
UPDATE_FILE,
UPDATE_ABORT,
UPDATE_OK,
UPDATE_DONE,
};
struct LZ4_readFile_s {
LZ4F_dctx *dctxPtr;
int socket;
LZ4_byte *srcBuf;
size_t srcBufNext;
size_t srcBufSize;
size_t srcBufMaxSize;
};
struct LZ4_writeFile_s {
LZ4F_cctx *cctxPtr;
int socket;
LZ4_byte *dstBuf;
size_t maxWriteSize;
size_t dstBufMaxSize;
LZ4F_errorCode_t errCode;
};
namespace LDN {
typedef struct {
// point to server's socket fd;
int serverFD;
// point to communicate socket fd, send meta data
int commFD;
// for client to bind with server, communicate create file socket fd
struct sockaddr_in serverAddr;
} LDNCommunicate;
typedef struct {
LDNCommunicate *comm;
unsigned int filesize = 0, writeLimit = 0;
std::string fullPath;
std::mutex bufferLock;
std::condition_variable cond;
std::vector<uint8_t> sharedBuffer;
bool bufferIsFull = false;
std::string dst, dev;
LZ4_writeFile_s* lz4fWrite;
} LDNfcopyArgs;
typedef struct {
u32 type;
size_t fsz;
} commMeta;
void destroyLDN();
LDN::LDNCommunicate *createCommunicate(void);
void destroyCommunicate(LDNCommunicate *comm);
Result createLDNServer(LDNCommunicate *comm);
Result createLDNClient(LDNCommunicate *comm);
int bindClient(int serverFD);
int bindServer(sockaddr_in *serverAddr);
bool waitForOK(int socketfd);
bool waitForDONE(int socketfd);
void sendOK(int socket_fd);
void sendDONE(int socket_fd);
void sendAbort(int socket_fd);
void reciveMeta(commMeta *meta, int socketfd);
void sendMeta(commMeta *meta, int socketfd);
void copySaveFileToRemote(const std::string &local, threadInfo *t);
void copyRemoteSaveFile(threadInfo *t);
};

18
include/fs/zip.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <string>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "type.h"
namespace fs
{
//threadInfo is optional and only used when threaded versions are used
void copyDirToZip(const std::string& src, zipFile dst, bool trimPath, int trimPlaces, threadInfo *t);
void copyDirToZipThreaded(const std::string& src, zipFile dst, bool trimPath, int trimPlaces);
void copyZipToDir(unzFile src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyZipToDirThreaded(unzFile src, const std::string& dst, const std::string& dev);
uint64_t getZipTotalSize(unzFile unz);
bool zipNotEmpty(unzFile unz);
}

44
include/threads.h Normal file
View File

@@ -0,0 +1,44 @@
#include <switch.h>
#include "type.h"
namespace threads {
//pad data cause i don't know where else to put it
extern PadState pad;
extern HidTouchScreenState touchState;
static inline void updateInput() {
touchState = {0};
padUpdate(&pad);
hidGetTouchScreenStates(&touchState, 1);
}
inline uint64_t padKeysDown() { return padGetButtonsDown(&pad); }
inline uint64_t padKeysHeld() { return padGetButtons(&pad); }
inline uint64_t padKeysUp() { return padGetButtonsUp(&pad); }
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
class threadProcMngr {
public:
~threadProcMngr();
//Draw function is used and called to draw on overlay
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
void update();
void draw();
bool empty() { return threads.empty(); }
private:
std::vector<threadInfo *> threads;
uint8_t lgFrame = 0, clrShft = 0;
bool clrAdd = true;
unsigned frameCount = 0;
Mutex threadLock = 0;
};
}

29
include/type.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <switch.h>
//Misc stuff for new menu code
typedef void (*funcPtr)(void *);
class threadStatus
{
public:
void setStatus(const char *fmt, ...);
void getStatus(std::string& statusOut);
private:
Mutex statusLock = 0;
std::string status;
};
typedef struct
{
bool running = false, finished = false;
Thread thrd;
ThreadFunc thrdFunc;
void *argPtr = NULL;
funcPtr drawFunc = NULL;//Draw func is passed threadInfo pointer too
threadStatus *status;
} threadInfo;

152
include/util.h Normal file
View File

@@ -0,0 +1,152 @@
#pragma once
#include "data.h"
//#include "ui.h"
#include "fs/file.h"
//#include "gfx.h"
namespace util
{
enum
{
DATE_FMT_YMD,
DATE_FMT_YDM,
DATE_FMT_HOYSTE,
DATE_FMT_JHK,
DATE_FMT_ASC
};
typedef enum
{
CPU_SPEED_204MHz = 204000000,
CPU_SPEED_306MHz = 306000000,
CPU_SPEED_408MHz = 408000000,
CPU_SPEED_510MHz = 510000000,
CPU_SPEED_612MHz = 612000000,
CPU_SPEED_714MHz = 714000000,
CPU_SPEED_816MHz = 816000000,
CPU_SPEED_918MHz = 918000000,
CPU_SPEED_1020MHz = 1020000000, //Default
CPU_SPEED_1122MHz = 1122000000,
CPU_SPEED_1224MHz = 1224000000,
CPU_SPEED_1326MHz = 1326000000,
CPU_SPEED_1428MHz = 1428000000,
CPU_SPEED_1581MHz = 1581000000,
CPU_SPEED_1683MHz = 1683000000,
CPU_SPEED_1785MHz = 1785000000
} cpuSpds;
typedef enum
{
GPU_SPEED_0MHz = 0,
GPU_SPEED_76MHz = 76800000,
GPU_SPEED_153MHz = 153600000,
GPU_SPEED_203MHz = 230400000,
GPU_SPEED_307MHz = 307200000, //Handheld 1
GPU_SPEED_384MHz = 384000000, //Handheld 2
GPU_SPEED_460MHz = 460800000,
GPU_SPEED_537MHz = 537600000,
GPU_SPEED_614MHz = 614400000,
GPU_SPEED_768MHz = 768000000, //Docked
GPU_SPEED_844MHz = 844800000,
GPU_SPEED_921MHZ = 921600000
} gpuSpds;
typedef enum
{
RAM_SPEED_0MHz = 0,
RAM_SPEED_40MHz = 40800000,
RAM_SPEED_68MHz = 68000000,
RAM_SPEED_102MHz = 102000000,
RAM_SPEED_204MHz = 204000000,
RAM_SPEED_408MHz = 408000000,
RAM_SPEED_665MHz = 665600000,
RAM_SPEED_800MHz = 800000000,
RAM_SPEED_1065MHz = 1065600000,
RAM_SPEED_1331MHz = 1331200000,
RAM_SPEED_1600MHz = 1600000000
} ramSpds;
//Returns string with date S+ time
std::string getDateTime(int fmt);
//Removes last folder from '_path'
void removeLastFolderFromString(std::string& _path);
size_t getTotalPlacesInPath(const std::string& _path);
void trimPath(std::string& _path, uint8_t _places);
inline bool isASCII(const uint32_t& t)
{
return t > 30 && t < 127;
}
std::string safeString(const std::string& s);
std::string getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
std::string getExtensionFromString(const std::string& get);
std::string getFilenameFromPath(const std::string& get);
std::string generateAbbrev(const uint64_t& tid);
//removes char from C++ string
void stripChar(char _c, std::string& _s);
void replaceStr(std::string& _str, const std::string& _find, const std::string& _rep);
//For future external translation support. Replaces [button] with button chars
void replaceButtonsInString(std::string& rep);
inline u128 accountUIDToU128(AccountUid uid)
{
return ((u128)uid.uid[0] << 64 | uid.uid[1]);
}
inline AccountUid u128ToAccountUID(u128 id)
{
AccountUid ret;
ret.uid[0] = id >> 64;
ret.uid[1] = id;
return ret;
}
inline std::string getIDStr(const uint64_t& _id)
{
char tmp[18];
sprintf(tmp, "%016lX", _id);
return std::string(tmp);
}
inline std::string getIDStrLower(const uint64_t& _id)
{
char tmp[18];
sprintf(tmp, "%08X", (uint32_t)_id);
return std::string(tmp);
}
inline std::string generatePathByTID(const uint64_t& tid)
{
return fs::getWorkDir() + data::getTitleSafeNameByTID(tid) + "/";
}
std::string getSizeString(const uint64_t& _size);
inline void createTitleDirectoryByTID(const uint64_t& tid)
{
std::string makePath = fs::getWorkDir() + data::getTitleSafeNameByTID(tid);
mkdir(makePath.c_str(), 777);
}
Result accountDeleteUser(AccountUid *uid);
void sysBoost();
void sysNormal();
inline bool isApplet()
{
AppletType type = appletGetAppletType();
return type == AppletType_LibraryApplet;
}
void checkForUpdate(void *a);
}