From 123a9f48b90ab010ccacf224b3b53c19fabdfa55 Mon Sep 17 00:00:00 2001 From: frysee Date: Sun, 19 Jul 2026 22:20:39 +0200 Subject: [PATCH] feat: FN1/FN2/HOME can now launch user-assigned actions --- skeleton/BASE/README.txt | 4 + workspace/all/common/api.c | 8 +- workspace/all/common/config.c | 59 ++++++++ workspace/all/common/config.h | 23 +++ workspace/all/common/defines.h | 3 + workspace/all/nextui/nextui.c | 44 ++++++ workspace/all/settings/fnbuttonmenu.cpp | 180 ++++++++++++++++++++++++ workspace/all/settings/fnbuttonmenu.hpp | 13 ++ workspace/all/settings/makefile | 2 +- workspace/all/settings/settings.cpp | 6 + workspace/desktop/platform/platform.h | 9 ++ workspace/tg5040/platform/platform.h | 9 ++ workspace/tg5050/platform/platform.h | 9 ++ 13 files changed, 364 insertions(+), 5 deletions(-) create mode 100644 workspace/all/settings/fnbuttonmenu.cpp create mode 100644 workspace/all/settings/fnbuttonmenu.hpp diff --git a/skeleton/BASE/README.txt b/skeleton/BASE/README.txt index 5e5de0700..5f6b965bd 100644 --- a/skeleton/BASE/README.txt +++ b/skeleton/BASE/README.txt @@ -56,6 +56,10 @@ TRIMUI SMART PRO / TRIMUI BRICK "TrimUI" button: Quick menu Select button: Game switcher +TRIMUI BRICK / BRICK PRO / SMART PRO S + + Buttons with no action of their own can be assigned a pak to launch: L3/R3 on the Brick, L4/R4 on the Brick Pro, and HOME on the Brick Pro and Smart Pro S. Assign them under Settings > Assignments. Assignments only apply in the main menu, not in-game. HOME no longer acts as a second menu button. + ---------------------------------------- Quicksave & auto-resume diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index aa5a299bb..19f3f5439 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -3386,8 +3386,8 @@ FALLBACK_IMPLEMENTATION void PLAT_pollInput(void) } else if (code == CODE_MENU_ALT) { - btn = BTN_MENU; - id = BTN_ID_MENU; + btn = BTN_HOME; + id = BTN_ID_HOME; } else if (code == CODE_L1) { @@ -3512,8 +3512,8 @@ FALLBACK_IMPLEMENTATION void PLAT_pollInput(void) } else if (joy == JOY_MENU_ALT) { - btn = BTN_MENU; - id = BTN_ID_MENU; + btn = BTN_HOME; + id = BTN_ID_HOME; } else if (joy == JOY_MENU_ALT2) { diff --git a/workspace/all/common/config.c b/workspace/all/common/config.c index 0b7e6e7df..e1ec3ba7b 100644 --- a/workspace/all/common/config.c +++ b/workspace/all/common/config.c @@ -65,6 +65,8 @@ void CFG_defaults(NextUISettings *cfg) .muteLeds = CFG_DEFAULT_MUTELEDS, + .fnAction = {CFG_DEFAULT_FN_ACTION, CFG_DEFAULT_FN_ACTION, CFG_DEFAULT_FN_ACTION}, + .screenTimeoutSecs = CFG_DEFAULT_SCREENTIMEOUTSECS, .suspendTimeoutSecs = CFG_DEFAULT_SUSPENDTIMEOUTSECS, .powerOffProtection = CFG_DEFAULT_POWEROFFPROTECTION, @@ -343,6 +345,27 @@ void CFG_init(FontLoad_callback_t cb, ColorSet_callback_t ccb) CFG_setMuteLEDs(temp_value); continue; } + if (strncmp(line, "fn1action=", 10) == 0) + { + char *value = line + 10; + value[strcspn(value, "\r\n")] = 0; + CFG_setFnAction(0, value); + continue; + } + if (strncmp(line, "fn2action=", 10) == 0) + { + char *value = line + 10; + value[strcspn(value, "\r\n")] = 0; + CFG_setFnAction(1, value); + continue; + } + if (strncmp(line, "fn3action=", 10) == 0) + { + char *value = line + 10; + value[strcspn(value, "\r\n")] = 0; + CFG_setFnAction(2, value); + continue; + } if (sscanf(line, "artWidth=%i", &temp_value) == 1) { CFG_setGameArtWidth((double)temp_value / 100.0); @@ -907,6 +930,24 @@ void CFG_setMuteLEDs(bool on) CFG_sync(); } +const char* CFG_getFnAction(int index) +{ + if (index < 0 || index >= FN_BUTTON_COUNT) + return ""; + return settings.fnAction[index]; +} + +void CFG_setFnAction(int index, const char* action) +{ + if (index < 0 || index >= FN_BUTTON_COUNT) + return; + if (!action) + action = ""; + strncpy(settings.fnAction[index], action, sizeof(settings.fnAction[index]) - 1); + settings.fnAction[index][sizeof(settings.fnAction[index]) - 1] = '\0'; + CFG_sync(); +} + double CFG_getGameArtWidth(void) { return settings.gameArtWidth; @@ -1400,6 +1441,18 @@ void CFG_get(const char *key, char *value) { sprintf(value, "%i", CFG_getMuteLEDs()); } + else if (strcmp(key, "fn1action") == 0) + { + sprintf(value, "%s", CFG_getFnAction(0)); + } + else if (strcmp(key, "fn2action") == 0) + { + sprintf(value, "%s", CFG_getFnAction(1)); + } + else if (strcmp(key, "fn3action") == 0) + { + sprintf(value, "%s", CFG_getFnAction(2)); + } else if (strcmp(key, "artWidth") == 0) { sprintf(value, "%i", (int)(CFG_getGameArtWidth()) * 100); @@ -1581,6 +1634,9 @@ void CFG_sync(void) fprintf(file, "stateFormat=%i\n", settings.stateFormat); fprintf(file, "useExtractedFileName=%i\n", settings.useExtractedFileName); fprintf(file, "muteLeds=%i\n", settings.muteLeds); + fprintf(file, "fn1action=%s\n", settings.fnAction[0]); + fprintf(file, "fn2action=%s\n", settings.fnAction[1]); + fprintf(file, "fn3action=%s\n", settings.fnAction[2]); fprintf(file, "artWidth=%i\n", (int)(settings.gameArtWidth * 100)); fprintf(file, "wifi=%i\n", settings.wifi); fprintf(file, "defaultView=%i\n", settings.defaultView); @@ -1652,6 +1708,9 @@ void CFG_print(void) printf("\t\"stateFormat\": %i,\n", settings.stateFormat); printf("\t\"useExtractedFileName\": %i,\n", settings.useExtractedFileName); printf("\t\"muteLeds\": %i,\n", settings.muteLeds); + printf("\t\"fn1action\": \"%s\",\n", settings.fnAction[0]); + printf("\t\"fn2action\": \"%s\",\n", settings.fnAction[1]); + printf("\t\"fn3action\": \"%s\",\n", settings.fnAction[2]); printf("\t\"artWidth\": %i,\n", (int)(settings.gameArtWidth * 100)); printf("\t\"wifi\": %i,\n", settings.wifi); printf("\t\"defaultView\": %i,\n", settings.defaultView); diff --git a/workspace/all/common/config.h b/workspace/all/common/config.h index fc2aeb0b3..cdd577866 100644 --- a/workspace/all/common/config.h +++ b/workspace/all/common/config.h @@ -82,6 +82,15 @@ enum { COLOR_BACKGROUND = 7 }; +// Number of user-assignable button slots (FN1/FN2/FN3). Slots are fixed and global, +// not per-device: which of them a given device actually exposes is a UI question. +#define FN_BUTTON_COUNT 3 + +// Prefix for the "launch a Tools pak" action, followed by a path relative to +// Tools/ (e.g. "pak:Bootlogo.pak"). The platform dir is resolved at launch +// time rather than stored, so settings stay portable when a card moves between devices. +#define FN_ACTION_PAK_PREFIX "pak:" + // Input hint styles enum { INPUT_STYLE_TEXT = -1, // Rendered text @@ -135,6 +144,10 @@ typedef struct // Mute switch bool muteLeds; + // User-assignable buttons (see BTN_FN1/BTN_FN2/BTN_FN3 in platform.h). + // Action strings, "" == unassigned. See CFG_getFnAction(). + char fnAction[FN_BUTTON_COUNT][256]; + // Power uint32_t screenTimeoutSecs; uint32_t suspendTimeoutSecs; @@ -223,6 +236,7 @@ typedef struct #define CFG_DEFAULT_STATEFORMAT STATE_FORMAT_SAV #define CFG_DEFAULT_EXTRACTEDFILENAME false #define CFG_DEFAULT_MUTELEDS false +#define CFG_DEFAULT_FN_ACTION "" // unassigned #define CFG_DEFAULT_GAMEARTWIDTH 0.45 #define CFG_DEFAULT_WIFI false #define CFG_DEFAULT_VIEW SCREEN_GAMELIST @@ -370,6 +384,15 @@ void CFG_setUseExtractedFileName(bool); // Enable/disable mute also shutting off LEDs. bool CFG_getMuteLEDs(void); void CFG_setMuteLEDs(bool); +// The action bound to a user-assignable button, where `index` is 0 (FN1), 1 (FN2) or +// 2 (FN3, the "HOME" button). +// The value is a ":" action string so more kinds can be added later without +// migrating existing settings; "" means unassigned. The only kind today is +// FN_ACTION_PAK_PREFIX. Callers must ignore kinds they don't recognise, so a card +// configured on a newer build degrades to "does nothing" on an older one. +// Returns "" for an out of range index. +const char* CFG_getFnAction(int index); +void CFG_setFnAction(int index, const char* action); // Set game art width percentage. double CFG_getGameArtWidth(void); void CFG_setGameArtWidth(double zeroToOne); diff --git a/workspace/all/common/defines.h b/workspace/all/common/defines.h index 1390cf1b0..2b71ce56a 100644 --- a/workspace/all/common/defines.h +++ b/workspace/all/common/defines.h @@ -193,6 +193,8 @@ enum { BTN_ID_ANALOG_LEFT, BTN_ID_ANALOG_RIGHT, + BTN_ID_HOME, + BTN_ID_COUNT, }; enum { @@ -225,6 +227,7 @@ enum { BTN_ANALOG_DOWN = 1 << BTN_ID_ANALOG_DOWN, BTN_ANALOG_LEFT = 1 << BTN_ID_ANALOG_LEFT, BTN_ANALOG_RIGHT= 1 << BTN_ID_ANALOG_RIGHT, + BTN_HOME = 1 << BTN_ID_HOME, BTN_UP = BTN_DPAD_UP | BTN_ANALOG_UP, BTN_DOWN = BTN_DPAD_DOWN | BTN_ANALOG_DOWN, diff --git a/workspace/all/nextui/nextui.c b/workspace/all/nextui/nextui.c index a4f68f9ef..5ed6d612e 100644 --- a/workspace/all/nextui/nextui.c +++ b/workspace/all/nextui/nextui.c @@ -1229,6 +1229,41 @@ static void openPak(char* path) { sprintf(cmd, "'%s/launch.sh'", escapeSingleQuotes(path)); queueNext(cmd); } + +// Run the action bound to a user-assignable button (0 == FN1, 1 == FN2). +// Returns 1 if something was launched. +static int runFnAction(int index) { + const char* action = CFG_getFnAction(index); + if (!action || !action[0]) return 0; // unassigned + + // only "launch a Tools pak" exists so far; ignore kinds we don't know so a card + // configured on a newer build just does nothing here instead of misfiring + size_t prefix_len = strlen(FN_ACTION_PAK_PREFIX); + if (strncmp(action, FN_ACTION_PAK_PREFIX, prefix_len)!=0) return 0; + + const char* rel = action + prefix_len; + if (!rel[0]) return 0; + + char pak_path[256]; + snprintf(pak_path, sizeof(pak_path), "%s/Tools/%s/%s", SDCARD_PATH, PLATFORM, rel); + + char launch_path[256]; + snprintf(launch_path, sizeof(launch_path), "%s/launch.sh", pak_path); + if (!exists(launch_path)) return 0; // stale binding, eg. the pak was deleted + + // unlike openPak() we save where the user *is*, not the pak itself, so exiting + // the pak comes back to the same spot in the list + if (top && top->entries->count>0) { + Entry* entry = top->entries->items[top->selected]; + saveLast(entry->path); + } + + char cmd[256]; + // NOTE: escapeSingleQuotes() modifies pak_path in place + snprintf(cmd, sizeof(cmd), "'%s/launch.sh'", escapeSingleQuotes(pak_path)); + queueNext(cmd); + return 1; +} static void openRom(char* path, char* last) { LOG_info("openRom(%s,%s)\n", path, last); @@ -2300,6 +2335,15 @@ int main (int argc, char *argv[]) { PWR_update(&dirty, &show_setting, NULL, NULL); + // user-assignable buttons, handled before the per-screen input so they work + // from the game list, the game switcher and the quick menu alike. + // skipped while the brightness/volume overlay owns input, same as L1/R1 below. + if (!show_setting) { + if (PAD_justPressed(BTN_FN1)) runFnAction(0); + else if (PAD_justPressed(BTN_FN2)) runFnAction(1); + else if (PAD_justPressed(BTN_FN3)) runFnAction(2); + } + int is_online = PWR_isOnline(); if (was_online!=is_online) dirty = 1; diff --git a/workspace/all/settings/fnbuttonmenu.cpp b/workspace/all/settings/fnbuttonmenu.cpp new file mode 100644 index 000000000..5659c16f8 --- /dev/null +++ b/workspace/all/settings/fnbuttonmenu.cpp @@ -0,0 +1,180 @@ +#include "fnbuttonmenu.hpp" + +extern "C" { +#include "config.h" +#include "utils.h" +} + +#include +#include +#include + +namespace { + +// The platform headers are the single source of truth for which buttons exist and +// what they're called, so a device that gains one only has to say so there. +const char* fnButtonName(int index) +{ + switch (index) { + case 0: return BTN_FN1_NAME; + case 1: return BTN_FN2_NAME; + case 2: return BTN_FN3_NAME; + default: return ""; + } +} + +struct PakEntry { + std::string action; // the action string to persist, eg. "pak:Bootlogo.pak" + std::string label; // pak name without the extension +}; + +bool isPak(const std::string &dir, const std::string &name) +{ + if (name.size() < 5 || name.compare(name.size() - 4, 4, ".pak") != 0) + return false; + // a pak without a launch.sh isn't launchable, don't offer it + std::string launch = dir + "/" + name + "/launch.sh"; + return exists(const_cast(launch.c_str())); +} + +PakEntry pakEntry(const std::string &rel, const std::string &name) +{ + return {std::string(FN_ACTION_PAK_PREFIX) + rel, name.substr(0, name.size() - 4)}; +} + +// Tools paks, including those one subfolder deep (Tools///.pak), +// which is how larger pak collections tend to organize themselves. +std::vector enumerateToolPaks() +{ + std::vector paks; + + std::string tools_path = std::string(SDCARD_PATH) + "/Tools/" + PLATFORM; + DIR *dir = opendir(tools_path.c_str()); + if (!dir) + return paks; + + struct dirent *ent; + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') continue; + std::string name(ent->d_name); + + if (isPak(tools_path, name)) { + paks.push_back(pakEntry(name, name)); + continue; + } + + // not a pak itself, look one level in + std::string sub_path = tools_path + "/" + name; + DIR *sub = opendir(sub_path.c_str()); + if (!sub) continue; + + struct dirent *sub_ent; + while ((sub_ent = readdir(sub)) != NULL) { + if (sub_ent->d_name[0] == '.') continue; + std::string sub_name(sub_ent->d_name); + if (!isPak(sub_path, sub_name)) continue; + paks.push_back(pakEntry(name + "/" + sub_name, sub_name)); + } + closedir(sub); + } + closedir(dir); + + std::sort(paks.begin(), paks.end(), [](const PakEntry &a, const PakEntry &b) { + return strcasecmp(a.label.c_str(), b.label.c_str()) < 0; + }); + return paks; +} + +// Row for one button. The label is read live from the config rather than from the +// cycled index, so picking from the submenu updates the row too. +class FnMenuItem : public MenuItem +{ +public: + using MenuItem::MenuItem; + + const std::string getLabel() const override + { + std::string current; + if (on_get) { + auto v = on_get(); + if (v.has_value()) + current = std::any_cast(v); + } + + const auto values = getValues(); + const auto labels = getLabels(); + for (size_t i = 0; i < values.size() && i < labels.size(); i++) + if (std::any_cast(values[i]) == current) + return labels[i]; + return "None"; + } + + InputReactionHint handleInput(int &dirty) override + { + // re-sync so Left/Right cycles on from whatever the submenu last set + if (!isDeferred()) + reselect(); + return MenuItem::handleInput(dirty); + } +}; + +} // namespace + +MenuList* buildFnButtonMenu() +{ + // Enumerate once when the menu is built. + const auto paks = enumerateToolPaks(); + + std::vector items; + for (int i = 0; i < FN_BUTTON_COUNT; i++) { + std::string button = fnButtonName(i); + if (button.empty()) continue; // this device doesn't have that button + + // "" == unassigned, followed by every pak we found + std::vector values = {std::string("")}; + std::vector labels = {"None"}; + + std::string current = CFG_getFnAction(i); + bool found = current.empty(); + for (const auto &p : paks) { + if (p.action == current) + found = true; + values.push_back(p.action); + labels.push_back(p.label); + } + // Keep an assignment pointing at a pak we can't find, so opening this menu + // doesn't silently drop a binding for a pak that is merely absent right now + // (card swapped, pak renamed, ...). + if (!found) { + values.push_back(current); + labels.push_back(current.substr(current.find(':') + 1) + " (missing)"); + } + + // Submenu: a plain list; selecting a row applies it and closes. + std::vector subItems; + for (size_t v = 0; v < values.size(); v++) { + std::string action = std::any_cast(values[v]); + subItems.push_back(new MenuItem{ListItemType::Button, labels[v], "", + [i, action](AbstractMenuItem &) -> InputReactionHint { + CFG_setFnAction(i, action.c_str()); + return Exit; + }}); + } + auto *submenu = new MenuList(MenuItemType::Fixed, button + " button", std::move(subItems)); + + items.push_back(new FnMenuItem{ListItemType::Generic, button + " button", + "The pak to launch when this button is pressed in the main menu.", + values, labels, + [i]() -> std::any { return std::string(CFG_getFnAction(i)); }, + [i](const std::any &value) { CFG_setFnAction(i, std::any_cast(value).c_str()); }, + [i]() { CFG_setFnAction(i, CFG_DEFAULT_FN_ACTION); }, + DeferToSubmenu, submenu}); + } + + if (items.empty()) + return nullptr; // no assignable buttons on this device + + items.push_back(new MenuItem{ListItemType::Button, "Reset to defaults", + "Resets all options in this menu to their default values.", ResetCurrentMenu}); + return new MenuList(MenuItemType::Fixed, "Assignments", std::move(items)); +} diff --git a/workspace/all/settings/fnbuttonmenu.hpp b/workspace/all/settings/fnbuttonmenu.hpp new file mode 100644 index 000000000..182691997 --- /dev/null +++ b/workspace/all/settings/fnbuttonmenu.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "menu.hpp" + +// Builds the "Assignments" menu: one row per user-assignable button this +// device actually has (BTN_FN1/FN2/FN3, named by BTN_FN*_NAME in platform.h), each +// bound to a Tools pak to launch. Left/Right cycles through the available paks and +// applies immediately; Confirm opens a submenu with the same choices for direct +// selection. +// +// Returns nullptr when the device has no assignable buttons, in which case the caller +// should leave the menu out entirely. +MenuList* buildFnButtonMenu(); diff --git a/workspace/all/settings/makefile b/workspace/all/settings/makefile index 6338d32e0..ea854f1c8 100644 --- a/workspace/all/settings/makefile +++ b/workspace/all/settings/makefile @@ -22,7 +22,7 @@ SDL?=SDL TARGET = settings INCDIR = -I. -I../common/ -I../../$(PLATFORM)/platform/ SOURCE = -c ../common/utils.c ../common/api.c ../common/config.c ../common/palette.c ../common/scaler.c ../common/http.c ../common/ra_auth.c ../common/ra_offline.c ../common/ra_sync.c ../common/ra_event_queue.c ../../$(PLATFORM)/platform/platform.c -CXXSOURCE = $(TARGET).cpp menu.cpp colorpickermenu.cpp palettemenu.cpp wifimenu.cpp btmenu.cpp keyboardprompt.cpp +CXXSOURCE = $(TARGET).cpp menu.cpp colorpickermenu.cpp palettemenu.cpp fnbuttonmenu.cpp wifimenu.cpp btmenu.cpp keyboardprompt.cpp CXXSOURCE += build/$(PLATFORM)/utils.o build/$(PLATFORM)/api.o build/$(PLATFORM)/config.o build/$(PLATFORM)/palette.o build/$(PLATFORM)/scaler.o build/$(PLATFORM)/http.o build/$(PLATFORM)/ra_auth.o build/$(PLATFORM)/ra_offline.o build/$(PLATFORM)/ra_sync.o build/$(PLATFORM)/ra_event_queue.o build/$(PLATFORM)/platform.o CC = $(CROSS_COMPILE)gcc diff --git a/workspace/all/settings/settings.cpp b/workspace/all/settings/settings.cpp index 0fe461046..7a3eeda49 100644 --- a/workspace/all/settings/settings.cpp +++ b/workspace/all/settings/settings.cpp @@ -26,6 +26,7 @@ extern "C" #include "keyboardprompt.hpp" #include "colorpickermenu.hpp" #include "palettemenu.hpp" +#include "fnbuttonmenu.hpp" #define BUSYBOX_STOCK_VERSION "1.27.2" @@ -1054,6 +1055,8 @@ int main(int argc, char *argv[]) }, }); + MenuList *buttonMenu = buildFnButtonMenu(); // nullptr if this device has none + std::vector mainItems = { new MenuItem{ListItemType::Generic, "Appearance", "UI customization", {}, {}, nullptr, nullptr, DeferToSubmenu, appearanceMenu}, new MenuItem{ListItemType::Generic, "Display", "", {}, {}, nullptr, nullptr, DeferToSubmenu, displayMenu}, @@ -1064,6 +1067,9 @@ int main(int argc, char *argv[]) mainItems.push_back(new MenuItem{ListItemType::Generic, "FN switch", "FN switch settings", {}, {}, nullptr, nullptr, DeferToSubmenu, new MenuList(MenuItemType::Fixed, "FN Switch", muteItems)}); + if(buttonMenu) + mainItems.push_back(new MenuItem{ListItemType::Generic, "Assignments", "Customize button assignments", {}, {}, nullptr, nullptr, DeferToSubmenu, buttonMenu}); + mainItems.push_back(new MenuItem{ListItemType::Generic, "In-Game", "In-game settings for MinArch", {}, {}, nullptr, nullptr, DeferToSubmenu, minarchMenu}); if(deviceInfo.hasWifi()) diff --git a/workspace/desktop/platform/platform.h b/workspace/desktop/platform/platform.h index 2dfdee28d..520782ae6 100644 --- a/workspace/desktop/platform/platform.h +++ b/workspace/desktop/platform/platform.h @@ -99,6 +99,15 @@ #define JOY_PLUS JOY_NA #define JOY_MINUS JOY_NA +/////////////////////////////// +// USER-ASSIGNABLE BUTTONS +#define BTN_FN1 BTN_NONE +#define BTN_FN2 BTN_NONE +#define BTN_FN3 BTN_NONE +#define BTN_FN1_NAME "" +#define BTN_FN2_NAME "" +#define BTN_FN3_NAME "" + /////////////////////////////// #define BTN_RESUME BTN_X diff --git a/workspace/tg5040/platform/platform.h b/workspace/tg5040/platform/platform.h index 838648cfc..88a0250d1 100644 --- a/workspace/tg5040/platform/platform.h +++ b/workspace/tg5040/platform/platform.h @@ -105,6 +105,15 @@ extern int is_brickpro; #define JOY_PLUS (is_brick||is_brickpro?14:128) #define JOY_MINUS (is_brick||is_brickpro?13:129) +/////////////////////////////// +// USER-ASSIGNABLE BUTTONS +#define BTN_FN1 (is_brick?BTN_L3:(is_brickpro?BTN_L4:BTN_NONE)) +#define BTN_FN2 (is_brick?BTN_R3:(is_brickpro?BTN_R4:BTN_NONE)) +#define BTN_FN1_NAME (is_brick?"L3":(is_brickpro?"L4":"")) +#define BTN_FN2_NAME (is_brick?"R3":(is_brickpro?"R4":"")) +#define BTN_FN3 (is_brickpro?BTN_HOME:BTN_NONE) +#define BTN_FN3_NAME (is_brickpro?"HOME":"") + /////////////////////////////// #define AXIS_L2 2 // ABSZ diff --git a/workspace/tg5050/platform/platform.h b/workspace/tg5050/platform/platform.h index 908006f81..06067be63 100644 --- a/workspace/tg5050/platform/platform.h +++ b/workspace/tg5050/platform/platform.h @@ -100,6 +100,15 @@ #define JOY_PLUS 128 #define JOY_MINUS 129 +/////////////////////////////// +// USER-ASSIGNABLE BUTTONS +#define BTN_FN1 BTN_NONE +#define BTN_FN2 BTN_NONE +#define BTN_FN3 BTN_HOME +#define BTN_FN1_NAME "" +#define BTN_FN2_NAME "" +#define BTN_FN3_NAME "HOME" + /////////////////////////////// #define AXIS_L2 2 // ABSZ