| Main-menu-only responsiveness. Does not skip any SRAM/CRC validation.
| F930..F933 is a volatile guarded menu-lifetime tag, cleared before leaving.
| Original game/pause/statistics audio and repeat readers remain unchanged.
 .equ ACTIVE,0xFFFFF930
 .equ SEEN,0xFFFFF934
 .equ PENDING,0xFFFFF935
 .equ MAGIC,0x4D4EB2B1
 .text
 .globl _start
_start:
 bra.w enter
 bra.w leave
 bra.w record_crc
 bra.w reset_crc
 .ascii "MM01"
 bra.w repeat
 bra.w menu_tick
 bra.w bank_sum
 bra.w bank_copy_d0
 bra.w bank_copy_d2
 bra.w bank_clear
enter:
 jsr 0xFE660
 move.w %sr,-(%sp)
 clr.w SEEN
 move.l #MAGIC,ACTIVE
 move.w (%sp)+,%sr
 rts
leave:
 move.w %sr,-(%sp)
 clr.w SEEN
 clr.l ACTIVE
 move.w (%sp)+,%sr
 jmp 0x2E6000
| The original CRC entry has already saved all registers and the caller SR.
| Replay exact displaced setup off-menu. On-menu compute the SAME CCITT CRC
| over all record bytes, with the SAME commit/checksum exclusions.
record_crc:
 cmpi.l #MAGIC,ACTIVE
 beq.s record_fast
 adda.w %d7,%a0
 move.w #0xFFFF,%d2
 jmp 0x2340B0
record_fast:
 adda.w %d7,%a0
 move.w #255,%d2
 move.w #255,%d5
 lea crc_table(%pc),%a2
 lea crc_table_low(%pc),%a1
 moveq #0,%d1
 moveq #14,%d3
record_first:
 move.b (%a0),%d1
 adda.w %d7,%a0
 move.w %d2,%d4
 eor.b %d1,%d4
 move.b (%a2,%d4.w),%d2
 eor.b %d5,%d2
 move.b (%a1,%d4.w),%d5
 dbra %d3,record_first
 move.w %d7,%d3
 lsl.w #2,%d3
 adda.w %d3,%a0
 move.w #506,%d3
record_rest:
 .rept 4
 move.b (%a0),%d1
 adda.w %d7,%a0
 move.w %d2,%d4
 eor.b %d1,%d4
 move.b (%a2,%d4.w),%d2
 eor.b %d5,%d2
 move.b (%a1,%d4.w),%d5
 .endr
 move.w %d3,%d4
 andi.w #7,%d4
 bne.s record_next
 bsr.w service_audio
record_next:
 dbra %d3,record_rest
record_done:
 bsr.w service_audio
 lsl.w #8,%d2
 or.w %d5,%d2
 moveq #0,%d0
 move.w %d2,%d0
 jmp 0x2340E6
| Replay-journal CRC: every one of the8192 bytes is still checked. Binding the
| accepted target slot runs through the original tail at25627A unchanged.
reset_crc:
 cmpi.l #MAGIC,ACTIVE
 beq.s reset_fast
 lea 0x20A000,%a0
 jmp 0x256256
reset_fast:
 movem.l %a1-%a2,-(%sp)
 lea 0x20A000,%a0
 lea crc_table(%pc),%a1
 lea crc_table_low(%pc),%a2
 move.w #255,%d1
 move.w #255,%d2
 move.w #2047,%d3
 moveq #0,%d0
reset_byte:
 .rept 4
 move.b (%a0),%d0
 eor.b %d1,%d0
 move.b (%a1,%d0.w),%d1
 eor.b %d2,%d1
 move.b (%a2,%d0.w),%d2
 addq.l #2,%a0
 .endr
 move.w %d3,%d0
 andi.w #15,%d0
 bne.s reset_no_service
 bsr.w service_audio
reset_no_service:
 dbra %d3,reset_byte
 bsr.w service_audio
 lsl.w #8,%d1
 or.w %d2,%d1
 movem.l (%sp)+,%a1-%a2
 jmp 0x25627A
| Preserve the real native reader's registers/status. Only main-menu fresh
| and held directional repeat delays change; selection/Start buttons do not.
repeat:
 jsr 0x11318
 move.w %sr,-(%sp)
 move.l %d0,-(%sp)
 move.w %d1,%d0
 andi.w #15,%d0
 beq.s repeat_done
 move.w %d2,%d0
 andi.w #15,%d0
 beq.s repeated_direction
 move.w %d3,%d0
 andi.w #15,%d0
 beq.s repeat_done
 move.w #7,0xFFFFB042
 bra.s repeat_done
repeated_direction:
 move.w #2,0xFFFFB042
repeat_done:
 move.l (%sp)+,%d0
 move.w (%sp)+,%sr
 rts
| Keep native music ticking during main-menu checks with IRQs masked.
| HV identifies physical VBlank. Mode5 status.bit7 distinguishes an unacked
| VINT from a previous native tick when a checksum starts just at the boundary.
| This read is only inside main-menu SRAM/checksum code (already status-polled
| by the native DMA waits); it writes no VDP/DMA command or game state.
| Each observed physical VBlank gets one original sound tick. The pending
| real main-menu IRQ subsequently skips its already serviced tick.
service_audio:
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 cmpi.l #MAGIC,ACTIVE
 bne.s audio_done
 cmpi.l #0x17C42,0xFFFFB03A
 bne.s audio_done
 move.l %d0,-(%sp)
 move.b 0xC00008,%d0
 cmpi.b #224,%d0
 blo.s audio_active
 tst.b SEEN
 beq.s audio_check_vint
 tst.b PENDING
 bne.s audio_restore_d0
audio_check_vint:
 btst #7,0xC00005
 beq.s audio_restore_d0
 st SEEN
 st PENDING
 addq.w #1,0xFFFFB03E
 movem.l %d1-%d7/%a0-%a6,-(%sp)
 jsr 0x1A50A
 movem.l (%sp)+,%d1-%d7/%a0-%a6
 bra.s audio_restore_d0
audio_active:
 clr.b SEEN
audio_restore_d0:
 move.l (%sp)+,%d0
audio_done:
 move.w (%sp)+,%sr
 rts
| Called ONLY by the original main-menu IRQ, after its palette/DMA work.
menu_tick:
 move.b SEEN,%d1
 clr.b SEEN
 move.b 0xC00008,%d0
 cmpi.b #224,%d0
 blo.s tick_pending
 st SEEN
tick_pending:
 tst.b PENDING
 beq.s tick_native
 clr.b PENDING
 tst.b SEEN
 beq.s tick_return
 tst.b %d1
 beq.s tick_native
 bra.s tick_return
tick_native:
 addq.w #1,0xFFFFB03E
 jsr 0x1A50A
tick_return:
 jmp 0x17C6C
| Exact8190-byte additive bank checksum for both validation and commit.
| Called at the two original loops; no metadata or checksum tail is changed.
bank_sum:
 cmpi.l #MAGIC,ACTIVE
 beq.s bank_sum_active
bank_sum_native:
 add.b (%a0),%d0
 addq.l #2,%a0
 dbra %d1,bank_sum_native
 rts
bank_sum_active:
 movem.l %d2-%d3,-(%sp)
 move.w %sr,-(%sp)
 moveq #0,%d2
 move.w %d1,%d2
 addq.l #1,%d2
 move.l %d2,%d3
 lsr.l #4,%d2
 andi.w #15,%d3
 subq.w #1,%d2
 subq.w #1,%d3
 move.w (%sp)+,%sr
 tst.w %d2
 bmi.w bank_sum_no_chunk
bank_sum_chunk:
 .rept 16
 add.b (%a0),%d0
 addq.l #2,%a0
 .endr
 bsr.w service_audio
 dbra %d2,bank_sum_chunk
bank_sum_no_chunk:
 move.w %sr,-(%sp)
 tst.w %d3
 bmi.s bank_sum_no_tail
 addq.l #2,%sp
bank_sum_tail:
 add.b (%a0),%d0
 addq.l #2,%a0
 dbra %d3,bank_sum_tail
 bra.s bank_sum_done
bank_sum_no_tail:
 move.w (%sp)+,%sr
bank_sum_done:
 bsr.w service_audio
 move.w %sr,-(%sp)
 move.w #0xFFFF,%d1
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d2-%d3
 rts
bank_copy_d0:
 cmpi.l #MAGIC,ACTIVE
 beq.s bank_copy_d0_active
bank_copy_d0_native:
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 dbra %d0,bank_copy_d0_native
 rts
bank_copy_d0_active:
 movem.l %d1-%d2,-(%sp)
 move.w %sr,-(%sp)
 moveq #0,%d1
 move.w %d0,%d1
 addq.l #1,%d1
 move.l %d1,%d2
 lsr.l #4,%d1
 andi.w #15,%d2
 subq.w #1,%d1
 subq.w #1,%d2
 move.w (%sp)+,%sr
 tst.w %d1
 bmi.w bank_copy_d0_no_chunk
bank_copy_d0_chunk:
 .rept 16
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 .endr
 bsr.w service_audio
 dbra %d1,bank_copy_d0_chunk
bank_copy_d0_no_chunk:
 move.w %sr,-(%sp)
 tst.w %d2
 bmi.s bank_copy_d0_no_tail
 addq.l #2,%sp
bank_copy_d0_tail:
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 dbra %d2,bank_copy_d0_tail
 bra.s bank_copy_d0_done
bank_copy_d0_no_tail:
 move.w (%sp)+,%sr
bank_copy_d0_done:
 bsr.w service_audio
 move.w %sr,-(%sp)
 move.w #0xFFFF,%d0
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d1-%d2
 rts
bank_copy_d2:
 cmpi.l #MAGIC,ACTIVE
 beq.s bank_copy_d2_active
bank_copy_d2_native:
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 dbra %d2,bank_copy_d2_native
 rts
bank_copy_d2_active:
 movem.l %d0-%d1,-(%sp)
 move.w %sr,-(%sp)
 moveq #0,%d0
 move.w %d2,%d0
 addq.l #1,%d0
 move.l %d0,%d1
 lsr.l #4,%d0
 andi.w #15,%d1
 subq.w #1,%d0
 subq.w #1,%d1
 move.w (%sp)+,%sr
 tst.w %d0
 bmi.w bank_copy_d2_no_chunk
bank_copy_d2_chunk:
 .rept 16
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 .endr
 bsr.w service_audio
 dbra %d0,bank_copy_d2_chunk
bank_copy_d2_no_chunk:
 move.w %sr,-(%sp)
 tst.w %d1
 bmi.s bank_copy_d2_no_tail
 addq.l #2,%sp
bank_copy_d2_tail:
 move.b (%a0),(%a1)
 addq.l #2,%a0
 addq.l #2,%a1
 dbra %d1,bank_copy_d2_tail
 bra.s bank_copy_d2_done
bank_copy_d2_no_tail:
 move.w (%sp)+,%sr
bank_copy_d2_done:
 bsr.w service_audio
 move.w %sr,-(%sp)
 move.w #0xFFFF,%d2
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d0-%d1
 rts
bank_clear:
 cmpi.l #MAGIC,ACTIVE
 beq.s bank_clear_active
bank_clear_native:
 clr.b (%a0)
 addq.l #2,%a0
 dbra %d0,bank_clear_native
 rts
bank_clear_active:
 movem.l %d1-%d2,-(%sp)
 move.w %sr,-(%sp)
 moveq #0,%d1
 move.w %d0,%d1
 addq.l #1,%d1
 move.l %d1,%d2
 lsr.l #4,%d1
 andi.w #15,%d2
 subq.w #1,%d1
 subq.w #1,%d2
 move.w (%sp)+,%sr
 tst.w %d1
 bmi.w bank_clear_no_chunk
bank_clear_chunk:
 .rept 16
 clr.b (%a0)
 addq.l #2,%a0
 .endr
 bsr.w service_audio
 dbra %d1,bank_clear_chunk
bank_clear_no_chunk:
 move.w %sr,-(%sp)
 tst.w %d2
 bmi.s bank_clear_no_tail
 addq.l #2,%sp
bank_clear_tail:
 clr.b (%a0)
 addq.l #2,%a0
 dbra %d2,bank_clear_tail
 bra.s bank_clear_done
bank_clear_no_tail:
 move.w (%sp)+,%sr
bank_clear_done:
 bsr.w service_audio
 move.w %sr,-(%sp)
 move.w #0xFFFF,%d0
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d1-%d2
 rts
 .org 0x800
crc_table:
 .byte 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xA1,0xB1,0xC1,0xD1,0xE1,0xF1
 .byte 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xB3,0xA3,0xD3,0xC3,0xF3,0xE3
 .byte 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xA5,0xB5,0x85,0x95,0xE5,0xF5,0xC5,0xD5
 .byte 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xB7,0xA7,0x97,0x87,0xF7,0xE7,0xD7,0xC7
 .byte 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xC9,0xD9,0xE9,0xF9,0x89,0x99,0xA9,0xB9
 .byte 0x5A,0x4A,0x7A,0x6A,0x1A,0x0A,0x3A,0x2A,0xDB,0xCB,0xFB,0xEB,0x9B,0x8B,0xBB,0xAB
 .byte 0x6C,0x7C,0x4C,0x5C,0x2C,0x3C,0x0C,0x1C,0xED,0xFD,0xCD,0xDD,0xAD,0xBD,0x8D,0x9D
 .byte 0x7E,0x6E,0x5E,0x4E,0x3E,0x2E,0x1E,0x0E,0xFF,0xEF,0xDF,0xCF,0xBF,0xAF,0x9F,0x8F
 .byte 0x91,0x81,0xB1,0xA1,0xD1,0xC1,0xF1,0xE1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60
 .byte 0x83,0x93,0xA3,0xB3,0xC3,0xD3,0xE3,0xF3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72
 .byte 0xB5,0xA5,0x95,0x85,0xF5,0xE5,0xD5,0xC5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44
 .byte 0xA7,0xB7,0x87,0x97,0xE7,0xF7,0xC7,0xD7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56
 .byte 0xD9,0xC9,0xF9,0xE9,0x99,0x89,0xB9,0xA9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28
 .byte 0xCB,0xDB,0xEB,0xFB,0x8B,0x9B,0xAB,0xBB,0x4A,0x5A,0x6A,0x7A,0x0A,0x1A,0x2A,0x3A
 .byte 0xFD,0xED,0xDD,0xCD,0xBD,0xAD,0x9D,0x8D,0x7C,0x6C,0x5C,0x4C,0x3C,0x2C,0x1C,0x0C
 .byte 0xEF,0xFF,0xCF,0xDF,0xAF,0xBF,0x8F,0x9F,0x6E,0x7E,0x4E,0x5E,0x2E,0x3E,0x0E,0x1E
crc_table_low:
 .byte 0x00,0x21,0x42,0x63,0x84,0xA5,0xC6,0xE7,0x08,0x29,0x4A,0x6B,0x8C,0xAD,0xCE,0xEF
 .byte 0x31,0x10,0x73,0x52,0xB5,0x94,0xF7,0xD6,0x39,0x18,0x7B,0x5A,0xBD,0x9C,0xFF,0xDE
 .byte 0x62,0x43,0x20,0x01,0xE6,0xC7,0xA4,0x85,0x6A,0x4B,0x28,0x09,0xEE,0xCF,0xAC,0x8D
 .byte 0x53,0x72,0x11,0x30,0xD7,0xF6,0x95,0xB4,0x5B,0x7A,0x19,0x38,0xDF,0xFE,0x9D,0xBC
 .byte 0xC4,0xE5,0x86,0xA7,0x40,0x61,0x02,0x23,0xCC,0xED,0x8E,0xAF,0x48,0x69,0x0A,0x2B
 .byte 0xF5,0xD4,0xB7,0x96,0x71,0x50,0x33,0x12,0xFD,0xDC,0xBF,0x9E,0x79,0x58,0x3B,0x1A
 .byte 0xA6,0x87,0xE4,0xC5,0x22,0x03,0x60,0x41,0xAE,0x8F,0xEC,0xCD,0x2A,0x0B,0x68,0x49
 .byte 0x97,0xB6,0xD5,0xF4,0x13,0x32,0x51,0x70,0x9F,0xBE,0xDD,0xFC,0x1B,0x3A,0x59,0x78
 .byte 0x88,0xA9,0xCA,0xEB,0x0C,0x2D,0x4E,0x6F,0x80,0xA1,0xC2,0xE3,0x04,0x25,0x46,0x67
 .byte 0xB9,0x98,0xFB,0xDA,0x3D,0x1C,0x7F,0x5E,0xB1,0x90,0xF3,0xD2,0x35,0x14,0x77,0x56
 .byte 0xEA,0xCB,0xA8,0x89,0x6E,0x4F,0x2C,0x0D,0xE2,0xC3,0xA0,0x81,0x66,0x47,0x24,0x05
 .byte 0xDB,0xFA,0x99,0xB8,0x5F,0x7E,0x1D,0x3C,0xD3,0xF2,0x91,0xB0,0x57,0x76,0x15,0x34
 .byte 0x4C,0x6D,0x0E,0x2F,0xC8,0xE9,0x8A,0xAB,0x44,0x65,0x06,0x27,0xC0,0xE1,0x82,0xA3
 .byte 0x7D,0x5C,0x3F,0x1E,0xF9,0xD8,0xBB,0x9A,0x75,0x54,0x37,0x16,0xF1,0xD0,0xB3,0x92
 .byte 0x2E,0x0F,0x6C,0x4D,0xAA,0x8B,0xE8,0xC9,0x26,0x07,0x64,0x45,0xA2,0x83,0xE0,0xC1
 .byte 0x1F,0x3E,0x5D,0x7C,0x9B,0xBA,0xD9,0xF8,0x17,0x36,0x55,0x74,0x93,0xB2,0xD1,0xF0
