| Dual-copy storage. Exports preserve every register except result D0, and
| original IRQ/X/SP. N/Z describe D0; V/C clear. No permanent scratch RAM.
| select: D0.W league1..3 -> D0.L even address,0 absent,-1 ambiguous/invalid.
| load: D0.W league,A0=FFE000 work image ->1 copied,0 absent,-1 error.
| save: D0.W league,A0=FFE000 sealed work image ->1 committed,0 rejected.
| Save requires exactly the next sequence, or sequence1 for a new league.
select_even:
    move.w %sr,-(%sp)
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.w #0x2700,%sr
    move.w %d0,%d6
    cmpi.w #1,%d6
    blo.w select_bad
    cmpi.w #3,%d6
    bhi.w select_bad
    subq.w #1,%d0
    andi.l #0xFFFF,%d0
    lsl.l #8,%d0
    lsl.l #5,%d0
    addi.l #0x204000,%d0
    movea.l %d0,%a4
    lea 0x1000(%a4),%a5
    moveq #0,%d5
    move.w %d6,%d0
    movea.l %a4,%a0
    bsr.w validate_even
    tst.l %d0
    beq.s select_second
    bset #0,%d5
select_second:
    move.w %d6,%d0
    movea.l %a5,%a0
    bsr.w validate_even
    tst.l %d0
    beq.s select_validated
    bset #1,%d5
select_validated:
    tst.w %d5
    beq.w select_absent
    cmpi.w #1,%d5
    beq.w select_first
    cmpi.w #2,%d5
    beq.w select_last
    bsr.w wait_dma
    move.b #1,MAPPER
    moveq #2,%d7
    lea 16(%a4),%a0
    bsr.w record_read_long
    move.l %d0,%d3
    lea 16(%a5),%a0
    bsr.w record_read_long
    sub.l %d3,%d0
    beq.s select_equal
    cmpi.l #0x80000000,%d0
    beq.s select_mapped_bad
    tst.l %d0
    bmi.s select_mapped_first
    move.b #0,MAPPER
    bra.s select_last
select_equal:
    movea.l %a4,%a0
    movea.l %a5,%a1
    move.w #2047,%d1
select_compare:
    move.b (%a0),%d2
    cmp.b (%a1),%d2
    bne.s select_mapped_bad
    addq.l #2,%a0
    addq.l #2,%a1
    dbra %d1,select_compare
select_mapped_first:
    move.b #0,MAPPER
select_first:
    move.l %a4,%d0
    bra.s select_done
select_last:
    move.l %a5,%d0
    bra.s select_done
select_mapped_bad:
    move.b #0,MAPPER
select_bad:
    moveq #-1,%d0
    bra.s select_done
select_absent:
    moveq #0,%d0
select_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    move.w (%sp)+,%sr
    tst.l %d0
    rts

load_even:
    move.w %sr,-(%sp)
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.w #0x2700,%sr
    move.l %a0,%d1
    andi.l #0xFFFFFF,%d1
    cmpi.l #0xFFE000,%d1
    bne.s load_bad
    bsr.w select_even
    tst.l %d0
    ble.s load_done
    movea.l %a0,%a1
    movea.l %d0,%a0
    bsr.w wait_dma
    move.b #1,MAPPER
    move.w #2047,%d1
load_byte:
    move.b (%a0),(%a1)+
    addq.l #2,%a0
    dbra %d1,load_byte
    move.b #0,MAPPER
    moveq #1,%d0
    bra.s load_done
load_bad:
    moveq #-1,%d0
load_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    move.w (%sp)+,%sr
    tst.l %d0
    rts

save_even:
    move.w %sr,-(%sp)
    movem.l %d1-%d7/%a0-%a6,-(%sp)
    move.w #0x2700,%sr
    move.l %a0,%d1
    andi.l #0xFFFFFF,%d1
    cmpi.l #0xFFE000,%d1
    bne.w save_bad
    move.w %d0,%d6
    movea.l %a0,%a6
    bsr.w validate_contiguous
    tst.l %d0
    beq.w save_bad
    move.w %d6,%d0
    bsr.w select_even
    tst.l %d0
    bmi.w save_bad
    beq.s save_new
    movea.l %d0,%a2
    move.l %d0,%d5
    eori.l #0x1000,%d5
    lea 16(%a2),%a0
    bsr.w wait_dma
    move.b #1,MAPPER
    moveq #2,%d7
    bsr.w record_read_long
    move.b #0,MAPPER
    addq.l #1,%d0
    cmp.l 8(%a6),%d0
    bne.w save_bad
    movea.l %d5,%a2
    bra.s save_write
save_new:
    cmpi.l #1,8(%a6)
    bne.s save_bad
    moveq #0,%d0
    move.w %d6,%d0
    subq.w #1,%d0
    lsl.l #8,%d0
    lsl.l #5,%d0
    addi.l #0x204000,%d0
    movea.l %d0,%a2
save_write:
    bsr.w wait_dma
    move.b #1,MAPPER
    clr.b (%a2)                    | Invalidate inactive target FIRST.
    lea 1(%a6),%a0
    lea 2(%a2),%a1
    move.w #2046,%d1
save_payload_byte:
    move.b (%a0)+,(%a1)
    addq.l #2,%a1
    dbra %d1,save_payload_byte
    move.b (%a6),(%a2)             | Publish commit byte LAST.
    move.b #0,MAPPER
    moveq #1,%d0
    bra.s save_done
save_bad:
    moveq #0,%d0
save_done:
    movem.l (%sp)+,%d1-%d7/%a0-%a6
    move.w (%sp)+,%sr
    tst.l %d0
    rts
