mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-03-21 17:24:37 -05:00
Add back RomFS opening to extras, add free space checks
This commit is contained in:
parent
1e03cbaf85
commit
cbea40e42e
2
Makefile
2
Makefile
|
|
@ -38,7 +38,7 @@ INCLUDES := inc
|
|||
EXEFS_SRC := exefs_src
|
||||
APP_TITLE := JKSV
|
||||
APP_AUTHOR := JK
|
||||
APP_VERSION := 04.30.2020
|
||||
APP_VERSION := 05.08.2020
|
||||
ROMFS := romfs
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ JKSV on Switch started as a small project/port to test some things and get famil
|
|||
* Ability to remove downloaded firmware updates from NAND.
|
||||
* Terminating processes by [ID](https://switchbrew.org/wiki/Title_list#System_Modules). Allowing you to dump normally unopenable system archives.
|
||||
* Mount by System Save [ID](https://switchbrew.org/wiki/Flash_Filesystem#System_Savegames). Normally used when the terminated process makes JKSV unable to rescan titles without the Switch crashing.
|
||||
* Mount and open RomFS of process the homebrew menu takes over (if launched as NRO) (To be re-added later)
|
||||
* Mount and open RomFS of process the homebrew menu takes over (if launched as NRO).
|
||||
* Hold R while opening a game or applet with Atmosphere so the homebrew menu loads. Open JKSV and press minus and select **Mount Process RomFS**. The romfs of the app should appear in the browser along with your SD on the right.
|
||||
|
||||
## Quick Guide
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ namespace fs
|
|||
void getDirProps(const std::string& _path, uint32_t& dirCount, uint32_t& fileCount, uint64_t& totalSize);
|
||||
|
||||
bool fileExists(const std::string& _path);
|
||||
//Returns file size
|
||||
size_t fsize(const std::string& _f);
|
||||
//Returns if device in path has space needed. Device is gotten from file path.
|
||||
bool hasFreeSpace(const std::string& _f, int needed);
|
||||
bool isDir(const std::string& _path);
|
||||
|
||||
std::string getWorkDir();
|
||||
|
|
|
|||
2
inc/ui.h
2
inc/ui.h
|
|
@ -66,7 +66,7 @@ namespace ui
|
|||
void initTheme();
|
||||
|
||||
//Loads graphics and stuff
|
||||
void init();
|
||||
void init(void *a);
|
||||
void exit();
|
||||
|
||||
//Prepares ui
|
||||
|
|
|
|||
35
src/ex.c
35
src/ex.c
|
|
@ -4,38 +4,5 @@
|
|||
|
||||
Result fsOpenDataFileSystemByCurrentProcess(FsFileSystem *out)
|
||||
{
|
||||
/*
|
||||
Result ret = 0;
|
||||
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
struct
|
||||
{
|
||||
uint64_t mag;
|
||||
uint64_t cmd;
|
||||
} *raw = serviceIpcPrepareHeader(fsGetServiceSession(), &c, sizeof(*raw));
|
||||
raw->mag = SFCI_MAGIC;
|
||||
raw->cmd = 2;
|
||||
|
||||
ret = serviceIpcDispatch(fsGetServiceSession());
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
IpcParsedCommand p;
|
||||
struct
|
||||
{
|
||||
uint64_t mag;
|
||||
uint64_t res;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(fsGetServiceSession(), &p, sizeof(*resp));
|
||||
resp = p.Raw;
|
||||
|
||||
ret = resp->res;
|
||||
if(R_SUCCEEDED(ret))
|
||||
serviceCreateSubservice(&out->s, fsGetServiceSession(), &p, 0);
|
||||
}
|
||||
|
||||
return ret;*/
|
||||
|
||||
return 1;
|
||||
return serviceDispatch(fsGetServiceSession(), 2, 0, .out_num_objects = 1, .out_objects = &out->s);
|
||||
}
|
||||
|
|
|
|||
52
src/file.cpp
52
src/file.cpp
|
|
@ -114,20 +114,6 @@ static void copyfileCommit_t(void *a)
|
|||
args->fin = true;
|
||||
}
|
||||
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
static void mkdirRec(const std::string& _p)
|
||||
{
|
||||
//skip first slash
|
||||
|
|
@ -177,7 +163,7 @@ namespace fs
|
|||
switch(open.getType())
|
||||
{
|
||||
case FsSaveDataType_System:
|
||||
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, open.getID(), (AccountUid){0});
|
||||
svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, open.getID(), (AccountUid) {0});
|
||||
break;
|
||||
|
||||
case FsSaveDataType_Account:
|
||||
|
|
@ -373,7 +359,10 @@ namespace fs
|
|||
std::string fullFrom = from + list.getItem(i);
|
||||
std::string fullTo = to + list.getItem(i);
|
||||
|
||||
copyFile(fullFrom, fullTo);
|
||||
if(hasFreeSpace(fullTo, fsize(fullFrom)))
|
||||
copyFile(fullFrom, fullTo);
|
||||
else
|
||||
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -398,7 +387,10 @@ namespace fs
|
|||
std::string fullFrom = from + list.getItem(i);
|
||||
std::string fullTo = to + list.getItem(i);
|
||||
|
||||
copyFileCommit(fullFrom, fullTo, dev);
|
||||
if(hasFreeSpace(fullTo, fsize(fullFrom)))
|
||||
copyFileCommit(fullFrom, fullTo, dev);
|
||||
else
|
||||
ui::showMessage("*Error*", "Not enough free space to copy #%s#!", fullFrom.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -517,6 +509,32 @@ namespace fs
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,15 @@ int main(int argc, const char *argv[])
|
|||
graphicsInit(1280, 720);
|
||||
//Needed for icon gen
|
||||
ui::initTheme();
|
||||
|
||||
/*Not completely stable yet
|
||||
Thread uiInitThrd;
|
||||
threadCreate(&uiInitThrd, ui::init, NULL, NULL, 0x80000, 0x2B, -2);
|
||||
threadStart(&uiInitThrd);*/
|
||||
data::init();
|
||||
ui::init();
|
||||
ui::init(NULL);
|
||||
/*threadWaitForExit(&uiInitThrd);
|
||||
threadClose(&uiInitThrd);*/
|
||||
|
||||
while(appletMainLoop())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "util.h"
|
||||
#include "file.h"
|
||||
|
||||
#define VER_STRING "v. 04.30.2020"
|
||||
#define VER_STRING "v. 05.08.2020"
|
||||
|
||||
//Nav buttons
|
||||
std::vector<ui::button> usrNav, ttlNav, fldNav;
|
||||
|
|
@ -123,7 +123,7 @@ namespace ui
|
|||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
void init(void *a)
|
||||
{
|
||||
mnuTopLeft = texLoadPNGFile("romfs:/img/fb/menuTopLeft.png");
|
||||
mnuTopRight = texLoadPNGFile("romfs:/img/fb/menuTopRight.png");
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ void performCopyMenuOps()
|
|||
//just copy file
|
||||
std::string fromPath = savePath + saveList.getItem(saveSel);
|
||||
std::string toPath = sdPath + saveList.getItem(saveSel);
|
||||
if(ui::confirmTransfer(fromPath, toPath))
|
||||
if(ui::confirmTransfer(fromPath, toPath) && fs::hasFreeSpace(toPath, fs::fsize(fromPath)))
|
||||
fs::copyFile(fromPath, toPath);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ void performCopyMenuOps()
|
|||
{
|
||||
std::string fromPath = sdPath + sdList.getItem(sdSel);
|
||||
std::string toPath = savePath + sdList.getItem(sdSel);
|
||||
if(ui::confirmTransfer(fromPath, toPath))
|
||||
if(ui::confirmTransfer(fromPath, toPath) && fs::hasFreeSpace(toPath, fs::fsize(fromPath)))
|
||||
commit ? fs::copyFileCommit(fromPath, toPath, dev) : fs::copyFile(fromPath, toPath);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace ui
|
|||
advModePrep("sv:/", true);
|
||||
mstate = ADV_MDE;
|
||||
}
|
||||
else if(down & KEY_ZR && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ namespace ui
|
|||
{
|
||||
data::titledata tempData = data::curUser.titles[data::selData];
|
||||
if(tempData.getType() == FsSaveDataType_System)
|
||||
ui::showMessage("Deleting system save archives is disabled.", "*NO*");
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ namespace ui
|
|||
{
|
||||
data::titledata tempData = data::curUser.titles[titleMenu.getSelected()];
|
||||
if(tempData.getType() == FsSaveDataType_System)
|
||||
ui::showMessage("Deleting system save archives is disabled.", "*NO*");
|
||||
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());
|
||||
|
|
@ -310,7 +310,7 @@ namespace ui
|
|||
advModePrep("sv:/", true);
|
||||
mstate = ADV_MDE;
|
||||
}
|
||||
else if(down & KEY_ZR && confirm(true, ui::confEraseFolder.c_str(), data::curData.getTitle().c_str()))
|
||||
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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user