# Optional pass height — 2026-10-31-r4

**r5 correction:** the r4 standalone2E20record was outside the excluded Full-bank
profile gap and aliased goalie data. Paired native menu input reproduces this.
r5 moves the combined standalone height/speed record to Light-bank4D20, adds
slot-circle/cold-boot/checksum/goalie-byte tests and retains season locks. The r4
QA below did not cover that alias and must not be read as proving it safe.
See PASS_SPEED_R5.md and current PASS_SPEED_RESULT.json.


## Behavior

Brodeur30 proposed independent pass-only lift and speed controls in forum post
[217609](https://forum.nhl94.com/index.php?/topic/40511-2-guys-one-ai/#comment-217609).
This release implements the lift part as a last main-menu row:
**Pass Height: Normal / Low**. Normal is the default. It uses the original cap12;
Low caps the vertical velocity's integer byte at6. Passes already below that
limit retain their native lift. The fractional byte is preserved in both modes.
This applies equally to both teams, CPU/human and skater/keeper targeted B passes.

The native horizontal intercept solver still uses its original D2 arrival-time
estimate and target prediction. Lowering lift does not recalculate horizontal
speed. It can change time airborne, landing, collisions and pass completion;
these tests do not establish human balance or a completion-rate improvement.
A flips, C shots and blind-pass code remain unmodified by this feature. Independent
pass speed, directional/cone/hold-release controls and rebound models remain open.

## Menu and persistence

The fourteenth row scrolls with the existing menu. Full, Light and Mini each save
their own value. It can be changed before their first completed game; afterwards
both directions are locked, including after reboot and slot changes. Native
exhibition/playoff menus retain a separate editable preference. A missing, corrupt
or unknown record reads Normal, without unlocking other settings or played saves.
Confirmed Abandon Season resets only that season to Normal; other slots survive.

Active RAM is F0DC..F0DD, an unused word between existing native-player count F0DA
and Replay F0DE. Per-season logical SRAM1EEE..1EEF occupies the two-byte gap after
the66-byte EXTRA snapshot and before PC1EF0. Standalone preference2E20..2E21 lies
after the existing CT record in the Full-bank shared-profile gap, outside slot
copies and standalone context. Records50AF/51AE encode Normal/Low plus complement.
The normal bank checksum is updated. Native preferences/password1EF6..1FFF and
all existing settings records retain their formats; no migration unlock is used.

## Hook and source

The helper is `experimental/pass_height.s` at ROM2DE400, with four exported
branches: +0lift, +4mapped load, +8mapped season store, +12menu writer. It fits
below labels2DE800; the builder also checks the preceding replay helper stays
below2DE400 when enabled. New-season clear is in season/slots.s; calls and row
mapping are in replaymenu.s and seasonplayers.s. Tables are in replaymenu.py.

| Site | Previous bytes | Current bytes |
|---|---|---|
| BF5E..BF6F |11C2B776B47C000C6D00000811FC000CB776|4EF9002DE4004E714E714E714E714E714E71|

The hook preserves the native initial byte assignment, compares D2 against12or6,
and resumes exactly at BF70. No D2 modification, horizontal solver, global puck
gravity, shot, actor rating, RNG, controller-owner or general frame hook is added.
Mapped load preserves D0/D1/A0 and entry SR. Season store preserves D0/A0 and
returns into the existing checksum path; it does not promise entry CCR. The
writer retains the native TST D2 row flags contract and season-lock predicate.
Build normally with --version2026-10-31-r4. `--legacy-pass-height --version
2026-10-31-r3` reconstructs the exact previous r3 ROM. Matching source and full
original-to-current hex exports are available on the site's forum tracker.

## Verification and limits

`verify_pass_height.py` executes installed instructions.80paired boundary cases
compare all15registers, SP, complete CCR and the native fractional velocity byte
against exactr3 or a control with only its two old cap bytes changed to6.
64native moving-target solver contexts across baseline/Normal/Low/two invalid
profiles preserve both horizontal velocities, D2arrival estimate and predicted
receiver coordinates. Cases include both directions and skater/keeper passers.

28native controller/menu cases cover ordinary pads and4-Way Play: rendered
Normal/Low values, default, left/right toggles, slot isolation, checksums, cold
boots, existing played-season locks, independent standalone mode and invalid
records. Actual native first-game completion uses an explicit late goal-line
puck fixture, not a fabricated score or completed-game header; it saves Low,
then a real reboot proves the newly played season stays locked. Confirmed
Abandon Season exercises the native reset and preserves another season's choice.

Separate cold-boot co-op games use real directional/B input to make targeted
passes, including human passes with an arrival estimate greater than6. Only a
private observer counter is initialized; no positions, owners, velocities,
settings, clock, RNG or outcomes are injected. A private preserving instruction
probe records the native cap result. This is automated controller input, not a
physical-controller playtest or paired identical match. Actual counts are in
PASS_HEIGHT_RESULT.json. The cap affects integer lift; a nonzero fraction is
expected and is retained, rather than rounded away by the test.

Failed experiments remain private: an early continuation incorrectly targeted
an operand word BF6E; another used scratch RAMF670 that a result routine overwrote.
Both were rejected before release. The persistent F0DC implementation passes the
first-game save/boot lifecycle. Early host assertions and their retained logs
are documented in the result JSON; unsuccessful runs are not qualifications.

All85shared suites execute against one exact ROM/source set.84pass; the inherited
finisher_hold receiver-positioning geometry check remains failed, so the strict
gate remains FAILED. It is not a claim that all earlier AI work is complete.
All40current ordinary600-frame scenes are recorded against fresh exactr3controls;
new dispatch instructions can change HV-counter timing even at Normal. This run
has 27raw-exact scenes and 13with differences. Every divergence is disclosed. The entire previous strict comparison chain runs on fresh parent
controls. Independent rebuild, exactr3rollback, original-base IPS and matched
feature ablations are verified. No Hard win-rate series or strength claim.

## Delivery

The new dated r4basename replaces current ROM/IPS in Downloads, canonical workspace
and website. Bodin receives the identical ROM in his existing playlist when online.
Fresh progress follows the user's release policy; an active RetroArch is never
closed and cleanup waits for its normal exit. Remaps/config/history retain hashes.
See PASS_HEIGHT_RESULT.json and QA_STATUS.json for actual local/remote status;
queued remote delivery is not reported as complete. No forum message was posted.
