Skip to content

fix(gui): land in-flight screen transitions under message boxes and wait screens - #359

Open
NathanNeurotic wants to merge 1 commit into
masterfrom
fix/msgbox-stale-background
Open

fix(gui): land in-flight screen transitions under message boxes and wait screens#359
NathanNeurotic wants to merge 1 commit into
masterfrom
fix/msgbox-stale-background

Conversation

@NathanNeurotic

@NathanNeurotic NathanNeurotic commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Addresses zackcage6's repeated report: error/notice message boxes show the previous frame as their background.

Cause

guiMsgBox and guiRenderTextScreen draw their background with guiShow(), which renders the current screenHandler. During a screen transition (the 26-frame cross-fade after guiSwitchScreen), guiShow() deliberately renders the old, fading-out screen for the first half. So a box raised right as a transition begins — exactly when errors tend to fire (pick a game → transition → launch fails) — sits on the previous screen for ~13 frames.

Verified the main screen otherwise repaints its own background every frame (menuRenderMain → theme background element), so guiShow() is not itself a stale-frame source outside a transition.

Fix

guiSnapTransition() completes any in-flight transition to its destination before the box renders — the same state assignments guiShow() makes when a fade finishes naturally. One file, +29 lines. The input-freeze release timing shift it introduces is benign (documented inline; the box consumes its own edge-triggered dismiss).

Deliberately out of scope

The other 'wrong background' shape — a box raised from a settings flow rendering the main screen instead of the dialog behind it — is not handled here. I prototyped it (record the active dialog, render it under the box) and adversarial review caught that it reintroduces the #154 dangling-enum landmine: the deferred error hook fires after the dialog's guiShowXxx setup returns and its stack-local enum arrays die, so rendering that dialog then dereferences freed stack (confirmed reachable via Network → Reconnect → sync eth re-init failure). A safe version requires making the affected dialog enum arrays static first — a separate change, only if the transition snap doesn't fully cover the report.

Separate from the #340 input work. HW test pending.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed screen transitions behind message boxes and text wait screens.
    • Modal content now appears immediately on the destination screen without displaying transitional frames.

…ait screens

Error boxes and blocking wait screens (guiMsgBox, guiRenderTextScreen)
draw their background with guiShow(), which during a screen transition
renders the OLD, fading-out screen for the first ~13 frames of the
26-frame fade -- so a box raised right as a transition starts sits on
the previous screen ('error messages always have the previous frame as
their background', zackcage6). Snap any in-flight transition to its
destination before the box's render loop, using the same assignments
guiShow() makes when a fade completes naturally.

Scope note: the other 'wrong background' shape -- a box raised from a
settings flow showing the main screen instead of the dialog behind it --
is deliberately left alone. The deferred error hook (errorMessageHook)
fires after the dialog's setup function has returned and its stack-local
enum arrays have died, so rendering that dialog then would dereference
freed stack (the #154 dangling-enum landmine). A safe version of that
needs the affected dialog enum arrays made static first; separate change
if the transition snap does not fully cover the report.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The GUI now completes an active screen transition before it renders a message box or text wait screen. The new helper promotes the transition target to the current screen and cancels the fade.

Changes

Screen transition snapping

Layer / File(s) Summary
Snap transitions before special screens
src/gui.c
Added guiSnapTransition() and called it from guiMsgBox() and guiRenderTextScreen() before rendering.
Estimated code review effort: 2 (Simple) ~10 minutes
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes fixing in-flight screen transitions before message boxes and wait screens render.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/msgbox-stale-background

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/gui.c`:
- Around line 2774-2781: Update guiSnapTransition so that, when
screenHandlerTarget is set and before clearing it, it calls
padFreezeEdgeBaseline(0) to release the pad edge-freeze state. Preserve the
existing handler swap, target reset, and transition-index reset behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 145ef1ff-6014-4734-b024-79cd1457c850

📥 Commits

Reviewing files that changed from the base of the PR and between 7e6dbbe and eb099bd.

📒 Files selected for processing (1)
  • src/gui.c
📜 Review details
⏰ Context from checks skipped due to timeout. (20)
  • GitHub Check: build-variants (EXTRA_FEATURES=1, PADEMU=1)
  • GitHub Check: build-variants-ps2dev-latest (EXTRA_FEATURES=1, PADEMU=1)
  • GitHub Check: build-debug-ps2dev-latest (iopcore_ppctty_debug)
  • GitHub Check: build-debug (eesio_debug, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95d9d35be995)
  • GitHub Check: build-debug-ps2dev-latest (iopcore_debug)
  • GitHub Check: build-debug (ingame_ppctty_debug, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95d...
  • GitHub Check: build-variants-ps2dev-latest (EXTRA_FEATURES=0, PADEMU=1)
  • GitHub Check: build-debug (iopcore_debug, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95d9d35be...
  • GitHub Check: build-variants-ps2dev-latest (EXTRA_FEATURES=0, PADEMU=0)
  • GitHub Check: build-debug-ps2dev-latest (DTL_T10000=1)
  • GitHub Check: build-variants-ps2dev-latest (EXTRA_FEATURES=1, PADEMU=0)
  • GitHub Check: build-debug-ps2dev-latest (eesio_debug)
  • GitHub Check: build-variants (EXTRA_FEATURES=0, PADEMU=1)
  • GitHub Check: build-debug (DTL_T10000=1, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95d9d35be995)
  • GitHub Check: build-debug (iopcore_ppctty_debug, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95...
  • GitHub Check: build-variants (EXTRA_FEATURES=1, PADEMU=0)
  • GitHub Check: build
  • GitHub Check: build-variants (EXTRA_FEATURES=0, PADEMU=0)
  • GitHub Check: build-debug (ingame_debug, @sha256:c64ae69c9817865ed98ff054e4ae5360b9e280ed952c97946bca95d9d35be995)
  • GitHub Check: build-ps2dev-latest
🔇 Additional comments (2)
src/gui.c (2)

2926-2933: LGTM!


3067-3070: LGTM!

Comment thread src/gui.c
Comment on lines +2774 to +2781
static void guiSnapTransition(void)
{
if (screenHandlerTarget) {
screenHandler = screenHandlerTarget;
screenHandlerTarget = NULL;
transIndex = 0;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  '\b(guiSnapTransition|screenHandlerTarget|screenHandler|transIndex|padFreezeEdgeBaseline)\b' \
  . --glob '*.c' --glob '*.h'

Repository: NathanNeurotic/Open-PS2-Loader

Length of output: 15764


🏁 Script executed:

#!/bin/bash
set -euo pipefail

wc -l src/pad.c src/gui.c include/pad.h
sed -n '140,180p' src/pad.c
sed -n '2,30p' include/pad.h

Repository: NathanNeurotic/Open-PS2-Loader

Length of output: 2005


Snap also clears the pad edge-freeze state.

guiShow only releases padFreezeEdgeBaseline() in guiReadPads() after screenHandlerTarget is cleared. If guiSnapTransition() occurs mid-transition, guiMsgBox() and guiRenderTextScreen() can start with input frozen on the destination screen. Update padFreezeEdgeBaseline(0) in the snap path while screenHandlerTarget is still set.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui.c` around lines 2774 - 2781, Update guiSnapTransition so that, when
screenHandlerTarget is set and before clearing it, it calls
padFreezeEdgeBaseline(0) to release the pad edge-freeze state. Preserve the
existing handler swap, target reset, and transition-index reset behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant