    .ifndef WITH_REFINEMENTS
    .equ WITH_REFINEMENTS,0
    .endif
| Optional additional shootout rules. Default Off. No normal-match frame hook.
| Native available skaters rotate before repeats; continuous full turns are misses.
| Full native participant loading, attempts, scoring and keeper paths remain native.
    .include "season-symbols.inc"
    .equ VALUE,0xFFFFF046
    .equ MAGIC,0xFFFFF820
    .equ HOME,0xFFFFF822
    .equ AWAY,0xFFFFF826
    .equ LIMIT,0xFFFFF82A
    .equ LASTACTOR,0xFFFFF82C
    .equ LASTDIR,0xFFFFF82E
    .equ ROTATION,0xFFFFF832
    .equ TEAMS,0xFFFFF836
    .equ INFO,0xFFFFF83E            | packed roster counts5+5bits, keeper counts3+3bits
    .equ CHECK,0xFFFFF83A
    .equ INVERSE,0xFFFFF83C
    .text
    .globl _start
_start:
    bra.w capture
    bra.w setup
    bra.w spin
    bra.w fresh
    bra.w load
    bra.w put
    bra.w reset
    bra.w pick

| D0=1 only for the shootout this block was captured from. No RNG or writes.
valid:
    moveq #0,%d0
    cmpi.w #1,VALUE
    bne.s invalid
    cmpi.w #1,0xFFFFF090
    bne.s invalid
    btst #0,0xFFFFC2FA
    beq.s invalid
    cmpi.w #0x5355,MAGIC
    bne.s invalid
    move.l TEAMS,%d0
    cmp.l 0xFFFFC330,%d0
    bne.s invalid
    move.w CHECK,%d0
    not.w %d0
    cmp.w INVERSE,%d0
    bne.s invalid
    bsr.w checksum
    cmp.w CHECK,%d0
    bne.s invalid
    cmpi.w #1,LIMIT
    bcs.s invalid
    cmpi.w #26,LIMIT
    bhi.s invalid
    moveq #1,%d0
    rts
invalid:
    moveq #0,%d0
    rts

| Eight static words, excluding actor plus two full16.16 mutable turn longs. D0 sum, A0/D1 scratch.
checksum:
    moveq #0,%d0
    lea HOME,%a0
    moveq #4,%d1
sum_first:
    add.w (%a0)+,%d0
    dbra %d1,sum_first
    lea TEAMS,%a0
    moveq #1,%d1
sum_second:
    add.w (%a0)+,%d0
    dbra %d1,sum_second
    add.w INFO,%d0
    rts

| A2 real club stats. D0 eligible32-bit mask, D1 count, D2 roster size, D3 keepers.
| The native game has injury states -3/-4 but no NHL misconduct-type exclusion.
mask:
    move.l 0x1E(%a2),%d0
    cmpi.l #0x200,%d0
    bcs.w bad_mask
    cmpi.l #0x300000,%d0
    bcc.w bad_mask
    move.l %d0,%d5                  | require the actual current club header, not a stale foreign pointer
    lea 0xFFFFC330,%a0
    cmpa.w #0xC6CE,%a2
    beq.s keeper_team
    cmpa.w #0xCA32,%a2
    bne.w bad_mask
    addq.w #2,%a0
keeper_team:
    moveq #0,%d0
    move.w (%a0),%d0
    cmpi.w #31,%d0
    bhi.w bad_mask
    lsl.w #2,%d0
    lea 0x30E,%a0
    cmp.l (%a0,%d0.w),%d5
    bne.w bad_mask
    lea GK_TAB,%a0
    .if WITH_TRANSFERS
    jsr 0x23602C
    .endif
    moveq #0,%d4
    move.b 2(%a0,%d0.w),%d4         | actual roster-derived keeper count, independent of historical header discrepancies
    cmpi.w #1,%d4
    bcs.w bad_mask
    cmpi.w #4,%d4
    bhi.w bad_mask
    jsr 0x9F9A
    cmpi.w #26,%d0
    bhi.w bad_mask
    cmp.w %d4,%d0
    bls.w bad_mask
    move.w %d0,%d5
    move.w %d4,%d3
    moveq #0,%d1
    moveq #0,%d2
mask_next:
    move.w %d3,%d0
    add.w %d0,%d0
    move.w 0x66(%a2,%d0.w),%d0
    cmpi.w #-3,%d0
    beq.s mask_skip
    cmpi.w #-4,%d0
    beq.s mask_skip
    bset %d3,%d2
    addq.w #1,%d1
mask_skip:
    addq.w #1,%d3
    cmp.w %d5,%d3
    bcs.s mask_next
    move.l %d2,%d0
    move.w %d5,%d2
    move.w %d4,%d3
    rts
bad_mask:
    moveq #0,%d0
    moveq #0,%d1
    moveq #0,%d2
    moveq #0,%d3
    rts

capture:
    move.w %sr,-(%sp)
    cmpi.w #1,VALUE
    bne.w capture_restore
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    clr.w MAGIC
    cmpi.w #1,0xFFFFF090
    bne.w capture_done
    btst #0,0xFFFFC2FA
    beq.w capture_done
    cmpi.w #31,0xFFFFC330
    bhi.w capture_done
    cmpi.w #31,0xFFFFC332
    bhi.w capture_done
    move.l 0xFFFFC330,TEAMS
    lea 0xFFFFC6CE,%a2
    bsr.w mask
    move.l %d0,HOME
    move.w %d2,INFO
    lsl.w #8,%d3
    lsl.w #2,%d3
    or.w %d3,INFO
    move.w %d1,%d6
    lea 0xFFFFCA32,%a2
    bsr.w mask
    move.l %d0,AWAY
    lsl.w #5,%d2
    or.w %d2,INFO
    lsl.w #8,%d3
    lsl.w #5,%d3
    or.w %d3,INFO
    cmp.w %d6,%d1
    bcc.s common_limit
    move.w %d1,%d6
common_limit:
    move.w %d6,LIMIT
    beq.s capture_done              | degenerate/no eligible pool retains bounded native fallback
    move.w #-1,LASTACTOR
    clr.l LASTDIR
    clr.l ROTATION
    bsr.w checksum
    move.w %d0,CHECK
    not.w %d0
    move.w %d0,INVERSE
    move.w #0x5355,MAGIC
capture_done:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
capture_restore:
    move.w (%sp)+,%sr
    rts

| Public pure selector: D0 own attempt index, D1 side0/1 -> D0 roster/-1.
| All other registers preserved. No RNG, outcome, actor or attribute writes.
pick:
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.w %d0,%d6
    move.w %d1,%d7
    bsr.w choose
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    tst.w %d0
    rts
choose:
    cmpi.w #1,%d7
    bhi.w no_choice
    bsr.w valid
    tst.w %d0
    beq.w no_choice
    andi.l #0xFFFF,%d6
    divu.w LIMIT,%d6
    swap %d6
    andi.l #0xFFFF,%d6
    lea 0xFFFFD57A,%a0
    move.l HOME,%d2
    tst.w %d7
    beq.s preferred_ready
    lea 0xFFFFD588,%a0
    move.l AWAY,%d2
preferred_ready:
    moveq #0,%d5                   | seen roster IDs, avoid duplicates in native preferred five
    moveq #4,%d4
preferred:
    move.w (%a0)+,%d0
    cmpi.w #25,%d0
    bhi.s preferred_skip
    btst %d0,%d2
    beq.s preferred_skip
    bset %d0,%d5
    bne.s preferred_skip
    tst.w %d6
    beq.s chosen
    subq.w #1,%d6
preferred_skip:
    dbra %d4,preferred
    moveq #0,%d0
bench:
    btst %d0,%d2
    beq.s bench_skip
    btst %d0,%d5
    bne.s bench_skip
    tst.w %d6
    beq.s chosen
    subq.w #1,%d6
bench_skip:
    addq.w #1,%d0
    cmpi.w #26,%d0
    bcs.s bench
no_choice:
    moveq #-1,%d0
chosen:
    rts

setup:
    jsr 0xFC4C0                    | all original setup/presentation/outputs first
    move.w %sr,-(%sp)
    cmpi.w #1,VALUE
    bne.s setup_restore
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    move.w 0xFFFFD594,%d7
    cmpi.w #1,%d7
    bhi.s setup_done
    move.w %d7,%d0
    add.w %d0,%d0
    lea 0xFFFFF09C,%a0
    move.w (%a0,%d0.w),%d6
    bsr.w choose
    tst.w %d0
    bmi.s setup_done
    move.w %d0,0xFFFFD40A           | native1592C loads this actual roster through15AA4
setup_done:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
setup_restore:
    move.w (%sp)+,%sr
    rts

fresh:
    move.w %sr,-(%sp)
    cmpi.w #1,VALUE
    bne.s fresh_restore
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w valid
    tst.w %d0
    beq.s fresh_done
    move.w #-1,LASTACTOR
    clr.l LASTDIR
    clr.l ROTATION
fresh_done:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
fresh_restore:
    move.w (%sp)+,%sr
    rts

| Called only within the protected pre-shot approach observer. D0=1 means miss.
| Native facing changes are sampled, not direction-button commands. Exact
| ambiguous half-turns reset the turn history; ordinary cuts/oscillations stay legal.
spin:
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    bsr.w valid
    tst.w %d0
    beq.w spin_done
    btst #5,0xFFFFC2F2
    bne.w spin_legal
    move.w 0xFFFFD406,%d1
    cmpi.w #11,%d1
    bhi.w spin_legal
    move.w %d1,%d2
    lsl.w #7,%d2
    lea 0xFFFFB04A,%a0
    adda.w %d2,%a0
    tst.w 0x34(%a0)
    ble.w spin_legal
    move.l 0x54(%a0),%d2            | native108B0 updates the complete16.16 body angle
    cmpi.l #0x00080000,%d2
    bcc.w spin_legal
    cmp.w LASTACTOR,%d1
    beq.s spin_existing
    move.w %d1,LASTACTOR
    move.l %d2,LASTDIR
    clr.l ROTATION
    bra.s spin_legal
spin_existing:
    move.l %d2,%d3
    sub.l LASTDIR,%d3
    move.l %d2,LASTDIR
    cmpi.l #0x00040000,%d3
    ble.s lower_wrap
    subi.l #0x00080000,%d3
lower_wrap:
    cmpi.l #-0x00040000,%d3
    bge.s turn_step
    addi.l #0x00080000,%d3
turn_step:
    cmpi.l #0x00040000,%d3
    beq.s ambiguous                 | an exact half-turn has no observable rotation direction
    cmpi.l #-0x00040000,%d3
    beq.s ambiguous
    add.l %d3,ROTATION
    move.l ROTATION,%d1
    cmpi.l #0x00080000,%d1
    bge.s spin_miss
    cmpi.l #-0x00080000,%d1
    ble.s spin_miss
    bra.s spin_legal
ambiguous:
    clr.l ROTATION
spin_legal:
    moveq #0,%d0
    bra.s spin_done
spin_miss:
    moveq #1,%d0
spin_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    tst.w %d0
    rts

record:
    lea 0x209A75,%a0                | native/Full/Light/Mini logical4D3A..4D41
    tst.w 0xFFFFF06C
    beq.s record_done
    move.w 0xFFFFF06A,%d0
    subq.w #1,%d0
    cmpi.w #2,%d0
    bhi.s record_done
    addq.w #1,%d0
    lsl.w #2,%d0
    adda.w %d0,%a0
record_done:
    rts
load:
    move.w %sr,-(%sp)
    movem.l %d0-%d1/%a0,-(%sp)
    .if WITH_REFINEMENTS
    move.w #1,VALUE
    .else
    clr.w VALUE
    .endif
    clr.w MAGIC
    bsr.s record
    moveq #0,%d0
    move.b (%a0),%d0
    move.w %d0,%d1
    andi.w #0xFE,%d1
    cmpi.w #0x74,%d1
    bne.s loaded
    not.b %d0
    cmp.b 2(%a0),%d0
    bne.s loaded
    not.b %d0
    andi.w #1,%d0
    move.w %d0,VALUE
loaded:
    .if WITH_REFINEMENTS
    move.w #1,VALUE                   | permanent user-selected rule; old saved Off cannot disable it
    .endif
    movem.l (%sp)+,%d0-%d1/%a0
    move.w (%sp)+,%sr
    rts
put:
    move.w %sr,-(%sp)
    movem.l %d0-%d1/%a0,-(%sp)
    bsr.w record
    moveq #0x74,%d0
    cmpi.w #1,VALUE
    bne.s write
    addq.w #1,%d0
write:
    move.b %d0,(%a0)
    not.b %d0
    move.b %d0,2(%a0)
    lea 0x208001,%a0
    moveq #0,%d0
    move.w #0x1FFD,%d1
sum:
    add.b (%a0),%d0
    addq.l #2,%a0
    dbra %d1,sum
    not.b %d0
    move.b %d0,(%a0)
    not.b %d0
    move.b %d0,2(%a0)
    movem.l (%sp)+,%d0-%d1/%a0
    move.w (%sp)+,%sr
    rts
reset:
    move.w 0xFFFFF06C,-(%sp)
    move.w #1,0xFFFFF06C
    .if WITH_REFINEMENTS
    move.w #1,VALUE
    .else
    clr.w VALUE
    .endif
    clr.w MAGIC
    bsr.w put
    move.w (%sp)+,0xFFFFF06C
    rts
