The async INTERNET STATUS fix left the row sized for the initial
CHECKING... text; when NOT CONNECTED arrived the component overflowed to
the right and clipped. Reserve the cell for the widest candidate string
and right-align it like the sibling rows.
The DISABLE POWER LED switch only wrote powerled.disabled, a conf key
with no consumer, so it silently did nothing. Apply it immediately
through the power LED backend (off kills the LED, re-enabling restores
the POWER LED COLOR choice, heartbeat when unset); the boot autostart
honours the key too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The audio and display enumerations are popen calls cached under a mutex;
on a cache miss they ran synchronously on the UI thread, so the first
open of those submenus stalled on serial shell spawns. Warm them from
the existing startup thread pool. WiFi channels are deliberately not
warmed: the adapter may not be up that early and an empty result would
be cached for the session.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The default mode keeps a 40ms wakeup tick that renders continuously,
measured at ~25% CPU sitting idle in the menu on the RK3326. Enhanced
blocks on events when idle and cut that to ~10% on hardware, with no
noticeable UX difference (instant measured the same, so enhanced is the
better tradeoff). Users can still change it in the UI settings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every boot fully re-parsed every gamelist.xml with pugixml and re-ran
migrate() and genre conversion per entry; on large libraries that
dominates startup time. Serialize the fully-processed entries (path plus
the final MetaDataList state, including unknown XML elements and scrape
dates so the write-back round-trip stays lossless) into a per-system
binary cache keyed on the XML's mtime and size, and replay it on boot
when nothing changed.
The cache only runs in the default !ParseGamelistOnly mode, whose replay
semantics it reproduces exactly (entries the disk scan did not find are
skipped, like the XML path does). Crash-recovery data bypasses it, and
both gamelist.xml writers drop the cache on save since mtime alone has
one-second granularity. A version field guards format changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every one of these calls ran system()/executeScript synchronously on the
render thread, freezing the interface:
- Network settings menu build ran ping() inline, which chains up to
three "ping -c 1 -W 2" calls: opening the menu could freeze for six
seconds before drawing. The status label now starts as CHECKING... and
a worker thread fills it in via postToUiThread.
- The ad-hoc WiFi toggle tears the association down and reconnects
(tens of seconds on slow dongles); it now uses the same GuiLoading
spinner as the WiFi connect path, and the plain disable paths run
detached.
- Bluetooth enable/disable (controllers toggle and save), audio output
device/profile, overclock, overscan and storage selection now apply in
the background instead of stalling the save path; the bluetooth toggle
that rebuilds its menu shows the busy spinner.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
enableWifi (wifictl scan + associate) can take 30+ seconds on slow USB
dongles and was called synchronously on the UI thread from both the
network settings save function and the WiFi enable toggle, so pressing B
after typing the passphrase left the console looking frozen with no
feedback while it silently tried to connect (bug report 4).
Wrap both call sites in GuiLoading<bool>, the same busy-spinner pattern
GuiWifi already uses for the network scan. The toggle path closes and
reopens the settings window from the completion callback; GuiLoading
deletes itself before invoking that callback, so this is safe.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
emulationstation2.mo dos idiomas é embarcado em
/usr/config/locale/<lang>/LC_MESSAGES/ via userconfig-setup, não no
/usr/share/locale do gettext. Sem essa preferência o ES caía
direto no fallback /usr/share/locale (vazio), bindtextdomain
retornava NULL e nenhuma string traduzida aparecia mesmo com o
usuário escolhendo pt_BR/es/etc no menu.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
getArchString() lia /usr/share/batocera/batocera.arch para identificar
o device. ArchR não embarca esse arquivo, então a função caía em
fallback de #if RK3326 que também não está definido (a build passa
-DHW_DEVICE="RK3326" como string, não como macro inteira), devolvendo
string vazia. Resultado: features.cfg condicionais por arch nunca
batiam. Ler HW_DEVICE do ambiente (já exportado por
/etc/profile.d/999-export) resolve sem precisar criar arquivo extra.
Scripting agora também procura hooks em /run/emulationstation/scripts
(além de /var/run/...). systemd-tmpfiles cria o dir vazio durante o
boot para que usuários possam dropar game-start/game-end/etc. sem
precisar mkdir manual após cada reboot do tmpfs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
These Settings references leaked from the partial badfc993b cherry-pick
but were intentionally excluded. They reference functions and settings
that don't exist in our codebase.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ThreadPool: Add missing includes (algorithm, chrono, memory, vector,
initializer_list) needed for WorkItem pattern
- Window: Improve storage merge prompt with "IGNORE THIS TIME" and
"IGNORE FOREVER" options using device uniqueId
Cherry-picked from ROCKNIX a8513aec1.
Split getAvailableGovernors into getAvailableCpuGovernors and
getAvailableGpuGovernors. GPU performance menu now reads actual
available governors from the system via get_available_gpu_governors
instead of hardcoded profiles.
Cherry-picked from ROCKNIX 5b0b876a9.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-picked and adapted from ROCKNIX badfc993b:
- ThreadPool: Add WorkItem/WorkItemPtr with waitAllExcept pattern for
fine-grained task synchronization
- main.cpp: Parallelize startup (VLC, IP, MetaData, MameNames, Genres,
HttpReq cookies) using ThreadPool - significant boot time improvement
- MetaData: Replace std::map<MetaDataId,string> with int8_t indices +
vector - eliminates 48+ bytes/node red-black tree overhead per game entry,
O(1) lookups instead of O(log n) - critical for 1GB RAM with large collections
- Gamelist/SystemData: Use readAllBytes + load_buffer_inplace for XML
parsing instead of load_file - avoids kernel file handle overhead
- ThemeData: Cache raw XML strings instead of parsed DOM trees - less memory
usage; Element::properties from map to unordered_map for faster lookups
- ThemeVariables: Iterative resolvePlaceholders instead of recursive -
prevents stack overflow on deeply nested variables, uses string_view
- StringUtil::trim: Skip substr allocation when string needs no trimming
- FileSystemUtil: Add readAllBytes utility
Excluded from original commit: packGamelist, BuildMultiDiskContentCache,
Win32 changes, reloadAllGames parameter, GuiMenu changes (branding conflict)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Call cleanupVRAM() in TextureLoader::threadProc() right before each async
texture load. Ensures VRAM is freed just before decode, preventing brief
overcommit when multiple textures are queued simultaneously on 1GB RAM.
Inspired by ROCKNIX 211530a33, adapted to our single-pass cleanup strategy.
- FileData: Skip lines where trim[0] == '\0' in m3u parsing (empty lines)
- SystemData: Check getType() == GAME before deleting fileMap entries to
prevent accidentally deleting folder entries that match content file paths
Cherry-picked fixes from ROCKNIX 39fde1086 (adapted to our codebase)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>