| CPU Hard far winger: choose one of three free finishing spots with a pass lane.
| Called only inside the existing Hard support guard. No gameplay state writes.
 .text
 .globl _start
_start:
 link.w %a6,#-40
 movem.l %d2-%d7/%a0-%a2,-(%sp)
 move.l %d0,-28(%a6)
 move.l %d1,-32(%a6)
 move.w %d6,-2(%a6)
 move.w %d3,-4(%a6)
 cmpi.w #4,0x34(%a3)
 beq.w done
 move.w %d6,%d0
 move.w 0xFFFFB74A,%d1
 eor.w %d1,%d0
 bpl.w done
 move.w %d1,%d0
 bpl.s puck_abs
 neg.w %d0
puck_abs:
 cmpi.w #48,%d0
 blt.w done
 move.w 0xFFFFB75E,%d0
 btst #7,0x62(%a3)
 bne.s puck_depth
 neg.w %d0
puck_depth:
 cmpi.w #160,%d0
 blt.w done
 cmpi.w #236,%d0
 bgt.w done
 addi.w #24,%d0
 cmpi.w #200,%d0
 bge.s lower_ok
 move.w #200,%d0
lower_ok:
 cmpi.w #232,%d0
 ble.s depth_ok
 move.w #232,%d0
depth_ok:
 move.w %d0,-8(%a6)
 lea 0xFFFFB04A,%a1
 cmpi.w #6,0x52(%a3)
 bcc.s opponent_base
 adda.w #768,%a1
opponent_base:
 move.l %a1,-12(%a6)
 moveq #5,%d7
keeper_loop:
 tst.w 0x34(%a1)
 bne.s keeper_next
 btst #2,0x63(%a1)
 bne.s keeper_next
 move.w (%a1),%d0
 cmpi.w #-40,%d0
 blt.w done
 cmpi.w #40,%d0
 bgt.w done
 move.w 0x14(%a1),%d0
 btst #7,0x62(%a3)
 bne.s keeper_depth
 neg.w %d0
keeper_depth:
 cmpi.w #232,%d0
 blt.w done
 cmpi.w #276,%d0
 bgt.w done
 bra.s begin
keeper_next:
 adda.w #128,%a1
 dbra %d7,keeper_loop
 bra.w done
begin:
 move.w #-32768,-6(%a6)
 lea spots,%a2
 moveq #2,%d7
spot:
 move.w (%a2)+,%d6
 tst.w -2(%a6)
 bpl.s spot_side
 neg.w %d6
spot_side:
 move.w -8(%a6),%d5
 add.w (%a2)+,%d5
 move.w %d6,%d0
 sub.w 0xFFFFB74A,%d0
 move.w %d0,-14(%a6)
 move.w %d5,%d1
 btst #7,0x62(%a3)
 bne.s spot_world
 neg.w %d1
spot_world:
 sub.w 0xFFFFB75E,%d1
 move.w %d1,-16(%a6)
 move.w %d0,%d2
 muls.w %d2,%d2
 move.w %d1,%d3
 muls.w %d3,%d3
 add.l %d3,%d2
 move.l %d2,-20(%a6)
 tst.w %d0
 bpl.s width_dx
 neg.w %d0
width_dx:
 tst.w %d1
 bpl.s width_dy
 neg.w %d1
width_dy:
 add.w %d1,%d0
 mulu.w #12,%d0
 move.l %d0,-24(%a6)
 moveq #0,%d4
 move.w #2304,%d4
 movea.l -12(%a6),%a1
 moveq #5,%d3
opponent:
 tst.w 0x34(%a1)
 ble.w opponent_next
 btst #2,0x63(%a1)
 bne.w opponent_next
 move.w (%a1),%d0
 sub.w %d6,%d0
 muls.w %d0,%d0
 move.w 0x14(%a1),%d1
 btst #7,0x62(%a3)
 bne.s opp_depth
 neg.w %d1
opp_depth:
 sub.w %d5,%d1
 muls.w %d1,%d1
 add.l %d1,%d0
 cmp.l %d4,%d0
 bge.s lane_check
 move.w %d0,%d4
lane_check:
 move.w (%a1),%d0
 sub.w 0xFFFFB74A,%d0
 move.w 0x14(%a1),%d1
 sub.w 0xFFFFB75E,%d1
 move.w %d0,%d2
 muls.w -14(%a6),%d2
 move.w %d1,-34(%a6)
 muls.w -16(%a6),%d1
 add.l %d1,%d2
 ble.s opponent_next
 cmp.l -20(%a6),%d2
 bge.s opponent_next
 muls.w -16(%a6),%d0
 move.w -34(%a6),%d1
 muls.w -14(%a6),%d1
 sub.l %d1,%d0
 bpl.s cross_abs
 neg.l %d0
cross_abs:
 cmp.l -24(%a6),%d0
 ble.w next_spot
opponent_next:
 adda.w #128,%a1
 dbra %d3,opponent
 | Keep distinct receiving space from other active friendly skaters.
 lea 0xFFFFB04A,%a1
 cmpi.w #6,0x52(%a3)
 bcs.s friend_base
 adda.w #768,%a1
friend_base:
 moveq #5,%d3
friend:
 cmpa.l %a3,%a1
 beq.s friend_next
 tst.w 0x34(%a1)
 ble.s friend_next
 btst #2,0x63(%a1)
 bne.s friend_next
 move.w (%a1),%d0
 sub.w %d6,%d0
 muls.w %d0,%d0
 move.w 0x14(%a1),%d1
 btst #7,0x62(%a3)
 bne.s friend_depth
 neg.w %d1
friend_depth:
 sub.w %d5,%d1
 muls.w %d1,%d1
 add.l %d1,%d0
 cmpi.l #576,%d0
 blt.w next_spot
friend_next:
 adda.w #128,%a1
 dbra %d3,friend
 cmpi.w #676,%d4
 blt.w next_spot
 | Prefer a central useful finish once all candidate lanes are safe enough.
 move.w %d6,%d0
 bpl.s cost_x
 neg.w %d0
cost_x:
 subi.w #44,%d0
 bpl.s cost_abs
 neg.w %d0
cost_abs:
 lsl.w #2,%d0
 sub.w %d0,%d4
 move.w %d5,%d0
 subi.w #224,%d0
 bpl.s cost_depth
 neg.w %d0
cost_depth:
 add.w %d0,%d0
 sub.w %d0,%d4
 cmp.w -6(%a6),%d4
 ble.s next_spot
 move.w %d4,-6(%a6)
 move.w %d6,-2(%a6)
 move.w %d5,-4(%a6)
next_spot:
 dbra %d7,spot
 done:
 movem.l (%sp)+,%d2-%d7/%a0-%a2
 move.l -28(%a6),%d0
 move.l -32(%a6),%d1
 move.w -2(%a6),%d0
 move.w -4(%a6),%d1
 unlk %a6
 btst #7,0x62(%a3)
 jmp 0x2D89A0
spots:
 .word 44,0,28,-24,68,-16
