diff --git a/source/install.c b/source/install.c index dd68165..9bfe0f8 100644 --- a/source/install.c +++ b/source/install.c @@ -3,14 +3,20 @@ */ #include "install.h" -#include "dram_fuse.h" #include "fs.h" +#include "screenshot.h" #include "version.h" #include "gfx.h" #include +#include +#include #include #include +#include +#include +#include #include +#include #define GROUPED_DELETE_MAX_ENTRIES 512 @@ -33,10 +39,25 @@ #define COLOR_ORANGE 0xFF00A5FF #define COLOR_RED 0xFFFF0000 +static inline bool cancel_combo_pressed(u8 btn) +{ + return (btn & (BTN_VOL_UP | BTN_VOL_DOWN)) == (BTN_VOL_UP | BTN_VOL_DOWN); +} + void install_set_color(u32 color) { gfx_con_setcol(color, gfx_con.fillbg, gfx_con.bgcol); } +/* Same top bar as main.c print_header() (without full screen clear). */ +static void install_print_main_header(void) +{ + install_set_color(COLOR_CYAN); + gfx_printf("===================================\n"); + gfx_printf(" OmniNX Installer Payload v%s\n", VERSION); + gfx_printf("===================================\n\n"); + install_set_color(COLOR_WHITE); +} + // Check if we need to clear screen (when getting close to bottom) void install_check_and_clear_screen_if_needed(void) { // In the gfx system: @@ -51,13 +72,7 @@ void install_check_and_clear_screen_if_needed(void) { // Clear screen and reset position gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); - - // Reprint same header as initial launch - install_set_color(COLOR_CYAN); - gfx_printf("===================================\n"); - gfx_printf(" OmniNX Installer Payload v%s\n", VERSION); - gfx_printf("===================================\n\n"); - install_set_color(COLOR_WHITE); + install_print_main_header(); } } @@ -619,9 +634,12 @@ int delete_path_list(const char* paths[], const char* description) { return (failed == 0) ? FR_OK : FR_DISK_ERR; } -#define HEKATE_8GB_SRC "sd:/bootloader/hekate_8gb.bin" -#define PAYLOAD_BIN_DST "sd:/payload.bin" -#define UPDATE_BIN_DST "sd:/bootloader/update.bin" +#define HEKATE_8GB_SRC "sd:/bootloader/hekate_8gb.bin" +#define PAYLOAD_BIN_DST "sd:/payload.bin" +#define UPDATE_BIN_DST "sd:/bootloader/update.bin" +#define RAM_CONFIG_PATH "sd:/config/omninx/ram_config.ini" + +enum { RAM_READ_OK = 0, RAM_READ_NEED_MENU = 1 }; static void unlink_ignore_err(const char *path) { @@ -633,31 +651,214 @@ static void unlink_ignore_err(const char *path) f_unlink(path); } -/* After pack copy: if >4 GiB fuse RAM, install 8GB Hekate to payload.bin + bootloader/update.bin; always remove hekate_8gb.bin when done or if not used. */ +static void ram_config_ensure_parent_dirs(void) +{ + f_mkdir("sd:/config"); + f_mkdir("sd:/config/omninx"); +} + +static int ram_config_write(bool use_8gb) +{ + ram_config_ensure_parent_dirs(); + FIL f; + if (f_open(&f, RAM_CONFIG_PATH, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) + return FR_DISK_ERR; + + static const char sec[] = "[Ram]\n"; + static const char line0[] = "8gb=0\n"; + static const char line1[] = "8gb=1\n"; + UINT bw; + f_write(&f, sec, sizeof(sec) - 1, &bw); + f_write(&f, use_8gb ? line1 : line0, sizeof(line0) - 1, &bw); + f_close(&f); + return FR_OK; +} + +static void ram_config_free_sections(link_t *sections) +{ + LIST_FOREACH_ENTRY(ini_sec_t, sec, sections, link) { + LIST_FOREACH_ENTRY(ini_kv_t, kv, &sec->kvs, link) { + if (kv->key) free(kv->key); + if (kv->val) free(kv->val); + } + if (sec->name) free(sec->name); + } +} + +/* Valid [Ram] 8gb=0|1 → silent; missing file or invalid → menu. */ +static int read_ram_config_silent(const char *path, bool *use_8gb) +{ + if (!install_path_exists(path)) + return RAM_READ_NEED_MENU; + + link_t sections; + list_init(§ions); + + if (ini_parse(§ions, (char *)path, false) != 1) { + ram_config_free_sections(§ions); + return RAM_READ_NEED_MENU; + } + + bool found = false; + bool eight = false; + LIST_FOREACH_ENTRY(ini_sec_t, sec, §ions, link) { + if (sec->name && !strcmp(sec->name, "Ram")) { + LIST_FOREACH_ENTRY(ini_kv_t, kv, &sec->kvs, link) { + if (kv->key && kv->val && !strcmp(kv->key, "8gb")) { + if (!strcmp(kv->val, "0")) { + found = true; + eight = false; + } else if (!strcmp(kv->val, "1")) { + found = true; + eight = true; + } + break; + } + } + break; + } + } + + ram_config_free_sections(§ions); + + if (!found) + return RAM_READ_NEED_MENU; + *use_8gb = eight; + return RAM_READ_OK; +} + +/* Same navigation as main.c multi-variant menu; returns false if user aborts (payload/reboot). */ +static bool install_ram_config_menu(bool *use_8gb) +{ + jc_init_hw(); + while (btn_read() & BTN_POWER) + msleep(50); + + int selected = 0; + int prev_selected = 0; + bool confirmed = false; + const int n = 2; + const char *labels[2] = { + "4 GB Konsole (Standard)", + "8 GB Konsole", + }; + + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + install_print_main_header(); + + install_set_color(COLOR_YELLOW); + gfx_printf("RAM / Hekate: Konsole-Typ\n\n"); + install_set_color(COLOR_RED); + gfx_printf("Wenn du dir absolut unsicher bist, waehle unbedingt 4 GB!\n"); + gfx_printf("Eine falsche 8-GB-Wahl kann Probleme verursachen.\n\n"); + install_set_color(COLOR_WHITE); + + u32 menu_x, menu_y; + gfx_con_getpos(&menu_x, &menu_y); + for (int i = 0; i < n; i++) { + if (i == selected) { + install_set_color(COLOR_GREEN); + gfx_printf(" > %s\n", labels[i]); + install_set_color(COLOR_WHITE); + } else { + gfx_printf(" %s\n", labels[i]); + } + } + gfx_printf("\n"); + install_set_color(COLOR_CYAN); + gfx_printf("D-Pad / Vol+/-: Auswahl | A oder Power: Bestaetigen\n"); + gfx_printf("Vol+ und Vol- gleichzeitig: Abbrechen (Hekate)\n"); + install_set_color(COLOR_WHITE); + + bool prev_up = false, prev_down = false; + bool menu_aborted = false; + + while (!confirmed && !menu_aborted) { + if (selected != prev_selected) { + gfx_con_setpos(menu_x, menu_y + (u32)prev_selected * 16); + install_set_color(COLOR_WHITE); + gfx_printf(" %s\n", labels[prev_selected]); + gfx_con_setpos(menu_x, menu_y + (u32)selected * 16); + install_set_color(COLOR_GREEN); + gfx_printf(" > %s\n", labels[selected]); + install_set_color(COLOR_WHITE); + prev_selected = selected; + } + + jc_gamepad_rpt_t *jc = joycon_poll(); + u8 btn = btn_read(); + + if (jc && jc->cap) + take_screenshot(); + + if (cancel_combo_pressed(btn)) { + menu_aborted = true; + break; + } + + bool cur_up = false, cur_down = false; + if (jc) { + cur_up = (jc->up != 0) && !jc->down; + cur_down = (jc->down != 0) && !jc->up; + } + if (btn & BTN_VOL_UP) + cur_up = true; + if (btn & BTN_VOL_DOWN) + cur_down = true; + + if (cur_up && !prev_up) + selected = (selected - 1 + n) % n; + else if (cur_down && !prev_down) + selected = (selected + 1) % n; + else if (jc && jc->a) + confirmed = true; + + prev_up = cur_up; + prev_down = cur_down; + + if (btn & BTN_POWER) + confirmed = true; + + msleep(50); + } + + if (menu_aborted) { + gfx_printf("\n"); + install_set_color(COLOR_YELLOW); + gfx_printf("Abgebrochen. Starte Hekate...\n"); + install_set_color(COLOR_WHITE); + msleep(500); + installer_launch_hekate_payload(); + return false; + } + + *use_8gb = (selected == 1); + ram_config_write(*use_8gb); + + gfx_clear_grey(0x1B); + gfx_con_setpos(0, 0); + install_print_main_header(); + return true; +} + +/* After pack copy: use ram_config.ini [Ram] 8gb=0|1 if present; else menu, write file, then apply. No fuse autodetect. */ static void install_hekate_8gb_post_copy(void) { if (!install_path_exists(HEKATE_8GB_SRC)) return; - int mib = dram_capacity_mib_from_fuse(); - if (mib > 4096) { - install_set_color(COLOR_CYAN); - gfx_printf("\nMehr als 4 GB RAM erkannt (Fuse). Die 8-GB-Hekate-Variante wird verwendet.\n"); - gfx_printf("Kopiere nach payload.bin und bootloader/update.bin...\n"); - install_set_color(COLOR_WHITE); + bool use_8gb; + if (read_ram_config_silent(RAM_CONFIG_PATH, &use_8gb) != RAM_READ_OK) { + if (!install_ram_config_menu(&use_8gb)) + return; + } + if (use_8gb) { int r1 = file_copy(HEKATE_8GB_SRC, PAYLOAD_BIN_DST); int r2 = file_copy(HEKATE_8GB_SRC, UPDATE_BIN_DST); - if (r1 == FR_OK && r2 == FR_OK) { - install_set_color(COLOR_GREEN); - gfx_printf(" [OK] Hekate 8 GB installiert.\n"); - install_set_color(COLOR_WHITE); + if (r1 == FR_OK && r2 == FR_OK) unlink_ignore_err(HEKATE_8GB_SRC); - } else { - install_set_color(COLOR_ORANGE); - gfx_printf(" [WARN] Kopie fehlgeschlagen (payload: %d, update: %d). hekate_8gb.bin bleibt.\n", r1, r2); - install_set_color(COLOR_WHITE); - } } else { unlink_ignore_err(HEKATE_8GB_SRC); }