MMCE art ordering: 1-frame COV head start replaces covPreempts drop#8
Merged
NathanNeurotic merged 10 commits intoincebtion-round-fourfrom Mar 19, 2026
Merged
Conversation
…g slash in prefix, allow queueing while aborting Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix MMCE art loading issues on device page
Fix MMCE art loading: remove blocking stat I/O, normalize prefix slash, allow queue during abort
Mar 18, 2026
… SPI channel Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix MMCE art loading: remove blocking stat I/O, normalize prefix slash, allow queue during abort
Fix MMCE art loading stall: remove double-attempt fallback, normalize prefix slash, allow queue-while-aborting
Mar 18, 2026
NathanNeurotic
approved these changes
Mar 18, 2026
… wait loops Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot stopped work on behalf of
NathanNeurotic due to an error
March 18, 2026 05:08
Copilot
AI
changed the title
Fix MMCE art loading stall: remove double-attempt fallback, normalize prefix slash, allow queue-while-aborting
texcache: yield to MMCE art thread during abort/wait loops to prevent fileXio corruption
Mar 18, 2026
After cacheEnd(1) calls TerminateThread on the art worker, the cache entry for the in-flight MMCE request stayed in CACHE_ENTRY_LOADING with entry->qr pointing to the just-freed request struct. Two problems followed: 1. The slot was never eligible for LRU eviction (LOADING is excluded from the victim selector), so the cache shrank by one usable slot per force-terminate cycle. After enough browsing, slots ran out and art stopped loading. 2. Future cacheInvalidateEntryLocked calls dereferenced the dangling entry->qr when calling cacheIsAbortableMmceRequest — use-after-free that produced random results, explaining art "loading randomly between titles". Fix: call cacheClearItem(req->entry, 0) before cacheFreeRequest(req) in the cacheEnd cleanup block. This returns the slot to CACHE_ENTRY_FREE, nulls entry->qr, and makes it available to the LRU pool again. freeTxt=0 is correct because entry->texture.Mem is always NULL during loading (the displaced texture lives in req->displacedTexture and is freed by cacheFreeRequest). Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
texcache: yield to MMCE art thread during abort/wait loops to prevent fileXio corruption
Fix stale LOADING cache entry / use-after-free after TerminateThread in cacheEnd
Mar 18, 2026
Two bugs caused "navigation clogged consistently / art barely loaded": 1. menuLoadConfigDirectInternal (menusys.c) cacheAbortMmceImageLoadsTimed(60) blocked the main thread for up to 60 ms on every CROSS/CIRCLE press (game launch / settings). When the abort timed out, cacheEnd(1)+cacheInit() added another ~240 ms AND called TerminateThread on the art worker mid-fileXio read, corrupting the fileXio RPC channel for the rest of the session. Fix: call cacheAbortMmceImageLoadsTimed(0) instead – this signals the abort (sets abortRequested, drops queued MMCE requests, wakes the worker) without any blocking wait or cacheEnd. The MMCE config read that follows is simply serialised behind the in-flight art chunk in the IOP queue (typically ≤ 20 ms extra at normal card speeds). 2. mmceLoadGame (mmcesupport.c) MMCE_ART_ABORT_WAIT_TICKS = 60 ms was barely one read-chunk's worth of time on a slow card (~40 ms/chunk at 100 KB/s), so TerminateThread was called frequently, corrupting fileXio and preventing all subsequent art loads. Fix: raise the timeout to 500 ms – 30+ chunk-reads of headroom even on very slow cards – so TerminateThread becomes a true last resort. Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix stale LOADING cache entry / use-after-free after TerminateThread in cacheEnd
Fix MMCE navigation freeze and art-loading degradation over session
Mar 18, 2026
…gate gMmceMainPageBrowseOnly caused drawGameImage to call cacheGetTextureIfReady (no queue) for all non-COV art on the MMCE main list page, so Background, Screenshot and other textures were only ever loaded when the user visited the game info page (where thmSetMmceMainPageBrowseOnly(0) cleared the flag). The texcache already limits MMCE interactive requests to one in flight at a time (texcache.c lines 1404-1416): if a request for a different value/cache is queued it is dropped and replaced; if one is already active or queued for the same game, cacheGetTexture returns NULL and retries on the next frame. This natural serialisation is sufficient -- the themes-layer restriction is not needed and causes the observed symptom. Remove gMmceMainPageBrowseOnly entirely: - src/themes.c: drop static flag, drop thmSetMmceMainPageBrowseOnly(), simplify drawGameImage to always use getGameImageTexture() - src/menusys.c: remove both thmSetMmceMainPageBrowseOnly() call-sites - include/themes.h: remove function declaration After this change, Cover loads first (first drawGameImage call per frame), then Background, Screenshot, etc. load sequentially in subsequent frames as the worker finishes each piece -- all without visiting the info page. Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix MMCE navigation freeze and art-loading degradation over session
Fix MMCE art load regression: navigation freeze, session-wide art failure, and non-Cover art never loading on main page
Mar 18, 2026
… art-type change The MMCE throttle drop condition in cacheGetTextureInternal was: (queuedMmceReq->cache != cache || strcmp(queuedMmceReq->value, value) != 0) COV, BG, SCR each use a different cache pointer but share the same value (game startup ID). In a single render frame for an uncached game: 1. COV queues its request 2. BG: different cache -> DROP COV, queue BG 3. SCR: different cache -> DROP BG, queue SCR Only SCR ever loaded. Each drop also evicted an LRU slot, freeing its displaced texture via the cleanup queue. On second pass this cascade of evictions trashed the entire cache built on the first pass: art stopped loading and the IOP was overloaded with constant eviction/cleanup work, causing the observed "navigation clogged, art not loading" regression. Fix: drop the queued request only when the GAME changes (different value), not when only the ART TYPE changes (different cache, same value): strcmp(queuedMmceReq->value, value) != 0 With this fix, same-game art types serialize correctly: COV queues first; BG and SCR see the queued request (same value -> no drop) and wait. After COV loads, BG queues; SCR waits. After BG loads, SCR queues. No evictions, no cache thrash. On a different-game request the old game's pending art is still properly dropped, and cacheAbortMmceImageLoadsTimed continues to flush all queued MMCE requests on context changes (info page, game launch). Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix MMCE art load regression: navigation freeze, session-wide art failure, and non-Cover art never loading on main page
Fix MMCE art: all types load on main page; fix cascading-drop cache thrash on second pass
Mar 18, 2026
Copilot stopped work on behalf of
NathanNeurotic due to an error
March 18, 2026 18:38
Background (main0) draws before ItemCover (main5) each frame, so BG always queued first under the MMCE serial throttle. When BG art does not exist on the card, open() can take 100-500 ms to fail, serialising Cover art behind every slow BG miss. After ~7 such navigations the user perceives navigation clogs and art not loading. Extend the drop condition in cacheGetTextureInternal: a COV request now also drops a same-game queued non-COV (BG/SCR) request so Cover art always loads first. The existing cacheHasQueuedInteractiveModeLocked guard prevents BG/SCR from re-queuing while COV is queued or active, avoiding the cascade eviction that the original cache!=cache condition caused. Load order: COV -> BG -> SCR. Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix MMCE art: all types load on main page; fix cascading-drop cache thrash on second pass
Fix MMCE art clog: COV preempts queued non-COV for same game
Mar 18, 2026
The covPreempts fix (c6f8bbe) caused "mostly missing" art: it dropped the queued BG request every time COV came in, so when COV didn't exist on the card its slow open() failure (100-500 ms) blocked all other art types. Users with BG/SCR but no COV saw art constantly reset before it could appear. Instead, give Cover art a 1-frame inactivity head start over non-COV art types in MMCE mode. The default theme draws Background (main0) before Cover (main5) each frame; after each navigation guiInactiveFrames resets to 0 and counts up, so: - frame 8: COV's delay (8) satisfied -> COV queues - frame 9: BG/SCR delay (8+1=9) -> MMCE throttle blocks them (COV is already in-flight) BG/SCR are never dropped and never have to wait for a COV failure. If COV loads fast (file exists), users see it immediately; BG/SCR follow naturally afterwards. If COV is missing, BG queues as soon as COV fails, with no extra penalty beyond one frame. Also revert the MMCE throttle drop condition to the simpler game-change- only rule from 0b93ffc: drop only when the queued request is for a different game (value mismatch), not when the art type changes. The new delay makes the covPreempts eviction unnecessary. Co-authored-by: NathanNeurotic <109461996+NathanNeurotic@users.noreply.github.com>
Copilot
AI
changed the title
Fix MMCE art clog: COV preempts queued non-COV for same game
MMCE art ordering: 1-frame COV head start replaces covPreempts drop
Mar 18, 2026
Copilot stopped work on behalf of
NathanNeurotic due to an error
March 19, 2026 00:31
Copilot stopped work on behalf of
NathanNeurotic due to an error
March 19, 2026 09:19
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.
menuInvalidateArtSelectionandmenuAdvanceArtSelectionOnMoveto preserve READY/PRIMED art for MMCE mode on navigation (matching APP mode behaviour)📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.