Add Borealis GUI for patch extraction on Switch.
All checks were successful
Build NRO / build (push) Successful in 1m48s
All checks were successful
Build NRO / build (push) Successful in 1m48s
Replace the console UI with a Borealis-based flow, bundle ROMFS assets and borealis as a submodule, and apply small upstream patches at build time. Self-delete runs after romfsExit on quit so the NRO can be removed like the old console build.
This commit is contained in:
134
source/extractor.cpp
Normal file
134
source/extractor.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "extractor.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __SWITCH__
|
||||
#include <switch.h>
|
||||
#endif
|
||||
|
||||
static constexpr size_t READ_BUF_SIZE = 8192;
|
||||
|
||||
int PatchExtractor::mkdirs(const char* path) {
|
||||
char tmp[512];
|
||||
snprintf(tmp, sizeof(tmp), "%s", path);
|
||||
size_t len = strlen(tmp);
|
||||
if (len == 0) return 0;
|
||||
if (tmp[len - 1] == '/') tmp[len - 1] = '\0';
|
||||
|
||||
for (char* p = tmp + 1; *p; p++) {
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
mkdir(tmp, 0755);
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
return mkdir(tmp, 0755);
|
||||
}
|
||||
|
||||
bool PatchExtractor::open() {
|
||||
zip = unzOpen(PATCHES_ZIP);
|
||||
if (!zip) return false;
|
||||
|
||||
unz_global_info gi{};
|
||||
if (unzGetGlobalInfo(zip, &gi) != UNZ_OK) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
total = gi.number_entry;
|
||||
extracted = 0;
|
||||
skipped = 0;
|
||||
finished = false;
|
||||
err = unzGoToFirstFile(zip);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PatchExtractor::close() {
|
||||
if (zip) {
|
||||
unzClose(zip);
|
||||
zip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int PatchExtractor::getProgressPercent() const {
|
||||
if (total == 0) return 100;
|
||||
return static_cast<int>((extracted * 100) / total);
|
||||
}
|
||||
|
||||
bool PatchExtractor::step() {
|
||||
if (!zip || finished) return false;
|
||||
|
||||
if (err != UNZ_OK) {
|
||||
finished = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
char filename[512];
|
||||
char fullpath[1024];
|
||||
unz_file_info fi{};
|
||||
|
||||
unzGetCurrentFileInfo(zip, &fi, filename, sizeof(filename), nullptr, 0, nullptr, 0);
|
||||
snprintf(fullpath, sizeof(fullpath), "%s%s", EXTRACT_DIR, filename);
|
||||
currentFile = filename;
|
||||
|
||||
size_t flen = strlen(filename);
|
||||
if (flen > 0 && filename[flen - 1] == '/') {
|
||||
mkdirs(fullpath);
|
||||
} else {
|
||||
char dirpart[1024];
|
||||
snprintf(dirpart, sizeof(dirpart), "%s", fullpath);
|
||||
char* last_slash = strrchr(dirpart, '/');
|
||||
if (last_slash) {
|
||||
*last_slash = '\0';
|
||||
mkdirs(dirpart);
|
||||
}
|
||||
|
||||
if (unzOpenCurrentFile(zip) == UNZ_OK) {
|
||||
FILE* out = fopen(fullpath, "wb");
|
||||
if (out) {
|
||||
unsigned char buf[READ_BUF_SIZE];
|
||||
int bytes;
|
||||
while ((bytes = unzReadCurrentFile(zip, buf, READ_BUF_SIZE)) > 0) {
|
||||
fwrite(buf, 1, static_cast<size_t>(bytes), out);
|
||||
}
|
||||
fclose(out);
|
||||
} else {
|
||||
skipped++;
|
||||
}
|
||||
unzCloseCurrentFile(zip);
|
||||
} else {
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
|
||||
extracted++;
|
||||
err = unzGoToNextFile(zip);
|
||||
if (err != UNZ_OK) finished = true;
|
||||
|
||||
return !finished;
|
||||
}
|
||||
|
||||
bool PatchExtractor::cleanup() {
|
||||
cleanupOk_ = true;
|
||||
|
||||
if (remove(PATCHES_ZIP) != 0)
|
||||
cleanupOk_ = false;
|
||||
|
||||
// Cannot delete our own NRO while the app is still running; try anyway for edge cases.
|
||||
remove(SELF_NRO);
|
||||
|
||||
remove("sdmc:/switch/.PatchExtractor.nro.star");
|
||||
remove("sdmc:/switch/.packages/boot_package.ini");
|
||||
|
||||
return cleanupOk_;
|
||||
}
|
||||
|
||||
void PatchExtractor::tryDeleteSelfOnExit() {
|
||||
#ifdef __SWITCH__
|
||||
// Embedded ROMFS keeps the .nro open on SD; unmount before unlink (console build had no ROMFS).
|
||||
romfsExit();
|
||||
#endif
|
||||
remove(SELF_NRO);
|
||||
}
|
||||
Reference in New Issue
Block a user