# Finished seasons are results, not extra matches — 2026-10-26

Completed Full/Light/Mini slots now say **See Old Full Season**, **See Old Light
Season** or **See Old Mini Season**. The Team row shows the saved club and the
Game row says **Season finished**. There is no editable fixture and Start opens
the saved all-team statistics, then Scoring Leaders. This replaces the misleading
Continue label and prevents an extra game, including Winnipeg vs Winnipeg.

After leaving Scoring Leaders, choose See Results Again, Start New [slot] Season
or Back to Main Menu with Up/Down and Xbox B/Start. Starting a new season uses
the existing Xbox X+B confirmation convention; Start cancels. Only the selected
slot is reset. Back in New Season, choose the new club normally. Other seasons
remain intact. Viewing/cancelling does not change any battery byte.

## Cause

The user's current Mini was Edmonton,8/8, champion flag4; Full was also a
completed championship. Previously force returned a completed season to a free
native Regular Season menu, while dispsel still called it Continue Mini and
Game used stale NEXTK/NEXTOPP. Native Start still launched an unrecorded game.
Free club changes could therefore leave the same club in Home and Away. r30
fixed only stale Team text; it did not make that terminal flow correct.

## Source and memory map

- `experimental/finished.s` / `.py`:1104 bytes at2E6000..2E644F. Export +0 main
  Start, +4 isfinished, +8 completed label, +12 Game text, +16 completed lock.
  `build_test.py` installs it. The check uses stack scratch, validates season
  view, SESN, saved club, no pending reset, games>=length, flag>=3. Native modes
  outside the season view and live/new seasons pass through unchanged.
- Hook F843E replaces the first8 bytes of native Start, before17AC8 saves
  settings. Non-completed modes replay both displaced instructions and jump
  F8446. Completed modes go directly to results, preserving every battery byte.
- `season/seasonmenu.s`:1966 bytes at2F9800..2F9FAD. Check completed slots before
  native playoff-mode handling; FORCED=4, SELV=1, saved club in USERW/Home. The
  completed menu blocks fixture/player edits but still permits slot changes.
  New/active games retain their normal schedule and input paths. Old native
  playoff mode values cannot reopen the completed season as another match.
- `experimental/seasonend.s`:3926 bytes at2E3000..2E3F55. New +8 export opens
  players without classifying or resimulating a completed season. Start-release
  waits for both pads; a held P2 Start previously could skip Scoring Leaders.
  Column alignment, empty footer row, orange sorting and Xbox B help remain.
- Menu-only SEL word FFE3FC selects the completed-season actions. Header/team/
  string scratch reuses the existing results buffers. No SRAM format change.
  Reset uses the existing slots.s +12; no duplicated save-layout logic.

## Verification and delivery

`verify_finished_season.py`:9 native cold-boot flows (three formats x
eliminated/champion/missed),108 checkpoints. Both pads browse/sort, enter
leaders and leave them; restart is cancelled once and then confirmed. Review
and cancel leave all65536 battery bytes identical. Confirm clears only the
active season; all three snapshot banks are byte-identical. Each test then
selects Winnipeg and starts the real first game: Winnipeg vs Columbus, not
itself. Header/checksum, native on-ice clubs and initialized sprites verified.

`verify_menu_team.py`:18 cases /240 checks, including completed owner locks,
all32 new-season choices and active away/co-op teams. Existing season navigation
12 cases /228 checks and browser347 checks pass. Actual user's Mini results
captured through the unmodified ROM with byte-identical SRAM. Fresh state9 is
captured from that real production entry, replacing the old code-position
preview; normal launch starts at the main menu.

Exact source rebuild, guarded3547-byte diff (menu/hooks/results/finished module,
title/checksum), no private probes and original-base IPS reconstruction pass.
2026-10-26 replaces2026-10-25-r30 in canonical, Downloads, site ROM+IPS and
Bodin's same current item. Saves/remaps carry across the date change; no extra
backups. Documentation/source and homepage are updated together.

SHA256:ac1ef1aebc902d14e2df44de23940df13f7a37ab830daee434f46dee222feef5.
CRC32:1F36E9AF. Private evidence:`work/finished-season-20261025-235908/`.

```sh
python3 tools/experimental/verify_finished_season.py /private/test.bin \
  /private/finished-tests --seed /private/current.srm
```

## Start Game hung after viewing season results (2026-10-26-r3)

jdc: deleted the finished Mini, started a new one (Edmonton vs Montreal) and the game hung
when starting the match. Reproduced from his pre-delete save in one session: See Old Mini
Season -> results/leaders -> Start New Mini Season (X+B) -> Game row to MTL -> Start ->
"Resume Game" pre-game menu, period 0 / 5:00, frozen; from a cold boot of the deleted
save the same match starts. Cause: replay.s kept its state in $FFF738.. (crowd block),
which the results/leaders/team-stats screens overwrite with text; a stale nonzero ARST made
the pad hook at $A41E (also used by the pre-game/pause menus) feed scripted input, so the
menu never saw the player's buttons. Fix: replay states are $A500..$A506 (anything else is
idle, the pad hook scripts only $A502..$A506), and crowd.s valid() (first frame of every
game) clears onetimer PEND $FFF736, replay $FFF738..$FFF73F and trail HN/HT/TL
$FFF630..$FFF635 (stale afterglow could have drawn flames from menu text).
Same flow now starts Montreal vs Edmonton and the clock runs. verify_finished_season 9/108,
verify_menu_team 18/240, verify_season_navigation 18/342, verify_goalie_request 41,
verify_critical_flash PASS; auto replay still runs ($A502..$A506).
Rule: never keep in-game state in $FFF100..$FFF7FF without a magic/validity check and a
reset at game start: menus use it as scratch.
SHA256 b6fb71635631a24f1c84c81a4802ff0ccfc821e891cb42ae63a5fe9a2c359239, CRC 4009ADA6.

