# Icing switch and Edmonton defaults — 2026-10-30-r5

jdc requested an Icing switch at the bottom of the start menu and Edmonton as
the default club, and explicitly confirmed **Icing On by default**.

## Behavior

The new logical row24 is below Auto Replays and Crit Shots. Its native On/Off
value is visible immediately, aligns with the other values and redraws after
Left/Right. It works with ordinary two-pad and 4-Way Play menu tables. Icing
locks like the ordinary match settings after the first completed season game;
Players and Auto Replays keep their established exceptions. Crit retains its
separate existing lock. Each Full/Light/Mini format keeps its own Icing choice.

Fresh boot uses Edmonton (native club10). Creating a previously empty format
or explicitly restarting a season also selects Edmonton and Icing On. The user
can still choose another club before starting. Existing ongoing seasons retain
their saved club; default initialization does not change their ownership.

## Code and storage

- `experimental/replaymenu.py` / `.s`: thirteen native rows, extra label and
  On/Off offset, both count tables, scroll bounds and full redraw through row24.
  Labels at2DE800; values2DE900; counts2DEF00/2DEF20. Row24 maps to **FFF0EE**,
  a new reserved word (0 On,1 Off). Hidden native User Records **D054 stays Off**.
- `experimental/icing.s`: **24 bytes at2DBA00**. At **101EE**, original bytes
  `30 3C 00 0C 61 00 1D 38` become `4E F9 00 2D BA 00 4E 71`.
  Only the already-qualified native touch-icing award is gated. On still calls
  AddPenalty11F2C with event0C. Off returns through native101F6, preserving the
  caller's saved actor pointer and stack. No global frame or physics hook.
  Native candidate arming, crossed-goal-line logic, goalkeeper/attacker touch
  exemptions and short-handed eligibility are unchanged.
- `experimental/seasonplayers.s`: **U** record in per-slot logical SRAM1FF6–1FFD.
  The five original enums remain at1FF7..1FFB; XOR at1FFC now also covers the
  new Icing byte1FFD. CRC1FFE/1FFF remains native. Old **S/T** records validate
  under their original XOR and load Icing On. Invalid/missing records default
  to On while retaining the existing played-season lock and old-setting recovery.
  Match Start captures the choice before native settings normalization.
- `experimental/build_test.py`: startup HOME word **17C92**,001E→000A.
  `season/slots.s` initializes Edmonton and Icing On only when clearing a new
  or explicitly restarted format. `season/build_season.py --menu-settings`
  emits that optional feature. Normal current builds enable it.
- `--legacy-icing-menu --version 2026-10-30-r4` reproduces the exact r4 image.
  This rollback flag disables the entire r5 menu/rule/defaults addition.

## Tests and limits

**All72 shared suites executed;71 pass.** The only retained failure is the
selected38-win base's `finisher_hold` geometry: native1.9046278288761302 versus
held2.777268439788352, early one-timers2vs2 and four unchanged Normal/Easy controls.
The strict gate remains **FAILED**; no new qualification or strength claim.

`verify_icing_menu.py` covers **34 cases**: actual native value-renderer calls
and screenshots, both adapters, both toggle directions, top/bottom scrolling,
On and Off in locked seasons, independent saved formats, first native Start
capturing Off, cold boots, old S/T records, corrupt U values/checksums, fresh
Edmonton defaults, manual selection, new-format defaults and a saved other club.
`verify_icing_rule.py` covers **56 synthetic native rule fixtures**, calling real
a2touchpuck1013E and AddPenalty and observing the native event queue. Both teams,
both ends, On/Off, goalkeeper/attacker touches, no candidate, no goal-line cross,
short-handed and even-strength arming are exercised. All28 On cases match r4's
native registers, CCR, stack, flags and event-buffer output exactly. These are
rule fixtures, **not independent matches or natural human reproductions**.

The maintenance guard declares the menu/settings/award ROM regions. All40
current default-On no-B scenes (24000 frames) match40 fresh r4 and40 fresh r3
controls;40 fresh r2 controls reproduce the immutable original traces. Historical
keeper/input guards are retained separately. A native full CPU game, all season
migration/restart/playoff checks and seven two-match controller lifecycles pass.

The initial full diagnostic run retained three obsolete assumptions: navigation
counts from the previous default club, duplicate club choices in fresh formats,
and a movement check that could occur during a natural stoppage. Inputs now
select distinct clubs explicitly; movement is verified in actual live skater
windows, with interrupted windows recorded and bounded retries. The playoff
fixture advances native variable-length postgame screens through real inputs,
retaining its strict bracket/password assertions. Failed logs remain private.
A complete second72-suite run repeats the current ROM. A final source-only
correction restores the historical eleven-row installer branch; the current
installer and emitted r5 ROM are unchanged. Its isolated legacy build and the
current menu checks are verified separately, and the report records the
source-manifest refresh explicitly.

An independent rebuild, byte-exact r4 rollback and IPS reconstruction from the
original base all pass. Original MD5:8f863ecb108c1d213953bada9b98f4f2.
ROM SHA256:a7e8bef0e8c78da6d37eacb432769af3f6d4b99e0196e451875c7991656ca182; CRC32:33894753.
Fresh progress is required for this release; controller config/remaps and history
are retained under the standing release policy. The faceoff alignment report
remains open. Hard investigation remains stopped.

Native rule analysis was cross-checked against the primary disassembly:
https://github.com/Chaos81/nhl94-disassembly/blob/main/nhl94.bin.lst
