Release 0.2.0: fix Display Options crash with voice prompts on

Screen Dim passed a plain literal ('100%'/'50%'/...) to
voicePromptsAppendLanguageString(), which derives the prompt index from the
string's offset within the language table; a foreign pointer produced a garbage
index and crashed (only with voice on). Route the value through
voicePromptsAppendString() instead. Also move the 3-bit dim level's high bit off
legacy option bit 2 to bit 29 and clamp the level against the option arrays.

Bump version to 0.2.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marcus Kida 2026-07-07 15:41:59 +02:00
parent 734b861917
commit 1c59622a77
5 changed files with 34 additions and 6 deletions

View file

@ -7,6 +7,17 @@ single running list until the first versioned release.
## Unreleased
_Nothing yet._
## 0.2.0
- **Fix crash** opening Display Options with **voice announcements on**: the Screen
Dim value ("100%"/"50%"/…) is a plain literal, but the shared menu code fed it to
`voicePromptsAppendLanguageString()`, which derives the prompt index from the
string's offset within the language table — a foreign pointer produced a garbage
index and crashed. The value now goes through `voicePromptsAppendString()`. Also
moved the dim-level high bit off a low legacy option bit (bit 2 → 29) and clamped
the level so it can never index past the option arrays.
- **7-segment frequency font:** inactive segments are now off (background) instead
of faintly lit — no dim "ghosting". "MHz" now matches the frequency colour, and
there's 1px more space between the RX and TX frequency lines.

View file

@ -5,9 +5,9 @@
#define _FREETRX_VERSION_H_
#define FREETRX_VERSION_MAJOR 0
#define FREETRX_VERSION_MINOR 1
#define FREETRX_VERSION_MINOR 2
#define FREETRX_VERSION_PATCH 0
#define FREETRX_VERSION "0.1.0"
#define FREETRX_VERSION "0.2.0"
#endif // _FREETRX_VERSION_H_

View file

@ -129,7 +129,7 @@ typedef enum
{
BIT_INVERSE_VIDEO = (SETTINGS_BITS_BANK_0 | (1 << 0)),
BIT_PTT_LATCH = (SETTINGS_BITS_BANK_0 | (1 << 1)),
BIT_SCREEN_DIM_2 = (SETTINGS_BITS_BANK_0 | (1 << 2)), // high bit of the 3-bit screen-dim level
BIT_UNUSED_2 = (SETTINGS_BITS_BANK_0 | (1 << 2)),
BIT_BATTERY_VOLTAGE_IN_HEADER = (SETTINGS_BITS_BANK_0 | (1 << 3)),
BIT_SETTINGS_UPDATED = (SETTINGS_BITS_BANK_0 | (1 << 4)),
BIT_TX_RX_FREQ_LOCK = (SETTINGS_BITS_BANK_0 | (1 << 5)),
@ -154,6 +154,7 @@ typedef enum
#endif
BIT_SECONDARY_LANGUAGE = (SETTINGS_BITS_BANK_0 | (1 << 19)),
BIT_SCREEN_DIM_1 = (SETTINGS_BITS_BANK_0 | (1 << 20)), // middle bit of the 3-bit screen-dim level
BIT_SCREEN_DIM_2 = (SETTINGS_BITS_BANK_0 | (1 << 29)), // high bit of the 3-bit screen-dim level (kept off low legacy bits)
BIT_DISPLAY_CHANNEL_DISTANCE = (SETTINGS_BITS_BANK_0 | (1 << 21)),
#if defined(PLATFORM_MD2017)
BIT_TRACKBALL_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 22)),

View file

@ -607,7 +607,9 @@ bool settingsIsOptionBitSet(bitfieldOptions_t bit)
// no new settings field (existing codeplugs keep both bits clear = SCREEN_DIM_OFF).
uint8_t settingsGetScreenDimLevel(void)
{
return (settingsIsOptionBitSet(BIT_SCREEN_DIM_0) ? 1 : 0) | (settingsIsOptionBitSet(BIT_SCREEN_DIM_1) ? 2 : 0) | (settingsIsOptionBitSet(BIT_SCREEN_DIM_2) ? 4 : 0);
uint8_t level = (settingsIsOptionBitSet(BIT_SCREEN_DIM_0) ? 1 : 0) | (settingsIsOptionBitSet(BIT_SCREEN_DIM_1) ? 2 : 0) | (settingsIsOptionBitSet(BIT_SCREEN_DIM_2) ? 4 : 0);
// Never return an out-of-range level: dimOpts[]/dimPercent[] are SCREEN_DIM_NUM long.
return (level < SCREEN_DIM_NUM) ? level : SCREEN_DIM_OFF;
}
void settingsSetScreenDimLevel(uint8_t level)

View file

@ -249,9 +249,23 @@ static void updateScreen(bool isFirstRun)
case DISPLAY_SCREEN_DIM:
{
const char *dimOpts[] = { currentLanguage->off, "100%", "50%", "30%", "15%" };
// The "%" values are plain string literals, not currentLanguage entries,
// so they must go through rightSideVar -> voicePromptsAppendString().
// Passing them to voicePromptsAppendLanguageString() (as the shared code
// does for rightSideConst) would treat the pointer as an offset into the
// language table and crash when voice prompts are enabled. "Off" is a real
// language string, so it can stay in rightSideConst.
const char *dimOpts[] = { NULL, "100%", "50%", "30%", "15%" };
uint8_t dimLevel = settingsGetScreenDimLevel();
leftSide = "Screen Dim";
rightSideConst = dimOpts[settingsGetScreenDimLevel()];
if (dimLevel == SCREEN_DIM_OFF)
{
rightSideConst = currentLanguage->off;
}
else
{
snprintf(rightSideVar, SCREEN_LINE_BUFFER_SIZE, "%s", dimOpts[dimLevel]);
}
}
break;