]> Chaos Git - corbenik/corbenik.git/commitdiff
Update menu code to use entirely funcpointers
authorchaoskagami <chaos.kagami@gmail.com>
Sat, 27 Aug 2016 21:43:14 +0000 (17:43 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Sat, 27 Aug 2016 22:10:57 +0000 (18:10 -0400)
host/copy.sh
include/menu-backend.h
include/option.h
include/std/memory.h
source/menu-backend.c
source/menu.c
source/patcher.c
source/std/memory.c

index 7033210dcb52a799806d979811db2cd84e860268..bac751b2d07fd046aef389b1d32ec54cc7801db7 100755 (executable)
@@ -4,7 +4,7 @@
 # You don't and shouldn't need to use it.
 
 mnt=/media/sd
-dev=/dev/sdb
+dev=/dev/sdc
 
 mnt=/mnt/ext1
 
index 3f46fb590472b48a9295eec7241757d66c15bc99..7375c832cbff449d09d85a81f803ede4158a1cee 100644 (file)
@@ -6,29 +6,23 @@
  */
 enum type
 {
-    boolean_val = 0,      ///< Toggleable boolean
-    ranged_val = 1,       ///< N1 - N2, left and right to pick.
-    mask_val = 2,         ///< Bitmask allowed values.
-    not_option = 3,       ///< Skip over this.
-    call_fun = 4,         ///< Call a function. Treat (a) as (void)(*)(void).
-    boolean_val_n3ds = 5, ///< Toggle, but only show on n3DS
-    break_menu = 6        ///< Exit the menu (same as B)
+    option       = 0,      ///< Option
+    option_n3ds  = 1,      ///< Option (N3DS only)
+    unselectable = 2,      ///< Skip over this.
+    break_menu   = 3       ///< Exit the menu (same as B)
 };
 
-typedef void (*func_call_t)(uint32_t data);
-
-struct range_str
-{
-    int a, b;
-};
+typedef void  (*func_call_t)(void* data);
+typedef char* (*get_value_t)(void* data);
 
 struct options_s
 {
-    int64_t index;     ///< Option index. Used for displaying values.
-    char name[64];     ///< Name of patch to display in menus.
-    char desc[256];    ///< Description of option, shown when pressing select
-    enum type allowed; ///< Misnomer, FIXME. Type of menu entry. See enum type.
-    uint32_t a, b;     ///< Should be union, FIXME. Data values used for menu entry.
+    char *name;        ///< Name of menu option
+    char *desc;        ///< Description of option, shown when pressing select
+    enum type handle;  ///< Type of menu entry. See enum type.
+    void *param;       ///< Parameter to pass to func_call_t
+    func_call_t func;  ///< Function to call on selection of option
+    get_value_t value; ///< Function to get the value of the menu entry
     uint8_t indent;    ///< Indentation/ownership level of menu.
 } __attribute__((packed));
 
@@ -42,8 +36,7 @@ void accent_color(void* screen, int fg);
 /* Display a menu structure.
  *
  * \param options Menu structure to display
- * \param toggles Array of bytes to have values changed according to options
  */
-int show_menu(struct options_s *options, uint8_t *toggles);
+int show_menu(struct options_s *options);
 
 #endif
index 04fc71bfde0d03ba855e031a400df3a12dd6617e..422e3a6a4f1a9d3875adcea2dbca3bfc60e721b9 100644 (file)
@@ -93,14 +93,4 @@ void save_config();
 
 #endif
 
-/*
-[CORBENIK]
-version=1
-option_<name>=<int>
-...
-[PATCHES]
-<uuid>=<1|0>
-...
-*/
-
 #endif
index a367c189b68ec597759d654505b088d547759d0e..b228e57c263419d896c4b4736557bff5db27b07f 100644 (file)
@@ -7,6 +7,16 @@
 #include <ctype.h>
 
 int atoi(const char *str);
+
 uint8_t *memfind(uint8_t *startPos, uint32_t size, const void *pattern, uint32_t patternSize);
 
+/* Basically strdup, because newlib's memory handling is crap.
+ *
+ * Note that the caller is reponsible for freeing memory.
+ *
+ * \param str String to duplicate
+ * \return Duplicated string.
+ */
+char* strdup_self(char* str);
+
 #endif
index d12576b88d058a00896a9a548a3fbdbc6fadebef..35c74a6502bab178186a60c8f3c68664fe1cc2d1 100644 (file)
@@ -29,7 +29,7 @@ void accent_color(void* screen, int fg) {
 }
 
 int
-show_menu(struct options_s *options, uint8_t *toggles)
+show_menu(struct options_s *options)
 {
     int cursor_y = 0;
     int cursor_min = -1;
@@ -43,7 +43,7 @@ show_menu(struct options_s *options, uint8_t *toggles)
 
     clear_disp(TOP_SCREEN);
 
-    if (options[0].index == -1) {
+    if (options[0].name == NULL) {
         set_cursor(TOP_SCREEN, 0, 0);
         header("Any:Back");
         fprintf(stdout, "No entries.\n");
@@ -57,10 +57,10 @@ show_menu(struct options_s *options, uint8_t *toggles)
         // Figure out the max if unset.
         if (cursor_max == -1) {
             cursor_max = 0;
-            while (options[cursor_max].index != -1)
+            while (options[cursor_max].name != NULL)
                 ++cursor_max;
 
-            while (options[cursor_max].allowed == not_option && cursor_max > 0)
+            while (options[cursor_max].handle == unselectable && cursor_max > 0)
                 --cursor_max;
         }
 
@@ -71,13 +71,13 @@ show_menu(struct options_s *options, uint8_t *toggles)
         if (cursor_min == -1) {
             if (less_mode == 1) {
                 cursor_max = 0;
-                while (options[cursor_max].index != -1)
+                while (options[cursor_max].name != NULL)
                     ++cursor_max;
 
                 cursor_min = 0;
             } else {
                 cursor_min = 0;
-                while (options[cursor_min].allowed == not_option)
+                while (options[cursor_min].handle == unselectable)
                     ++cursor_min;
                 cursor_y = cursor_min;
             }
@@ -90,11 +90,11 @@ show_menu(struct options_s *options, uint8_t *toggles)
         else
             header("A:Enter B:Back DPAD:Nav Select:Info");
 
-        for (int i = window_top, skip = 0; options[i].index != -1; ++i) { // -1 Sentinel.
+        for (int i = window_top, skip = 0; options[i].name != NULL; ++i) { // -1 Sentinel.
             if (i > window_bottom + skip)
                 break;
 
-            if (options[i].allowed == boolean_val_n3ds && !is_n3ds) {
+            if (options[i].handle == option_n3ds && !is_n3ds) {
                 ++skip;
                 continue;
             }
@@ -102,11 +102,12 @@ show_menu(struct options_s *options, uint8_t *toggles)
             // NOTE - Signed to unsigned conversion here. Again, not an issue.
             set_cursor(TOP_SCREEN, 0, (unsigned int)(i - window_top - skip + 2) );
 
-            int indent = options[i].indent;
-            for(int j=0; j < indent; j++)
-                fprintf(TOP_SCREEN, "  ");
+            // Print option
+            if (options[i].handle != unselectable) {
+                int indent = options[i].indent;
+                for(int j=0; j < indent; j++)
+                    fprintf(TOP_SCREEN, "  ");
 
-            if (options[i].allowed == boolean_val || options[i].allowed == boolean_val_n3ds) {
                 if (cursor_y == i) {
                     accent_color(TOP_SCREEN, 1);
                     fprintf(TOP_SCREEN, ">>\x1b[0m ");
@@ -114,29 +115,12 @@ show_menu(struct options_s *options, uint8_t *toggles)
                     fprintf(TOP_SCREEN, "   ");
                 }
 
-                fprintf(TOP_SCREEN, "[%c]  %s", (toggles[options[i].index] ? '*' : ' '), options[i].name);
-            } else if (options[i].allowed == call_fun || options[i].allowed == break_menu) {
-                if (cursor_y == i) {
-                    accent_color(TOP_SCREEN, 1);
-                    fprintf(TOP_SCREEN, ">>\x1b[0m ");
-                } else {
-                    fprintf(TOP_SCREEN, "   ");
-                }
-
-                fprintf(TOP_SCREEN, "%s", options[i].name);
-            } else if (options[i].allowed == ranged_val) {
-                if (cursor_y == i) {
-                    accent_color(TOP_SCREEN, 1);
-                    fprintf(TOP_SCREEN, ">>\x1b[0m ");
-                } else {
-                    fprintf(TOP_SCREEN, "   ");
+                if (options[i].handle != break_menu && options[i].value != NULL) {
+                    fprintf(TOP_SCREEN, "[%s]  ", options[i].value(options[i].param));
                 }
-                fprintf(TOP_SCREEN, "[%u]  %s  ", toggles[options[i].index], options[i].name);
-            } else if (options[i].allowed == not_option) {
-                if (options[i].a == 1)
-                    accent_color(TOP_SCREEN, 1);
-                fprintf(TOP_SCREEN, "%s\x1b[0m", options[i].name);
             }
+
+            fprintf(TOP_SCREEN, "%s", options[i].name);
         }
 
         uint32_t key = wait_key(1);
@@ -146,57 +130,42 @@ show_menu(struct options_s *options, uint8_t *toggles)
                 if (cursor_min == cursor_max)
                     break;
                 cursor_y -= 1;
-                while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y >= cursor_min && !less_mode)
+                while ((options[cursor_y].handle == unselectable || (options[cursor_y].handle == option_n3ds && !is_n3ds)) && cursor_y >= cursor_min && !less_mode)
                     cursor_y--;
                 break;
             case CTR_HID_DOWN:
                 if (cursor_min == cursor_max)
                     break;
                 cursor_y += 1;
-                while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y < cursor_max && !less_mode)
+                while ((options[cursor_y].handle == unselectable || (options[cursor_y].handle == option_n3ds && !is_n3ds)) && cursor_y < cursor_max && !less_mode)
                     cursor_y++;
                 break;
             case CTR_HID_LEFT:
                 if (cursor_min == cursor_max)
                     break;
                 cursor_y -= 5;
-                while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y >= cursor_min && !less_mode)
+                while ((options[cursor_y].handle == unselectable || (options[cursor_y].handle == option_n3ds && !is_n3ds)) && cursor_y >= cursor_min && !less_mode)
                     cursor_y--;
                 break;
             case CTR_HID_RIGHT:
                 if (cursor_min == cursor_max)
                     break;
                 cursor_y += 5;
-                while ((options[cursor_y].allowed == not_option || (options[cursor_y].allowed == boolean_val_n3ds && !is_n3ds)) && cursor_y < cursor_max && !less_mode)
+                while ((options[cursor_y].handle == unselectable || (options[cursor_y].handle == option_n3ds && !is_n3ds)) && cursor_y < cursor_max && !less_mode)
                     cursor_y++;
                 break;
             case CTR_HID_A:
                 if (less_mode)
                     break;
 
-                if (options[cursor_y].allowed == boolean_val || options[cursor_y].allowed == boolean_val_n3ds) {
-                    toggles[options[cursor_y].index] = !toggles[options[cursor_y].index];
-                } else if (options[cursor_y].allowed == ranged_val) {
-                    if (toggles[options[cursor_y].index] == options[cursor_y].b)
-                        toggles[options[cursor_y].index] = options[cursor_y].a;
-                    else
-                        toggles[options[cursor_y].index]++;
-                } else if (options[cursor_y].allowed == call_fun) {
-                    ((func_call_t)(options[cursor_y].a))(options[cursor_y].b); // Call 'a' as a function.
-                } else if (options[cursor_y].allowed == break_menu) {
+                if (options[cursor_y].handle == option || options[cursor_y].handle == option_n3ds) {
+                    options[cursor_y].func(options[cursor_y].param);
+                } else if (options[cursor_y].handle == break_menu) {
                     exit = 1;
                     clear_disp(TOP_SCREEN);
                     cursor_y = cursor_min;
                 }
                 break;
-            case CTR_HID_X:
-                if (options[cursor_y].allowed == ranged_val) {
-                    if (toggles[options[cursor_y].index] == options[cursor_y].a)
-                        toggles[options[cursor_y].index] = options[cursor_y].b;
-                    else
-                        toggles[options[cursor_y].index]--;
-                }
-                break;
             case CTR_HID_B:
                 exit = 1;
                 clear_disp(TOP_SCREEN);
index 337b4e1781db53ad285cb32375a465f306d9948c..65d2e162dee1dbbfdc3a7caa56b1189b0c3b9d48 100644 (file)
 struct options_s *patches = NULL;
 uint8_t *enable_list;
 
-static struct options_s options[] = {
-    // Patches.
-    { 0, "General Options", "", not_option, 1, 0, 0 },
-
-    { OPTION_LOADER, "System Module Inject", "Replaces system modules in FIRM like loader, fs, pxi, etc.", boolean_val, 0, 0, 0 },
-
-    { OPTION_SVCS, "svcBackdoor Fixup", "Reinserts svcBackdoor on 11.0 NATIVE_FIRM. svcBackdoor allows executing arbitrary functions with ARM11 kernel permissions, and is required by some (poorly coded) applications.", boolean_val, 0, 0, 0 },
-
-    { OPTION_REBOOT, "Firmlaunch Hook", "Hooks firmlaunch to allow largemem games on o3DS. Also allows patching TWL/AGB on all consoles. Previously called 'Reboot hook' but renamed for accuracy.", boolean_val, 0, 0, 0 },
-
-    { OPTION_EMUNAND, "Use EmuNAND", "Redirects NAND write/read to the SD. This supports both Gateway and redirected layouts.", boolean_val, 0, 0, 0 },
-    { OPTION_EMUNAND_INDEX, "Index", "Which EmuNAND to use. If you only have one, you want 0. Currently the maximum supported is 10 (0-9), but this is arbitrary.", ranged_val, 0, 0x9, 1 },
-
-    { OPTION_AUTOBOOT, "Autoboot", "Boot the system automatically, unless the R key is held while booting.", boolean_val, 0, 0, 0 },
-    { OPTION_SILENCE, "Silent mode", "Suppress all debug output during autoboot. You'll see the screen turn on and then off once.", boolean_val, 0, 0, 1 },
-
-    { OPTION_DIM_MODE, "Dim Background", "Experimental! Dims colors on lighter backgrounds to improve readability with text. You won't notice the change until scrolling or exiting the current menu due to the way rendering works.", boolean_val, 0, 0, 0 },
+void change_opt(void* val) {
+    uint32_t opt = (uint32_t)val;
+    uint8_t* set = & (config->options[opt]);
+    switch(opt) {
+        case OPTION_EMUNAND_INDEX:
+            // 0-9
+            set[0]++;
+            if (set[0] > 9)
+                set[0] = 0;
+            break;
+        case OPTION_BRIGHTNESS:
+            // 0-3
+            set[0]++;
+            if (set[0] > 3)
+                set[0] = 0;
+            break;
+        case OPTION_ACCENT_COLOR:
+            // 1-7
+            set[0]++;
+            if (set[0] > 7 || set[0] < 1)
+                set[0] = 1;
+            break;
+        default:
+            set[0] = !(set[0]);
+            break;
+    }
+}
 
-    { OPTION_ACCENT_COLOR, "Accent color", "Changes the accent color in menus.", ranged_val, 1, 7, 0},
+char* get_opt(void* val) {
+    uint32_t opt = (uint32_t)val;
+    char raw = config->options[opt];
+    static char str[2] = "0";
+    str[0] = '0';
+    switch(opt) {
+        case OPTION_EMUNAND_INDEX:
+        case OPTION_BRIGHTNESS:
+        case OPTION_ACCENT_COLOR:
+            str[0] += raw;
+            return str;
+        default:
+            return (raw) ? "*" : " ";
+    }
+}
 
-    { OPTION_BRIGHTNESS, "Brightness", "Changes the screeninit brightness in menu. WIP, only takes effect on reboot (this will change.)", ranged_val, 0, 3, 0},
+static struct options_s options[] = {
+    // Patches.
+    { "General Options", "", unselectable, 0, NULL, NULL, 0 },
+
+    { "System Module Inject",
+      "Replaces system modules in FIRM like loader, fs, pxi, etc.",
+      option, (void*)OPTION_LOADER, change_opt, get_opt, 0 },
+
+    { "svcBackdoor Fixup",
+      "Reinserts svcBackdoor on 11.0 NATIVE_FIRM. svcBackdoor allows executing arbitrary functions with ARM11 kernel permissions, and is required by some (poorly coded) applications.",
+      option, (void*)OPTION_SVCS, change_opt, get_opt, 0 },
+
+    { "Firmlaunch Hook",
+      "Hooks firmlaunch to allow largemem games on o3DS. Also allows patching TWL/AGB on all consoles. Previously called 'Reboot hook' but renamed for accuracy.",
+      option, (void*)OPTION_REBOOT, change_opt, get_opt, 0 },
+
+    { "Use EmuNAND",
+      "Redirects NAND write/read to the SD. This supports both Gateway and redirected layouts.",
+      option, (void*)OPTION_EMUNAND, change_opt, get_opt, 0 },
+    { "Index",
+      "Which EmuNAND to use. If you only have one, you want 0. Currently the maximum supported is 10 (0-9), but this is arbitrary.",
+      option, (void*)OPTION_EMUNAND_INDEX, change_opt, get_opt, 1 },
+
+    { "Autoboot",
+      "Boot the system automatically, unless the R key is held while booting.",
+      option, (void*)OPTION_AUTOBOOT, change_opt, get_opt, 0 },
+    { "Silent mode",
+      "Suppress all debug output during autoboot. You'll see the screen turn on and then off once.",
+      option, (void*)OPTION_SILENCE, change_opt, get_opt, 1 },
+
+    { "Dim Background",
+      "Experimental! Dims colors on lighter backgrounds to improve readability with text. You won't notice the change until scrolling or exiting the current menu due to the way rendering works.",
+      option, (void*)OPTION_DIM_MODE, change_opt, get_opt, 0 },
+
+    { "Accent color",
+      "Changes the accent color in menus.",
+      option, (void*)OPTION_ACCENT_COLOR, change_opt, get_opt, 0},
+
+    { "Brightness",
+      "Changes the screeninit brightness in menu. WIP, only takes effect on reboot (this will change.)",
+      option, (void*)OPTION_BRIGHTNESS, change_opt, get_opt, 0},
 
     // space
-    { 0, "", "", not_option, 0, 0, 0 },
+    { "", "", unselectable, 0, NULL, NULL, 0 },
     // Patches.
-    { 0, "Loader Options", "", not_option, 1, 0, 0 },
-
-    { OPTION_LOADER_CPU_L2, "CPU - L2 cache", "Forces the system to use the L2 cache on all applications. If you have issues with crashes, try turning this off.", boolean_val_n3ds, 0, 0, 0 },
-    { OPTION_LOADER_CPU_800MHZ, "CPU - 804Mhz", "Forces the system to run in 804Mhz mode on all applications.", boolean_val_n3ds, 0, 0, 0 },
-    { OPTION_LOADER_LANGEMU, "Language Emulation", "Reads language emulation configuration from `" PATH_LOCEMU "` and imitates the region/language.", boolean_val, 0, 0, 0 },
-    { OPTION_LOADER_LOADCODE, "Load Code Sections", "Loads code sections (text/ro/data) from SD card and patches afterwards.", boolean_val, 0, 0, 0 },
-
-    { OPTION_LOADER_DUMPCODE, "Dump Code Sections",
-      "Dumps code sections for titles to SD card the first time they're loaded. Slows things down on first launch.", boolean_val, 0, 0, 0 },
-
-    { OPTION_LOADER_DUMPCODE_ALL, "+ System Titles",
-      "Dumps code sections for system titles, too. Expect to sit at a blank screen for >3mins on the first time you do this, because it dumps everything.", boolean_val, 0, 0, 1 },
+    { "Loader Options", "", unselectable, 0, NULL, NULL, 0 },
+
+    { "CPU - L2 cache",
+      "Forces the system to use the L2 cache on all applications. If you have issues with crashes, try turning this off.",
+      option_n3ds, (void*)OPTION_LOADER_CPU_L2, change_opt, get_opt, 0 },
+    { "CPU - 804Mhz",
+      "Forces the system to run in 804Mhz mode on all applications.",
+      option_n3ds, (void*)OPTION_LOADER_CPU_800MHZ, change_opt, get_opt, 0 },
+    { "Language Emulation",
+      "Reads language emulation configuration from `" PATH_LOCEMU "` and imitates the region/language.",
+      option, (void*)OPTION_LOADER_LANGEMU, change_opt, get_opt, 0 },
+    { "Load Code Sections",
+      "Loads code sections (text/ro/data) from SD card and patches afterwards.",
+      option, (void*)OPTION_LOADER_LOADCODE, change_opt, get_opt, 0 },
+
+    { "Dump Code Sections",
+      "Dumps code sections for titles to SD card the first time they're loaded. Slows things down on first launch.",
+      option, (void*)OPTION_LOADER_DUMPCODE, change_opt, get_opt, 0 },
+
+    { "+ System Titles",
+      "Dumps code sections for system titles, too. Expect to sit at a blank screen for >3mins on the first time you do this, because it dumps everything.",
+      option, (void*)OPTION_LOADER_DUMPCODE_ALL, change_opt, get_opt, 1 },
 
     // space
-    { 0, "", "", not_option, 0, 0, 0 },
+    { "", "", unselectable, 0, NULL, NULL, 0 },
     // Patches.
-    { 0, "Developer Options", "", not_option, 1, 0, 0 },
-
-    { OPTION_TRACE, "Step Through", "After each important step, [WAIT] will be shown and you'll need to press a key. Debug feature.", boolean_val, 0, 0, 0 },
-    { OPTION_OVERLY_VERBOSE, "Verbose", "Output more debug information than the average user needs.", boolean_val, 0, 0, 0 },
-    { OPTION_SAVE_LOGS, "Logging", "Save logs to `" LOCALSTATEDIR "` as `boot.log` and `loader.log`. Slows operation a bit.", boolean_val, 0, 0, 0 },
-
-    //    { OPTION_ARM9THREAD,        "ARM9 Thread", boolean_val, 0, 0 },
-    //    { IGNORE_PATCH_DEPS,   "Ignore dependencies", boolean_val, 0, 0 },
-    //    { IGNORE_BROKEN_SHIT,  "Allow unsafe options", boolean_val, 0, 0 },
+    { "Developer Options", "", unselectable, 0, NULL, NULL, 0 },
+
+    { "Step Through",
+      "After each important step, [WAIT] will be shown and you'll need to press a key. Debug feature.",
+      option, (void*)OPTION_TRACE, change_opt, get_opt, 0 },
+    { "Verbose",
+      "Output more debug information than the average user needs.",
+      option, (void*)OPTION_OVERLY_VERBOSE, change_opt, get_opt, 0 },
+    { "Logging",
+      "Save logs to `" LOCALSTATEDIR "` as `boot.log` and `loader.log`. Slows operation a bit.",
+      option, (void*)OPTION_SAVE_LOGS, change_opt, get_opt, 0 },
 
     // Sentinel.
-    { -1, "", "", 0, 0, 0, 0 }, // cursor_min and cursor_max are stored in the last two.
+    { NULL, NULL, 0, 0, NULL, NULL, 0 }, // cursor_min and cursor_max are stored in the last two.
 };
 
 static int current_menu_index_patches = 0;
 
 static int desc_is_fname_sto = 0;
 
+char* patch_get_enable(void* val) {
+    uint32_t opt = (uint32_t)val;
+    uint32_t raw = enable_list[opt];
+    return (raw) ? "*" : " ";
+}
+
+void patch_set_enable(void* val) {
+    uint32_t opt = (uint32_t)val;
+    enable_list[opt] = !enable_list[opt];
+}
+
 void patch_func(char* fpath) {
     FILINFO f2;
     if (f_stat(fpath, &f2) != FR_OK)
@@ -77,16 +164,22 @@ void patch_func(char* fpath) {
         if (memcmp(p.magic, "AIDA", 4))
             return;
 
-        memcpy(patches[current_menu_index_patches].name, p.name, 64);
+        patches[current_menu_index_patches].name = strdup_self(p.name);
         if (desc_is_fname_sto)
-            memcpy(patches[current_menu_index_patches].desc, fpath, 255);
+            patches[current_menu_index_patches].param = strdup_self(fpath);
         else
-            memcpy(patches[current_menu_index_patches].desc, p.desc, 255);
-        patches[current_menu_index_patches].index = (int64_t)p.uuid;
-        patches[current_menu_index_patches].allowed = boolean_val;
-        patches[current_menu_index_patches].a = 0;
-        patches[current_menu_index_patches].b = 0;
+            patches[current_menu_index_patches].desc = strdup_self(p.desc);
+
+        uint32_t val = p.uuid;
+
+        patches[current_menu_index_patches].param = (void*)val;
+
+        patches[current_menu_index_patches].handle = option;
         patches[current_menu_index_patches].indent = 0;
+
+        patches[current_menu_index_patches].func  = patch_set_enable;
+        patches[current_menu_index_patches].value = patch_get_enable;
+
         if (desc_is_fname_sto)
             enable_list[p.uuid] = 0;
 
@@ -108,79 +201,47 @@ list_patches_build(char *name, int desc_is_fname)
     if (!patches)
         patches = malloc(sizeof(struct options_s) * 258); // FIXME - hard limit. Implement realloc.
 
-    strncpy(patches[0].name, "Patches", 64);
-    strncpy(patches[0].desc, "", 255);
-    patches[0].index = 0;
-    patches[0].allowed = not_option;
-    patches[0].a = 1;
-    patches[0].b = 0;
+    patches[0].name   = "Patches";
+    patches[0].desc   = "";
+    patches[0].handle = unselectable;
     patches[0].indent = 0;
+    patches[0].func   = NULL;
+    patches[0].value  = NULL;
 
     current_menu_index_patches += 1;
 
     recurse_call(name, patch_func);
 
-    patches[current_menu_index_patches].index = -1;
+    patches[current_menu_index_patches].name = NULL;
 }
 
 void
 menu_patches()
 {
-    show_menu(patches, enable_list);
+    show_menu(patches);
 }
 
 void
 menu_options()
 {
-    show_menu(options, config->options);
+    show_menu(options);
 }
 
 #ifndef REL
 #define REL "master"
 #endif
 
-static struct options_s info_d[] = {
-    { 0, "Native FIRM: ", "The version of NATIVE_FIRM in use.", not_option, 0, 0, 1},
-    { 0, "AGB FIRM:    ", "The version of AGB_FIRM in use. This is used to run GBA games.", not_option, 0, 0, 1},
-    { 0, "TWL FIRM:    ", "The version of TWL_FIRM in use. This is used to run DS games and DSiWare.", not_option, 0, 0, 1},
-    { 0, FW_NAME ":    " REVISION " (" REL ")", FW_NAME "'s version.", not_option, 0, 0, 1},
-    { -1, "", "", not_option, 0, 0, 0 }
-};
-static int is_setup_info = 0;
-
-void
-menu_info()
-{
-    if (!is_setup_info) {
-        // This menu requres firm to be loaded. Unfortunately.
-        load_firms(); // Lazy load!
-
-        struct firm_signature *native = get_firm_info(firm_loc);
-        struct firm_signature *agb = get_firm_info(agb_firm_loc);
-        struct firm_signature *twl = get_firm_info(twl_firm_loc);
-
-        memcpy(&info_d[0].name[strlen(info_d[0].name)], native->version_string, strlen(native->version_string));
-        memcpy(&info_d[1].name[strlen(info_d[1].name)], agb->version_string, strlen(agb->version_string));
-        memcpy(&info_d[2].name[strlen(info_d[2].name)], twl->version_string, strlen(twl->version_string));
-
-        is_setup_info = 1;
-    }
-
-    show_menu(info_d, NULL);
-}
-
-#define ln(s) { 0, s, "", not_option, 0, 0, 0 }
-#define lnh(s) { 0, s, "", not_option, 1, 0, 0 }
+#define ln(s) { s, "", unselectable, 0, NULL, NULL, 0 }
 
 static struct options_s help_d[] = {
-    lnh("About"),
+    ln("About"),
     ln("  This is another 3DS CFW for power users."),
     ln("  It seeks to address some faults in other"),
     ln("  CFWs and is generally just another choice"),
     ln("  for users - but primarily is intended for"),
     ln("  developers. It is not for the faint of heart."),
     ln(""),
-    lnh("Usage"),
+    ln("Usage"),
     ln("  A         -> Select/Toggle/Increment"),
     ln("  B         -> Back/Boot"),
     ln("  X         -> Decrement"),
@@ -191,7 +252,7 @@ static struct options_s help_d[] = {
     ln("  Left      -> Up five"),
     ln("  L+R+Start -> Menu Screenshot"),
     ln(""),
-    lnh("Credits"),
+    ln("Credits"),
     ln("  @mid-kid, @Wolfvak, @Reisyukaku, @AuroraWright"),
     ln("  @d0k3, @TuxSH, @Steveice10, @delebile,"),
     ln("  @Normmatt, @b1l1s, @dark-samus, @TiniVi,"),
@@ -199,13 +260,13 @@ static struct options_s help_d[] = {
     ln("  forgotten (yell at me, please!)"),
     ln(""),
     ln("  <https://github.com/chaoskagami/corbenik>"),
-    { -1, "", "", not_option, 0, 0, 0 }
+    { NULL, NULL, unselectable, 0, NULL, NULL, 0 }, // cursor_min and cursor_max are stored in the last two.
 };
 
 void
 menu_help()
 {
-    show_menu(help_d, NULL);
+    show_menu(help_d);
 }
 
 void
@@ -239,15 +300,19 @@ void chainload_menu();
 #endif
 
 static struct options_s config_opts[] = {
-    { 0, "Options",            "Internal options for the CFW.\nThese are part of " FW_NAME " itself.", call_fun, (uint32_t)menu_options, 0, 0 },
-    { 0, "Patches",            "External bytecode patches found in `" PATH_PATCHES "`.\nYou can choose which to enable.", call_fun, (uint32_t)menu_patches, 0, 0 },
+    { "Options",
+      "Internal options for the CFW.\nThese are part of " FW_NAME " itself.",
+      option, 0, menu_options, NULL, 0 },
+    { "Patches",
+      "External bytecode patches found in `" PATH_PATCHES "`.\nYou can choose which to enable.",
+      option, 0, menu_patches, NULL, 0 },
 
     // Sentinel.
-    { -1, "", "", 0, 0, 0, 0 },
+    { NULL, NULL, 0, 0, NULL, NULL, 0 }, // cursor_min and cursor_max are stored in the last two.
 };
 
 void config_main_menu() {
-    show_menu(config_opts, NULL);
+    show_menu(config_opts);
 
     save_config(); // Save config when exiting.
 
@@ -255,22 +320,33 @@ void config_main_menu() {
 }
 
 static struct options_s main_s[] = {
-    { 0, "Configuration",      "Configuration options for the CFW.", call_fun, (uint32_t)config_main_menu, 0, 0 },
-    { 0, "Info",               "Shows the current FIRM versions (and loads them, if needed)", call_fun, (uint32_t)menu_info,    0, 0 },
-    { 0, "Readme",             "Mini-readme.\nWhy are you opening help on this, though?\nThat's kind of silly.", call_fun, (uint32_t)menu_help,    0, 0 },
-    { 0, "Reboot",             "Reboots the console.", call_fun, (uint32_t)reset,        0, 0 },
-    { 0, "Power off",          "Powers off the console.", call_fun, (uint32_t)poweroff,     0, 0 },
+    { "Configuration",
+      "Configuration options for the CFW.",
+      option, 0, config_main_menu, NULL, 0 },
+    { "Readme",
+      "Mini-readme.\nWhy are you opening help on this, though?\nThat's kind of silly.",
+      option, 0, menu_help, NULL, 0 },
+    { "Reboot",
+      "Reboots the console.",
+      option, 0, reset, NULL, 0 },
+    { "Power off",
+      "Powers off the console.",
+      option, 0, poweroff, NULL, 0 },
 #if defined(CHAINLOADER) && CHAINLOADER == 1
-    { 0, "Chainload",          "Boot another ARM9 payload file.", call_fun, (uint32_t)chainload_menu, 0, 0 },
+    { "Chainload",
+      "Boot another ARM9 payload file.",
+       option, 0, chainload_menu, NULL, 0},
 #endif
-    { 0, "Boot Firmware",      "Generates caches, patches the firmware, and boots it.\nMake sure to 'Save Configuration' first if any options changed.", break_menu, 0, 0, 0 },
+    { "Boot Firmware",
+      "Generates caches, patches the firmware, and boots it.\nMake sure to 'Save Configuration' first if any options changed.",
+      break_menu, 0, NULL, NULL, 0 },
 
     // Sentinel.
-    { -1, "", "", 0, 0, 0, 0 }, // cursor_min and cursor_max are stored in the last two.
+    { NULL, NULL, 0, 0, NULL, NULL, 0 }, // cursor_min and cursor_max are stored in the last two.
 };
 
 void
 menu_handler()
 {
-    show_menu(main_s, NULL);
+    show_menu(main_s);
 }
index d24256f7ec2be11b037e6e8f6d451178386afef9..decebea270b0eedb67dbd764f4eeef4863e8cb83 100644 (file)
@@ -13,8 +13,6 @@ extern uint8_t *enable_list;
 
 extern struct options_s* patches;
 
-void list_patches_build(char *name, int desc_is_fname);
-
 void
 patch_cache_func(char* fpath)
 {
index 45bfd9be65ce9975d6eda318fc7923eda8b79edb..f1c946594d1030a49a1502b2cdb937f41f64e1b8 100644 (file)
@@ -3,6 +3,15 @@
 #include <stdint.h>
 #include <stddef.h>
 
+char*
+strdup_self(char* str)
+{
+    size_t l = strlen(str);
+    char* new_st = malloc(l+1);
+    memcpy(new_st, str, l+1); // Copy the nul byte
+    return new_st;
+}
+
 int
 atoi(const char *str)
 {