    .ifndef WITH_FRIENDLY_RECEPTION
    .equ WITH_FRIENDLY_RECEPTION,0
    .endif
    .ifndef WITH_FINISH_POSITION
    .equ WITH_FINISH_POSITION,0
    .endif
| Hard: one native nearest chaser, open point shots, deliberate one-timer spots.
| No persistent RAM. Native assignments, skating, passes and shots execute actions.
    .ifndef WITH_AI_FREECROSS
    .equ WITH_AI_FREECROSS,0
    .endif
    .text
    .globl _start
_start:
    bra.w pressure
    bra.w pointshot
    bra.w reception
    bra.w receive_skate
    bra.w frame
    .if WITH_AI_FREECROSS
    bra.w finish_ready
    bra.w clearlane
    .endif

guard:
    moveq #0,%d0
    cmpi.w #1,0xFFFFF07A
    bne.s guard_done
    btst #3,0x62(%a3)
    bne.s guard_done
    btst #5,0x62(%a3)
    bne.s guard_done
    btst #2,0x63(%a3)
    bne.s guard_done
    tst.w 0x34(%a3)
    ble.s guard_done
    btst #0,0xFFFFC2EA
    bne.s guard_done
    .if WITH_PASS_PLAN
    btst #4,0xFFFFC2EA
    bne.s guard_done
    .endif
    btst #7,0xFFFFC2EC
    bne.s guard_done
    btst #7,0xFFFFC2EE
    bne.s guard_done
    btst #2,0xFFFFC2F2
    bne.s guard_done
    move.b 0xFFFFC2FA,%d0
    andi.w #5,%d0
    bne.s guard_no
    moveq #1,%d0
    rts
guard_no:
    moveq #0,%d0
guard_done:
    rts

pressure:
    movem.l %d0/%d2-%d3,-(%sp)
    bsr.w guard
    tst.w %d0
    beq.s pressure_native
    .if WITH_PASS_CONTINUITY
    bsr.w flight_owner
    .else
    move.w 0xFFFFB7AA,%d2
    .endif
    cmpi.w #11,%d2
    bhi.s pressure_native
    move.w 0x52(%a3),%d3
    subi.w #6,%d2
    subi.w #6,%d3
    eor.w %d3,%d2
    bpl.s pressure_native
    movem.l (%sp)+,%d0/%d2-%d3
    move.w 0xFFFFB74A,%d0
    move.w 0xFFFFB75E,%d1
    jmp 0xEA04
pressure_native:
    movem.l (%sp)+,%d0/%d2-%d3
    btst #2,0x30(%a2)
    beq.s pressure_plain
    jmp 0xE9DE
pressure_plain:
    jmp 0xEA04

| A3's clear shooting lane to goal centre. Exclude goalies, boxed/unavailable.
| D0 boolean; every other register preserved. Conservative 12-unit corridor.
clearlane:
    movem.l %d1-%d7/%a0,-(%sp)
    moveq #0,%d0
    move.w 0x14(%a3),%d6
    btst #7,0x62(%a3)
    bne.s lane_depth
    neg.w %d6
lane_depth:
    move.w #264,%d5
    sub.w %d6,%d5                  | positive distance toward attacking goal
    ble.w lane_done
    lea 0xFFFFB04A,%a0
    cmpi.w #6,0x52(%a3)
    bcc.s lane_base
    adda.w #768,%a0
lane_base:
    .if WITH_AI_FREECROSS
    moveq #5,%d7                   | all real actors; keepers may change object slot
    .else
    moveq #4,%d7
    .endif
lane_opponent:
    tst.w 0x34(%a0)
    ble.s lane_next
    btst #2,0x63(%a0)
    bne.s lane_next
    move.w 0x14(%a0),%d2
    btst #7,0x62(%a3)
    bne.s lane_opp_depth
    neg.w %d2
lane_opp_depth:
    sub.w %d6,%d2
    bmi.s lane_next
    cmp.w %d5,%d2
    bge.s lane_next
    move.w (%a0),%d1
    sub.w (%a3),%d1
    muls.w %d5,%d1
    muls.w (%a3),%d2
    add.l %d2,%d1                  | cross with (-actorX, goalDepth-actorDepth)
    bpl.s lane_abs
    neg.l %d1
lane_abs:
    move.w (%a3),%d3
    bpl.s lane_width
    neg.w %d3
lane_width:
    add.w %d5,%d3
    mulu.w #12,%d3
    cmp.l %d3,%d1
    ble.s lane_done
lane_next:
    adda.w #128,%a0
    dbra %d7,lane_opponent
    moveq #1,%d0
lane_done:
    movem.l (%sp)+,%d1-%d7/%a0
    rts

pointshot:
    movem.l %d1-%d2,-(%sp)
    bsr.w guard
    tst.w %d0
    beq.s point_done
    moveq #0,%d0
    btst #1,0x64(%a3)
    bne.s point_done
    move.w 0x52(%a3),%d1
    cmp.w 0xFFFFB7AA,%d1
    bne.s point_done
    move.w 0x14(%a3),%d1
    btst #7,0x62(%a3)
    bne.s point_depth
    neg.w %d1
point_depth:
    cmpi.w #88,%d1
    blt.s point_done
    cmpi.w #144,%d1
    bgt.s point_done
    move.w (%a3),%d2
    bpl.s point_abs
    neg.w %d2
point_abs:
    cmpi.w #100,%d2
    bgt.s point_done
    bsr.w clearlane
    tst.w %d0
    beq.s point_done
    moveq #4,%d0                   | one in four eligible native decision checks
    jsr 0x11086
    tst.w %d0
    seq %d0
    andi.w #1,%d0
point_done:
    movem.l (%sp)+,%d1-%d2
    rts

| Native receiver used to wind up from anywhere beyond blue. Let point/wide
| receivers catch and relay; finishers arm a native catch-and-release shot.
reception:
    cmpi.w #1,0xFFFFF07A
    bne.w reception_native
    bsr.w guard
    tst.w %d0
    beq.s reception_native
    move.b #64,0x40(%a3)            | wait for a native catch, then relay/finish
    bsr.w finish_ready
    tst.w %d0
    beq.s reception_return
    move.w #0x5042,0xFFFFF086
    move.w 0x52(%a3),%d0
    addq.w #1,%d0
    move.w %d0,0xFFFFF088
    move.w #64,0xFFFFF08A
reception_return:
    moveq #0,%d0                   | CPU keeps skating until the pass arrives
    rts
reception_native:
    jmp 0xF6C44

| Free finishing position; D0 boolean, other registers preserved.
finish_ready:
    movem.l %d1-%d2,-(%sp)
    bsr.w guard
    tst.w %d0
    beq.s ready_done
    moveq #0,%d0
    move.w 0x14(%a3),%d1
    btst #7,0x62(%a3)
    bne.s ready_depth
    neg.w %d1
ready_depth:
    cmpi.w #160,%d1
    blt.s ready_done
    cmpi.w #252,%d1
    bgt.s ready_done
    move.w (%a3),%d2
    bpl.s ready_abs
    neg.w %d2
ready_abs:
    cmpi.w #92,%d2
    bgt.s ready_done
    bsr.w clearlane
ready_done:
    movem.l (%sp)+,%d1-%d2
    rts

| Catch-and-relay receivers track the incoming puck with native steering.
receive_skate:
    movem.l %d0-%d7/%a0-%a3,-(%sp)
    bsr.w guard
    tst.w %d0
    .if WITH_FINISH_HOLD
    beq.w receive_tick
    .else
    beq.s receive_tick
    .endif
    tst.w 0xFFFFB7AA
    .if WITH_FINISH_HOLD
    bpl.w receive_tick
    .else
    bpl.s receive_tick
    .endif
    move.w 0x52(%a3),%d0
    cmp.w 0xFFFFBEE0,%d0
    .if WITH_FINISH_HOLD
    bne.w receive_tick
    .else
    bne.s receive_tick
    .endif
    .if WITH_FINISH_HOLD
    | Keep an armed, free finisher in his slot while the pass approaches.
    | Track point/wide receivers, expired buffers, blocked slots and missed passes.
    cmpi.w #0x5042,0xFFFFF086
    bne.s receive_track
    tst.w 0xFFFFF08A
    ble.s receive_track
    addq.w #1,%d0
    cmp.w 0xFFFFF088,%d0
    bne.s receive_track
    move.w 0xFFFFB74A,%d0
    sub.w (%a3),%d0
    move.w 0xFFFFB75E,%d1
    sub.w 0x14(%a3),%d1
    move.w %d0,%d2
    bpl.s receiver_dx
    neg.w %d2
receiver_dx:
    move.w %d1,%d3
    bpl.s receiver_dy
    neg.w %d3
receiver_dy:
    add.w %d3,%d2
    cmpi.w #64,%d2
    .if WITH_FINISH_POSITION
    bls.w receive_close             | actual near reception uses a fresh native target
    .else
    bls.s receive_track
    .endif
    muls.w 0xFFFFB772,%d0
    muls.w 0xFFFFB774,%d1
    add.l %d1,%d0
    bpl.s receive_track
    bsr.w finish_ready
    tst.w %d0
    .if WITH_FINISH_POSITION
    beq.s receive_track
    jsr 0x225000                  | native steer toward actual pass-course interception
    tst.w %d0
    bne.s receive_tick
    .else
    bne.s receive_tick
    .endif
    .endif
    .if WITH_FINISH_POSITION
    bra.s receive_track
receive_close:
    bsr.w finish_ready
    tst.w %d0
    beq.s receive_track
    jsr 0x225004
    tst.w %d0
    bne.s receive_tick
    .endif
receive_track:
    jsr 0x105A2
receive_tick:
    movem.l (%sp)+,%d0-%d7/%a0-%a3
    sub.b %d7,0x40(%a3)
    bpl.s receive_wait
    jmp 0xEC68
receive_wait:
    jmp 0x15464

| Once per rendered frame, same native catch-and-release path as human buffer.
| Transient F086 magic, F088 object+1, F08A TTL. Never stored in saves.
frame:
    .if WITH_PASS_PLAN
    jsr 0x2DF804
    .endif
    cmpi.w #0x5042,0xFFFFF086
    bne.w frame_empty
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    subq.w #1,0xFFFFF08A
    bmi.w frame_clear
    move.w 0xFFFFF088,%d0
    subq.w #1,%d0
    cmpi.w #11,%d0
    bhi.w frame_clear
    move.w %d0,%d7
    lsl.w #7,%d0
    lea 0xFFFFB04A,%a3
    adda.w %d0,%a3
    .if WITH_FRIENDLY_RECEPTION
    jsr 0x225800
    .else
    bsr.w guard
    .endif
    tst.w %d0
    beq.w frame_clear
    cmp.w 0xFFFFB7AA,%d7
    beq.s frame_caught
    tst.w 0xFFFFB7AA
    bpl.s frame_clear
    cmp.w 0xFFFFBEE0,%d7
    bne.s frame_clear
    bra.s frame_done
frame_caught:
    .if WITH_FRIENDLY_RECEPTION
    jsr 0x225804
    .else
    bsr.w finish_ready
    .endif
    tst.w %d0
    beq.s frame_clear
    .if WITH_CATCH_OPENING
    jsr 0x2DF004
    tst.w %d0
    beq.s frame_clear
    .endif
    clr.l 0xFFFFF086
    clr.w 0xFFFFF08A
    .if WITH_AI_FREECROSS
| A buffered catch can release before FF5A observes the new native owner.
| Run that same possession bookkeeping first: real scorer/assist chain,
| last-possession coordinates and native zone state, without touching counters.
    movea.l %a3,%a2
    jsr 0x1013E
    .endif
    bset #3,0x64(%a3)
    move.w #0x7FC,%d1
    jsr 0x1073A
    jsr 0xC2F2
    bclr #3,0x64(%a3)
    bra.s frame_done
frame_clear:
    clr.l 0xFFFFF086
    clr.w 0xFFFFF08A
frame_done:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
frame_empty:
    rts

    .if WITH_PASS_CONTINUITY
flight_owner:
    jsr 0x2DD680
    rts
    .endif
