    .ifndef WITH_COSMETIC_UI
    .equ WITH_COSMETIC_UI,0
    .endif
| Consistent Xbox labels: native Genesis C = Xbox B (select), native B = Xbox
| A (back alias), Start retains the reference Line Editor's done/back action.
| Explicit menu-only call sites; never remap skating/pass/shot controller input.
 .text
 .globl _start
_start:
 bra.w common_back
 bra.w line_back
 bra.w player_back
 bra.w line_footer_end
 bra.w common_footer_end
 bra.w main_footer_end
 bra.w main_play
 bra.w footer_line
 bra.w footer_common
 bra.w footer_main
 bra.w normalize_back
 bra.w pregame_wait_footer
 bra.w footer_pregame
 bra.w resume_hud
 bra.w input_footer
 bra.w footer_standings
 bra.w footer_leaders
 bra.w footer_teamstats
 bra.w replay_exit
 bra.w footer_confirm
 bra.w root_without_help

common_back:
 move.w %sr,-(%sp)
 cmpi.l #0x7D64,2(%sp)            | pictured root pause/period scoreboard
 beq.s common_root_no_help
 cmpi.l #0x1127E,2(%sp)           | same native pregame/intermission scoreboard
 beq.s common_root_no_help
 move.w (%sp)+,%sr
 bsr.w footer_common              | nested selection/confirmation keeps its actual help
 bra.s common_keys
common_root_no_help:
 move.w (%sp)+,%sr
 bsr.w root_without_help
common_keys:
 btst #4,%d1
 beq.s common_start
 move.w %sr,-(%sp)
 cmpi.l #0x1127E,2(%sp)
 bne.s common_back_parent
 cmpi.l #0x13190,40(%sp)
 bne.s common_back_parent
 tst.w 0xFFFFC3F4
 bne.s common_back_parent
 move.w (%sp)+,%sr
 jmp 0x172FA                      | pregame A returns to settings, never starts the match
common_back_parent:
 move.w (%sp)+,%sr
 bra.s common_leave
common_start:
 btst #7,%d1
 bne.s common_leave
 jmp 0x7E90
common_leave:
 jmp 0x7EEC
line_back:
 btst #4,%d1
 bne.s line_leave
 btst #7,%d1
 bne.s line_leave
 jmp 0x8338
line_leave:
 jmp 0x8812
player_back:
 btst #4,%d1
 bne.s player_leave
 btst #7,%d1
 bne.s player_leave
 jmp 0x8446
player_leave:
 jmp 0x831A
main_play:
 btst #5,%d1                       | Xbox B, same actual select button as Line Editor
 bne.s main_go
 btst #7,%d1
 bne.s main_go
 jmp 0xF7496
main_go:
 jmp 0xF843E
line_footer_end:
 bsr.w footer_line
 clr.w 0xFFFFB030                  | exact displaced native CLR/RTS
 rts
common_footer_end:
 move.w %sr,-(%sp)
 cmpi.l #0x7DCE,0xFFFFCF28        | native root scoreboard redraw callback
 bne.s common_footer_with_help
 move.w (%sp)+,%sr
 bsr.w root_without_help
 bra.s common_footer_delay
common_footer_with_help:
 move.w (%sp)+,%sr
 bsr.w footer_common
common_footer_delay:
 move.w #24,0xFFFFBD26             | native menu animation delay remains
 rts
main_footer_end:
 bsr.w footer_main
 movem.l (%sp)+,%d0-%d7/%a0-%a6    | exact original renderer epilogue
 rts
footer_line:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea line_text(%pc),%a1
 lea navigation_text(%pc),%a3
 bra.s footer
footer_pregame:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #2,%a2
 lea pregame_text(%pc),%a1
 lea navigation_text(%pc),%a3
 bra.s footer
footer_common:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea common_text(%pc),%a1
 lea navigation_text(%pc),%a3
 bra.s footer
footer_main:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #0,%a2
 lea main_text(%pc),%a1
 lea navigation_text(%pc),%a3
footer:
 move.w %sr,-(%sp)
 movem.w 0xFFFFB028,%d0-%d4         | x,y,attribute,plane VM fields
 movem.w %d0-%d4,-(%sp)
 move.w 0xFFFFBF78,-(%sp)
 move.w 0xFFFFC2F8,-(%sp)
 ori.w #0x700,%sr
 cmpa.l #0,%a2
 bne.s footer_font_ready
 bset #3,0xFFFFC2F8                | main help uses the same crisp small font as native menu labels
footer_font_ready:
 cmpa.l #3,%a2
 beq.w footer_replay
 cmpa.l #0,%a2
 beq.s footer_plane_ready
 | Own a fixed40-column bottom strip in both native32/40-column modes. Native
 | news remains above it; the last24 cells of each64-column row stay untouched.
 bclr #0,0xFFFFC2F0               | repaint native score/clock after this menu-owned overlay
 move.w #0x9218,0xC00004
 clr.w 0xFFFFB02E
 move.w #0x8F02,0xC00004
 move.l #0x6C000003,%d2
 moveq #3,%d1
footer_backing_row:
 move.l %d2,0xC00004
 moveq #39,%d0
footer_backing:
 move.w #0xA403,0xC00000
 dbra %d0,footer_backing
 addi.l #0x00800000,%d2             | next128-byte row, preserve24 hidden cells
 dbra %d1,footer_backing_row
 | Native blank font tiles are transparent. Retire the obsolete lower-panel
 | artwork on plane B too, otherwise its old arrows/frame shine through help.
 move.l #0x4C000003,%d2
 moveq #3,%d1
footer_old_panel_row:
 move.l %d2,0xC00004
 moveq #39,%d0
footer_old_panel:
 move.w #0x07FF,0xC00000
 dbra %d0,footer_old_panel
 addi.l #0x00800000,%d2
 dbra %d1,footer_old_panel_row
footer_plane_ready:
 jsr 0x25D01C                     | stable grey help panel before native text writes
 .if WITH_COSMETIC_UI
 cmpa.l #0,%a2
 bne.s main_frame_done
 bsr.w main_frame
main_frame_done:
 .endif
 cmpa.l #0,%a2
 beq.s footer_navigation_done
 move.l %a1,-(%sp)
 move.w #1,0xFFFFB028
 move.w #25,0xFFFFB02A
 move.w #0x8000,0xFFFFB02C
 movea.l %a3,%a1
 jsr 0x25D004                     | centre the actual native navigation help
 jsr 0x11BA4
 movea.l (%sp)+,%a1
footer_navigation_done:
 .if WITH_COSMETIC_UI
 cmpa.l #0,%a2
 bne.s ordinary_footer_position
 move.w #7,0xFFFFB028             | 26 visible glyph cells, centred in36-cell interior
 move.w #26,0xFFFFB02A
 bra.s final_footer_position
ordinary_footer_position:
 .endif
 move.w #1,0xFFFFB028
 move.w #27,0xFFFFB02A
 cmpa.l #1,%a2
 bne.s help_row_ready
 move.w #26,0xFFFFB02A
help_row_ready:
 jsr 0x25D004                     | retain keys/meaning; centre the trimmed help
 .if WITH_COSMETIC_UI
final_footer_position:
 .endif
 move.w #0x8000,0xFFFFB02C
 | Common/LineEditor menus expose the dedicated planeA footer above. Main
 | settings retain their own native selected text plane.
 jsr 0x11BA4                      | native game text, original fonts/palette
footer_restore:
 move.w (%sp)+,0xFFFFC2F8
 move.w (%sp)+,0xFFFFBF78
 movem.w (%sp)+,%d0-%d4
 movem.w %d0-%d4,0xFFFFB028
 jsr 0x11952                      | restore actual native text-cell VDP destination
 jsr 0x25D008                     | private grey blue-content modal preview
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d0-%d7/%a0-%a6
 rts
footer_replay:
 | Manual VCR help owns only the centre of the last row: leave both HUD boxes
 | untouched. The scripted automatic-replay branch never calls input_footer.
 clr.w 0xFFFFB02E
 move.w #9,0xFFFFB028
 move.w #27,0xFFFFB02A
 move.w #0x8000,0xFFFFB02C
 jsr 0x11952
 move.w #0x8F02,0xC00004
 moveq #22,%d0
footer_replay_clear:
 move.w #0xA403,0xC00000
 dbra %d0,footer_replay_clear
 jsr 0x11BA4
 btst #0,0xFFFFC2F6
 beq.w footer_restore
 | Retire obsolete Genesis B/C button artwork in the manual options window.
 | Keep its native frame/pattern bank, and describe the actual Xbox controls.
 move.w #8,0xFFFFB02E
 move.w #4,0xFFFFB02A
 moveq #5,%d1
footer_replay_option_row:
 cmpi.w #6,0xFFFFB02A
 beq.s footer_replay_option_next
 move.w #3,0xFFFFB028
 jsr 0x11952
 moveq #13,%d0
footer_replay_option_clear:
 move.w #0x8521,0xC00000
 dbra %d0,footer_replay_option_clear
footer_replay_option_next:
 addq.w #1,0xFFFFB02A
 dbra %d1,footer_replay_option_row
 move.w #3,0xFFFFB028
 move.w #4,0xFFFFB02A
 lea replay_heading(%pc),%a1
 jsr 0x11BA4
 move.w #3,0xFFFFB028
 move.w #7,0xFFFFB02A
 lea replay_reverse(%pc),%a1
 jsr 0x11BA4
 move.w #3,0xFFFFB028
 move.w #9,0xFFFFB02A
 lea replay_back(%pc),%a1
 jsr 0x11BA4
 bra.w footer_restore
normalize_back:
 btst #4,%d1
 beq.s no_new_back
 bset #7,%d1
no_new_back:
 btst #4,%d3
 beq.s no_held_back
 bset #7,%d3
no_held_back:
 rts
line_text:   .word 34
 .ascii "A Back  B Select  Start Done    "
 .even
common_text: .word 34
 .ascii "A Back  B Select  Start Back    "
 .even
 .if WITH_COSMETIC_UI
main_text: .word 28
 .ascii "D-pad Change  B/Start Play"
 .else
main_text:   .word 34
 .ascii "D-pad Change   B/Start Play     "
 .endif
 .even

| Native pregame's timed idle loop redraws its news ticker without invoking
| the key handler. Draw help AFTER that native call, scoped to its authenticated
| saved return13190. Matchups/ordinary clock waits retain their original maps.
pregame_wait_footer:
 jsr 0x15EC0
 cmpi.l #0x13190,32(%sp)
 bne.s pregame_wait_original
 bsr.w root_without_help
pregame_wait_original:
 move.w 0xFFFFB03E,%d0
 jmp 0x11298

resume_hud:
 | The native rink renderer restores plane B before this hook. Retire only
 | menu-owned plane A text; then let the native code rebuild BOTH HUD boxes.
 move.w %sr,-(%sp)
 movem.l %d0-%d2,-(%sp)
 ori.w #0x700,%sr
 move.w #0x8F02,0xC00004
 move.l #0x6C000003,%d2
 moveq #3,%d1
resume_help_row:
 move.l %d2,0xC00004
 moveq #39,%d0
resume_help_clear:
 move.w #0x07FF,0xC00000
 dbra %d0,resume_help_clear
 addi.l #0x00800000,%d2
 dbra %d1,resume_help_row
 movem.l (%sp)+,%d0-%d2
 move.w (%sp)+,%sr
 bclr #0,0xFFFFC2F0               | footer owns the lower rows only while the menu is open
 jsr 0x12C04                      | redraw both native real-score and clock boxes on return
 jmp 0x7DB4                       | tail-hook: preserve native wait/palette fade-in before pause RTS
pregame_text: .word 34
 .ascii "A Back  B Select  Start Play    "
 .even

navigation_text: .word 34
 .ascii "D-pad: Move selection           "
 .even

root_without_help:
 | jdc rr.png exception: restore the native full-height scoreboard window.
 | Other pages retain their contextual help. Resume retires hidden help cells.
 move.w %sr,-(%sp)
 ori.w #0x700,%sr
 move.w #0x921C,0xC00004
 move.w (%sp)+,%sr
 rts

| Called only by the normal (not scripted automatic replay) native A41E
| menu reader. Its caller is at6(SP): our return4 + reader's saved SR2.
| Draw after the page itself, using the page's actual native button actions.
input_footer:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 move.w %sr,-(%sp)
 move.l 68(%sp),%d0
 lea common_text(%pc),%a1
 lea navigation_text(%pc),%a3
 cmpi.l #0x832A,%d0
 beq.w input_line
 cmpi.l #0x8438,%d0
 beq.w input_draw
 cmpi.l #0x8172,%d0
 beq.w input_scroll
 cmpi.l #0x8F7A,%d0
 beq.w input_scroll
 cmpi.l #0x920C,%d0
 beq.w input_scroll
 cmpi.l #0xFDCE2,%d0
 beq.w input_scroll
 cmpi.l #0x8A8A,%d0
 beq.w input_roster
 cmpi.l #0x950C,%d0
 beq.w input_stats
 cmpi.l #0xFA220,%d0
 beq.w input_cards
 cmpi.l #0x9FC6,%d0
 beq.w input_wait
 cmpi.l #0xA0AA,%d0
 beq.w input_replay
 move.w (%sp)+,%sr
 movem.l (%sp)+,%d0-%d7/%a0-%a6
 rts
input_replay:
 lea replay_text(%pc),%a1
 btst #0,0xFFFFC2F6
 beq.s input_replay_ready
 lea replay_options(%pc),%a1
input_replay_ready:
 btst #4,%d1
 beq.s input_replay_draw
 bset #0,0xFFFFC2F6               | A backs directly to pause, Start still opens VCR options
input_replay_draw:
 movea.l #3,%a2
 move.w (%sp)+,%sr
 bra.w footer
input_line:
 lea line_text(%pc),%a1
 bra.s input_draw
input_scroll:
 lea back_text(%pc),%a1
 lea scroll_text(%pc),%a3
 bra.s input_draw
input_roster:
 lea teams_text(%pc),%a1
 lea roster_nav(%pc),%a3
 bra.s input_draw
input_stats:
 lea teams_text(%pc),%a1
 lea stats_nav(%pc),%a3
 bra.s input_draw
input_cards:
 lea cards_text(%pc),%a1
 lea cards_nav(%pc),%a3
 bra.s input_draw
input_wait:
 lea back_text(%pc),%a1
 lea blank_text(%pc),%a3
 cmpi.l #0x9E24,72(%sp)            | Change Goalie is a real selector, not a read-only page
 bne.s input_wait_readonly
 lea common_text(%pc),%a1
 lea navigation_text(%pc),%a3
 bra.s input_draw
input_wait_readonly:
 cmpi.l #0xFDAC2,72(%sp)
 bne.s input_draw
 lea period_nav(%pc),%a3
input_draw:
 movea.l #1,%a2
 move.w (%sp)+,%sr
 bra.w footer

footer_standings:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea standings_text(%pc),%a1
 lea standings_nav(%pc),%a3
 bra.w footer
footer_leaders:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea leaders_text(%pc),%a1
 lea page_nav(%pc),%a3
 bra.w footer
footer_teamstats:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea back_text(%pc),%a1
 lea page_nav(%pc),%a3
 bra.w footer
footer_confirm:
 movem.l %d0-%d7/%a0-%a6,-(%sp)
 movea.l #1,%a2
 lea confirm_text(%pc),%a1
 lea blank_text(%pc),%a3
 bra.w footer

back_text: .word 34
 .ascii "A/Start Back"
 .space 32-(.-back_text-2),32
scroll_text: .word 34
 .ascii "Up/Down: Scroll"
 .space 32-(.-scroll_text-2),32
teams_text: .word 34
 .ascii "A/Start Back  X Teams"
 .space 32-(.-teams_text-2),32
roster_nav: .word 34
 .ascii "L/R Line  U/D Status"
 .space 32-(.-roster_nav-2),32
stats_nav: .word 34
 .ascii "L/R Stat  U/D Scroll"
 .space 32-(.-stats_nav-2),32
cards_text: .word 34
 .ascii "A/Start Back  B Next  X Teams"
 .space 32-(.-cards_text-2),32
cards_nav: .word 34
 .ascii "Left/Right: Player"
 .space 32-(.-cards_nav-2),32
blank_text: .word 34
 .space 32,32
period_nav: .word 34
 .ascii "Left/Right: Stat"
 .space 32-(.-period_nav-2),32
standings_text: .word 34
 .ascii "A/Start Back  B Players"
 .space 32-(.-standings_text-2),32
standings_nav: .word 34
 .ascii "L/R Division  U/D Team"
 .space 32-(.-standings_nav-2),32
leaders_text: .word 34
 .ascii "A/Start Back  B Sort"
 .space 32-(.-leaders_text-2),32
page_nav: .word 34
 .ascii "Left/Right: Page"
 .space 32-(.-page_nav-2),32
replay_text: .word 25
 .ascii "A Back B Play Start Opt"
 .space 23-(.-replay_text-2),32
 .even
replay_options: .word 25
 .ascii "A/Start Back B Reverse"
 .space 23-(.-replay_options-2),32
 .even
replay_heading: .word 16
 .ascii "Replay Options"
replay_reverse: .word 16
 .ascii "B Reverse     "
replay_back: .word 16
 .ascii "A/Start Back  "
confirm_text: .word 34
 .ascii "A/Start Cancel  B Confirm"
 .space 32-(.-confirm_text-2),32

replay_exit:
 btst #4,%d1
 bne.s replay_exit_parent
 clr.w 0xFFFFCF20                 | exact native Start/automatic exit: return to game
 bset #1,0xFFFFC2F6
 jmp 0xA3A8
replay_exit_parent:
 move.w #1,0xFFFFCF20              | A returns to the parent pause menu, not Resume Game
 bclr #1,0xFFFFC2F6                | parent must redraw after VCR retired its maps
 jmp 0xA3A8

 .if WITH_COSMETIC_UI
| Main menu only: five rows stay in the original settings panel. Retire its
| unused sixth row with its original lower border atrow24; own a second native
| frame atrows25..27. Exact original3x3 frame tiles05B4..05BC, no new artwork.
| PlaneA columns1..38 only; all borders/hidden cells/planeB/palette preserved.
main_frame:
 move.w #0x8F02,0xC00004
 lea main_frame_tiles(%pc),%a0
 move.l #0x6C020003,%d2
 moveq #3,%d1
main_frame_row:
 move.l %d2,0xC00004
 move.w (%a0)+,0xC00000
 move.w (%a0)+,%d3
 moveq #35,%d0
main_frame_fill:
 move.w %d3,0xC00000
 dbra %d0,main_frame_fill
 move.w (%a0)+,0xC00000
 addi.l #0x00800000,%d2
 dbra %d1,main_frame_row
 | The fifth visible value's native selection also ends on row24. Our
 | outer-panel bottom has just covered its lower-left corner at column16.
 | Restore only that original corner; other selections keep a straight
 | outer bottom, so scrolling upward never leaves a stale selection notch.
 move.w %d7,%d0
 lsr.w #1,%d0
 sub.w 0xFFFFD422,%d0
 cmpi.w #4,%d0
 bne.s main_frame_done_corner
 move.l #0x6C200003,0xC00004
 move.w #0x8034,0xC00000
main_frame_done_corner:
 rts
main_frame_tiles:
 .word 0x05BA,0x05BB,0x05BC         | original settings bottom
 .word 0x05B4,0x05B5,0x05B6         | help top
 .word 0x05B7,0x05B8,0x05B9         | help interior
 .word 0x05BA,0x05BB,0x05BC         | help bottom, last visible row
 .endif
