// #include // #include "tools.h" #include #include "../fs/readers/folderReader.h" #include "../fs/fstypes.h" #include "../fs/fscopy.h" #include #include #include #include "../gfx/gfx.h" #include "../gfx/gfxutils.h" #include "../gfx/menu.h" #include "../hid/hid.h" // #include "utils.h" #include "../utils/utils.h" #include "../fs/fsutils.h" #include #include // #include // #include #include #include void _DeleteFileSimple(char *thing){ //char *thing = CombinePaths(path, entry.name); int res = f_unlink(thing); if (res) DrawError(newErrCode(res)); free(thing); } void _RenameFileSimple(char *sourcePath, char *destPath){ int res = f_rename(sourcePath, destPath); if (res){ DrawError(newErrCode(res)); } } ErrCode_t _FolderDelete(const char *path){ int res = 0; ErrCode_t ret = newErrCode(0); u32 x, y; gfx_con_getpos(&x, &y); Vector_t fileVec = ReadFolder(path, &res); if (res){ ret = newErrCode(res); } else { vecDefArray(FSEntry_t *, fs, fileVec); for (int i = 0; i < fileVec.count && !ret.err; i++){ char *temp = CombinePaths(path, fs[i].name); if (fs[i].isDir){ ret = _FolderDelete(temp); } else { res = f_unlink(temp); if (res){ ret = newErrCode(res); } } free(temp); } } if (!ret.err){ res = f_unlink(path); if (res) ret = newErrCode(res); } clearFileVector(&fileVec); return ret; } int _StartsWith(const char *a, const char *b) { if(strncmp(a, b, strlen(b)) == 0) return 1; return 0; } int listdir(char *path, u32 hos_folder, int *deleted_count) { FRESULT res; DIR dir; u32 dirLength = 0; static FILINFO fno; // Open directory. res = f_opendir(&dir, path); if (res != FR_OK) return res; dirLength = strlen(path); for (;;) { // Clear file or folder path. path[dirLength] = 0; // Read a directory item. res = f_readdir(&dir, &fno); // Break on error or end of dir. if (res != FR_OK || fno.fname[0] == 0) break; // Skip official Nintendo dir if started from root. if (!hos_folder && !strcmp(fno.fname, "Nintendo")) continue; // Set new directory or file. memcpy(&path[dirLength], "/", 1); memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1); // Is it a directory? if (fno.fattrib & AM_DIR) { if ( strcmp(fno.fname, ".Trash") == 0 || strcmp(fno.fname, ".Trashes") == 0 || strcmp(fno.fname, ".DS_Store") == 0 || strcmp(fno.fname, ".Spotlight-V100") == 0 || strcmp(fno.fname, ".apDisk") == 0 || strcmp(fno.fname, ".VolumeIcon.icns") == 0 || strcmp(fno.fname, ".fseventsd") == 0 || strcmp(fno.fname, ".TemporaryItems") == 0 ) { _FolderDelete(path); if (deleted_count) (*deleted_count)++; } else { // Only recurse into directories that were not deleted. listdir(path, 0, deleted_count); } if (res != FR_OK) break; } else { if ( strcmp(fno.fname, ".DS_Store") == 0 || strcmp(fno.fname, ".Spotlight-V100") == 0 || strcmp(fno.fname, ".apDisk") == 0 || strcmp(fno.fname, ".VolumeIcon.icns") == 0 || strcmp(fno.fname, ".fseventsd") == 0 || strcmp(fno.fname, ".TemporaryItems") == 0 || _StartsWith(fno.fname, "._") ) { res = f_unlink(path); if (res) DrawError(newErrCode(res)); if (deleted_count) (*deleted_count)++; } } } f_closedir(&dir); return res; } int _fix_attributes(char *path, u32 *total, u32 hos_folder, u32 check_first_run){ FRESULT res; DIR dir; u32 dirLength = 0; static FILINFO fno; if (check_first_run) { // Read file attributes. res = f_stat(path, &fno); if (res != FR_OK) return res; // Check if archive bit is set. if (fno.fattrib & AM_ARC) { *(u32 *)total = *(u32 *)total + 1; f_chmod(path, 0, AM_ARC); } } // Open directory. res = f_opendir(&dir, path); if (res != FR_OK) return res; dirLength = strlen(path); for (;;) { // Clear file or folder path. path[dirLength] = 0; // Read a directory item. res = f_readdir(&dir, &fno); // Break on error or end of dir. if (res != FR_OK || fno.fname[0] == 0) break; // Skip official Nintendo dir if started from root. if (!hos_folder && !strcmp(fno.fname, "Nintendo")) continue; // Set new directory or file. memcpy(&path[dirLength], "/", 1); memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1); // Check if archive bit is set. if (fno.fattrib & AM_ARC) { *total = *total + 1; f_chmod(path, 0, AM_ARC); } // Is it a directory? if (fno.fattrib & AM_DIR) { // Set archive bit to NCA folders. if (hos_folder && !strcmp(fno.fname + strlen(fno.fname) - 4, ".nca")) { *total = *total + 1; f_chmod(path, AM_ARC, AM_ARC); } // Enter the directory. res = _fix_attributes(path, total, hos_folder, 0); if (res != FR_OK) break; } } f_closedir(&dir); return res; } void m_entry_fixArchiveBit(u32 type){ gfx_clearscreen(); gfx_printf("\n\n-- Behebe Archive Bit\n\n"); char path[256]; char label[16]; u32 total = 0; if (sd_mount()) { switch (type) { case 0: strcpy(path, "/"); strcpy(label, "SD-Karte"); break; case 1: default: strcpy(path, "/Nintendo"); strcpy(label, "Nintendo Ordner"); break; } gfx_printf("Durchlaufe alle %s Dateien!\nDas kann einige Zeit dauern...\n\n", label); _fix_attributes(path, &total, type, type); gfx_printf("%kAnzahl reparierter Archiv bits: %d!%k", 0xFF96FF00, total, 0xFFCCCCCC); gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren"); hidWait(); } } static void _fixAMSErrorFolder(const char *titleId, const char *label){ gfx_clearscreen(); gfx_printf("\n\n-- Fix Fehlercode %s --\n\n", label); if (!sd_mount()) { gfx_printf("SD-Karte konnte nicht gemountet werden.\n"); hidWait(); return; } char *path = CpyStr("sd:/atmosphere/contents"); char *full = CombinePaths(path, titleId); free(path); if (FileExists(full)) { gfx_printf("Entferne Ordner %s ...\n", titleId); FolderDelete(full); gfx_printf("Ordner erfolgreich geloescht.\n"); } else { gfx_printf("Ordner %s nicht gefunden (evtl. bereits behoben).\n", titleId); } free(full); gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren"); hidWait(); } void m_entry_fixAMSError_4200(void){ _fixAMSErrorFolder("4200000000000010", "4200000000000010"); } void m_entry_fixAMSError_6900(void){ _fixAMSErrorFolder("690000000000000D", "690000000000000D"); } void m_entry_fixAMSError_BD00(void){ _fixAMSErrorFolder("010000000000BD00", "010000000000BD00"); } static int _deleteTheme(char* basePath, char* folderId){ int removed = 0; char *path = CombinePaths(basePath, folderId); if (FileExists(path)) { gfx_printf("-- Theme gefunden: %s\n", path); FolderDelete(path); removed = 1; } free(path); return removed; } void m_entry_deleteInstalledThemes(){ gfx_clearscreen(); gfx_printf("\n\n-- Loesche installierte Themes.\n\n"); int count = 0; count += _deleteTheme("sd:/atmosphere/contents", "0100000000001000"); count += _deleteTheme("sd:/atmosphere/contents", "0100000000001007"); count += _deleteTheme("sd:/atmosphere/contents", "0100000000001013"); if (count > 0) gfx_printf("\n%d Theme(s) geloescht.\n", count); else gfx_printf("\nKeine installierten Themes gefunden.\n"); gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren"); hidWait(); } void m_entry_deleteBootFlags(){ gfx_clearscreen(); gfx_printf("\n\n-- Automatisches starten der sysmodule deaktivieren.\n\n"); char *storedPath = CpyStr("sd:/atmosphere/contents"); int readRes = 0; int count = 0; Vector_t fileVec = ReadFolder(storedPath, &readRes); if (readRes){ clearFileVector(&fileVec); free(storedPath); DrawError(newErrCode(readRes)); } else { vecDefArray(FSEntry_t*, fsEntries, fileVec); for (int i = 0; i < fileVec.count; i++){ char *suf = "/flags/boot2.flag"; char *subPath = CombinePaths(storedPath, fsEntries[i].name); char *flagPath = CombinePaths(subPath, suf); free(subPath); if (FileExists(flagPath)) { gfx_printf("Loesche: %s\n", flagPath); _DeleteFileSimple(flagPath); count++; } else { free(flagPath); } } clearFileVector(&fileVec); free(storedPath); } if (count > 0) gfx_printf("\n%d Boot-Flag(s) geloescht.\n", count); else if (!readRes) gfx_printf("\nKeine Boot-Flags gefunden.\n"); gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren"); hidWait(); } void m_entry_fixMacSpecialFolders(){ gfx_clearscreen(); gfx_printf("\n\n-- Mac-Ordner reparieren (dies kann ein wenig dauern, bitte warten.)\n\n"); int deleted = 0; char path[1024]; strcpy(path, "sd:/"); listdir(path, 0, &deleted); if (deleted > 0) gfx_printf("\n%d Mac-Datei(en)/Ordner entfernt.\n", deleted); else gfx_printf("\nKeine Mac-Sonderdateien oder -ordner gefunden.\n"); gfx_printf("\n\n Fertig! Druecke eine Taste um zurueckzukehren"); hidWait(); } void m_entry_stillNoBootInfo(){ gfx_clearscreen(); gfx_printf("\n\n-- Meine Switch startet immer noch nicht.\n\n"); gfx_printf("%kSteckt eine Spiel-Cardrige im Slot?\n", COLOR_WHITE); gfx_printf("Entferne sie und starte neu.\n\n"); gfx_printf("%kHast du vor kurzem Atmosphere/OmniNX aktualisiert?\n", COLOR_WHITE); gfx_printf("Stecke die SD-Karte in deinen PC, hol das neue Paket vom NiklasCFW Discord-Server und entpacke die .zip Datei auf deine SD-Karte und überschreibe alle Dateien.\nDanach kannst du den OmniNX-Installer-Payload ausfuehren.\n\n"); gfx_printf("%kHast du eine neue SD-Karte gekauft?\n", COLOR_WHITE); gfx_printf("Vergewissere dich das es keine fake/SanDisk Karte ist.\n\n"); gfx_printf("\n\n Druecke eine Taste um zurueckzukehren"); hidWait(); } void m_entry_ViewCredits(){ gfx_clearscreen(); gfx_printf("\nAllgemeinerProblemLoeser %d.%d.%d\nVon Team Neptune - (NiklasCFW Fork - Uebersetzt von Switch Bros.)\n\nBasierend auf TegraExplorer von SuchMemeManySkill,\nLockpick_RCM & Hekate, von shchmue & CTCaer\n\n\n", APL_VER_MJ, APL_VER_MN, APL_VER_BF); hidWait(); } void m_entry_fixAll(){ gfx_clearscreen(); m_entry_deleteBootFlags(); m_entry_deleteInstalledThemes(); m_entry_stillNoBootInfo(); }