GameSwitcher: Favorites toggle + fix crashes and game switching - #1939
Open
robcodedev wants to merge 1 commit into
Open
GameSwitcher: Favorites toggle + fix crashes and game switching#1939robcodedev wants to merge 1 commit into
robcodedev wants to merge 1 commit into
Conversation
Switching games shortly after opening GameSwitcher killed the new game and relaunched it at the boot screen, and exiting from there autosaved over the real state. resumeGame() writes cmd_to_run.sh and syncs before overlay_exit() runs, so runtime.sh can start the new game as soon as the old one exits. overlay_exit() meanwhile shut RetroArch down by name: killall -TERM, a loop polling pidof retroarch, then killall -9 after the timeout. Neither distinguishes instances, so pidof matches the newly launched game, the wait runs to its full five seconds, and the final kill takes that game down. force_auto_load_state is already set by then, which is why it comes back at the boot screen. overlay_init() now captures the RetroArch PID and overlay_exit() signals and waits on that instance alone. If no PID was captured, the old killall path remains as fallback. Also adds a menu item that adds or removes the current game from Roms/favourite.json, written through a temp file and renamed into place so an interrupted write can't leave a broken list. Both labels are new strings, 302 and 303, registered next to NEXT and RESUME. Stock string 55 would have come pre-translated but runs to 24 characters in some languages, which doesn't fit the popup, so these are deliberately shorter. Only en.lang defines them so far; the other languages fall back to English until translations are added. Making room for a fifth item turned up three ways to end up in freed memory. list_free() leaves item_count and the items pointer alone, so list_currentItem() could hand back a pointer into the freed array; popMenu_destroy() now clears the struct after freeing rather than changing list_free() for every other consumer. action_saveGame() destroys the popup from inside its own callback and handleUpdateKeystatePopMenu() carried on using the list afterwards. The save state scan thread also called setLoadPreview(), which mutates ListItems and frees SDL surfaces, while the main thread was rendering them; it now publishes plain data only and the preview update happens on the main thread after the join. list_addItem() does no bounds checking either, so the popup allocation grows from four to six.
Copilot AI
added a commit
to Amiga500/Onion
that referenced
this pull request
Sep 9, 2026
…and previews, GameSwitcher favorites + crash fixes, fbmode framebuffer transitions Co-authored-by: Amiga500 <16525337+Amiga500@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Favorites management to the GameSwitcher popup, and fixes several bugs found while extending that menu, including a race that killed the game you had just switched to.
Switching games could kill the game you switched to
Switching games shortly after opening GameSwitcher killed the new game and relaunched it at the boot screen, and exiting from there autosaved over the real state.
resumeGame()writescmd_to_run.shand syncs beforeoverlay_exit()runs, so runtime.sh can start the new game as soon as the old RetroArch process exits.overlay_exit()meanwhile was shutting RetroArch down by name:killall -TERM retroarch, a wait loop pollingpidof retroarch, and a finalkillall -9 retroarchafter the timeout. Neither command distinguishes instances.If the old process exits while that wait loop is still running,
pidofmatches the newly launched instance instead, the loop runs to its full five seconds, and the finalkillall -9takes down the game that just started. BecauseresumeGame()also setsforce_auto_load_state, the relaunch lands at the boot screen.overlay_init() now captures the PID of the RetroArch instance that was running when GameSwitcher opened, and overlay_exit() signals and waits on that PID alone. On the normal captured-PID path, a new instance launched during the handoff is therefore not mistaken for the one being closed. If no PID was captured it falls back to the previous killall behaviour rather than risking leaving RetroArch running.
Favorites
Adds a popup item that adds or removes the current game from
Roms/favourite.json, showingAdd favoriteorRemove favoriteas appropriate. The file is written through a temporary file and renamed into place, so an interrupted write cannot leave a partially written favorites list.Both labels are new strings,
302(remove) and303(add), registered alongsideNEXTandRESUME. Stock string 55 ("Add to favorites") already exists in all shipped.langfiles and would have been translated automatically, but it reaches 24 characters in Dutch and Hungarian and 23 in German and Portuguese, which does not fit comfortably in aLIST_SMALLrow. The shorter wording is deliberate.Only en.lang defines them so far; the other languages fall back to English until translations are added.
Crash fixes
Making room for a fifth popup item exposed three existing lifetime and threading problems.
list_free()leaves stale state behindIt frees the item array but leaves
item_countand theitemspointer unchanged, so a laterlist_currentItem()could return a pointer into freed memory.popMenu_destroy()now clears the struct after freeing it. Fixing this insidelist_free()would have been tidier but changes behaviour for every other consumer, so it is left alone here.Saving from the popup continued using a destroyed list
action_saveGame()destroys the popup from inside its own callback, andhandleUpdateKeystatePopMenu()carried on afterwards and accessed the list that callback had already freed. The handler now stops touching the list once an action has destroyed it.The save-state scan thread modified UI objects
It called
setLoadPreview()directly, which mutatesListItemstate and frees SDL surfaces, while the main thread could be rendering those same objects. The worker now publishes only plain scan results; the preview update happens on the main thread after the join, keeping surfaces andListItems owned by the UI thread.The popup also allocated space for exactly four items and
list_addItem()does no bounds checking, so the allocation grows to six: five in use and one spare.Testing
On device:
Roms/favourite.json, and MainUI reflects the change