; ======================================================================
; lib-set-01: MENU, source candidate r006 (HD61 Rev 0.45, unassembled).
; A reusable, non-blinking, caller-owned selection interface.
;
; Group record (ROM, contiguous, exactly 68 bytes each):
;  +00..31 : 32 ASCII title/status cells, physical row 1
;  +32..63 : four 8-byte bracketed lower-case FK captions, row 4
;  +64..67 : aliases for FK1..FK4: 0 = numeric default '1'..'4',
;            otherwise a single ASCII alphabetic shortcut. Explicit
;            aliases REPLACE, rather than supplement, defaults.
; Each group uses physical rows 1 and 4; rows 2 and 3 are blank.
;
; MNU_INIT input: $10/$11 = ROM pointer to first 68-byte record,
;                 $12 = count (1..255, enough ROM for all records).
;          output: $0=0 success, 1 invalid group count, 2 alias collision,
;                      3 invalid explicit alias. Groups validated upfront.
;          resets active group to group 1 (explicit initialization only).
; MNU_SHOW: renders active group, clearing rows 2/3; returns $0=0.
; MNU_WAIT: blocks for one normalized selection. Handles ETC with wrap,
;           redraw and key release inside the service.
;     output: $0=0 selection, $8=1-based group, $9=1..4 FK ordinal;
;             $0=1 MENU, $0=2 BRK, $9=0 (distinct caller-owned exit).
;           Physical FK and effective alias return same group/FK.
;           Unrecognized presses ignored after release.
; MNU_NEXT: programmatic one-group advance (ETC's only mechanism).
; MNU_GROUP RAM persists across service calls; MNU_SHOW does not reset it.
;
; Depends on LCD_CLEAR/LCD_ROM32, KEY_WAIT, RAW_READY, OFFCHK and
; SYS540 platform $SY=1, UA=14 RAM with MNU_* allocations. No cursor.
; Scratch/clobbers: $0..$13, $20..$25, IX/IZ and flags; not reentrant.
; Exact ABI/register clobbers and dual-model key delivery need native tests.
; ======================================================================
MNU_INIT:
        PST     UA,&H14
        AN      $12,$12
        JP      Z,MNU_INVAL
        PRE     IX,MNU_TABLE
        STW     $10,(IX+$SX)
        PRE     IX,MNU_COUNT
        ST      $12,(IX+$SX)
        PRE     IX,MNU_GROUP
        LD      $0,0
        ST      $0,(IX+$SX)
        PRE     IX,MNU_SCAN
        ST      $0,(IX+$SX)
MNU_IVAL:
        PRE     IX,MNU_SCAN
        LD      $0,(IX+$SX)
        PRE     IX,MNU_GROUP
        ST      $0,(IX+$SX)
        CAL     MNU_ALIASES
        AN      $0,$0
        JP      NZ,MNU_IFAIL
        PRE     IX,MNU_SCAN
        LD      $0,(IX+$SX)
        AD      $0,$SY
        ST      $0,(IX+$SX)
        PRE     IX,MNU_COUNT
        LD      $1,(IX+$SX)
        SBC     $0,$1
        JP      C,MNU_IVAL
; restore first group's active aliases after validation of every group
        PRE     IX,MNU_GROUP
        LD      $0,0
        ST      $0,(IX+$SX)
        CAL     MNU_ALIASES
        RTN
MNU_IFAIL:
; A failed configuration must not leave a dispatchable Menu.
        LD      $2,$0
        PRE     IX,MNU_COUNT
        LD      $0,0
        ST      $0,(IX+$SX)
        LD      $0,$2
        RTN
MNU_INVAL:
        LD      $0,1
        RTN

; Build ROM pointer to currently active group's record into $10/$11.
; ADDW is register-to-register; no assembler-illegal word immediates.
MNU_ADDR:
        PRE     IX,MNU_TABLE
        LDW     $10,(IX+$SX)
        PRE     IX,MNU_GROUP
        LD      $21,(IX+$SX)
        LDW     $22,68
MNU_ASTEP:
        AN      $21,$21
        RTN     Z
        ADW     $10,$22
        SB      $21,$SY
        JR      MNU_ASTEP

; Recompute four active aliases for current group in RAM. Detect and
; reject collisions after case folding, including implicit defaults.
MNU_ALIASES:
        CAL     MNU_ADDR
        LDW     $20,64
        ADW     $10,$20
        PRE     IZ,$10
        LD      $24,0
MNU_AREAD:
        LDI     $0,(IZ+$SX)
        AN      $0,$0
        JR      Z,MNU_ADEFAULT
; Explicit aliases are ASCII letters only; fold to uppercase.
        SBC     $0,&H61
        JR      C,MNU_AUPPER
        SBC     $0,&H7B
        JR      NC,MNU_AINVALID
        SB      $0,32
MNU_AUPPER:
        SBC     $0,&H41
        JR      C,MNU_AINVALID
        SBC     $0,&H5B
        JR      NC,MNU_AINVALID
        JR      MNU_ASAVE
MNU_ADEFAULT:
        LD      $0,&H31
        AD      $0,$24
MNU_ASAVE:
        PRE     IX,MNU_ALIAS
        ST      $0,(IX+$24)
        AD      $24,$SY
        SBC     $24,4
        JR      C,MNU_AREAD
; Six pairwise comparisons, with no unchecked first-match dispatch.
        PRE     IX,MNU_ALIAS
        LD      $2,(IX+$SX)
        PRE     IX,MNU_ALIAS+1
        LD      $3,(IX+$SX)
        PRE     IX,MNU_ALIAS+2
        LD      $4,(IX+$SX)
        PRE     IX,MNU_ALIAS+3
        LD      $5,(IX+$SX)
        SBC     $2,$3
        JR      Z,MNU_ACOLLIDE
        SBC     $2,$4
        JR      Z,MNU_ACOLLIDE
        SBC     $2,$5
        JR      Z,MNU_ACOLLIDE
        SBC     $3,$4
        JR      Z,MNU_ACOLLIDE
        SBC     $3,$5
        JR      Z,MNU_ACOLLIDE
        SBC     $4,$5
        JR      Z,MNU_ACOLLIDE
        LD      $0,0
        RTN
MNU_ACOLLIDE:
        LD      $0,2
        RTN
MNU_AINVALID:
        LD      $0,3
        RTN

MNU_SHOW:
        PST     UA,&H14
        PRE     IX,MNU_COUNT
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,MNU_INVAL
        CAL     LCD_CLEAR
        CAL     MNU_ADDR
        PRE     IZ,$10
        LD      $6,0
        CAL     LCD_ROM32
        CAL     MNU_ADDR
        LDW     $20,32
        ADW     $10,$20
        PRE     IZ,$10
        LD      $6,&H60
        CAL     LCD_ROM32
        CAL     CUR_OFF
        LD      $0,0
        RTN

MNU_NEXT:
        PST     UA,&H14
        PRE     IX,MNU_GROUP
        LD      $0,(IX+$SX)
        AD      $0,$SY
        PRE     IX,MNU_COUNT
        LD      $2,(IX+$SX)
        SBC     $0,$2
        JR      C,MNU_NSTORE
        LD      $0,0
MNU_NSTORE:
        PRE     IX,MNU_GROUP
        ST      $0,(IX+$SX)
        CAL     MNU_ALIASES
        AN      $0,$0
        RTN     NZ
        JP      MNU_SHOW

MNU_WAIT:
        PST     UA,&H14
        PRE     IX,MNU_COUNT
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,MNU_INVAL
MNU_KEY:
        CAL     KEY_WAIT
        SBC     $17,2
        JP      Z,MNU_BRK
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,MNU_EXIT
        SBC     $12,KEYETC
        JP      Z,MNU_ETC
        SBC     $12,KEYF1
        JP      Z,MNU_F1
        SBC     $12,KEYF2
        JP      Z,MNU_F2
        SBC     $12,KEYF3
        JP      Z,MNU_F3
        SBC     $12,KEYF4
        JP      Z,MNU_F4
; Both CRTKY lower-case and upper-case letters are supported.
        SBC     $12,&H61
        JR      C,MNU_KCHECK
        SBC     $12,&H7B
        JR      NC,MNU_KCHECK
        SB      $12,32
MNU_KCHECK:
        PRE     IX,MNU_ALIAS
        LD      $2,(IX+$SX)
        SBC     $12,$2
        JP      Z,MNU_F1
        PRE     IX,MNU_ALIAS+1
        LD      $2,(IX+$SX)
        SBC     $12,$2
        JP      Z,MNU_F2
        PRE     IX,MNU_ALIAS+2
        LD      $2,(IX+$SX)
        SBC     $12,$2
        JP      Z,MNU_F3
        PRE     IX,MNU_ALIAS+3
        LD      $2,(IX+$SX)
        SBC     $12,$2
        JP      Z,MNU_F4
        CAL     MNU_RELEASE
        JP      MNU_KEY
MNU_ETC:
        CAL     MNU_RELEASE
        CAL     MNU_NEXT
        AN      $0,$0
        JP      NZ,MNU_CFGFAIL
        JP      MNU_KEY
MNU_F1:
        LD      $22,1
        JP      MNU_SELECTED
MNU_F2:
        LD      $22,2
        JP      MNU_SELECTED
MNU_F3:
        LD      $22,3
        JP      MNU_SELECTED
MNU_F4:
        LD      $22,4
MNU_SELECTED:
        PRE     IX,MNU_SEL
        ST      $22,(IX+$SX)
        CAL     MNU_RELEASE
        PRE     IX,MNU_GROUP
        LD      $8,(IX+$SX)
        AD      $8,$SY
        PRE     IX,MNU_SEL
        LD      $9,(IX+$SX)
        LD      $0,0
        RTN
MNU_EXIT:
        LD      $23,1
        JP      MNU_EVEXIT
MNU_BRK:
        LD      $23,2
MNU_EVEXIT:
        CAL     MNU_RELEASE
        PRE     IX,MNU_GROUP
        LD      $8,(IX+$SX)
        AD      $8,$SY
        LD      $9,0
        LD      $0,$23
        RTN
MNU_CFGFAIL:
        LD      $0,3
        RTN

; Key-up discipline: once a press is accepted, wait until the physical
; scan reports no key before another menu event is accepted.
MNU_RELEASE:
        CAL     RAW_READY
        AN      $17,$17
        JR      NZ,MNU_RELEASE
        RTN
