| In-place transaction on an explicitly owned modal work image at FFE000.
| FFE800..FFEFFF is private speculative scratch, never active season statistics.
| D0.W league1..3,D1.W club,D2.W UID,D3.W action,D4.W games played.
| actions0 sell/1 buy/2 ready/3 disable/4 enable.
| Returns D0.L0 rejected,1 changed,2 already requested flag. All other GPRs,
| original IRQ/X/SP preserved. On rejection/no-op the input image is EXACT.
| No SRAM writes here: validated changed image is published by save_even.
transact:
    move.w %sr,-(%sp)
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.l %a0,%d5
    andi.l #0xFFFFFF,%d5
    cmpi.l #0xFFE000,%d5
    bne.w tx_bad
    tst.w %d4
    bne.w tx_bad
    move.w %d0,%d6
    move.w %d3,%d5
    move.w %d2,%d4
    move.w %d1,%d3
    movea.l %a0,%a6
    bsr.w validate_contiguous
    tst.l %d0
    beq.w tx_bad
    cmpi.w #4,%d5
    bhi.w tx_bad
    cmpi.w #3,%d5
    bhs.s tx_flag
    tst.b 6(%a6)
    beq.w tx_bad
    cmpi.w #2,%d5
    bne.s tx_copy
    tst.b 7(%a6)
    bne.w tx_noop
    bra.s tx_copy
tx_flag:
    move.w %d5,%d0
    subq.w #3,%d0
    cmp.b 6(%a6),%d0
    beq.w tx_noop
tx_copy:
    lea 0x800(%a6),%a5
    movea.l %a5,%a1
    move.w #511,%d0
tx_copy_long:
    move.l (%a0)+,(%a1)+
    dbra %d0,tx_copy_long
    clr.b 7(%a5)
    cmpi.w #2,%d5
    blo.s tx_player
    beq.s tx_ready
    move.w %d5,%d0
    subq.w #3,%d0
    move.b %d0,6(%a5)
    bra.w tx_seal
tx_ready:
    move.b #1,7(%a5)
    bra.w tx_seal
tx_player:
    cmpi.w #31,%d3
    bhi.w tx_bad
    move.w %d4,%d0
    bsr.w price
    tst.l %d0
    bmi.w tx_bad
    move.l %d0,%d2
    moveq #-1,%d7
    lea 32(%a5),%a0
    moveq #0,%d0
tx_owner_club:
    moveq #25,%d1
tx_owner_slot:
    cmp.w (%a0),%d4
    beq.s tx_owner_found
    addq.l #2,%a0
    dbra %d1,tx_owner_slot
    addq.w #1,%d0
    cmpi.w #32,%d0
    blo.s tx_owner_club
    bra.s tx_owner_done
tx_owner_found:
    move.w %d0,%d7
    movea.l %a0,%a1
tx_owner_done:
    tst.w %d5
    beq.w tx_sell
    cmp.w %d7,%d3
    beq.w tx_bad
    move.w %d3,%d0
    mulu.w #52,%d0
    lea 32(%a5),%a2
    adda.l %d0,%a2
    cmpi.w #0xFFFF,50(%a2)
    bne.w tx_bad
    move.w %d3,%d0
    lsl.w #2,%d0
    lea 1696(%a5),%a0
    adda.w %d0,%a0
    cmp.l (%a0),%d2
    bhi.w tx_bad
    sub.l %d2,(%a0)
    tst.w %d7
    bmi.s tx_insert
    bsr.w tx_remove_credit
tx_insert:
    movea.l %a2,%a0
tx_empty_slot:
    cmpi.w #0xFFFF,(%a0)
    beq.s tx_put_uid
    addq.l #2,%a0
    bra.s tx_empty_slot
tx_put_uid:
    move.w %d4,(%a0)
    movea.l %a0,%a1
    lea RANKS,%a3
    move.w %d4,%d0
    add.w %d0,%d0
    move.w (%a3,%d0.w),%d1
tx_insert_sort:
    cmpa.l %a2,%a1
    beq.s tx_count_buyer
    move.w -2(%a1),%d0
    add.w %d0,%d0
    cmp.w (%a3,%d0.w),%d1
    bhs.s tx_count_buyer
    move.w -2(%a1),(%a1)
    move.w %d4,-2(%a1)
    subq.l #2,%a1
    bra.s tx_insert_sort
tx_count_buyer:
    move.w %d3,%d0
    mulu.w #6,%d0
    lea 1824(%a5),%a0
    adda.l %d0,%a0
    lea POSITIONS,%a3
    moveq #0,%d0
    move.b (%a3,%d4.w),%d0
    addq.b #1,(%a0,%d0.w)
    bra.s tx_seal
tx_sell:
    cmp.w %d7,%d3
    bne.w tx_bad
    bsr.s tx_remove_credit
tx_seal:
    addq.l #1,8(%a5)
    move.l 8(%a5),%d0
    not.l %d0
    move.l %d0,12(%a5)
    movea.l %a5,%a0
    bsr.w crc_contiguous
    move.w %d0,16(%a5)
    not.w %d0
    move.w %d0,18(%a5)
    move.w %d6,%d0
    bsr.w validate_contiguous
    tst.l %d0
    beq.s tx_bad
    movea.l %a5,%a0
    movea.l %a6,%a1
    move.w #511,%d0
tx_publish:
    move.l (%a0)+,(%a1)+
    dbra %d0,tx_publish
    moveq #1,%d0
    bra.s tx_done
tx_noop:
    moveq #2,%d0
    bra.s tx_done
tx_bad:
    moveq #0,%d0
tx_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    move.w (%sp)+,%sr
    tst.l %d0
    rts

| Known owner D7, UID D4, price D2, entry A1. Preserve buyer row A2.
tx_remove_credit:
    move.w %d7,%d0
    lsl.w #2,%d0
    lea 1696(%a5),%a0
    adda.w %d0,%a0
    add.l %d2,(%a0)
    move.w %d7,%d0
    mulu.w #52,%d0
    lea 84(%a5),%a3
    adda.l %d0,%a3
tx_shift:
    addq.l #2,%a1
    cmpa.l %a3,%a1
    bhs.s tx_shift_done
    move.w (%a1),-2(%a1)
    bra.s tx_shift
tx_shift_done:
    move.w #0xFFFF,-2(%a1)
    move.w %d7,%d0
    mulu.w #6,%d0
    lea 1824(%a5),%a0
    adda.l %d0,%a0
    lea POSITIONS,%a3
    moveq #0,%d0
    move.b (%a3,%d4.w),%d0
    subq.b #1,(%a0,%d0.w)
    rts
