From 43761677de5f89990d01921e379212a5326ca1a5 Mon Sep 17 00:00:00 2001 From: drjones Date: Thu, 24 Sep 2026 20:51:48 -0700 Subject: [PATCH] Fix screen flicker: incremental menu redraw instead of full fillScreen every 60ms --- src/core/shell.cpp | 47 +++++++++++++++++++++++++++++----------------- src/core/shell.h | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/core/shell.cpp b/src/core/shell.cpp index 4cde5f5..80ee917 100644 --- a/src/core/shell.cpp +++ b/src/core/shell.cpp @@ -103,25 +103,38 @@ void Shell::begin() { add(makeActiveExploit()); add(makeLogViewer()); ui::bootSplash(); - drawMenu(); + drawMenu(true); } -void Shell::drawMenu() { +void Shell::drawMenu(bool force) { auto& d = M5.Display; - d.fillScreen(ui::bg()); - ui::titleBar("Card-Crack", CARDCRACK_VERSION); - // animated selection glow bar - int y = ui::BODY_Y + sel * 12; - uint16_t sb = ui::mix(theme::active().panel, theme::active().accent, 0.25f + 0.25f * ui::pulse(900)); - d.fillRect(0, y, ui::W, 12, sb); - for (int i = 0; i < nmods; i++) { - bool cur = i == sel; - uint16_t c = cur ? ui::accent() : ui::fg(); - d.setTextColor(c, cur ? sb : ui::bg()); - d.setCursor(5, ui::BODY_Y + i * 12 + 1); + if (force) { + d.fillScreen(ui::bg()); + ui::titleBar("Card-Crack", CARDCRACK_VERSION); + d.setTextColor(ui::fg(), ui::bg()); + d.setTextSize(1); + for (int i = 0; i < nmods; i++) { + d.setCursor(5, ui::BODY_Y + i * 12 + 1); + d.printf(" %-9s %s", mods[i]->name(), mods[i]->blurb()); + } + ui::hintBar("; up . down enter open home-lab only"); + } + // Flicker-free: repaint ONLY the selection-bar strip (previous + current rows) + static int lastSel = -1; + int rows[2] = { lastSel, sel }; + for (int k = 0; k < 2; k++) { + int i = rows[k]; + if (i < 0 || i >= nmods) continue; + bool cur = (i == sel); + int y = ui::BODY_Y + i * 12; + uint16_t sb = cur ? ui::mix(theme::active().panel, theme::active().accent, 0.25f + 0.25f * ui::pulse(900)) : ui::bg(); + d.fillRect(0, y, ui::W, 12, sb); + d.setTextColor(cur ? ui::accent() : ui::fg(), sb); + d.setTextSize(1); + d.setCursor(5, y + 1); d.printf("%c %-9s %s", cur ? char(0x10) : ' ', mods[i]->name(), mods[i]->blurb()); } - ui::hintBar("; up . down enter open home-lab only"); + lastSel = sel; } void Shell::enter(int i) { @@ -136,7 +149,7 @@ void Shell::enter(int i) { void Shell::back() { if (active >= 0) mods[active]->onExit(); active = -1; - drawMenu(); + drawMenu(true); } void Shell::loop() { @@ -158,8 +171,8 @@ void Shell::loop() { } if (active < 0) { - // keep the menu selection breathing - if (millis() - lastTick > 60) { lastTick = millis(); drawMenu(); } + // keep the selection glow breathing — repaints only the bar strip (flicker-free) + if (millis() - lastTick > 90) { lastTick = millis(); drawMenu(false); } return; } if (millis() - lastTick > 33) { diff --git a/src/core/shell.h b/src/core/shell.h index 816c089..5facb71 100644 --- a/src/core/shell.h +++ b/src/core/shell.h @@ -14,7 +14,7 @@ private: int active = -1; // -1 == in menu uint32_t lastTick = 0; void add(Module* m) { if (nmods < MAX) mods[nmods++] = m; } - void drawMenu(); + void drawMenu(bool force = false); void enter(int i); void back(); };