| ygoalie.s — Y on a 6-button pad takes control of your goalie (Goalie Ctrl = Manual, your team without the puck).
| Assembled at $2FE040 by build.sh (m68kasm.sh) and put into the ROM by patch.py (fix 9).
|
| The hack's 6-button reader ($1FFBC4) tests Y at $1FFC02 (bit 1 of the third TH-high byte, active low) and turns Y
| into a B press (pass / switch to the nearest player). Hook there:
|   - Y with Goalie Ctrl Manual ($D05A/$D05C = 0) and your team not holding the puck → YREQ[pad] = $FF, no B press.
|   - otherwise the hack's old Y (= B), so Y still passes when you have the puck.
| The game's player-input handler ($B258, jmp $20011a) is hooked too: if YREQ is set for this pad (d4) it does what
| the game's own manual-goalie switch at $B3E4 does: goalie of the team (d6 ≤ 5 → object 5, else 11) via $B86A,
| skip if another human controls him, then $C0BC (P1) / $C0DA (P2) as a tail call (returns from the handler).

        .equ YREQ,    0xFFF0E0          | byte per pad (pad offset 0 / 2): goalie wanted; +4: Y held ($FF goalie, 1 = as B)
        .equ GKCTRL,  0xFFD05A          | word per pad, 0 = Manual
        .equ CTRLOBJ, 0xFFC320          | word per pad, controlled object (-1 = none)
        .equ PUCK,    0xFFB7AA          | puck owner (negative = loose)
        .equ OBJ,     0xFFB04A          | objects, $80 bytes each

        .text
        .globl _start
| ---- reader hook: replaces  btst #1,d2 / bne.w $1FFBF0  at $1FFC02 (jmp + nop) ----
| in: d1 = pad bits (kept), d2 = third TH-high byte, a0 = data port. d0/d2 are free here.
_start:
        move.l  %a1,-(%sp)
        move.l  %d3,-(%sp)
        moveq   #0,%d0
        cmpa.l  #0xA10003,%a0
        beq.s   rd_pad
        moveq   #2,%d0
        cmpa.l  #0xA10005,%a0
        bne.s   rd_old                  | not pad 1/2: hack's behaviour
rd_pad:
        lea     YREQ,%a1
        btst    #1,%d2
        bne.s   rd_noy                  | Y not pressed
        tst.b   4(%a1,%d0.w)            | Y still held: keep what the press did
        bmi.s   rd_ret                  |   goalie press: nothing until released
        bne.s   rd_oldy                 |   B press: keep holding B
        tst.w   0xFFD046                | 4-player adaptor: keep the hack's Y
        bne.s   rd_oldy
        lea     GKCTRL,%a1
        tst.w   (%a1,%d0.w)
        bne.s   rd_oldy                  | Auto goalie
        lea     CTRLOBJ,%a1
        move.w  (%a1,%d0.w),%d2
        bmi.s   rd_oldy                  | no controlled player
        move.w  PUCK,%d3
        bmi.s   rd_want                 | loose puck
        subq.w  #6,%d2                   | team = sign of (object - 6)
        subq.w  #6,%d3
        eor.w   %d2,%d3
        bpl.s   rd_oldb                 | own team has the puck: Y = B (pass)
rd_want:
        lea     YREQ,%a1
        st      (%a1,%d0.w)
        st      4(%a1,%d0.w)            | held as a goalie press
        bra.s   rd_ret                  | and no B press
rd_oldb:
        lea     YREQ,%a1
        move.b  #1,4(%a1,%d0.w)         | held as a B press
        bra.s   rd_oldy
rd_noy:
        clr.b   (%a1,%d0.w)
        clr.b   4(%a1,%d0.w)
rd_ret:
        move.l  (%sp)+,%d3
        movea.l (%sp)+,%a1
        jmp     0x1FFBF0                | return the pad bits
rd_oldy:                                | Y pressed (d2 may be changed): hack's Y = press B
        move.l  (%sp)+,%d3
        movea.l (%sp)+,%a1
        jmp     0x1FFC0A
rd_old:
        move.l  (%sp)+,%d3
        movea.l (%sp)+,%a1
        btst    #1,%d2
        bne.s   rd_none
        jmp     0x1FFC0A                | hack's Y: press B
rd_none:
        jmp     0x1FFBF0

        .org    0xC0                    | handler at $2FE100 (patch.py relies on it)
| ---- handler hook: replaces  jmp $20011a  at $B258 ----
| d4 = pad (0/1), d6 = controlled object. d0/d1/a1 must survive for $20011a.
        .globl handler
handler:
        movem.l %d0-%d1/%a1,-(%sp)
        move.w  %d4,%d0
        add.w   %d0,%d0
        lea     YREQ,%a1
        tst.b   (%a1,%d0.w)
        beq.s   h_no
        clr.b   (%a1,%d0.w)
        tst.w   0xFFD412
        bne.s   h_no
        move.w  PUCK,%d0                | own team got the puck since the press: no switch
        bmi.s   h_go
        move.w  %d6,%d1
        subq.w  #6,%d0
        subq.w  #6,%d1
        eor.w   %d1,%d0
        bpl.s   h_no
h_go:
        moveq   #5,%d0
        cmp.w   #5,%d6
        ble.s   h_team
        moveq   #11,%d0
h_team:
        jsr     0xB86A                  | goalie object of that team, -1 if pulled
        tst.w   %d0
        bmi.s   h_no
        move.w  %d0,%d1
        lsl.w   #7,%d1
        lea     OBJ,%a1
        btst    #3,0x62(%a1,%d1.w)
        bne.s   h_no                    | another human has him
        addq.l  #4,%sp                   | d0 = goalie
        movem.l (%sp)+,%d1/%a1
        tst.w   %d4
        bne.s   h_p2
        jmp     0xC0BC
h_p2:
        jmp     0xC0DA
h_no:
        movem.l (%sp)+,%d0-%d1/%a1
        jmp     0x20011A
