    .ifndef WITH_REFINEMENTS
    .equ WITH_REFINEMENTS,0
    .endif
    .ifndef WITH_REPLAY_HUD
    .equ WITH_REPLAY_HUD,0
    .endif
    .equ MAGIC,0xFFF640
    .equ SHOOT,0xFFF642                | shooter object + 1
    .equ CHG,0xFFF644
    .equ SHOW,0xFFF646
    .equ LIVE,0xFFF648
    .equ BLINK,0xFFF64A
    .equ OBJ,0xFFFFB04A
    .equ TILE,0x7E1                    | crowd.s bar tiles: +0 black 32x8, +4 white, +8 red, partials
    .equ PANEL,0xFFF64C                | 1 while the panel is in the HUD plane
    .equ HELD,0xFFF64E                 | last shot held throughout automatic replay
    .equ KMH,0xFFF650
    .equ MPH,0xFFF652
    .equ STILE,0x7E1                   | r38: the bar's own 4 tiles (crowd.s mkbar), HUD-plane cells
    .equ SBUF,0xFFEA00                 | crowd.s BBUF+256
    .equ VDATA,0xC00000
    .equ VCTRL,0xC00004
 .text
 .globl _start
_start:
 bra.w panel_left
 bra.w badge_available
 bra.w wipe_logo
 bra.w compact_clear
 bra.w above_owned
| Compact shot display uses only the native NHL badge's 7x2 interior.
| Actual native penalty text owns that same interior: fall back above it.
| Availability reads VDP memory atomically and accepts only NHL/our own cells.
badge_available:
 movem.l %d1-%d7/%a0-%a2,-(%sp)
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 suba.w #28,%sp
 movea.l %sp,%a0
 move.w #0x8F02,VCTRL
 move.l #0x2C820003,VCTRL
 moveq #6,%d1
badge_read1:
 move.w VDATA,(%a0)+
 dbra %d1,badge_read1
 move.l #0x2D020003,VCTRL
 moveq #6,%d1
badge_read2:
 move.w VDATA,(%a0)+
 dbra %d1,badge_read2
 movea.l %sp,%a0
 move.w #0xA1C8,%d1
 moveq #13,%d2
badge_logo_check:
 cmp.w (%a0)+,%d1
 bne.s badge_check_ours
 addq.w #1,%d1
 dbra %d2,badge_logo_check
 moveq #2,%d0
 bra.w badge_done
badge_check_ours:
 movea.l %sp,%a0
 moveq #6,%d2
badge_bar_check:
 move.w (%a0)+,%d1
 cmpi.w #0xA403,%d1
 beq.s badge_bar_next
 cmpi.w #0x841B,%d1
 beq.s badge_bar_next
 tst.w HELD
 beq.s badge_check_bar_tile
 cmpi.w #0x07FF,%d1
 beq.s badge_bar_next
badge_check_bar_tile:
 andi.w #0x9FFF,%d1
 cmpi.w #0x87E1,%d1
 bcs.w badge_foreign
 .if WITH_REFINEMENTS
 cmpi.w #0x87E6,%d1
 .else
 cmpi.w #0x87E4,%d1
 .endif
 bhi.w badge_foreign
badge_bar_next:
 dbra %d2,badge_bar_check
 movea.l %a0,%a2
 moveq #6,%d2
badge_blank_check:
 move.w (%a0)+,%d1
 cmpi.w #0xA403,%d1
 beq.s badge_blank_next
 tst.w HELD
 beq.s badge_font_check
 cmpi.w #0x07FF,%d1
 bne.s badge_font_check
badge_blank_next:
 dbra %d2,badge_blank_check
 moveq #1,%d0
 bra.s badge_done
badge_font_check:
 movea.l %a2,%a0
 lea compact_map,%a1
 moveq #6,%d2
badge_font_loop:
 cmpm.w (%a0)+,(%a1)+
 bne.s badge_foreign
 dbra %d2,badge_font_loop
 moveq #1,%d0
 bra.s badge_done
badge_foreign:
 moveq #0,%d0
badge_done:
 adda.w #28,%sp
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d1-%d7/%a0-%a2
 tst.w %d0
 rts
compact_map:
 .if WITH_REFINEMENTS
 .word 0x87F4,0x87F5,0x87F6,0xA403,0xA403,0xA403,0xA403
 .else
 .word 0x87F4,0x87F5,0x87F6,0xA403,0x87F7,0x87F8,0x87F9
 .endif

wipe_logo:
 movem.l %d0-%d2/%a1,-(%sp)
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 move.w #0x8F02,VCTRL
 move.l #0x2C820003,VCTRL
 move.w VDATA,%d0
 cmpi.w #0xA1C8,%d0
 bne.s wipe_done
 | The common already-erased case costs just one read. Verify all14native
 | badge cells before clearing; penalty text and our existing panel stay intact.
 bsr.w badge_available
 cmpi.w #2,%d0
 bne.s wipe_done
 bsr.w compact_clear
wipe_done:
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d0-%d2/%a1
 rts
compact_clear:
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 lea VDATA,%a1
 move.w #0x8F02,VCTRL
 move.l #0x6C820003,VCTRL
 moveq #6,%d2
compact_clear1:
 move.w #0xA403,(%a1)
 dbra %d2,compact_clear1
 move.l #0x6D020003,VCTRL
 moveq #6,%d2
compact_clear2:
 move.w #0xA403,(%a1)
 dbra %d2,compact_clear2
 move.w (%sp)+,%sr
 rts

panel_left:
 movem.l %d0-%d7/%a0-%a1,-(%sp)
 bsr.w badge_available
 .if WITH_REPLAY_HUD && !WITH_REFINEMENTS
 | Native timer redraws can temporarily blank the badge before PP text returns.
 | Actual unequal manpower still owns that interior, even in that blank phase.
 move.w 0xFFFFC6F2,%d1
 cmp.w 0xFFFFCA56,%d1
 beq.s panel_caption_ready
 moveq #0,%d0
panel_caption_ready:
 .endif
 moveq #2,%d2
 tst.w %d0
 beq.s choose_layout
 moveq #1,%d2
choose_layout:
 cmp.w PANEL,%d2
 beq.s layout_ready
 jsr 0x2ED010
layout_ready:
 tst.w PANEL
 bne.s font_cache_ready
 move.l #-1,0xFFE8F6                | a new panel may follow a native VRAM clear
font_cache_ready:
 movem.l (%sp),%d0-%d1
 move.l 16(%sp),%d4
 cmpi.w #1,%d2
 beq.s draw_compact
 jsr 0x2ED014
 bra.s panel_left_done
draw_compact:
 bsr.w compact_panel
panel_left_done:
 movem.l (%sp)+,%d0-%d7/%a0-%a1
 rts
compact_panel:
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 lea VDATA,%a1
 move.w %d0,%d5
 move.w #0x8F02,VCTRL
 move.l #0x6C820003,VCTRL
 tst.w HELD
 bne.s compact_replay
compact_coloured:
 jsr 0x2ED00C
 move.w %d0,(%a1)
 addq.w #1,%d0
 move.w %d0,(%a1)
 addq.w #1,%d0
 move.w %d0,(%a1)
 addq.w #1,%d0
 move.w %d0,(%a1)
 move.w #0xA403,(%a1)
 move.w #0xA403,(%a1)
 move.w #0xA403,(%a1)
 bra.s compact_speed
compact_replay:
 .if WITH_REPLAY_HUD
 bra.w compact_coloured
 .endif
 move.w CHG,%d6
 subi.w #15,%d6
 bpl.s compact_positive
 moveq #0,%d6
compact_positive:
 cmpi.w #16,%d6
 bls.s compact_capped
 moveq #16,%d6
compact_capped:
 mulu.w #6,%d6
 addi.w #15,%d6
 divu.w #16,%d6
 moveq #0,%d2
compact_dash:
 move.w #0xA403,%d0
 cmp.w %d6,%d2
 bcc.s compact_dash_write
 move.w #0x841B,%d0
compact_dash_write:
 move.w %d0,(%a1)
 addq.w #1,%d2
 cmpi.w #6,%d2
 bcs.s compact_dash
 move.w #0xA403,(%a1)
compact_speed:
 move.l #0x6D020003,VCTRL
 tst.w SHOW
 bne.s compact_numbers
 moveq #6,%d2
compact_blank:
 move.w #0xA403,(%a1)
 dbra %d2,compact_blank
 bra.w compact_done
compact_numbers:
 lea compact_map,%a0
 moveq #6,%d2
compact_map_loop:
 move.w (%a0)+,(%a1)
 dbra %d2,compact_map_loop
 .if WITH_REFINEMENTS
 cmpi.w #1,0xFFFFF8D8
 bne.s compact_kmh
 move.w %d4,%d0
 lea 0x277700,%a0
 bra.s compact_unit_ready
compact_kmh:
 .endif
 move.w %d5,%d0
 lea 0x260000,%a0
 .if WITH_REFINEMENTS
compact_unit_ready:
 .endif
 move.w #0xFE80,%d1
 lea 0xFFE8F6,%a1
 bsr.w compact_font
 .if WITH_REFINEMENTS
 bra.s compact_done
 .endif
 move.w %d4,%d0
 lea 0x277700,%a0
 move.w #0xFEE0,%d1
 lea 0xFFE8F8,%a1
 bsr.w compact_font
compact_done:
 move.w #1,PANEL
 move.w (%sp)+,%sr
 rts
compact_font:
 andi.l #0xFFFF,%d0
 cmpi.w #999,%d0
 bls.s font_capped
 move.w #999,%d0
font_capped:
 tst.w PANEL
 beq.s font_load
 tst.w HELD
 bne.s font_load
 cmp.w (%a1),%d0
 beq.s font_done
font_load:
 move.w %d0,(%a1)
 mulu.w #96,%d0
 adda.l %d0,%a0
 move.l %a0,(%a5)+
 move.w #48,(%a5)+
 move.w %d1,(%a5)+
font_done:
 rts

| Only erase an above-clock rectangle still carrying BOTH of our full frames.
| Native pause/penalty/period windows have already replaced them: leave intact.
above_owned:
 movem.l %d1-%d2/%a0,-(%sp)
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 lea above_frame,%a0
 move.w #0x8F02,VCTRL
 move.l #0x29000003,VCTRL
 moveq #7,%d1
above_top:
 move.w VDATA,%d2
 cmp.w (%a0)+,%d2
 bne.s above_foreign
 dbra %d1,above_top
 move.l #0x2B000003,VCTRL
 moveq #7,%d1
above_bottom:
 move.w VDATA,%d2
 cmp.w (%a0)+,%d2
 bne.s above_foreign
 dbra %d1,above_bottom
 moveq #1,%d0
 bra.s above_done
above_foreign:
 moveq #0,%d0
above_done:
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d1-%d2/%a0
 tst.w %d0
 rts
above_frame:
 .word 0xA3FF,0xA400,0xA400,0xA400,0xA400,0xA400,0xA400,0xA401
 .word 0xA405,0xA406,0xA406,0xA406,0xA406,0xA406,0xA406,0xA407
