feat(runtime): add a title screen idle behavior setting

Merged
TM
21d ago
+1217-23

Summary

Adds a Title screen idle behavior choice to the three launchers (RECOMP_TITLE_IDLE for the runner, saved as title_idle in launcher.json). It sets what the game does when its title screen is left idle:

  • Default: the game's own attract sequence. The runtime changes nothing.
  • No cutscene (no-cutscene): the attract sequence without the movies. The game alternates between the title screen and the real-time volleyball demo, and the title screen stays for 10 seconds instead of 30.
  • CPU Exhibition (cpu-exhibition): after 9 seconds idle at the title screen, Exhibition matches start in which the CPU plays all four girls. Each match has four random girls in random swimsuits on a random court. When a match ends the next one loads with a new cast. START ends the matches and shows the title screen.

This replaces #113 and #114, which offered the same two features as a launch mode and a checkbox. CPU Exhibition is no longer something the game is launched into: startup is the same for all three choices (logos, movie, title screen), and nothing happens until the title screen has been left idle.

Behavior, guest addresses and seams are in docs/title-idle.md.

How it works

title_idle.c reads the setting and wraps the title step's update (0x0006B290) through recomp_lookup_manual. The title scene shown after a match is quit runs the same step, so both title screens are covered.

  • For No cutscene it repoints the jump at the end of the attract step table so the loop never reaches the movie step again, and moves the title's frame counter to its fade at frame 540. This is the code from #114.
  • For CPU Exhibition it calls recomp_cpu_exhibition_start() when the title's frame counter reaches 540 (9 seconds, the same hold No cutscene uses) and the step is not already leaving after START.

cpu_exhibition.c is the code from #113, changed from always on to started and stopped. Once started it runs per presented frame: it ends the title step the way START does, casts a match at the main menu and leaves the menu through the game's own routine at 0x000F2C10, and answers the results menu with Character Select so the next match is cast. START, or a scene the matches never ask for, puts the players back and stops it until the title screen is idle again. The hook on the routine the logos leave through is gone, so the startup movie plays as usual.

Seams: the swap adapter (per frame), one manual lookup entry, and the recomp_dispatch call to 0x000F2C10. The recipe is unchanged.

Verification

  • The runtime ctest suite passes on macOS in a public configure, including title_idle_test.c (three cases) and cpu_exhibition_test.c. tools/public_export.py verify --require-public-tree passes.
  • python -m unittest discover -s tools -p "test_*.py": test_extract_iso.py, with the new test for the saved setting, passes. Twelve tests in test_build_prerequisites.py, test_update_lifter_pin.py and test_build_game.py fail on this Mac; this change does not touch those files, and I did not run them on main to compare.
  • One scripted run on macOS (Apple Silicon, Metal) with CPU Exhibition chosen, against a copy of a save, following logged scene changes: START skipped the logos and the movie, the title screen was left idle, and after 1744 frames (the idle time was 29 seconds for that run; it is 9 now, and the shorter time has a unit test only) the menus showed for two seconds and a match loaded. It ran for about five minutes, returned to the menus, and a second match loaded.
  • The macOS and SDL launchers were built.
  • Not checked: that the second match's cast differed (the run had no screenshots; the cast is drawn at random each time and the unit test covers one draw), the attract sequence's own title screen leading to CPU Exhibition, START ending the matches in a run of the game, No cutscene since it was folded into this setting, the launcher choice on screen in any of the three launchers, sound, and Windows and Linux. The PowerShell launcher change is untested.

Play-tested by hand on macOS and on a Steam Deck (Linux build) after the scripted run; a launcher screenshot and a video of CPU Exhibition are in the comments below. The "not checked" list above describes the scripted run only. Windows has not been run.

Touches the same launcher lines as #112; whichever lands later needs a small rebase.

Contribution checklist

  • The change follows AGENTS.md and CONTRIBUTING.md.
  • No XBE, generated game C, retail instruction bytes, extracted assets or
    filenames, saves, BIOS data, private paths, or run evidence are included.
  • Third-party material and its license are identified, if applicable.