diff --git a/source/deletion_lists_clean.h b/source/deletion_lists_clean.h new file mode 100644 index 0000000..915b080 --- /dev/null +++ b/source/deletion_lists_clean.h @@ -0,0 +1,298 @@ +/* + * OmniNX Installer - Deletion Lists for Clean Install Mode + * Selective deletion when no OmniNX install was found. + * Only listed paths are removed; does not wipe whole card or user configs. + */ + +#pragma once + +// Atmosphere subdirectories to delete +static const char* clean_atmosphere_dirs_to_delete[] = { + "sd:/atmosphere/config", + "sd:/atmosphere/crash_reports", + "sd:/atmosphere/erpt_reports", + "sd:/atmosphere/exefs_patches/CrunchPatch", + "sd:/atmosphere/exefs_patches/Crunchyroll Patch 1.10.0", + "sd:/atmosphere/exefs_patches/bluetooth_patches", + "sd:/atmosphere/exefs_patches/bootlogo", + "sd:/atmosphere/exefs_patches/btm_patches", + "sd:/atmosphere/exefs_patches/es_patches", + "sd:/atmosphere/exefs_patches/hid_patches", + "sd:/atmosphere/exefs_patches/logo1", + "sd:/atmosphere/exefs_patches/nfim_ctest", + "sd:/atmosphere/exefs_patches/nim_ctest", + "sd:/atmosphere/exefs_patches/nvnflinger_cmu", + "sd:/atmosphere/extrazz", + "sd:/atmosphere/fatal_errors", + "sd:/atmosphere/fatal_reports", + "sd:/atmosphere/flags", + "sd:/atmosphere/hbl_html", + "sd:/atmosphere/hosts", + "sd:/atmosphere/kips", + "sd:/atmosphere/kip1", + "sd:/atmosphere/kip_patches", + "sd:/atmosphere/logs", + NULL +}; + +// Atmosphere contents directories (title IDs; only under atmosphere/contents/) +static const char* clean_atmosphere_contents_dirs_to_delete[] = { + "sd:/atmosphere/contents/0000000000534C56", + "sd:/atmosphere/contents/00FF0000B378D640", + "sd:/atmosphere/contents/00FF0000636C6BFF", + "sd:/atmosphere/contents/00FF0000A53BB665", + "sd:/atmosphere/contents/0100000000000008", + "sd:/atmosphere/contents/010000000000000D", + "sd:/atmosphere/contents/010000000000002B", + "sd:/atmosphere/contents/0100000000000032", + "sd:/atmosphere/contents/0100000000000034", + "sd:/atmosphere/contents/0100000000000036", + "sd:/atmosphere/contents/0100000000000037", + "sd:/atmosphere/contents/010000000000003C", + "sd:/atmosphere/contents/0100000000000042", + "sd:/atmosphere/contents/0100000000000895", + "sd:/atmosphere/contents/0100000000000F12", + "sd:/atmosphere/contents/0100000000001000", + "sd:/atmosphere/contents/0100000000001007", + "sd:/atmosphere/contents/0100000000001013", + "sd:/atmosphere/contents/010000000000DA7A", + "sd:/atmosphere/contents/010000000000bd00", + "sd:/atmosphere/contents/01006a800016e000", + "sd:/atmosphere/contents/01009D901BC56000", + "sd:/atmosphere/contents/0100A3900C3E2000", + "sd:/atmosphere/contents/0100F43008C44000", + "sd:/atmosphere/contents/050000BADDAD0000", + "sd:/atmosphere/contents/4200000000000000", + "sd:/atmosphere/contents/420000000000000B", + "sd:/atmosphere/contents/420000000000000E", + "sd:/atmosphere/contents/4200000000000010", + "sd:/atmosphere/contents/4200000000000FFF", + "sd:/atmosphere/contents/420000000007E51A", + "sd:/atmosphere/contents/420000000007E51B", + "sd:/atmosphere/contents/690000000000000D", + NULL +}; + +// Atmosphere files to delete +static const char* clean_atmosphere_files_to_delete[] = { + "sd:/atmosphere/config/exosphere.ini", + "sd:/atmosphere/config/stratosphere.ini", + "sd:/atmosphere/hbl.nsp", + "sd:/atmosphere/package3", + "sd:/atmosphere/reboot_payload.bin", + "sd:/atmosphere/stratosphere.romfs", + NULL +}; + +// Bootloader directories to delete +static const char* clean_bootloader_dirs_to_delete[] = { + "sd:/bootloader/boot", + "sd:/bootloader/bootlogo", + "sd:/bootloader/ini2", + "sd:/bootloader/payloads", + "sd:/bootloader/reboot", + "sd:/bootloader/res", + "sd:/bootloader/sys", + NULL +}; + +// Bootloader files to delete +static const char* clean_bootloader_files_to_delete[] = { + "sd:/bootloader/ArgonNX.bin", + "sd:/bootloader/bootlogo.bmp", + "sd:/bootloader/hekate_ipl.ini", + "sd:/bootloader/nyx.ini", + "sd:/bootloader/patches.ini", + "sd:/bootloader/update.bin", + "sd:/bootloader/ini/EmuMMC ohne Mods.ini", + NULL +}; + +// Config directories to delete +static const char* clean_config_dirs_to_delete[] = { + "sd:/config/aio-switch-updater", + "sd:/config/blue_pack_updater", + "sd:/config/kefir-updater", + "sd:/config/nx-hbmenu", + "sd:/config/quickntp", + "sd:/config/sys-con", + "sd:/config/sys-patch", + "sd:/config/uberhand", + "sd:/config/ultrahand", + NULL +}; + +// Switch directories to delete +static const char* clean_switch_dirs_to_delete[] = { + "sd:/switch/.overlays", + "sd:/switch/.packages", + "sd:/switch/90DNS_tester", + "sd:/switch/aio-switch-updater", + "sd:/switch/amsPLUS-downloader", + "sd:/switch/appstore", + "sd:/switch/AtmoXL-Titel-Installer", + "sd:/switch/breeze", + "sd:/switch/checkpoint", + "sd:/switch/cheats-updater", + "sd:/switch/chiaki", + "sd:/switch/ChoiDujourNX", + "sd:/switch/crash_ams", + "sd:/switch/Daybreak", + "sd:/switch/DBI_658_EN", + "sd:/switch/DBI_810", + "sd:/switch/DBI_810_DE", + "sd:/switch/DBI_810_EN", + "sd:/switch/DBI_RU", + "sd:/switch/DNS_mitm Tester", + "sd:/switch/EdiZon", + "sd:/switch/Fizeau", + "sd:/switch/FTPD", + "sd:/switch/fw-downloader", + "sd:/switch/gamecard_installer", + "sd:/switch/Goldleaf", + "sd:/switch/haze", + "sd:/switch/JKSV", + "sd:/switch/kefir-updater", + "sd:/switch/ldnmitm_config", + "sd:/switch/Linkalho", + "sd:/switch/Moonlight-Switch", + "sd:/switch/Neumann", + "sd:/switch/NX-Activity-Log", + "sd:/switch/NX-Save-Sync", + "sd:/switch/NX-Shell", + "sd:/switch/NX-Update-Checker ", + "sd:/switch/NXGallery", + "sd:/switch/NXRemoteLauncher", + "sd:/switch/NXThemesInstaller", + "sd:/switch/nxdumptool", + "sd:/switch/nxmtp", + "sd:/switch/Payload_launcher", + "sd:/switch/Reboot", + "sd:/switch/reboot_to_argonNX", + "sd:/switch/reboot_to_hekate", + "sd:/switch/Shutdown_System", + "sd:/switch/SimpleModDownloader", + "sd:/switch/SimpleModManager", + "sd:/switch/sphaira", + "sd:/switch/studious-pancake", + "sd:/switch/Switch-Time", + "sd:/switch/SwitchIdent", + "sd:/switch/Switch_themes_Installer", + "sd:/switch/Switchfin", + "sd:/switch/Sys-Clk Manager", + "sd:/switch/Sys-Con", + "sd:/switch/sys-clk-manager", + "sd:/switch/themezer-nx", + "sd:/switch/themezernx", + "sd:/switch/tinwoo", + NULL +}; + +// Switch files (NRO) to delete +static const char* clean_switch_files_to_delete[] = { + "sd:/switch/90DNS_tester/90DNS_tester.nro", + "sd:/switch/breeze.nro", + "sd:/switch/cheats-updater.nro", + "sd:/switch/chiaki.nro", + "sd:/switch/ChoiDujourNX.nro", + "sd:/switch/daybreak.nro", + "sd:/switch/DBI.nro", + "sd:/switch/DBI/DBI.nro", + "sd:/switch/DBI/DBI_810_DE.nro", + "sd:/switch/DBI/DBI_810_EN.nro", + "sd:/switch/DBI/DBI_845_DE.nro", + "sd:/switch/DBI/DBI_845_EN.nro", + "sd:/switch/DBI/DBI_849_DE.nro", + "sd:/switch/DBI/DBI_849_EN.nro", + "sd:/switch/DBI_810_DE/DBI_810.nro", + "sd:/switch/DBI_810_DE/DBI_810_DE.nro", + "sd:/switch/DBI_810_EN/DBI_810_EN.nro", + "sd:/switch/DBI_RU/DBI_RU.nro", + "sd:/switch/DNS_mitm Tester.nro", + "sd:/switch/EdiZon.nro", + "sd:/switch/Fizeau.nro", + "sd:/switch/Goldleaf.nro", + "sd:/switch/haze.nro", + "sd:/switch/JKSV.nro", + "sd:/switch/ldnmitm_config.nro", + "sd:/switch/linkalho.nro", + "sd:/switch/Moonlight-Switch.nro", + "sd:/switch/Neumann.nro", + "sd:/switch/NX-Shell.nro", + "sd:/switch/NXGallery.nro", + "sd:/switch/NXThemesInstaller.nro", + "sd:/switch/nxdumptool.nro", + "sd:/switch/nxtc.bin", + "sd:/switch/reboot_to_payload.nro", + "sd:/switch/SimpleModDownloader.nro", + "sd:/switch/SimpleModManager.nro", + "sd:/switch/sphaira.nro", + "sd:/switch/SwitchIdent.nro", + "sd:/switch/Switch_themes_Installer/NXThemesInstaller.nro", + "sd:/switch/Switchfin.nro", + "sd:/switch/Sys-Clk Manager/sys-clk-manager.nro", + "sd:/switch/Sys-Con.nro", + "sd:/switch/sys-clk-manager.nro", + "sd:/switch/tinfoil.nro", + "sd:/switch/tinfoil/tinfoil.nro", + "sd:/switch/tinwoo.nro", + "sd:/switch/tinwoo/tinwoo.nro", + NULL +}; + +// Root CFW files to delete +static const char* clean_root_files_to_delete[] = { + "sd:/boot.dat", + "sd:/boot.ini", + "sd:/exosphere.bin", + "sd:/exosphere.ini", + "sd:/hbmenu.nro", + "sd:/install.bat", + "sd:/license", + "sd:/loader.bin", + "sd:/mc-mitm.log", + "sd:/payload.bin", + "sd:/update.bin", + "sd:/version", + NULL +}; + +// Miscellaneous directories to delete +static const char* clean_misc_dirs_to_delete[] = { + "sd:/argon", + "sd:/games", + "sd:/NSPs (Tools)", + "sd:/Patched Apps", + "sd:/SaltySD/flags", + "sd:/scripts", + "sd:/switch/tinfoil/db", + "sd:/tools", + "sd:/warmboot_mariko", + NULL +}; + +// Miscellaneous files to delete +static const char* clean_misc_files_to_delete[] = { + "sd:/fusee-primary.bin", + "sd:/fusee.bin", + "sd:/SaltySD/exceptions.txt", + "sd:/SaltySD/saltysd_bootstrap.elf", + "sd:/SaltySD/saltysd_bootstrap32_3k.elf", + "sd:/SaltySD/saltysd_bootstrap32_5k.elf", + "sd:/SaltySD/saltysd_core.elf", + "sd:/SaltySD/saltysd_core32.elf", + NULL +}; + +// Old version marker files to delete (clean install only) +static const char* old_version_files_to_delete[] = { + "sd:/1.0.0l", + "sd:/1.0.0s", + "sd:/1.0.0oc", + "sd:/1.4.0-pre", + "sd:/1.4.0-pre-c", + "sd:/1.4.0-pre-d", + "sd:/1.4.1", + "sd:/1.5.0", + NULL +}; diff --git a/source/deletion_lists.h b/source/deletion_lists_update.h similarity index 81% rename from source/deletion_lists.h rename to source/deletion_lists_update.h index 1a7a85e..da9cf40 100644 --- a/source/deletion_lists.h +++ b/source/deletion_lists_update.h @@ -1,342 +1,284 @@ -/* - * OmniNX Installer - Deletion Lists for Update Mode - * Arrays of paths to delete during update installation - */ - -#pragma once - -// Atmosphere subdirectories to delete -static const char* atmosphere_dirs_to_delete[] = { - "sd:/atmosphere/config", - "sd:/atmosphere/crash_reports", - "sd:/atmosphere/erpt_reports", - "sd:/atmosphere/exefs_patches/CrunchPatch", - "sd:/atmosphere/exefs_patches/Crunchyroll Patch 1.10.0", - "sd:/atmosphere/exefs_patches/bluetooth_patches", - "sd:/atmosphere/exefs_patches/bootlogo", - "sd:/atmosphere/exefs_patches/btm_patches", - "sd:/atmosphere/exefs_patches/es_patches", - "sd:/atmosphere/exefs_patches/hid_patches", - "sd:/atmosphere/exefs_patches/logo1", - "sd:/atmosphere/exefs_patches/nfim_ctest", - "sd:/atmosphere/exefs_patches/nim_ctest", - "sd:/atmosphere/exefs_patches/nvnflinger_cmu", - "sd:/atmosphere/extrazz", - "sd:/atmosphere/fatal_errors", - "sd:/atmosphere/fatal_reports", - "sd:/atmosphere/flags", - "sd:/atmosphere/hbl_html", - "sd:/atmosphere/hosts", - "sd:/atmosphere/kips", - "sd:/atmosphere/kip1", - "sd:/atmosphere/kip_patches", - "sd:/atmosphere/logs", - NULL -}; - -// Atmosphere root directories (title IDs) -static const char* atmosphere_root_dirs_to_delete[] = { - "sd:/atmosphere/0000000000534C56", - "sd:/atmosphere/00FF0000B378D640", - "sd:/atmosphere/00FF0000636C6BFF", - "sd:/atmosphere/00FF0000A53BB665", - "sd:/atmosphere/0100000000000008", - "sd:/atmosphere/010000000000000D", - "sd:/atmosphere/010000000000002B", - "sd:/atmosphere/0100000000000032", - "sd:/atmosphere/0100000000000034", - "sd:/atmosphere/0100000000000036", - "sd:/atmosphere/0100000000000037", - "sd:/atmosphere/010000000000003C", - "sd:/atmosphere/0100000000000042", - "sd:/atmosphere/0100000000000F12", - "sd:/atmosphere/0100000000001000", - "sd:/atmosphere/0100000000001007", - "sd:/atmosphere/0100000000001013", - "sd:/atmosphere/010000000000DA7A", - "sd:/atmosphere/010000000000bd00", - "sd:/atmosphere/01006a800016e000", - "sd:/atmosphere/01009D901BC56000", - "sd:/atmosphere/0100A3900C3E2000", - "sd:/atmosphere/0100F43008C44000", - "sd:/atmosphere/050000BADDAD0000", - "sd:/atmosphere/4200000000000000", - "sd:/atmosphere/420000000000000B", - "sd:/atmosphere/420000000000000E", - "sd:/atmosphere/4200000000000010", - "sd:/atmosphere/4200000000000FFF", - "sd:/atmosphere/420000000007E51A", - "sd:/atmosphere/420000000007E51B", - "sd:/atmosphere/690000000000000D", - NULL -}; - -// Atmosphere contents directories (title IDs) -static const char* atmosphere_contents_dirs_to_delete[] = { - "sd:/atmosphere/contents/0000000000534C56", - "sd:/atmosphere/contents/00FF0000B378D640", - "sd:/atmosphere/contents/00FF0000636C6BFF", - "sd:/atmosphere/contents/00FF0000A53BB665", - "sd:/atmosphere/contents/0100000000000008", - "sd:/atmosphere/contents/010000000000000D", - "sd:/atmosphere/contents/010000000000002B", - "sd:/atmosphere/contents/0100000000000032", - "sd:/atmosphere/contents/0100000000000034", - "sd:/atmosphere/contents/0100000000000036", - "sd:/atmosphere/contents/0100000000000037", - "sd:/atmosphere/contents/010000000000003C", - "sd:/atmosphere/contents/0100000000000042", - "sd:/atmosphere/contents/0100000000000895", - "sd:/atmosphere/contents/0100000000000F12", - "sd:/atmosphere/contents/0100000000001000", - "sd:/atmosphere/contents/0100000000001007", - "sd:/atmosphere/contents/0100000000001013", - "sd:/atmosphere/contents/010000000000DA7A", - "sd:/atmosphere/contents/010000000000bd00", - "sd:/atmosphere/contents/01006a800016e000", - "sd:/atmosphere/contents/01009D901BC56000", - "sd:/atmosphere/contents/0100A3900C3E2000", - "sd:/atmosphere/contents/0100F43008C44000", - "sd:/atmosphere/contents/050000BADDAD0000", - "sd:/atmosphere/contents/4200000000000000", - "sd:/atmosphere/contents/420000000000000B", - "sd:/atmosphere/contents/420000000000000E", - "sd:/atmosphere/contents/4200000000000010", - "sd:/atmosphere/contents/4200000000000FFF", - "sd:/atmosphere/contents/420000000007E51A", - "sd:/atmosphere/contents/420000000007E51B", - "sd:/atmosphere/contents/690000000000000D", - NULL -}; - -// Atmosphere files to delete -static const char* atmosphere_files_to_delete[] = { - "sd:/atmosphere/config/exosphere.ini", - "sd:/atmosphere/config/override_config.ini", - "sd:/atmosphere/config/stratosphere.ini", - "sd:/atmosphere/hbl.nsp", - "sd:/atmosphere/package3", - "sd:/atmosphere/reboot_payload.bin", - "sd:/atmosphere/stratosphere.romfs", - NULL -}; - -// Bootloader directories to delete -static const char* bootloader_dirs_to_delete[] = { - "sd:/bootloader/boot", - "sd:/bootloader/bootlogo", - "sd:/bootloader/ini2", - "sd:/bootloader/payloads", - "sd:/bootloader/reboot", - "sd:/bootloader/res", - "sd:/bootloader/sys", - NULL -}; - -// Bootloader files to delete -static const char* bootloader_files_to_delete[] = { - "sd:/bootloader/ArgonNX.bin", - "sd:/bootloader/bootlogo.bmp", - "sd:/bootloader/hekate_ipl.ini", - "sd:/bootloader/nyx.ini", - "sd:/bootloader/patches.ini", - "sd:/bootloader/update.bin", - "sd:/bootloader/ini/EmuMMC ohne Mods.ini", - NULL -}; - -// Config directories to delete -static const char* config_dirs_to_delete[] = { - "sd:/config/aio-switch-updater", - "sd:/config/blue_pack_updater", - "sd:/config/kefir-updater", - "sd:/config/nx-hbmenu", - "sd:/config/quickntp", - "sd:/config/sys-con", - "sd:/config/sys-patch", - "sd:/config/uberhand", - "sd:/config/ultrahand", - NULL -}; - -// Switch directories to delete -static const char* switch_dirs_to_delete[] = { - "sd:/switch/.overlays", - "sd:/switch/.packages", - "sd:/switch/90DNS_tester", - "sd:/switch/aio-switch-updater", - "sd:/switch/amsPLUS-downloader", - "sd:/switch/appstore", - "sd:/switch/AtmoXL-Titel-Installer", - "sd:/switch/breeze", - "sd:/switch/checkpoint", - "sd:/switch/cheats-updater", - "sd:/switch/chiaki", - "sd:/switch/ChoiDujourNX", - "sd:/switch/crash_ams", - "sd:/switch/Daybreak", - "sd:/switch/DBI_658_EN", - "sd:/switch/DBI_810", - "sd:/switch/DBI_810_DE", - "sd:/switch/DBI_810_EN", - "sd:/switch/DBI_RU", - "sd:/switch/DNS_mitm Tester", - "sd:/switch/EdiZon", - "sd:/switch/Fizeau", - "sd:/switch/FTPD", - "sd:/switch/fw-downloader", - "sd:/switch/gamecard_installer", - "sd:/switch/Goldleaf", - "sd:/switch/haze", - "sd:/switch/JKSV", - "sd:/switch/kefir-updater", - "sd:/switch/ldnmitm_config", - "sd:/switch/Linkalho", - "sd:/switch/Moonlight-Switch", - "sd:/switch/Neumann", - "sd:/switch/NX-Activity-Log", - "sd:/switch/NX-Save-Sync", - "sd:/switch/NX-Shell", - "sd:/switch/NX-Update-Checker ", - "sd:/switch/NXGallery", - "sd:/switch/NXRemoteLauncher", - "sd:/switch/NXThemesInstaller", - "sd:/switch/nxdumptool", - "sd:/switch/nxmtp", - "sd:/switch/Payload_launcher", - "sd:/switch/Reboot", - "sd:/switch/reboot_to_argonNX", - "sd:/switch/reboot_to_hekate", - "sd:/switch/Shutdown_System", - "sd:/switch/SimpleModDownloader", - "sd:/switch/SimpleModManager", - "sd:/switch/sphaira", - "sd:/switch/studious-pancake", - "sd:/switch/Switch-Time", - "sd:/switch/SwitchIdent", - "sd:/switch/Switch_themes_Installer", - "sd:/switch/Switchfin", - "sd:/switch/Sys-Clk Manager", - "sd:/switch/Sys-Con", - "sd:/switch/sys-clk-manager", - "sd:/switch/themezer-nx", - "sd:/switch/themezernx", - "sd:/switch/tinwoo", - NULL -}; - -// Switch files (NRO) to delete -static const char* switch_files_to_delete[] = { - "sd:/switch/90DNS_tester/90DNS_tester.nro", - "sd:/switch/breeze.nro", - "sd:/switch/cheats-updater.nro", - "sd:/switch/chiaki.nro", - "sd:/switch/ChoiDujourNX.nro", - "sd:/switch/daybreak.nro", - "sd:/switch/DBI.nro", - "sd:/switch/DBI/DBI.nro", - "sd:/switch/DBI/DBI_810_DE.nro", - "sd:/switch/DBI/DBI_810_EN.nro", - "sd:/switch/DBI/DBI_845_DE.nro", - "sd:/switch/DBI/DBI_845_EN.nro", - "sd:/switch/DBI/DBI_849_DE.nro", - "sd:/switch/DBI/DBI_849_EN.nro", - "sd:/switch/DBI_810_DE/DBI_810.nro", - "sd:/switch/DBI_810_DE/DBI_810_DE.nro", - "sd:/switch/DBI_810_EN/DBI_810_EN.nro", - "sd:/switch/DBI_RU/DBI_RU.nro", - "sd:/switch/DNS_mitm Tester.nro", - "sd:/switch/EdiZon.nro", - "sd:/switch/Fizeau.nro", - "sd:/switch/Goldleaf.nro", - "sd:/switch/haze.nro", - "sd:/switch/JKSV.nro", - "sd:/switch/ldnmitm_config.nro", - "sd:/switch/linkalho.nro", - "sd:/switch/Moonlight-Switch.nro", - "sd:/switch/Neumann.nro", - "sd:/switch/NX-Shell.nro", - "sd:/switch/NXGallery.nro", - "sd:/switch/NXThemesInstaller.nro", - "sd:/switch/nxdumptool.nro", - "sd:/switch/nxtc.bin", - "sd:/switch/reboot_to_payload.nro", - "sd:/switch/SimpleModDownloader.nro", - "sd:/switch/SimpleModManager.nro", - "sd:/switch/sphaira.nro", - "sd:/switch/SwitchIdent.nro", - "sd:/switch/Switch_themes_Installer/NXThemesInstaller.nro", - "sd:/switch/Switchfin.nro", - "sd:/switch/Sys-Clk Manager/sys-clk-manager.nro", - "sd:/switch/Sys-Con.nro", - "sd:/switch/sys-clk-manager.nro", - "sd:/switch/tinfoil.nro", - "sd:/switch/tinfoil/tinfoil.nro", - "sd:/switch/tinwoo.nro", - "sd:/switch/tinwoo/tinwoo.nro", - NULL -}; - -// Root CFW files to delete -static const char* root_files_to_delete[] = { - "sd:/boot.dat", - "sd:/boot.ini", - "sd:/exosphere.bin", - "sd:/exosphere.ini", - "sd:/hbmenu.nro", - "sd:/install.bat", - "sd:/license", - "sd:/loader.bin", - "sd:/mc-mitm.log", - "sd:/payload.bin", - "sd:/update.bin", - "sd:/version", - NULL -}; - -// Miscellaneous directories to delete -static const char* misc_dirs_to_delete[] = { - "sd:/argon", - "sd:/games", - "sd:/NSPs (Tools)", - "sd:/Patched Apps", - "sd:/SaltySD", - "sd:/scripts", - "sd:/switch/tinfoil/db", - "sd:/tools", - "sd:/warmboot_mariko", - NULL -}; - -// Miscellaneous files to delete -static const char* misc_files_to_delete[] = { - "sd:/fusee-primary.bin", - "sd:/fusee.bin", - "sd:/SaltySD/exceptions.txt", - "sd:/SaltySD/saltysd_bootstrap.elf", - "sd:/SaltySD/saltysd_bootstrap32_3k.elf", - "sd:/SaltySD/saltysd_bootstrap32_5k.elf", - "sd:/SaltySD/saltysd_core.elf", - "sd:/SaltySD/saltysd_core32.elf", - NULL -}; - -// Old version marker files to delete -static const char* old_version_files_to_delete[] = { - "sd:/1.0.0l", - "sd:/1.0.0s", - "sd:/1.0.0oc", - "sd:/1.4.0-pre", - "sd:/1.4.0-pre-c", - "sd:/1.4.0-pre-d", - "sd:/1.4.1", - "sd:/1.5.0", - NULL -}; - -// Helper function to count array elements (excluding NULL terminator) -static inline int count_paths(const char* paths[]) { - int count = 0; - while (paths[count] != NULL) count++; - return count; -} +/* + * OmniNX Installer - Deletion Lists for Update Mode + * Selective deletion when OmniNX is already installed. + */ + +#pragma once + +// Atmosphere subdirectories to delete +static const char* atmosphere_dirs_to_delete[] = { + "sd:/atmosphere/config", + "sd:/atmosphere/crash_reports", + "sd:/atmosphere/erpt_reports", + "sd:/atmosphere/exefs_patches/CrunchPatch", + "sd:/atmosphere/exefs_patches/Crunchyroll Patch 1.10.0", + "sd:/atmosphere/exefs_patches/bluetooth_patches", + "sd:/atmosphere/exefs_patches/bootlogo", + "sd:/atmosphere/exefs_patches/btm_patches", + "sd:/atmosphere/exefs_patches/es_patches", + "sd:/atmosphere/exefs_patches/hid_patches", + "sd:/atmosphere/exefs_patches/logo1", + "sd:/atmosphere/exefs_patches/nfim_ctest", + "sd:/atmosphere/exefs_patches/nim_ctest", + "sd:/atmosphere/exefs_patches/nvnflinger_cmu", + "sd:/atmosphere/extrazz", + "sd:/atmosphere/fatal_errors", + "sd:/atmosphere/fatal_reports", + "sd:/atmosphere/flags", + "sd:/atmosphere/hbl_html", + "sd:/atmosphere/hosts", + "sd:/atmosphere/kips", + "sd:/atmosphere/kip1", + "sd:/atmosphere/kip_patches", + "sd:/atmosphere/logs", + NULL +}; + +// Atmosphere contents directories (title IDs; only under atmosphere/contents/) +static const char* atmosphere_contents_dirs_to_delete[] = { + "sd:/atmosphere/contents/0000000000534C56", + "sd:/atmosphere/contents/00FF0000B378D640", + "sd:/atmosphere/contents/00FF0000636C6BFF", + "sd:/atmosphere/contents/00FF0000A53BB665", + "sd:/atmosphere/contents/0100000000000008", + "sd:/atmosphere/contents/010000000000000D", + "sd:/atmosphere/contents/010000000000002B", + "sd:/atmosphere/contents/0100000000000032", + "sd:/atmosphere/contents/0100000000000034", + "sd:/atmosphere/contents/0100000000000036", + "sd:/atmosphere/contents/0100000000000037", + "sd:/atmosphere/contents/010000000000003C", + "sd:/atmosphere/contents/0100000000000042", + "sd:/atmosphere/contents/0100000000000895", + "sd:/atmosphere/contents/0100000000000F12", + "sd:/atmosphere/contents/0100000000001000", + "sd:/atmosphere/contents/0100000000001007", + "sd:/atmosphere/contents/0100000000001013", + "sd:/atmosphere/contents/010000000000DA7A", + "sd:/atmosphere/contents/010000000000bd00", + "sd:/atmosphere/contents/01006a800016e000", + "sd:/atmosphere/contents/01009D901BC56000", + "sd:/atmosphere/contents/0100A3900C3E2000", + "sd:/atmosphere/contents/0100F43008C44000", + "sd:/atmosphere/contents/050000BADDAD0000", + "sd:/atmosphere/contents/4200000000000000", + "sd:/atmosphere/contents/420000000000000B", + "sd:/atmosphere/contents/420000000000000E", + "sd:/atmosphere/contents/4200000000000010", + "sd:/atmosphere/contents/4200000000000FFF", + "sd:/atmosphere/contents/420000000007E51A", + "sd:/atmosphere/contents/420000000007E51B", + "sd:/atmosphere/contents/690000000000000D", + NULL +}; + +// Atmosphere files to delete +static const char* atmosphere_files_to_delete[] = { + "sd:/atmosphere/config/exosphere.ini", + "sd:/atmosphere/config/stratosphere.ini", + "sd:/atmosphere/hbl.nsp", + "sd:/atmosphere/package3", + "sd:/atmosphere/reboot_payload.bin", + "sd:/atmosphere/stratosphere.romfs", + NULL +}; + +// Bootloader directories to delete +static const char* bootloader_dirs_to_delete[] = { + "sd:/bootloader/boot", + "sd:/bootloader/bootlogo", + "sd:/bootloader/ini2", + "sd:/bootloader/payloads", + "sd:/bootloader/reboot", + "sd:/bootloader/res", + "sd:/bootloader/sys", + NULL +}; + +// Bootloader files to delete +static const char* bootloader_files_to_delete[] = { + "sd:/bootloader/ArgonNX.bin", + "sd:/bootloader/bootlogo.bmp", + "sd:/bootloader/hekate_ipl.ini", + "sd:/bootloader/nyx.ini", + "sd:/bootloader/patches.ini", + "sd:/bootloader/update.bin", + "sd:/bootloader/ini/EmuMMC ohne Mods.ini", + NULL +}; + +// Config directories to delete +static const char* config_dirs_to_delete[] = { + "sd:/config/aio-switch-updater", + "sd:/config/blue_pack_updater", + "sd:/config/kefir-updater", + "sd:/config/nx-hbmenu", + "sd:/config/quickntp", + "sd:/config/sys-con", + "sd:/config/sys-patch", + "sd:/config/uberhand", + "sd:/config/ultrahand", + NULL +}; + +// Switch directories to delete +static const char* switch_dirs_to_delete[] = { + "sd:/switch/.overlays", + "sd:/switch/.packages", + "sd:/switch/90DNS_tester", + "sd:/switch/aio-switch-updater", + "sd:/switch/amsPLUS-downloader", + "sd:/switch/appstore", + "sd:/switch/AtmoXL-Titel-Installer", + "sd:/switch/breeze", + "sd:/switch/checkpoint", + "sd:/switch/cheats-updater", + "sd:/switch/chiaki", + "sd:/switch/ChoiDujourNX", + "sd:/switch/crash_ams", + "sd:/switch/Daybreak", + "sd:/switch/DBI_658_EN", + "sd:/switch/DBI_810", + "sd:/switch/DBI_810_DE", + "sd:/switch/DBI_810_EN", + "sd:/switch/DBI_RU", + "sd:/switch/DNS_mitm Tester", + "sd:/switch/EdiZon", + "sd:/switch/Fizeau", + "sd:/switch/FTPD", + "sd:/switch/fw-downloader", + "sd:/switch/gamecard_installer", + "sd:/switch/Goldleaf", + "sd:/switch/haze", + "sd:/switch/JKSV", + "sd:/switch/kefir-updater", + "sd:/switch/ldnmitm_config", + "sd:/switch/Linkalho", + "sd:/switch/Moonlight-Switch", + "sd:/switch/Neumann", + "sd:/switch/NX-Activity-Log", + "sd:/switch/NX-Save-Sync", + "sd:/switch/NX-Shell", + "sd:/switch/NX-Update-Checker ", + "sd:/switch/NXGallery", + "sd:/switch/NXRemoteLauncher", + "sd:/switch/NXThemesInstaller", + "sd:/switch/nxdumptool", + "sd:/switch/nxmtp", + "sd:/switch/Payload_launcher", + "sd:/switch/Reboot", + "sd:/switch/reboot_to_argonNX", + "sd:/switch/reboot_to_hekate", + "sd:/switch/Shutdown_System", + "sd:/switch/SimpleModDownloader", + "sd:/switch/SimpleModManager", + "sd:/switch/sphaira", + "sd:/switch/studious-pancake", + "sd:/switch/Switch-Time", + "sd:/switch/SwitchIdent", + "sd:/switch/Switch_themes_Installer", + "sd:/switch/Switchfin", + "sd:/switch/Sys-Clk Manager", + "sd:/switch/Sys-Con", + "sd:/switch/sys-clk-manager", + "sd:/switch/themezer-nx", + "sd:/switch/themezernx", + "sd:/switch/tinwoo", + NULL +}; + +// Switch files (NRO) to delete +static const char* switch_files_to_delete[] = { + "sd:/switch/90DNS_tester/90DNS_tester.nro", + "sd:/switch/breeze.nro", + "sd:/switch/cheats-updater.nro", + "sd:/switch/chiaki.nro", + "sd:/switch/ChoiDujourNX.nro", + "sd:/switch/daybreak.nro", + "sd:/switch/DBI.nro", + "sd:/switch/DBI/DBI.nro", + "sd:/switch/DBI/DBI_810_DE.nro", + "sd:/switch/DBI/DBI_810_EN.nro", + "sd:/switch/DBI/DBI_845_DE.nro", + "sd:/switch/DBI/DBI_845_EN.nro", + "sd:/switch/DBI/DBI_849_DE.nro", + "sd:/switch/DBI/DBI_849_EN.nro", + "sd:/switch/DBI_810_DE/DBI_810.nro", + "sd:/switch/DBI_810_DE/DBI_810_DE.nro", + "sd:/switch/DBI_810_EN/DBI_810_EN.nro", + "sd:/switch/DBI_RU/DBI_RU.nro", + "sd:/switch/DNS_mitm Tester.nro", + "sd:/switch/EdiZon.nro", + "sd:/switch/Fizeau.nro", + "sd:/switch/Goldleaf.nro", + "sd:/switch/haze.nro", + "sd:/switch/JKSV.nro", + "sd:/switch/ldnmitm_config.nro", + "sd:/switch/linkalho.nro", + "sd:/switch/Moonlight-Switch.nro", + "sd:/switch/Neumann.nro", + "sd:/switch/NX-Shell.nro", + "sd:/switch/NXGallery.nro", + "sd:/switch/NXThemesInstaller.nro", + "sd:/switch/nxdumptool.nro", + "sd:/switch/nxtc.bin", + "sd:/switch/reboot_to_payload.nro", + "sd:/switch/SimpleModDownloader.nro", + "sd:/switch/SimpleModManager.nro", + "sd:/switch/sphaira.nro", + "sd:/switch/SwitchIdent.nro", + "sd:/switch/Switch_themes_Installer/NXThemesInstaller.nro", + "sd:/switch/Switchfin.nro", + "sd:/switch/Sys-Clk Manager/sys-clk-manager.nro", + "sd:/switch/Sys-Con.nro", + "sd:/switch/sys-clk-manager.nro", + "sd:/switch/tinfoil.nro", + "sd:/switch/tinfoil/tinfoil.nro", + "sd:/switch/tinwoo.nro", + "sd:/switch/tinwoo/tinwoo.nro", + NULL +}; + +// Root CFW files to delete +static const char* root_files_to_delete[] = { + "sd:/boot.dat", + "sd:/boot.ini", + "sd:/exosphere.bin", + "sd:/exosphere.ini", + "sd:/hbmenu.nro", + "sd:/install.bat", + "sd:/license", + "sd:/loader.bin", + "sd:/mc-mitm.log", + "sd:/payload.bin", + "sd:/update.bin", + "sd:/version", + NULL +}; + +// Miscellaneous directories to delete +static const char* misc_dirs_to_delete[] = { + "sd:/argon", + "sd:/games", + "sd:/NSPs (Tools)", + "sd:/Patched Apps", + "sd:/SaltySD/flags", + "sd:/scripts", + "sd:/switch/tinfoil/db", + "sd:/tools", + "sd:/warmboot_mariko", + NULL +}; + +// Miscellaneous files to delete +static const char* misc_files_to_delete[] = { + "sd:/fusee-primary.bin", + "sd:/fusee.bin", + "sd:/SaltySD/exceptions.txt", + "sd:/SaltySD/saltysd_bootstrap.elf", + "sd:/SaltySD/saltysd_bootstrap32_3k.elf", + "sd:/SaltySD/saltysd_bootstrap32_5k.elf", + "sd:/SaltySD/saltysd_core.elf", + "sd:/SaltySD/saltysd_core32.elf", + NULL +}; diff --git a/source/fs.c b/source/fs.c index dac196b..80e9ba3 100644 --- a/source/fs.c +++ b/source/fs.c @@ -218,6 +218,12 @@ int folder_delete(const char *path) { } else { file_count++; log_write(" DEL: %s\n", fno.fname); + + // Clear read-only attribute if set (common with some CFW packs) + if (fno.fattrib & AM_RDO) { + f_chmod(full_path, fno.fattrib & ~AM_RDO, AM_RDO); + } + res = f_unlink(full_path); if (res != FR_OK) { log_write(" ERROR: %s\n", fs_error_str(res)); @@ -232,6 +238,13 @@ int folder_delete(const char *path) { if (res == FR_OK || res == FR_NO_FILE) { log_write(" Removing dir: %s (%d files, %d subdirs)\n", path, file_count, dir_count); + + // Check and clear read-only attribute on directory if set + FILINFO dir_info; + if (f_stat(path, &dir_info) == FR_OK && (dir_info.fattrib & AM_RDO)) { + f_chmod(path, dir_info.fattrib & ~AM_RDO, AM_RDO); + } + res = f_unlink(path); if (res != FR_OK) { log_write(" ERROR rmdir: %s\n", fs_error_str(res)); diff --git a/source/install.c b/source/install.c index 6384a10..9ffcf11 100644 --- a/source/install.c +++ b/source/install.c @@ -3,8 +3,6 @@ */ #include "install.h" -#include "backup.h" -#include "deletion_lists.h" #include "fs.h" #include "version.h" #include "gfx.h" @@ -16,8 +14,6 @@ #define VERSION "1.0.0" #endif -// Forward declaration -static void combine_path(char *result, size_t size, const char *base, const char *add); // Color definitions (some already defined in types.h, but we override for consistency) #undef COLOR_CYAN @@ -33,12 +29,12 @@ static void combine_path(char *result, size_t size, const char *base, const char #define COLOR_ORANGE 0xFF00A5FF #define COLOR_RED 0xFFFF0000 -static void set_color(u32 color) { +void install_set_color(u32 color) { gfx_con_setcol(color, gfx_con.fillbg, gfx_con.bgcol); } // Check if we need to clear screen (when getting close to bottom) -static void check_and_clear_screen_if_needed(void) { +void install_check_and_clear_screen_if_needed(void) { // In the gfx system: // - gfx_con.x is the vertical position (line number, increments by 16 per line) // - gfx_con.y is the horizontal position (pixels from left) @@ -53,22 +49,22 @@ static void check_and_clear_screen_if_needed(void) { gfx_con_setpos(0, 0); // Reprint same header as initial launch - set_color(COLOR_CYAN); - gfx_printf("========================================\n"); + install_set_color(COLOR_CYAN); + gfx_printf("===================================\n"); gfx_printf(" OmniNX Installer Payload v%s\n", VERSION); - gfx_printf("========================================\n\n"); - set_color(COLOR_WHITE); + gfx_printf("===================================\n\n"); + install_set_color(COLOR_WHITE); } } // Check if file/directory exists -static bool path_exists(const char *path) { +bool install_path_exists(const char *path) { FILINFO fno; return (f_stat(path, &fno) == FR_OK); } // Count total items (files + directories) in a directory tree recursively -static int count_directory_items(const char *path) { +int install_count_directory_items(const char *path) { DIR dir; FILINFO fno; int res; @@ -94,7 +90,7 @@ static int count_directory_items(const char *path) { if (fno.fattrib & AM_DIR) { char sub_path[256]; s_printf(sub_path, "%s/%s", path, fno.fname); - count += count_directory_items(sub_path); + count += install_count_directory_items(sub_path); } } @@ -103,7 +99,7 @@ static int count_directory_items(const char *path) { } // Helper to combine paths (handles trailing slashes properly) -static void combine_path(char *result, size_t size, const char *base, const char *add) { +void install_combine_path(char *result, size_t size, const char *base, const char *add) { size_t base_len = strlen(base); if (base_len > 0 && base[base_len - 1] == '/') { // Base has trailing slash, just append @@ -137,7 +133,7 @@ static int folder_copy_progress_recursive(const char *src, const char *dst, int } // Create destination folder path (handle trailing slash in dst) - combine_path(dst_dir, sizeof(dst_dir), dst, folder_name); + install_combine_path(dst_dir, sizeof(dst_dir), dst, folder_name); // Try to create the directory (ignore if it already exists) res = f_mkdir(dst_dir); @@ -171,8 +167,8 @@ static int folder_copy_progress_recursive(const char *src, const char *dst, int } // Build source and destination paths - combine_path(src_full, sizeof(src_full), src, fno.fname); - combine_path(dst_full, sizeof(dst_full), dst_dir, fno.fname); + install_combine_path(src_full, sizeof(src_full), src, fno.fname); + install_combine_path(dst_full, sizeof(dst_full), dst_dir, fno.fname); if (fno.fattrib & AM_DIR) { res = folder_copy_progress_recursive(src_full, dst_dir, copied, total, start_x, start_y, display_name, last_percent); @@ -188,9 +184,9 @@ static int folder_copy_progress_recursive(const char *src, const char *dst, int int percent = total > 0 ? (*copied * 100) / total : 0; if (percent != *last_percent || *copied % 50 == 0) { gfx_con_setpos(start_x, start_y); - set_color(COLOR_CYAN); + install_set_color(COLOR_CYAN); gfx_printf(" Kopiere: %s [%3d%%] (%d/%d)", display_name, percent, *copied, total); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); *last_percent = percent; } } @@ -203,7 +199,7 @@ static int folder_copy_progress_recursive(const char *src, const char *dst, int } // Progress-aware folder copy (improved version) -static int folder_copy_with_progress_v2(const char *src, const char *dst, const char *display_name) { +int folder_copy_with_progress_v2(const char *src, const char *dst, const char *display_name) { int copied = 0; int total = 0; int last_percent = -1; @@ -211,15 +207,15 @@ static int folder_copy_with_progress_v2(const char *src, const char *dst, const int res; // Check if source exists - if (!path_exists(src)) { - set_color(COLOR_ORANGE); + if (!install_path_exists(src)) { + install_set_color(COLOR_ORANGE); gfx_printf(" Ueberspringe: %s (nicht gefunden)\n", display_name); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); return FR_NO_FILE; } // Count total items first - total = count_directory_items(src); + total = install_count_directory_items(src); if (total == 0) { // Empty directory, just create destination @@ -227,7 +223,7 @@ static int folder_copy_with_progress_v2(const char *src, const char *dst, const if (folder_name) folder_name++; else folder_name = src; char dst_path[256]; - combine_path(dst_path, sizeof(dst_path), dst, folder_name); + install_combine_path(dst_path, sizeof(dst_path), dst, folder_name); res = f_mkdir(dst_path); if (res == FR_OK || res == FR_EXIST) { return FR_OK; @@ -239,9 +235,9 @@ static int folder_copy_with_progress_v2(const char *src, const char *dst, const gfx_con_getpos(&start_x, &start_y); // Show initial status - set_color(COLOR_CYAN); + install_set_color(COLOR_CYAN); gfx_printf(" Kopiere: %s [ 0%%] (0/%d)", display_name, total); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); // Perform the copy with progress updates res = folder_copy_progress_recursive(src, dst, &copied, total, start_x, start_y, display_name, &last_percent); @@ -249,26 +245,26 @@ static int folder_copy_with_progress_v2(const char *src, const char *dst, const // Final update - overwrite the same line gfx_con_setpos(start_x, start_y); if (res == FR_OK) { - set_color(COLOR_GREEN); + install_set_color(COLOR_GREEN); gfx_printf(" Kopiere: %s [100%%] (%d/%d) - Fertig!\n", display_name, copied, total); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); } else { - set_color(COLOR_RED); + install_set_color(COLOR_RED); gfx_printf(" Kopiere: %s - Fehlgeschlagen!\n", display_name); gfx_printf(" Fehler: %s (Code=%d)\n", fs_error_str(res), res); gfx_printf(" Quelle: %s\n", src); gfx_printf(" Ziel: %s\n", dst); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); // Fallback: try using the original folder_copy function - set_color(COLOR_ORANGE); + install_set_color(COLOR_ORANGE); gfx_printf(" Versuche alternative Kopiermethode...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); int fallback_res = folder_copy(src, dst); if (fallback_res == FR_OK) { - set_color(COLOR_GREEN); + install_set_color(COLOR_GREEN); gfx_printf(" Alternative Kopie erfolgreich!\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); return FR_OK; } } @@ -276,20 +272,186 @@ static int folder_copy_with_progress_v2(const char *src, const char *dst, const return res; } -// Delete a list of paths +// Recursive folder delete with progress tracking (shared implementation) +int folder_delete_progress_recursive(const char *path, int *deleted, int total, u32 start_x, u32 start_y, const char *display_name, int *last_percent) { + DIR dir; + FILINFO fno; + int res; + + res = f_opendir(&dir, path); + if (res != FR_OK) { + // Maybe it's a file, try to delete it + res = f_unlink(path); + if (res == FR_OK || res == FR_NO_FILE) { + (*deleted)++; + } + return res; + } + + while (1) { + res = f_readdir(&dir, &fno); + if (res != FR_OK || fno.fname[0] == 0) break; + + // Skip . and .. + if (fno.fname[0] == '.' && (fno.fname[1] == '\0' || (fno.fname[1] == '.' && fno.fname[2] == '\0'))) { + continue; + } + + char full_path[256]; + install_combine_path(full_path, sizeof(full_path), path, fno.fname); + + if (fno.fattrib & AM_DIR) { + res = folder_delete_progress_recursive(full_path, deleted, total, start_x, start_y, display_name, last_percent); + (*deleted)++; + } else { + // Clear read-only attribute if set + if (fno.fattrib & AM_RDO) { + f_chmod(full_path, fno.fattrib & ~AM_RDO, AM_RDO); + } + res = f_unlink(full_path); + if (res == FR_OK || res == FR_NO_FILE) { + (*deleted)++; + } + } + + // Update progress every 10 items or when percentage changes + if ((*deleted % 10 == 0 || total == 0) && (res == FR_OK || res == FR_NO_FILE)) { + int percent = total > 0 ? (*deleted * 100) / total : 0; + if (percent != *last_percent || *deleted % 50 == 0) { + gfx_con_setpos(start_x, start_y); + install_set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [%3d%%] (%d/%d)", display_name, percent, *deleted, total); + install_set_color(COLOR_WHITE); + *last_percent = percent; + } + } + + if (res != FR_OK && res != FR_NO_FILE) break; + } + + f_closedir(&dir); + + if (res == FR_OK || res == FR_NO_FILE) { + // Check and clear read-only attribute on directory if set + FILINFO dir_info; + if (f_stat(path, &dir_info) == FR_OK && (dir_info.fattrib & AM_RDO)) { + f_chmod(path, dir_info.fattrib & ~AM_RDO, AM_RDO); + } + res = f_unlink(path); + } + + return res; +} + +// Progress-aware delete for a single directory (used for large directories) +int folder_delete_single_with_progress(const char *path, const char *display_name) { + int deleted = 0; + int total = 0; + int last_percent = -1; + u32 start_x, start_y; + int res; + + // Count total items first + total = install_count_directory_items(path); + + if (total == 0) { + // Empty directory, just delete it + FILINFO fno; + if (f_stat(path, &fno) == FR_OK) { + if (fno.fattrib & AM_RDO) { + f_chmod(path, fno.fattrib & ~AM_RDO, AM_RDO); + } + res = f_unlink(path); + } else { + res = FR_NO_FILE; + } + return res; + } + + // Save cursor position + gfx_con_getpos(&start_x, &start_y); + + // Show initial status + install_set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [ 0%%] (0/%d)", display_name, total); + install_set_color(COLOR_WHITE); + + // Use the shared recursive progress function + res = folder_delete_progress_recursive(path, &deleted, total, start_x, start_y, display_name, &last_percent); + + // Final update + gfx_con_setpos(start_x, start_y); + if (res == FR_OK || res == FR_NO_FILE) { + install_set_color(COLOR_GREEN); + gfx_printf(" Loesche: %s [100%%] (%d/%d) - Fertig!\n", display_name, deleted, total); + install_set_color(COLOR_WHITE); + } else { + install_set_color(COLOR_RED); + gfx_printf(" Loesche: %s - Fehlgeschlagen!\n", display_name); + install_set_color(COLOR_WHITE); + } + + return res; +} + +// Delete a list of paths with progress tracking int delete_path_list(const char* paths[], const char* description) { int res; int deleted = 0; int failed = 0; + int total_paths = 0; + u32 start_x, start_y; + int last_percent = -1; + + // Count total paths first + for (int i = 0; paths[i] != NULL; i++) { + if (install_path_exists(paths[i])) { + total_paths++; + } + } + + if (total_paths == 0) { + return FR_OK; // Nothing to delete + } + + // Save cursor position + gfx_con_getpos(&start_x, &start_y); + + // Show initial status + install_set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [ 0%%] (0/%d)", description, total_paths); + install_set_color(COLOR_WHITE); for (int i = 0; paths[i] != NULL; i++) { - if (path_exists(paths[i])) { + if (install_path_exists(paths[i])) { FILINFO fno; f_stat(paths[i], &fno); - if (fno.fattrib & AM_DIR) { - res = folder_delete(paths[i]); + // Extract just the folder/file name for display + const char *item_name = strrchr(paths[i], '/'); + if (item_name) { + item_name++; // Skip the '/' } else { + item_name = paths[i]; + } + + if (fno.fattrib & AM_DIR) { + // Check if directory has many items - if so, show detailed progress + int item_count = install_count_directory_items(paths[i]); + if (item_count > 50) { + // Large directory - show individual progress + // Move to new line for the detailed progress + gfx_printf("\n"); + res = folder_delete_single_with_progress(paths[i], item_name); + } else { + // Small directory - use regular delete + res = folder_delete(paths[i]); + } + } else { + // Clear read-only attribute if set + if (fno.fattrib & AM_RDO) { + f_chmod(paths[i], fno.fattrib & ~AM_RDO, AM_RDO); + } res = f_unlink(paths[i]); } @@ -298,420 +460,103 @@ int delete_path_list(const char* paths[], const char* description) { } else { failed++; } + + // Update list-level progress (only if not showing detailed progress) + if (fno.fattrib & AM_DIR && install_count_directory_items(paths[i]) <= 50) { + int percent = (deleted * 100) / total_paths; + if (percent != last_percent || deleted % 5 == 0) { + gfx_con_setpos(start_x, start_y); + install_set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [%3d%%] (%d/%d)", description, percent, deleted, total_paths); + install_set_color(COLOR_WHITE); + last_percent = percent; + } + } else if (!(fno.fattrib & AM_DIR)) { + // Update for files + int percent = (deleted * 100) / total_paths; + if (percent != last_percent || deleted % 5 == 0) { + gfx_con_setpos(start_x, start_y); + install_set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [%3d%%] (%d/%d)", description, percent, deleted, total_paths); + install_set_color(COLOR_WHITE); + last_percent = percent; + } + } } } + // Final update + gfx_con_setpos(start_x, start_y); + if (failed == 0) { + install_set_color(COLOR_GREEN); + gfx_printf(" Loesche: %s [100%%] (%d/%d) - Fertig!\n", description, deleted, total_paths); + install_set_color(COLOR_WHITE); + } else { + install_set_color(COLOR_ORANGE); + gfx_printf(" Loesche: %s [%3d%%] (%d/%d) - %d Fehler\n", description, last_percent, deleted, total_paths, failed); + install_set_color(COLOR_WHITE); + } + return (failed == 0) ? FR_OK : FR_DISK_ERR; } -// Delete old version markers (legacy files from old system) -int cleanup_old_version_markers(omninx_variant_t current_variant) { - // Delete all old version files (they're no longer used) - for (int i = 0; old_version_files_to_delete[i] != NULL; i++) { - const char* path = old_version_files_to_delete[i]; - if (path_exists(path)) { - f_unlink(path); - } - } - - return FR_OK; -} - -// Update mode: Cleanup specific directories/files -int update_mode_cleanup(omninx_variant_t variant) { - check_and_clear_screen_if_needed(); - - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: atmosphere/\n"); - set_color(COLOR_WHITE); - // Delete atmosphere subdirectories - delete_path_list(atmosphere_dirs_to_delete, "atmosphere subdirs"); - - // Delete atmosphere root directories (title IDs) - delete_path_list(atmosphere_root_dirs_to_delete, "atmosphere root dirs"); - - // Delete atmosphere contents directories (title IDs) - delete_path_list(atmosphere_contents_dirs_to_delete, "atmosphere contents dirs"); - - // Delete atmosphere files - delete_path_list(atmosphere_files_to_delete, "atmosphere files"); - - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: bootloader/\n"); - set_color(COLOR_WHITE); - // Delete bootloader directories - delete_path_list(bootloader_dirs_to_delete, "bootloader dirs"); - - // Delete bootloader files - delete_path_list(bootloader_files_to_delete, "bootloader files"); - - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: config/\n"); - set_color(COLOR_WHITE); - // Delete config directories - delete_path_list(config_dirs_to_delete, "config dirs"); - - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: switch/\n"); - set_color(COLOR_WHITE); - // Delete switch directories - delete_path_list(switch_dirs_to_delete, "switch dirs"); - - // Delete switch files - delete_path_list(switch_files_to_delete, "switch files"); - - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: Root-Dateien\n"); - set_color(COLOR_WHITE); - // Delete root files - delete_path_list(root_files_to_delete, "root files"); - - // Delete miscellaneous directories - delete_path_list(misc_dirs_to_delete, "misc dirs"); - - // Delete miscellaneous files - delete_path_list(misc_files_to_delete, "misc files"); - - set_color(COLOR_GREEN); - gfx_printf(" Bereinigung abgeschlossen!\n"); - set_color(COLOR_WHITE); - - return FR_OK; -} - -// Update mode: Copy files from staging -int update_mode_install(omninx_variant_t variant) { - int res; - const char* staging = get_staging_path(variant); - char src_path[256]; - char dst_path[256]; - - if (!staging) { - return FR_INVALID_PARAMETER; - } - - check_and_clear_screen_if_needed(); - - set_color(COLOR_YELLOW); - gfx_printf("Dateien werden kopiert...\n"); - set_color(COLOR_WHITE); - - // Copy directories (use progress-aware copy for large directories) - s_printf(src_path, "%s/atmosphere", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "atmosphere/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - - s_printf(src_path, "%s/bootloader", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "bootloader/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - - s_printf(src_path, "%s/config", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "config/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - - s_printf(src_path, "%s/switch", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "switch/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - - s_printf(src_path, "%s/warmboot_mariko", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "warmboot_mariko/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - - // OC variant includes SaltySD (this is the large one with ~2500 files) - if (variant == VARIANT_OC) { - s_printf(src_path, "%s/SaltySD", staging); - res = folder_copy_with_progress_v2(src_path, "sd:/", "SaltySD/"); - if (res != FR_OK && res != FR_NO_FILE) return res; - } - - // Copy root files - set_color(COLOR_CYAN); - gfx_printf(" Kopiere Root-Dateien...\n"); - set_color(COLOR_WHITE); - - s_printf(src_path, "%s/boot.dat", staging); - s_printf(dst_path, "sd:/boot.dat"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - s_printf(src_path, "%s/boot.ini", staging); - s_printf(dst_path, "sd:/boot.ini"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - s_printf(src_path, "%s/exosphere.ini", staging); - s_printf(dst_path, "sd:/exosphere.ini"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - s_printf(src_path, "%s/hbmenu.nro", staging); - s_printf(dst_path, "sd:/hbmenu.nro"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - s_printf(src_path, "%s/loader.bin", staging); - s_printf(dst_path, "sd:/loader.bin"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - s_printf(src_path, "%s/payload.bin", staging); - s_printf(dst_path, "sd:/payload.bin"); - if (path_exists(src_path)) { - file_copy(src_path, dst_path); - } - - // Create manifest.ini file - set_color(COLOR_CYAN); - gfx_printf(" Erstelle manifest.ini...\n"); - set_color(COLOR_WHITE); - - // Ensure config/omninx directory exists - s_printf(dst_path, "sd:/config/omninx"); - f_mkdir(dst_path); - - // Determine pack name and update channel - const char* pack_name; - int update_channel; - switch (variant) { - case VARIANT_STANDARD: - pack_name = "standard"; - update_channel = 2; - break; - case VARIANT_LIGHT: - pack_name = "light"; - update_channel = 0; - break; - case VARIANT_OC: - pack_name = "oc"; - update_channel = 1; - break; - default: - pack_name = "unknown"; - update_channel = 0; - break; - } - - // Create manifest.ini - s_printf(dst_path, "sd:/config/omninx/manifest.ini"); - FIL fp; - if (f_open(&fp, dst_path, FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) { - f_printf(&fp, "[OmniNX]\n"); - f_printf(&fp, "current_pack=%s\n", pack_name); - f_printf(&fp, "version=%s\n", VERSION); - f_printf(&fp, "update_channel=%d\n", update_channel); - f_printf(&fp, "channel_pack=%s\n", pack_name); - f_close(&fp); - set_color(COLOR_GREEN); - gfx_printf(" [OK] manifest.ini erstellt\n"); - set_color(COLOR_WHITE); - } else { - set_color(COLOR_ORANGE); - gfx_printf(" [WARN] manifest.ini konnte nicht erstellt werden\n"); - set_color(COLOR_WHITE); - } - - // Cleanup old version markers (legacy files) - cleanup_old_version_markers(variant); - - set_color(COLOR_GREEN); - gfx_printf(" Kopie abgeschlossen!\n"); - set_color(COLOR_WHITE); - - return FR_OK; -} - -// Clean mode: Backup user data -int clean_mode_backup(void) { - set_color(COLOR_CYAN); - gfx_printf(" Sichere: DBI, Tinfoil, prod.keys\n"); - set_color(COLOR_WHITE); - int res = backup_user_data(); - if (res == FR_OK) { - set_color(COLOR_GREEN); - gfx_printf(" [OK] Sicherung abgeschlossen\n"); - set_color(COLOR_WHITE); - } - return res; -} - -// Clean mode: Wipe directories -int clean_mode_wipe(void) { - int res; - - // Delete entire directories - if (path_exists("sd:/atmosphere")) { - set_color(COLOR_CYAN); - gfx_printf(" Loesche: atmosphere/\n"); - set_color(COLOR_WHITE); - res = folder_delete("sd:/atmosphere"); - if (res != FR_OK && res != FR_NO_FILE) return res; - } - - if (path_exists("sd:/bootloader")) { - set_color(COLOR_CYAN); - gfx_printf(" Loesche: bootloader/\n"); - set_color(COLOR_WHITE); - res = folder_delete("sd:/bootloader"); - if (res != FR_OK && res != FR_NO_FILE) return res; - } - - if (path_exists("sd:/config")) { - set_color(COLOR_CYAN); - gfx_printf(" Loesche: config/\n"); - set_color(COLOR_WHITE); - res = folder_delete("sd:/config"); - if (res != FR_OK && res != FR_NO_FILE) return res; - } - - if (path_exists("sd:/switch")) { - set_color(COLOR_CYAN); - gfx_printf(" Loesche: switch/\n"); - set_color(COLOR_WHITE); - res = folder_delete("sd:/switch"); - if (res != FR_OK && res != FR_NO_FILE) return res; - } - - // Delete root files - set_color(COLOR_CYAN); - gfx_printf(" Bereinige: Root-Dateien\n"); - set_color(COLOR_WHITE); - delete_path_list(root_files_to_delete, "root files"); - - // Delete miscellaneous directories - delete_path_list(misc_dirs_to_delete, "misc dirs"); - - // Delete miscellaneous files - delete_path_list(misc_files_to_delete, "misc files"); - - // Recreate switch directory - set_color(COLOR_CYAN); - gfx_printf(" Erstelle: switch/\n"); - set_color(COLOR_WHITE); - f_mkdir("sd:/switch"); - - set_color(COLOR_GREEN); - gfx_printf(" Bereinigung abgeschlossen!\n"); - set_color(COLOR_WHITE); - - return FR_OK; -} - -// Clean mode: Restore user data -int clean_mode_restore(void) { - set_color(COLOR_CYAN); - gfx_printf(" Stelle wieder her: DBI, Tinfoil, prod.keys\n"); - set_color(COLOR_WHITE); - int res = restore_user_data(); - if (res == FR_OK) { - set_color(COLOR_GREEN); - gfx_printf(" [OK] Wiederherstellung abgeschlossen\n"); - set_color(COLOR_WHITE); - } - cleanup_backup(); // Clean up temp backup - return res; -} - -// Clean mode: Install files -int clean_mode_install(omninx_variant_t variant) { - // Same as update mode install - return update_mode_install(variant); -} - -// Remove staging directory after installation -int cleanup_staging_directory(omninx_variant_t pack_variant) { - const char* staging = get_staging_path(pack_variant); - if (!staging) { - return FR_INVALID_PARAMETER; - } - - check_and_clear_screen_if_needed(); - - if (path_exists(staging)) { - set_color(COLOR_YELLOW); - gfx_printf("\nEntferne Installationsordner...\n"); - set_color(COLOR_WHITE); - set_color(COLOR_CYAN); - gfx_printf(" Loesche: %s\n", staging); - set_color(COLOR_WHITE); - - int res = folder_delete(staging); - if (res == FR_OK) { - set_color(COLOR_GREEN); - gfx_printf(" [OK] Installationsordner entfernt\n"); - set_color(COLOR_WHITE); - } else { - set_color(COLOR_ORANGE); - gfx_printf(" [WARN] Ordner konnte nicht entfernt werden (err=%d)\n", res); - set_color(COLOR_WHITE); - } - return res; - } - - return FR_OK; -} - // Main installation function int perform_installation(omninx_variant_t pack_variant, install_mode_t mode) { int res; if (mode == INSTALL_MODE_UPDATE) { // Update mode: selective cleanup then install - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 1: Bereinigung...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = update_mode_cleanup(pack_variant); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); gfx_printf("\n"); - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 2: Dateien kopieren...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = update_mode_install(pack_variant); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); // Remove staging directory res = cleanup_staging_directory(pack_variant); return res; } else { // Clean mode: backup, wipe, restore, install - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 1: Sichere Benutzerdaten...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = clean_mode_backup(); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); gfx_printf("\n"); - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 2: Bereinige alte Installation...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = clean_mode_wipe(); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); gfx_printf("\n"); - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 3: Stelle Benutzerdaten wieder her...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = clean_mode_restore(); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); gfx_printf("\n"); - set_color(COLOR_YELLOW); + install_set_color(COLOR_YELLOW); gfx_printf("Schritt 4: Dateien kopieren...\n"); - set_color(COLOR_WHITE); + install_set_color(COLOR_WHITE); res = clean_mode_install(pack_variant); if (res != FR_OK) return res; - check_and_clear_screen_if_needed(); + install_check_and_clear_screen_if_needed(); // Remove staging directory res = cleanup_staging_directory(pack_variant); return res; diff --git a/source/install.h b/source/install.h index cc4ca50..687bc1a 100644 --- a/source/install.h +++ b/source/install.h @@ -5,31 +5,35 @@ #pragma once #include "version.h" #include +#include // Installation modes typedef enum { INSTALL_MODE_UPDATE, // OmniNX detected - selective deletion - INSTALL_MODE_CLEAN // No OmniNX - full wipe + INSTALL_MODE_CLEAN // No OmniNX - selective deletion from clean list } install_mode_t; // Main installation function int perform_installation(omninx_variant_t pack_variant, install_mode_t mode); -// Update mode operations +// Update mode operations (install_update.c) int update_mode_cleanup(omninx_variant_t variant); int update_mode_install(omninx_variant_t variant); +int cleanup_staging_directory(omninx_variant_t pack_variant); -// Clean install operations +// Clean install operations (install_clean.c) int clean_mode_backup(void); int clean_mode_wipe(void); int clean_mode_restore(void); int clean_mode_install(omninx_variant_t variant); -// Helper: Delete a list of paths +// Shared helpers (install.c) - used by install_update.c and install_clean.c +void install_set_color(u32 color); +void install_check_and_clear_screen_if_needed(void); +bool install_path_exists(const char *path); +int install_count_directory_items(const char *path); +void install_combine_path(char *result, size_t size, const char *base, const char *add); int delete_path_list(const char* paths[], const char* description); - -// Helper: Delete old version markers (except current variant) -int cleanup_old_version_markers(omninx_variant_t current_variant); - -// Remove staging directory after installation -int cleanup_staging_directory(omninx_variant_t pack_variant); +int folder_delete_single_with_progress(const char *path, const char *display_name); +int folder_delete_progress_recursive(const char *path, int *deleted, int total, u32 start_x, u32 start_y, const char *display_name, int *last_percent); +int folder_copy_with_progress_v2(const char *src, const char *dst, const char *display_name); diff --git a/source/install_clean.c b/source/install_clean.c new file mode 100644 index 0000000..296a729 --- /dev/null +++ b/source/install_clean.c @@ -0,0 +1,111 @@ +/* + * OmniNX Installer - Clean Install Mode + * Backup, selective cleanup from list, restore, then install when no OmniNX found. + * Does not wipe whole card; only paths in deletion_lists_clean.h are removed. + */ + +#include "install.h" +#include "backup.h" +#include "deletion_lists_clean.h" +#include "fs.h" +#include "gfx.h" +#include + +#undef COLOR_CYAN +#undef COLOR_WHITE +#undef COLOR_GREEN +#undef COLOR_RED +#define COLOR_CYAN 0xFF00FFFF +#define COLOR_WHITE 0xFFFFFFFF +#define COLOR_GREEN 0xFF00FF00 +#define COLOR_RED 0xFFFF0000 + +#define set_color install_set_color +#define check_and_clear_screen_if_needed install_check_and_clear_screen_if_needed +#define path_exists install_path_exists + +// Clean mode: Backup user data +int clean_mode_backup(void) { + set_color(COLOR_CYAN); + gfx_printf(" Sichere: DBI, Tinfoil, prod.keys\n"); + set_color(COLOR_WHITE); + int res = backup_user_data(); + if (res == FR_OK) { + set_color(COLOR_GREEN); + gfx_printf(" [OK] Sicherung abgeschlossen\n"); + set_color(COLOR_WHITE); + } + return res; +} + +// Clean mode: Wipe using selective deletion list (does not wipe whole card) +int clean_mode_wipe(void) { + check_and_clear_screen_if_needed(); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: atmosphere/\n"); + set_color(COLOR_WHITE); + delete_path_list(clean_atmosphere_dirs_to_delete, "atmosphere subdirs"); + delete_path_list(clean_atmosphere_contents_dirs_to_delete, "atmosphere contents dirs"); + delete_path_list(clean_atmosphere_files_to_delete, "atmosphere files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: bootloader/\n"); + set_color(COLOR_WHITE); + delete_path_list(clean_bootloader_dirs_to_delete, "bootloader dirs"); + delete_path_list(clean_bootloader_files_to_delete, "bootloader files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: config/\n"); + set_color(COLOR_WHITE); + delete_path_list(clean_config_dirs_to_delete, "config dirs"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: switch/\n"); + set_color(COLOR_WHITE); + delete_path_list(clean_switch_dirs_to_delete, "switch dirs"); + delete_path_list(clean_switch_files_to_delete, "switch files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: Root-Dateien\n"); + set_color(COLOR_WHITE); + delete_path_list(clean_root_files_to_delete, "root files"); + delete_path_list(clean_misc_dirs_to_delete, "misc dirs"); + delete_path_list(clean_misc_files_to_delete, "misc files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: Alte Versionsmarker\n"); + set_color(COLOR_WHITE); + delete_path_list(old_version_files_to_delete, "old version markers"); + + set_color(COLOR_CYAN); + gfx_printf(" Erstelle: switch/\n"); + set_color(COLOR_WHITE); + f_mkdir("sd:/switch"); + + set_color(COLOR_GREEN); + gfx_printf(" Bereinigung abgeschlossen!\n"); + set_color(COLOR_WHITE); + + return FR_OK; +} + +// Clean mode: Restore user data +int clean_mode_restore(void) { + set_color(COLOR_CYAN); + gfx_printf(" Stelle wieder her: DBI, Tinfoil, prod.keys\n"); + set_color(COLOR_WHITE); + int res = restore_user_data(); + if (res == FR_OK) { + set_color(COLOR_GREEN); + gfx_printf(" [OK] Wiederherstellung abgeschlossen\n"); + set_color(COLOR_WHITE); + } + cleanup_backup(); + return res; +} + +// Clean mode: Install files (reuse update mode install) +int clean_mode_install(omninx_variant_t variant) { + return update_mode_install(variant); +} diff --git a/source/install_update.c b/source/install_update.c new file mode 100644 index 0000000..57ac999 --- /dev/null +++ b/source/install_update.c @@ -0,0 +1,237 @@ +/* + * OmniNX Installer - Update Mode + * Selective cleanup and install when OmniNX is already installed. + */ + +#include "install.h" +#include "deletion_lists_update.h" +#include "fs.h" +#include "version.h" +#include "gfx.h" +#include +#include +#include + +#ifndef VERSION +#define VERSION "1.0.0" +#endif + +#undef COLOR_CYAN +#undef COLOR_WHITE +#undef COLOR_GREEN +#undef COLOR_YELLOW +#undef COLOR_ORANGE +#undef COLOR_RED +#define COLOR_CYAN 0xFF00FFFF +#define COLOR_WHITE 0xFFFFFFFF +#define COLOR_GREEN 0xFF00FF00 +#define COLOR_YELLOW 0xFFFFDD00 +#define COLOR_ORANGE 0xFF00A5FF +#define COLOR_RED 0xFFFF0000 + +#define set_color install_set_color +#define check_and_clear_screen_if_needed install_check_and_clear_screen_if_needed +#define path_exists install_path_exists +#define count_directory_items install_count_directory_items + +// Update mode: Cleanup specific directories/files +int update_mode_cleanup(omninx_variant_t variant) { + (void)variant; + check_and_clear_screen_if_needed(); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: atmosphere/\n"); + set_color(COLOR_WHITE); + delete_path_list(atmosphere_dirs_to_delete, "atmosphere subdirs"); + delete_path_list(atmosphere_contents_dirs_to_delete, "atmosphere contents dirs"); + delete_path_list(atmosphere_files_to_delete, "atmosphere files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: bootloader/\n"); + set_color(COLOR_WHITE); + delete_path_list(bootloader_dirs_to_delete, "bootloader dirs"); + delete_path_list(bootloader_files_to_delete, "bootloader files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: config/\n"); + set_color(COLOR_WHITE); + delete_path_list(config_dirs_to_delete, "config dirs"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: switch/\n"); + set_color(COLOR_WHITE); + delete_path_list(switch_dirs_to_delete, "switch dirs"); + delete_path_list(switch_files_to_delete, "switch files"); + + set_color(COLOR_CYAN); + gfx_printf(" Bereinige: Root-Dateien\n"); + set_color(COLOR_WHITE); + delete_path_list(root_files_to_delete, "root files"); + delete_path_list(misc_dirs_to_delete, "misc dirs"); + delete_path_list(misc_files_to_delete, "misc files"); + + set_color(COLOR_GREEN); + gfx_printf(" Bereinigung abgeschlossen!\n"); + set_color(COLOR_WHITE); + + return FR_OK; +} + +// Update mode: Copy files from staging +int update_mode_install(omninx_variant_t variant) { + int res; + const char* staging = get_staging_path(variant); + char src_path[256]; + char dst_path[256]; + + if (!staging) { + return FR_INVALID_PARAMETER; + } + + check_and_clear_screen_if_needed(); + + set_color(COLOR_YELLOW); + gfx_printf("Dateien werden kopiert...\n"); + set_color(COLOR_WHITE); + + s_printf(src_path, "%s/atmosphere", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "atmosphere/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + + s_printf(src_path, "%s/bootloader", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "bootloader/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + + s_printf(src_path, "%s/config", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "config/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + + s_printf(src_path, "%s/switch", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "switch/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + + s_printf(src_path, "%s/warmboot_mariko", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "warmboot_mariko/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + + if (variant == VARIANT_OC) { + s_printf(src_path, "%s/SaltySD", staging); + res = folder_copy_with_progress_v2(src_path, "sd:/", "SaltySD/"); + if (res != FR_OK && res != FR_NO_FILE) return res; + } + + set_color(COLOR_CYAN); + gfx_printf(" Kopiere Root-Dateien...\n"); + set_color(COLOR_WHITE); + + s_printf(src_path, "%s/boot.dat", staging); + s_printf(dst_path, "sd:/boot.dat"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + s_printf(src_path, "%s/boot.ini", staging); + s_printf(dst_path, "sd:/boot.ini"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + s_printf(src_path, "%s/exosphere.ini", staging); + s_printf(dst_path, "sd:/exosphere.ini"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + s_printf(src_path, "%s/hbmenu.nro", staging); + s_printf(dst_path, "sd:/hbmenu.nro"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + s_printf(src_path, "%s/loader.bin", staging); + s_printf(dst_path, "sd:/loader.bin"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + s_printf(src_path, "%s/payload.bin", staging); + s_printf(dst_path, "sd:/payload.bin"); + if (path_exists(src_path)) file_copy(src_path, dst_path); + + set_color(COLOR_CYAN); + gfx_printf(" Erstelle manifest.ini...\n"); + set_color(COLOR_WHITE); + + s_printf(dst_path, "sd:/config/omninx"); + f_mkdir(dst_path); + + const char* pack_name; + int update_channel; + switch (variant) { + case VARIANT_STANDARD: pack_name = "standard"; update_channel = 2; break; + case VARIANT_LIGHT: pack_name = "light"; update_channel = 0; break; + case VARIANT_OC: pack_name = "oc"; update_channel = 1; break; + default: pack_name = "unknown"; update_channel = 0; break; + } + + s_printf(dst_path, "sd:/config/omninx/manifest.ini"); + FIL fp; + if (f_open(&fp, dst_path, FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) { + f_printf(&fp, "[OmniNX]\n"); + f_printf(&fp, "current_pack=%s\n", pack_name); + f_printf(&fp, "version=%s\n", VERSION); + f_printf(&fp, "update_channel=%d\n", update_channel); + f_printf(&fp, "channel_pack=%s\n", pack_name); + f_close(&fp); + set_color(COLOR_GREEN); + gfx_printf(" [OK] manifest.ini erstellt\n"); + set_color(COLOR_WHITE); + } else { + set_color(COLOR_ORANGE); + gfx_printf(" [WARN] manifest.ini konnte nicht erstellt werden\n"); + set_color(COLOR_WHITE); + } + + set_color(COLOR_GREEN); + gfx_printf(" Kopie abgeschlossen!\n"); + set_color(COLOR_WHITE); + + return FR_OK; +} + +// Remove staging directory after installation +int cleanup_staging_directory(omninx_variant_t pack_variant) { + const char* staging = get_staging_path(pack_variant); + if (!staging) { + return FR_INVALID_PARAMETER; + } + + check_and_clear_screen_if_needed(); + + if (path_exists(staging)) { + set_color(COLOR_YELLOW); + gfx_printf("\nEntferne Installationsordner...\n"); + set_color(COLOR_WHITE); + + int total = count_directory_items(staging); + u32 start_x, start_y; + gfx_con_getpos(&start_x, &start_y); + + const char *folder_name = strrchr(staging, '/'); + if (folder_name) folder_name++; + else folder_name = staging; + + set_color(COLOR_CYAN); + gfx_printf(" Loesche: %s [ 0%%] (0/%d)", folder_name, total); + set_color(COLOR_WHITE); + + int deleted = 0; + int last_percent = -1; + int res = folder_delete_progress_recursive(staging, &deleted, total, start_x, start_y, folder_name, &last_percent); + + gfx_con_setpos(start_x, start_y); + if (res == FR_OK) { + set_color(COLOR_GREEN); + gfx_printf(" Loesche: %s [100%%] (%d/%d) - Fertig!\n", folder_name, deleted, total); + set_color(COLOR_WHITE); + } else { + set_color(COLOR_ORANGE); + gfx_printf(" Loesche: %s - Fehlgeschlagen!\n", folder_name); + gfx_printf(" [WARN] Ordner konnte nicht entfernt werden (err=%d)\n", res); + set_color(COLOR_WHITE); + } + return res; + } + + return FR_OK; +} diff --git a/source/main.c b/source/main.c index d11bcb0..bbc5498 100644 --- a/source/main.c +++ b/source/main.c @@ -105,9 +105,9 @@ static void print_header(void) { gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); set_color(COLOR_CYAN); - gfx_printf("========================================\n"); + gfx_printf("===================================\n"); gfx_printf(" OmniNX Installer Payload v%s\n", VERSION); - gfx_printf("========================================\n\n"); + gfx_printf("===================================\n\n"); set_color(COLOR_WHITE); } @@ -349,6 +349,9 @@ void ipl_main(void) { int result = perform_installation(pack_variant, mode); + // Wait 3 seconds before clearing screen to allow errors to be visible + msleep(3000); + // Clear screen for final summary to ensure it's visible gfx_clear_grey(0x1B); gfx_con_setpos(0, 0);