From 86e48f5f692f5f261c1790c4ae9d09325195e100 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Wed, 19 Aug 2026 14:42:46 +0200 Subject: [PATCH] Add slot tag to SysInfo --- App/ui/menu.c | 40 ++++++++++++++++++++++++++++++++++++++++ App/ui/multiboot.c | 21 +++++++++++++++++---- App/ui/multiboot.h | 4 ++++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/App/ui/menu.c b/App/ui/menu.c index cb16b751..6b048d28 100644 --- a/App/ui/menu.c +++ b/App/ui/menu.c @@ -42,6 +42,9 @@ #include "menu.h" #include "ui.h" #include "welcome.h" +#ifdef ENABLE_FEAT_F4HWN_MULTIBOOT + #include "multiboot.h" +#endif const t_menu_item MenuList[] = @@ -836,6 +839,35 @@ static void UI_MENU_DrawTopRightRoundedBadge(const char *text, const uint8_t lin UI_PrintStringSmallNormalInverse(text, text_x, 0, line); } +/* Single-line variant for tight gaps: unlike UI_PrintStringSmallNormalInverse, + * the rounded edge stays entirely inside `line` and never touches line - 1. */ +static void UI_MENU_DrawInlineRoundedBadge(const char *text, const uint8_t line, + const uint8_t area_x1, const uint8_t area_x2) +{ + const size_t length = strlen(text); + const size_t char_pitch = ARRAY_SIZE(gFontSmall[0]) + 1u; + const size_t text_width = length * char_pitch; + const size_t capsule_width = text_width + 3u; + + if (length == 0 || line >= FRAME_LINES || area_x2 <= area_x1) { + return; + } + + const size_t area_width = area_x2 - area_x1 + 1u; + if (capsule_width >= area_width) + return; + + const uint8_t capsule_left = (uint8_t)(area_x1 + ((area_width - capsule_width) / 2u)); + const uint8_t text_x = (uint8_t)(capsule_left + 1u); + const uint8_t x_end = (uint8_t)(text_x + text_width + 1u); + + UI_PrintStringSmallNormal(text, text_x, 0, line); + gFrameBuffer[line][text_x - 1u] ^= 0x7Eu; + for (uint8_t x = text_x; x < x_end; x++) + gFrameBuffer[line][x] ^= 0xFFu; + gFrameBuffer[line][x_end] ^= 0x7Eu; +} + void UI_DisplayMenu(void) { const unsigned int menu_list_width = 6; // max no. of characters on the menu list (left side) @@ -1421,6 +1453,14 @@ void UI_DisplayMenu(void) #ifdef ENABLE_FEAT_F4HWN sprintf(String, "%s\n%s", AUTHOR_STRING_2, DISPLAY_VERSION_STRING_2); UI_PrintStringSmallNormal(Edition, menu_item_x1 - 1, menu_item_x2, 6); +#ifdef ENABLE_FEAT_F4HWN_MULTIBOOT + const uint8_t running_slot = MB_GetRunningSlot(); + char slot_badge[2]; + + slot_badge[0] = (running_slot == 0u) ? 'M' : (char)('0' + running_slot); + slot_badge[1] = '\0'; + UI_MENU_DrawInlineRoundedBadge(slot_badge, 5, menu_item_x1, menu_item_x2); +#endif #else sprintf(String, "%u.%02uV\n%u%%", gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, diff --git a/App/ui/multiboot.c b/App/ui/multiboot.c index 9a733de7..ffa34025 100644 --- a/App/ui/multiboot.c +++ b/App/ui/multiboot.c @@ -13,6 +13,19 @@ #include "ui/helper.h" #include "ui/multiboot.h" +static uint8_t gRunningSlot = MB_SLOT_BACKUP; + +static uint8_t mb_remember_running_slot(uint8_t slot) +{ + gRunningSlot = slot; + return slot; +} + +uint8_t MB_GetRunningSlot(void) +{ + return gRunningSlot; +} + static const char *mb_error_text(uint8_t err) { switch (err) @@ -430,14 +443,14 @@ uint8_t MB_BootResolveProfile(void) if (ms == MB_MARK_VALID) { if (MB_InternalMatchesProfile(&mark)) - return mark.index; /* running the slot the marker names */ + return mb_remember_running_slot(mark.index); /* slot named by the marker */ /* Marker read fine but internal no longer carries its identity -> the * firmware was replaced outside multiboot (a plain Flash-Firmware). Adopt * it as Main. Deliberately NOT a content scan here: a build that merely * duplicates a user slot (or a marker that already points at such a slot) * must still refresh Main. */ - return mb_adopt_internal_as_main(); + return mb_remember_running_slot(mb_adopt_internal_as_main()); } /* Marker unreliable (MISSING / LEGACY / CORRUPT / IO): identify the running @@ -453,7 +466,7 @@ uint8_t MB_BootResolveProfile(void) if (m == MB_FW_MATCH) { (void)MB_SetActiveProfile(slot); /* record/repair the marker */ - return slot; + return mb_remember_running_slot(slot); } if (m == MB_FW_IO) had_io = true; @@ -471,5 +484,5 @@ uint8_t MB_BootResolveProfile(void) mb_profile_error_halt(); } - return mb_adopt_internal_as_main(); + return mb_remember_running_slot(mb_adopt_internal_as_main()); } diff --git a/App/ui/multiboot.h b/App/ui/multiboot.h index 32bba490..d7b4d1d1 100644 --- a/App/ui/multiboot.h +++ b/App/ui/multiboot.h @@ -17,4 +17,8 @@ void UI_MultibootSelector(void); * the profile index (0..MB_SLOT_COUNT-1) to feed PY25Q16_SetProfileBase(). */ uint8_t MB_BootResolveProfile(void); +/* Slot selected by MB_BootResolveProfile for the current session. This is kept + * in RAM so UI callers do not have to reread the external-flash marker. */ +uint8_t MB_GetRunningSlot(void); + #endif