feat(runtime): add a CPU Exhibition launch mode

Draft
TM
21d ago
+806-42

Summary

Adds a CPU Exhibition button to the three launchers (RECOMP_CPU_EXHIBITION=1 for the runner, or ./run_game.sh --cpu-exhibition). It starts Exhibition matches in which the CPU plays all four girls, one match after another, so the game can be left running. It is off by default, and with it off the runtime changes nothing.

  • Cast: four different girls chosen at random for each match, each in a swimsuit chosen at random from all the suits she can wear (307 of the 328), on one of the ten Exhibition courts chosen at random.
  • Matches: a full 7 point match under the game's own rules. When it ends, the results stay up for five seconds and the next match loads with a new cast.
  • No input: the logos play, then the opening movie and the title are each left after a second. No controller is needed. The mode lasts until the game is closed.
  • Saves: nothing is added to a save; the swimsuits are only worn for the match.

Behavior, guest addresses and seams are in docs/cpu-exhibition.md.

How it works

cpu_exhibition.c runs once per presented frame and stores the requests the game stores for itself:

  • Title and attract sequence: it stores one frame left in the byte START sets, so the game's own sequence code ends the step.
  • Menus: it marks the four players as the CPU's, fills in character select's four choices and court, stores the menu's start exit code and calls the game's own "leave for screen" routine (0x000F2C10). The menu's callback then copies the choices to the match as it does when character select is confirmed.
  • Results: it ends the results menu's wait and answers it with Character Select, which returns to the menus for the next match.

Seams: the swap adapter (per frame), and one call into a generated game routine through recomp_dispatch with the guest registers and FPU state saved around it. That call is what makes the main menu clear itself from the screen; it is recorded in the doc page. No game function is replaced and the recipe is unchanged.

The launchers pass the choice without saving it: the PowerShell launcher sets the variable, and the macOS and Linux launchers exit with 3 instead of 0, which launcher.sh and run_game.py turn into the variable.

Verification

  • python -m unittest discover -s tools -p "test_*.py", tools/public_export.py verify --require-public-tree, and the runtime ctest suite pass on macOS (25 of 25, including the new cpu_exhibition_test.c: the title, menu and results steps on synthetic guest memory, and that the cast is four different girls in swimsuits each can wear). The tools tests now cover run_game.py passing the variable.
  • Scripted runs on macOS (Apple Silicon, Metal) with no input, against a copy of a save: a match was on screen about 30 seconds after the game started, with no menu left over it. In a ten minute run the first match was played to 7 points with rallies, replays and the match point banner; its results showed, and a second match started on another court with another cast.
  • Save storage was byte-identical after a 400 second run.
  • The macOS and SDL launchers were built; the SDL launcher's new row was checked in a screenshot.
  • Not checked: sound (runs were muted), sessions longer than ten minutes, a controller pressed during a match, and Windows and Linux. The PowerShell launcher change is untested. It has not been play-tested.

Draft until it has had a play test.

Touches the same launcher lines as #112; whichever lands second 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.

Summary by cubic

Adds an opt-in CPU Exhibition mode that runs endless Exhibition matches with the CPU on all four sides, no controller needed. It is off by default; when disabled, runtime behavior is unchanged.

The mode starts from the launcher's new CPU Exhibition button in the PowerShell, Swift, and SDL launchers, from RECOMP_CPU_EXHIBITION=1, or from ./run_game.sh --cpu-exhibition.

  • Each match uses four random girls, each in a random swimsuit she can wear (307 of 328), on a random Exhibition court.
  • The runtime (cpu_exhibition.c) stores the same requests the game stores for itself: it skips the opening movie by leaving the logos into the title, leaves the title and attract screens after a second, fills character select's choices, closes the main menu through the game's own routine, and answers the results menu with Character Select after showing results for five seconds.
  • START on any controller ends the mode; during a match it quits to the title and the game is played as usual from there.
  • Nothing is written to save data; swimsuits are match-only.
  • Adds docs/cpu-exhibition.md documenting the guest contract and seams, plus cpu_exhibition_test.c and launcher tests.

Notes

  • Not yet play-tested, so the PR remains a draft.
  • Sound, sessions longer than ten minutes, and Windows/Linux were not checked; the PowerShell launcher change is untested.