#include #include #include #include #include #include #include #include #define PATCHES_ZIP "sdmc:/SaltySD/plugins/FPSLocker/patches.zip" #define EXTRACT_DIR "sdmc:/SaltySD/plugins/FPSLocker/" #define SELF_NRO "sdmc:/switch/PatchExtractor.nro" #define READ_BUF_SIZE 8192 #define STATUS_ROW 11 static PrintConsole *con; static void status(const char *fmt, ...) { printf("\x1b[%d;0H\x1b[2K", STATUS_ROW); va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } static int 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); } int main(int argc, char *argv[]) { con = consoleInit(NULL); padConfigureInput(1, HidNpadStyleSet_NpadStandard); PadState pad; padInitializeDefault(&pad); printf("\n"); printf(" ========================================\n"); printf(" PatchExtractor - OmniNX OC\n"); printf(" SaltyNX / FPSLocker Patch Installer\n"); printf(" ========================================\n\n"); unzFile zip = unzOpen(PATCHES_ZIP); if (!zip) { printf(" \x1b[31mFEHLER:\x1b[0m patches.zip nicht gefunden!\n\n"); printf(" Pfad: %s\n\n", PATCHES_ZIP); printf(" Bist du sicher, dass du OmniNX OC installiert hast?\n\n"); printf(" Die Datei patches.zip muss unter\n"); printf(" sd:/SaltySD/plugins/FPSLocker/ liegen.\n\n"); printf(" ----------------------------------------\n"); printf(" Druecke + zum Beenden.\n"); while (appletMainLoop()) { padUpdate(&pad); if (padGetButtonsDown(&pad) & HidNpadButton_Plus) break; consoleUpdate(NULL); } consoleExit(NULL); return 1; } unz_global_info gi; unzGetGlobalInfo(zip, &gi); unsigned long total = gi.number_entry; printf(" patches.zip gefunden! (%lu Eintraege)\n", total); printf(" Druecke A zum Entpacken, + zum Abbrechen.\n\n"); consoleUpdate(NULL); while (appletMainLoop()) { padUpdate(&pad); u64 kDown = padGetButtonsDown(&pad); if (kDown & HidNpadButton_A) break; if (kDown & HidNpadButton_Plus) { unzClose(zip); consoleExit(NULL); return 0; } consoleUpdate(NULL); } printf("\x1b[10;0H \x1b[93mBitte nicht beenden, bis der Vorgang abgeschlossen ist!\x1b[0m\n"); consoleUpdate(NULL); char filename[512]; char fullpath[1024]; unsigned char buf[READ_BUF_SIZE]; unsigned long extracted = 0; unsigned long skipped = 0; int err = unzGoToFirstFile(zip); while (err == UNZ_OK) { unz_file_info fi; unzGetCurrentFileInfo(zip, &fi, filename, sizeof(filename), NULL, 0, NULL, 0); snprintf(fullpath, sizeof(fullpath), "%s%s", EXTRACT_DIR, filename); unsigned long progress = (unsigned long)((extracted * 100) / total); size_t flen = strlen(filename); if (flen > 0 && filename[flen - 1] == '/') { mkdirs(fullpath); status(" [%3lu%%] DIR %s", progress, filename); } 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) { status(" [%3lu%%] \x1b[31mERR\x1b[0m %s", progress, filename); skipped++; extracted++; err = unzGoToNextFile(zip); continue; } FILE *out = fopen(fullpath, "wb"); if (!out) { status(" [%3lu%%] \x1b[31mERR\x1b[0m %s", progress, filename); unzCloseCurrentFile(zip); skipped++; extracted++; err = unzGoToNextFile(zip); continue; } int bytes; while ((bytes = unzReadCurrentFile(zip, buf, READ_BUF_SIZE)) > 0) { fwrite(buf, 1, bytes, out); } fclose(out); unzCloseCurrentFile(zip); status(" [%3lu%%] FILE %s", progress, filename); } extracted++; consoleUpdate(NULL); err = unzGoToNextFile(zip); } unzClose(zip); status(" [100%%] Fertig! %lu / %lu entpackt.", extracted - skipped, total); consoleUpdate(NULL); int cleanup_ok = 1; printf("\x1b[%d;0H", STATUS_ROW + 2); if (remove(PATCHES_ZIP) == 0) { printf(" patches.zip geloescht.\n"); } else { printf(" \x1b[31mpatches.zip konnte nicht geloescht werden.\x1b[0m\n"); cleanup_ok = 0; } if (remove(SELF_NRO) == 0) { printf(" PatchExtractor.nro geloescht (Selbstreinigung).\n"); } else { printf(" \x1b[31mPatchExtractor.nro konnte nicht geloescht werden.\x1b[0m\n"); cleanup_ok = 0; } printf("\n ========================================\n"); if (skipped == 0 && cleanup_ok) { printf(" \x1b[32mAlles erledigt!\x1b[0m\n"); } else { printf(" \x1b[32mEntpacken abgeschlossen.\x1b[0m\n"); if (skipped > 0) printf(" \x1b[31m%lu Eintraege fehlgeschlagen.\x1b[0m\n", skipped); } printf(" ========================================\n\n"); printf(" Druecke + zum Beenden.\n"); while (appletMainLoop()) { padUpdate(&pad); if (padGetButtonsDown(&pad) & HidNpadButton_Plus) break; consoleUpdate(NULL); } consoleExit(NULL); return 0; }