| Conditional real-player getters. Active52UID cache avoids SRAM mapping while
| game animation/audio DMA is running. Other-club menu reads wait for DMA under
| masked IRQs. Allocation F860..F8D7 still requires complete lifetime/stack QA.
    .equ TAG,0xFFFFF860
    .equ LEAGUE,0xFFFFF862
    .equ BANK,0xFFFFF864
    .equ HOMEID,0xFFFFF868
    .equ AWAYID,0xFFFFF86A
    .equ CACHE,0xFFFFF870
    .equ MAPPER,0xA130F1
    .text
    .globl _start
_start:
    bra.w preload_hook
    bra.w uid
    bra.w pointer
    bra.w enabled
    bra.w count_g
    bra.w count_gf
    bra.w count_f
    bra.w count_all
    bra.w attribute_hook
    bra.w name_hook
    bra.w preload
    bra.w goalie_base_a0
    bra.w goalie_base_a1
    bra.w keeper_candidate
    bra.w critical_base
    bra.w profile_photo
    bra.w card_photo
    bra.w card_limit
    bra.w card_name
    bra.w line_initializer
    bra.w active_line_a0
    bra.w player_load
    bra.w selection_attribute
    bra.w goalkeeper_name
    bra.w roster_number
    bra.w keeper_label
    bra.w profile_number
    bra.w receiver_record
    bra.w profile_record_a2
    bra.w editor_record_a2
    bra.w season_pick
    bra.w season_skater
    bra.w season_record_a1
    bra.w season_prepare
    bra.w card_starting_line
    bra.w card_position
enabled:
    move.w %sr,-(%sp)
    moveq #0,%d0
    cmpi.w #0x5452,TAG
    bne.s disabled
    tst.w 0xFFFFF06C
    beq.s disabled
    tst.w 0xFFFFF84C
    bne.s disabled
    cmpi.w #1,0xFFFFF85C
    bne.s disabled
    move.w 0xFFFFF06A,%d0
    cmp.w LEAGUE,%d0
    bne.s not_enabled
    subq.w #1,%d0
    cmpi.w #2,%d0
    bhi.s not_enabled
    andi.l #0xFFFF,%d0
    lsl.l #8,%d0
    lsl.l #5,%d0
    addi.l #0x204000,%d0
    cmp.l BANK,%d0
    beq.s bank_valid
    addi.l #0x1000,%d0
    cmp.l BANK,%d0
    bne.s not_enabled
bank_valid:
    moveq #1,%d0
    bra.s disabled
not_enabled:
    moveq #0,%d0
disabled:
    move.w (%sp)+,%sr
    tst.l %d0
    rts
preload_hook:
    bsr.w preload
    move.w 0xFFFFC6F4,-(%sp)
    move.w 0xFFFFCA58,-(%sp)
    movem.l %a1-%a3,-(%sp)
    jmp 0x1710E
preload:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    clr.w TAG
    tst.w 0xFFFFF06C
    beq.w preload_done
    tst.w 0xFFFFF84C
    bne.w preload_done
    jsr 0x254000
    cmpi.w #1,0xFFFFF85C
    bne.w preload_done
    move.w 0xFFFFF06A,%d0
    jsr 0x234014
    tst.l %d0
    ble.w preload_done
    movea.l %d0,%a4
    move.w #0x2700,%sr
    bsr.w wait_dma
    move.b #1,MAPPER
    cmpi.b #1,12(%a4)
    bne.s preload_unmap
    | Valid unready preseason ownership may also be previewed in native menus.
    | The actual match Start modal still requires Ready before continuing.
    move.w 0xFFFFC330,%d0
    cmpi.w #31,%d0
    bhi.s preload_unmap
    move.w %d0,HOMEID
    mulu.w #104,%d0
    lea 64(%a4),%a0
    adda.l %d0,%a0
    lea CACHE,%a1
    bsr.s copy_row
    move.w 0xFFFFC332,%d0
    cmpi.w #31,%d0
    bhi.s preload_unmap
    move.w %d0,AWAYID
    mulu.w #104,%d0
    lea 64(%a4),%a0
    adda.l %d0,%a0
    bsr.s copy_row
    move.l %a4,BANK
    move.w 0xFFFFF06A,LEAGUE
    move.w #0x5452,TAG
preload_unmap:
    move.b #0,MAPPER
preload_done:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
copy_row:
    moveq #25,%d2
copy_uid:
    moveq #0,%d0
    move.b (%a0),%d0
    lsl.w #8,%d0
    move.b 2(%a0),%d0
    addq.l #4,%a0
    move.w %d0,(%a1)+
    dbra %d2,copy_uid
    rts
wait_dma:
    btst #1,0xC00005
    bne.s wait_dma
    rts

| D0.W club,D1.W slot -> D0.L UID orFFFFFFFF. All other GPRs and IRQ/X
| preserved; NZVC from TST.L result. Off maps the original catalogue identity.
uid:
    move.w %sr,-(%sp)
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.w %d0,%d6
    cmpi.w #31,%d6
    bhi.w uid_bad
    cmpi.w #25,%d1
    bhi.w uid_bad
    bsr.w enabled
    beq.s original_uid
    lea CACHE,%a0
    cmp.w HOMEID,%d6
    beq.s cached
    lea CACHE+52,%a0
    cmp.w AWAYID,%d6
    beq.s cached
    move.w #0x2700,%sr
    bsr.s wait_dma
    movea.l BANK,%a0
    adda.w #64,%a0
    mulu.w #104,%d6
    adda.l %d6,%a0
    move.w %d1,%d0
    lsl.w #2,%d0
    adda.w %d0,%a0
    move.b #1,MAPPER
    moveq #0,%d0
    move.b (%a0),%d0
    lsl.w #8,%d0
    move.b 2(%a0),%d0
    move.b #0,MAPPER
    bra.s uid_check
cached:
    move.w %d1,%d0
    add.w %d0,%d0
    moveq #0,%d2
    move.w (%a0,%d0.w),%d2
    move.l %d2,%d0
uid_check:
    cmpi.w #831,%d0
    bhi.s uid_bad
    bra.s uid_done
original_uid:
    mulu.w #26,%d6
    moveq #0,%d0
    move.w %d6,%d0
    add.w %d1,%d0
    bra.s uid_done
uid_bad:
    moveq #-1,%d0
uid_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    move.w (%sp)+,%sr
    tst.l %d0
    rts
pointer:
    move.w %sr,-(%sp)
    bsr.w uid
    tst.l %d0
    bmi.s empty_pointer
    move.l %d1,-(%sp)
    move.w %d0,%d1
    lsl.w #2,%d1
    lea 0x238800,%a0
    movea.l (%a0,%d1.w),%a0
    move.l (%sp)+,%d1
    move.w (%sp)+,%sr
    tst.l %d0
    rts
empty_pointer:
    lea 0x23B588,%a0
    move.w (%sp)+,%sr
    tst.l %d0
    rts

| D0=club -> D0=G,D1=F,D2=total. Wrapper owns register preservation.
counts:
    move.w %d0,%d7
    moveq #0,%d5
    moveq #0,%d6
    moveq #0,%d4
    moveq #0,%d3
count_next:
    move.w %d7,%d0
    move.w %d3,%d1
    bsr.w uid
    tst.l %d0
    bmi.s count_skip
    addq.w #1,%d4
    lea 0x239B80,%a0
    moveq #0,%d1
    move.b (%a0,%d0.w),%d1
    tst.w %d1
    bne.s count_forward
    addq.w #1,%d5
    bra.s count_skip
count_forward:
    cmpi.w #4,%d1
    bhi.s count_skip
    addq.w #1,%d6
count_skip:
    addq.w #1,%d3
    cmpi.w #26,%d3
    blo.s count_next
    move.w %d5,%d0
    move.w %d6,%d1
    move.w %d4,%d2
    rts

    .macro count_wrapper label,kind,continuation
\label:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.w \label\()_old
    move.w 0x28(%a2),%d0
    bsr.w counts
    .if \kind == 0
    move.w %d0,2(%sp)
    moveq #0x15,%d3
    .elseif \kind == 1
    add.w %d1,%d0
    move.w %d0,2(%sp)
    moveq #0,%d3
    .elseif \kind == 2
    move.w %d1,2(%sp)
    sub.w %d0,%d2
    sub.w %d1,%d2
    move.w %d2,%d3
    andi.w #8,%d3
    lsl.w #1,%d3
    .else
    move.w %d2,2(%sp)
    moveq #4,%d3
    .endif
    andi.w #0xFFE0,60(%sp)
    or.w %d3,60(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
\label\()_old:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    .if \kind == 0
    movem.l %d1/%a0,-(%sp)
    movea.l 0x1E(%a2),%a0
    .elseif \kind == 1
    movem.l %a0,-(%sp)
    jsr 0x9F40
    .else
    movem.l %a0,-(%sp)
    movea.l 0x1E(%a2),%a0
    .endif
    jmp \continuation
    .endm
    count_wrapper count_g,0,0x9F48
    count_wrapper count_gf,1,0x9F62
    count_wrapper count_f,2,0x9F86
    count_wrapper count_all,3,0x9FA2

attribute_hook:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s attribute_old
    move.w 2(%sp),%d1
    move.w 0x28(%a2),%d0
    bsr.w pointer
    adda.w (%a0),%a0
    addq.l #8,%a0
    move.l %a0,32(%sp)
    move.w #0xFFFF,2(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
attribute_old:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    adda.w (%a0),%a0
attribute_next:
    adda.w (%a0),%a0
    addq.w #8,%a0
    dbra %d0,attribute_next
    rts
name_hook:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s name_old
    move.w 2(%sp),%d1
    move.w 0x28(%a2),%d0
    bsr.w pointer
    move.l %a0,32(%sp)
    move.w #0xFFFF,2(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
name_old:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    movea.l 0x1E(%a2),%a0
    adda.w (%a0),%a0
    jmp 0x18BCE

| Original Allstar-aware bases have already been selected. Off retains that
| exact pointer and every flag; On adapts indexed4-byte goalkeeper metadata.
goalie_base_a0:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a1-%a6,-(%sp)
    bsr.w enabled
    beq.s goalie_a0_done
    move.w 2(%sp),%d0
    lsr.w #2,%d0
    bsr.w counts
    lea keeper_signatures(%pc),%a0
    cmpi.w #3,%d0
    bne.s goalie_a0_index
    addq.l #4,%a0
goalie_a0_index:
    move.w 2(%sp),%d0
    suba.w %d0,%a0
goalie_a0_done:
    movem.l (%sp)+,%d0-%d7/%a1-%a6
    move.w (%sp)+,%sr
    rts
goalie_base_a1:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0/%a2-%a6,-(%sp)
    bsr.w enabled
    beq.s goalie_a1_done
    move.w 10(%sp),%d0
    lsr.w #2,%d0
    bsr.w counts
    lea keeper_signatures(%pc),%a1
    cmpi.w #3,%d0
    bne.s goalie_a1_index
    addq.l #4,%a1
goalie_a1_index:
    move.w 10(%sp),%d0
    suba.w %d0,%a1
goalie_a1_done:
    movem.l (%sp)+,%d0-%d7/%a0/%a2-%a6
    move.w (%sp)+,%sr
    rts
keeper_candidate:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s keeper_old
    move.w 26(%sp),%d1
    move.w 0x28(%a2),%d0
    bsr.w pointer
    adda.w (%a0),%a0
    move.l %a0,36(%sp)
    addq.l #8,%a0
    move.l %a0,48(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
keeper_old:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    movea.l %a4,%a1
    adda.w (%a1),%a1
    lea 8(%a1),%a4
    rts
keeper_signatures:
    .byte 0,1,2,0,0,1,3,0

| Preserve the original indexed lookup and its flags. Only its base changes.
critical_base:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a1-%a6,-(%sp)
    bsr.w enabled
    beq.s critical_base_done
    move.l (%sp),%d0
    andi.l #0xFFFF,%d0
    divu.w #26,%d0
    move.l %d0,%d1
    swap %d1
    bsr.w uid
    tst.l %d0
    bmi.s critical_empty
    lea 0x2FF800,%a0
    adda.w %d0,%a0
    bra.s critical_adjust
critical_empty:
    lea 0x23B58A,%a0
critical_adjust:
    move.w 2(%sp),%d0
    suba.w %d0,%a0
critical_base_done:
    movem.l (%sp)+,%d0-%d7/%a1-%a6
    move.w (%sp)+,%sr
    rts

| NativeFAE26 D0=slot,D1=club -> actual source photo,A0 only.
| Flags match the native source-photo entry search, precomputed from real order.
profile_photo:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a1-%a6,-(%sp)
    bsr.w enabled
    beq.s profile_original
    move.w 2(%sp),%d1
    move.w 6(%sp),%d0
    bsr.w uid
    tst.l %d0
    bmi.s profile_empty
    lea 0x23B600,%a1
    moveq #0,%d2
    move.b (%a1,%d0.w),%d2
    lsl.w #2,%d0
    lea 0x23A200,%a0
    movea.l (%a0,%d0.w),%a0
    bra.s profile_flags
profile_empty:
    lea 0xC63F8,%a0
    moveq #4,%d2
profile_flags:
    andi.w #0xFFE0,56(%sp)
    or.w %d2,56(%sp)
    movem.l (%sp)+,%d0-%d7/%a1-%a6
    move.w (%sp)+,%sr
    rts
profile_original:
    movem.l (%sp)+,%d0-%d7/%a1-%a6
    move.w (%sp)+,%sr
    movem.l %d0-%d7/%a1-%a6,-(%sp)
    jsr 0x22C018
    jmp 0xFAE30

| Native card index D0=4*club,D3=6*current-slot. Retain current slot for
| the following mapped name/ratings renderer; portrait follows the real UID.
card_photo:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s card_photo_original
    move.l 12(%sp),%d1
    andi.l #0xFFFF,%d1
    divu.w #6,%d1
    move.w %d1,0xFFFFD434
    andi.w #0xFFF0,60(%sp)
    tst.w %d1
    bne.s card_photo_slot
    ori.w #4,60(%sp)
card_photo_slot:
    move.w 2(%sp),%d0
    lsr.w #2,%d0
    bsr.w uid
    lea 0xC63F8,%a0
    tst.l %d0
    bmi.s card_photo_done
    lsl.w #2,%d0
    lea 0x23A200,%a0
    movea.l (%a0,%d0.w),%a0
card_photo_done:
    move.l %a0,32(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
card_photo_original:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    movea.l (%a0,%d0.w),%a0
    move.w 4(%a0,%d3.w),0xFFFFD434
    movea.l (%a0,%d3.w),%a0
    rts
card_limit:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s card_limit_original
    move.w 0xFFFFC330,%d0
    btst #1,0xFFFFD42E
    beq.s card_limit_team
    move.w 0xFFFFC332,%d0
card_limit_team:
    bsr.w counts
    move.w 0xFFFFD43E,%d1
    cmp.w %d2,%d1
    move.w %sr,%d0
    andi.w #15,%d0
    andi.w #0xFFF0,60(%sp)
    or.w %d0,60(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
card_limit_original:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    cmpi.w #26,0xFFFFD43E
    rts
card_name:
    move.w %sr,-(%sp)
    movem.l %d0-%d7/%a0-%a6,-(%sp)
    bsr.w enabled
    beq.s card_name_original
    move.w 0xFFFFD434,%d1
    andi.w #0xFFF0,60(%sp)
    tst.w %d1
    bne.s card_name_slot
    ori.w #4,60(%sp)
card_name_slot:
    move.w 0xFFFFD446,%d0
    bsr.w pointer
    move.l %a0,40(%sp)
    move.w #0xFFFF,2(%sp)
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    rts
card_name_original:
    movem.l (%sp)+,%d0-%d7/%a0-%a6
    move.w (%sp)+,%sr
    movea.l (%a2,%d0.w),%a2
    adda.w (%a2),%a2
    move.w 0xFFFFD434,%d0
    bra.s card_name_test
card_name_next:
    adda.w (%a2),%a2
    addq.w #8,%a2
card_name_test:
    dbra %d0,card_name_next
    rts

    .include "transfers_lines.s"
    .include "transfers_getters.s"

    .include "transfers_season.s"

    .include "transfers_cards.s"
