; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > Sources.Menu

rom_menustart

m_iconbarmenu           Menu    T00
mo_ic_info              Item    M01
mo_ic_mode              Item    M02,,N

m_coloursmenu           Menu    T01
mo_co_mono              Item    M11,,S
mo_co_grey4             Item    M12,,S
mo_co_grey16            Item    M13,,S
mo_co_colour16          Item    M14,,S
mo_co_grey256           Item    M15,,S
mo_co_colour256         Item    M16,,S
mo_co_32K               Item    M17,,S
mo_co_16M               Item    M18,,S
                        DCB     0                       ; Terminator.
                        ALIGN
colours_count           *       8

rom_resolutionmenu
                        DCB     "T02",0                 ; Title.
                        DCB     7,2,7,0                 ; Title fg, bg, work fg, bg.
                        DCB     44,0                    ; Item height, gap.
                        DCB     "MX1",0                 ; Dummy menu item.
                        ALIGN
                        DCD     mi_it_lastitem          ; Item flags.
                        DCD     0                       ; Item submenu pointer.
menu_resolutionflags
                        DCD     (0:SHL:ifb_bcol):OR:(7:SHL:ifb_fcol):OR:if_filled:OR:if_text:OR:if_indirected
                        DCB     0                       ; Terminator.
                        ALIGN

 [ SelectFrameRate
rom_ratemenu
                        DCB     "T03",0                 ; Title.
                        DCB     7,2,7,0                 ; Title fg, bg, work fg, bg.
                        DCB     44,0                    ; Item height, gap.
                        DCB     "MX1",0                 ; Dummy menu item.
                        ALIGN
                        DCD     mi_it_lastitem          ; Item flags.
                        DCD     0                       ; Item submenu pointer.
menu_rateflags
                        DCD     (0:SHL:ifb_bcol):OR:(7:SHL:ifb_fcol):OR:if_filled:OR:if_text
                        DCB     0                       ; Terminator.
                        ALIGN
 ]

;---------------------------------------------------------------------------
; Menu_Init
;
;       Out:    r0 corrupted
;
;       Make menus for icon bar and display window.
;
Menu_Init
 [ NewShading
        Entry   "r1-r5"
 |
        Entry   "r1-r3"
 ]

        Debug   menu,"Menu_Init"

        MOV     lr, #0
        STR     lr, menu_handle         ; No current menu.

        BL      MsgTrans_OpenFile
        EXIT    VS

        ADR     r1, rom_menustart
        ADR     r2, ram_menustart
        MOV     r3, #ram_menuend - ram_menustart
        SWI     XMessageTrans_MakeMenus
        EXIT    VS

        LDR     lr, info_handle         ; Set up dialogue pointers.
        STR     lr, mm_info
        LDR     lr, mode_handle
        STR     lr, mm_mode

        BL      Menu_Resolution
        EXIT    VS

        ; All colour menu items are shaded so unshade the ones which are available.
 [ NewShading
        LDR     r0, mode_menulist       ; r0 -> mode_menulist entry
        TEQ     r0, #0
        EXIT    EQ

        ; FOR resolution = 1 TO resolution_count
        ;     FOR mode = 1 TO maxmodeinthisclass
        ;         maskofdepths = maskofdepths OR depth(mode)
        ;     NEXT
        ; NEXT

        MOV     r4, #0                                  ; r4 = bitmask of found modes
        MOV     r5, #1
        LDRB    r1, resolution_count    ; r1 = number of entries in resolution menu
10
        SUBS    r1, r1, #1
        BCC     %FT40                   ; Apply the changes when no more menu resolutions

        LDR     r2, [r0], #4            ; r2 -> class pointer for current resolution menu item
        LDMIA   r2, {r2,r3}             ; r2 -> this class, r3 -> next class (or = 0)
20
        LDR     lr, [r2], #4            ; lr -> mode descriptor
        TEQ     lr, #0                  ; If no more modes in this class then
        BEQ     %BT10                   ;   try the next menu resolution.

        LDR     lr, [lr, #mode_desc_depth]
        ORR     r4, r4, r5, LSL lr      ; factor this depth into the mask
        TEQ     r4, #2_111111
        BEQ     %FT40                   ; all bpps are now available so no point checking any more

        CMP     r2, r3                  ; If more modes in this class then
        BNE     %BT20                   ;   try them.

        B       %BT10                   ; Try next menu resolution.

40
        ADR     r5, m_coloursmenu + m_headersize - mi_size    ; r5 -> corresponding menu item
        MOV     r3, #-1
45
        TEQ     r4, #0
        EXIT    EQ                      ; no bpp bits set anyway
        ADD     r3, r3, #1              ; the bitdepth in natural numbers
        ADD     r5, r5, #mi_size
        MOVS    r4, r4, LSR#1

        LDRCS   lr, [r5, #mi_iconflags] ; Otherwise, unshade menu item for this depth.
        BICCS   lr, lr, #is_shaded
        STRCS   lr, [r5, #mi_iconflags]
        TEQ     r3, #2                  ; If this was 4bpp (we've done 16 greys)
        TEQNE   r3, #3                  ;   or 8bpp (we've done 256 greys) then
        ADDEQ   r5, r5, #mi_size        ;   unshade menu item for colour 16 or colour 256.
        LDRCS   lr, [r5, #mi_iconflags]
        BICCS   lr, lr, #is_shaded
        STRCS   lr, [r5, #mi_iconflags]
        B       %BT45

 |
        LDR     r0, mode_sortedlist
        TEQ     r0, #0
        EXIT    EQ
        ADRL    r2, log2bpp_to_greyitem
        ADR     r3, m_coloursmenu + m_headersize
10
        LDR     r1, [r0], #4            ; Get pointer to mode.
        TEQ     r1, #0
        EXIT    EQ

        LDR     r1, [r1, #mode_desc_depth]
        LDRB    r1, [r2, r1]            ; Get menu item corresponding to depth.
        ASSERT  mi_size=24
        MOV     lr, r1, LSL #3
        ADD     lr, lr, lr, LSL #1
        ADD     lr, r3, lr              ; Point to it.

        TEQ     r1, #mo_co_grey16       ; If grey16 or grey256 then we'll have to do colour items too.
        TEQNE   r1, #mo_co_grey256
20
        LDR     r1, [lr, #mi_iconflags]
        BIC     r1, r1, #is_shaded
        STR     r1, [lr, #mi_iconflags]
        BNE     %BT10                   ; Not grey so move on to next mode.
        ADDS    lr, lr, #mi_size        ; Otherwise do colour16 or colour256 but don't get into endless loop.
        B       %BT20
 ]


;---------------------------------------------------------------------------
; Menu_Resolution
;
;       Out:    r0 corrupted
;
;       Build resolution menu.
;
Menu_Resolution
        ROUT
 [ SortOnPixelShape
        Entry   "r1-r10"
 |
        Entry   "r1-r9"
 ]
        Debug   menu,"Menu_Resolution"

        MOV     r8, #0                  ; No valid menu items yet.

        BL      Mode_GetTable
        BLVC    MsgTrans_OpenFile
        BVS     %FT30

        LDR     r9, mode_menulist
        Debug   menu," mode_menulist =",r9

        ADR     r1, rom_resolutionmenu  ; Make dummy menu.
        LDR     r2, m_resolutionmenu
        TEQ     r2, #0
        BEQ     %FT30
        LDR     r3, m_resolutionsize
        Debug   mode," menu,size =",r2,r3
        SWI     XMessageTrans_MakeMenus
        BVS     %FT20

        Debug   mode," creating real menu"
        ASSERT  mi_size = 24            ; Create real menu items.
        LDR     r0, mode_classlist      ; r0 -> list of mode classes (resolutions).
        LDR     r1, m_resolutionmenu
        ADD     r1, r1, #m_headersize   ; r1 -> menu items
        MOV     r3, #0                  ; No sub-menus.
        LDR     r4, menu_resolutionflags
        MOV     r6, #0                  ; No validation strings.
        MOV     r7, #128                ; Large value for text length (it's null terminated).

        LDR     lr, [r0]
        TEQ     lr, #0                  ; If no valid modes then
        BEQ     %FT20                   ;   don't leave dummy menu lying around.
 [ SortOnPixelShape
        LDR     r10, [lr, #mode_desc_flags]
        AND     r10, r10, #flags_squarepixel
 ]
10
        STR     r0, [r9], #4            ; Build list of pointers into mode_classlist in mode_menulist.
        LDR     lr, [lr]                ; Get pointer to mode descriptor.
        ADD     r5, lr, #mode_desc_name ; Pointer to mode descriptor string.
        LDRB    r2, [r5]
        TEQ     r2, #0                  ; If mode class has no name then
        SUBEQ   r9, r9, #4              ;   backtrack in mode_menulist
        BEQ     %FT15                   ;   and try next class.

 [ SortOnPixelShape
        LDR     r2, [r5, #mode_desc_flags-mode_desc_name]
        AND     r2, r2, #flags_squarepixel
	TEQ     r8, #0                  ; don't do dotted above first entry
	TEQNE   r2, r10                 ; If different pixel shape then
        MOVNE   r10, r2                 ;   put in a separator after last item.
        LDRNE   r2, [r1, #mi_itemflags-mi_size]
        ORRNE   r2, r2, #mi_it_dotted
        STRNE   r2, [r1, #mi_itemflags-mi_size]
 ]
        MOV     r2, #0
        STMIA   r1!, {r2-r7}            ; Create menu item.
        ADD     r8, r8, #1
15
        LDR     lr, [r0, #4]!           ; Try next class (resolution).
        TEQ     lr, #0
        BNE     %BT10
20
        MOV     lr, #0
        STR     lr, [r9]                ; Terminate mode_menulist.
30
        STRB    r8, resolution_count    ; Store the count.
        TEQ     r8, #0                  ; If we failed to create a valid menu then
        STREQ   r8, m_resolutionmenu    ;   don't leave it hanging around
        LDRNE   lr, [r1, #mi_itemflags-mi_size]!        ; else flag last item.
        ORRNE   lr, lr, #mi_it_lastitem
        STRNE   lr, [r1]

        EXIT


 [ SelectFrameRate

;---------------------------------------------------------------------------
; Menu_Rate
;
;       Out:    r0 corrupted
;
;       Build rate menu for current selection.
;
Menu_Rate
        ROUT
        Entry   "r1-r8"

        Debug   menu,"Menu_Rate"

        LDR     r4, selected_subclass
        Debug   menu," subclass =",r4
        CMP     r4, #-1
        BEQ     %FT20

        BL      MsgTrans_OpenFile

        ADR     r1, rom_ratemenu
        LDR     r2, m_ratemenu
        TEQ     r2, #0
        BEQ     %FT20
        LDR     r3, m_ratesize
        SWI     XMessageTrans_MakeMenus
        BVS     %FT20

        ASSERT  mode_desc_yres = mode_desc_xres + 4
        LDR     r3, m_ratemenu
        ADD     r3, r3, #m_headersize   ; Point to menu entries.
        LDR     lr, [r4], #4            ; Get pointer to first mode in subclass.
        LDR     r5, [lr, #mode_desc_depth]      ; Stop when depth changes
        ADD     r6, lr, #mode_desc_xres
        LDMIA   r6, {r6,r7}                     ;   or when resolution changes.
        MOV     r8, #0                          ; Count items in rate menu.
10
        LDR     r0, [lr, #mode_desc_rate]       ; Fill in menu text.
        ADD     r1, r3, #mi_icondata
        MOV     r2, #12
        SWI     XOS_ConvertInteger4     ; lr now corrupt.
        BVS     %FT20
        ADR     r0, menu_hz
        BL      Mod_CopyString

        ADD     r8, r8, #1              ; Increment item count.

        LDR     lr, [r4], #4            ; Get pointer to next mode in subclass.
        TEQ     lr, #0                  ; If reached end of sorted list then
        MOVEQ   r0, #mi_it_lastitem     ;   this is the last item.
        BEQ     %FT15

        LDR     r1, [lr, #mode_desc_depth]
        TEQ     r5, r1                  ; If depth has changed then
        MOVNE   r0, #mi_it_lastitem     ;   last item.
        BNE     %FT15

        ADD     r1, lr, #mode_desc_xres
        LDMIA   r1, {r1,r2}
        TEQ     r1, r6                  ; If resolution has changed then
        TEQEQ   r2, r7
        MOVNE   r0, #mi_it_lastitem     ;   last item
        MOVEQ   r0, #0                  ; else more to do.
15
        MOV     r1, #0                  ; No submenu.
        LDR     r2, menu_rateflags
        STMIA   r3, {r0-r2}             ; Fill in menu entry.
        ADDEQ   r3, r3, #mi_size
        TEQ     r0, #0                  ; If more to do then do it.
        BEQ     %BT10
        LDRB    lr, flags
        ORR     lr, lr, #f_ratemenuvalid
        STRB    lr, flags
        STRB    r8, rate_count          ; Store item count.
        LDR     lr, menu_handle
        LDR     r8, m_ratemenu
        TEQ     r8, lr
        MOVEQ   lr, #&FF                ; Menu has just been rebuilt so no tick to remove.
        STREQB  lr, menu_tick
        EXIT

20
        Debug   menu," can't build rate menu"
        LDRB    lr, flags
        BIC     lr, lr, #f_ratemenuvalid
        STRB    lr, flags
        MOV     lr, #0
        STRB    lr, rate_count
        EXIT

menu_hz DCB     "Hz",0
        ALIGN
 ]


;---------------------------------------------------------------------------
; Menu_Show
;
;       In:     r1 -> menu to be displayed
;               r2 = x coordinate
;               r3 = y coordinate
;       Out:    r0 corrupted
;
;       Tick the appropriate menu item and show the menu.
;
Menu_Show
        ROUT
        Entry   "r1"

        Debug   menu,"Menu_Show",r1,r2,r3

        LDR     r1, menu_handle
        Debug   menu," stored handle =",r1
        BL      Menu_RemoveTick

        MOV     r0, #&FF                ; Assume to tick for this menu.
        LDR     r1, [sp]                ; Get back menu we are to display.

        ADR     lr, m_coloursmenu
        TEQ     r1, lr
        BNE     %FT10

        LDRB    r0, selected_colours
        CMP     r0, #colours_count
        MOVCS   r0, #&FF                ; No tick for this menu.
        BLCC    Menu_ChangeTick         ; Tick colours menu if selection in range.
        B       %FT30
10
        LDR     lr, m_resolutionmenu
        TEQ     r1, lr
        BNE     %FT20

        LDRB    r0, selected_class
        BL      Menu_ClassToResolution
        LDRB    lr, resolution_count
        CMP     r0, lr
        MOVCS   r0, #&FF                ; No tick for this menu.
        BLCC    Menu_ChangeTick         ; Tick resolution menu if selection in range.
 [ SelectFrameRate
        B       %FT30
20
        LDR     lr, m_ratemenu
        TEQ     r1, lr
        BNE     %FT30

        LDR     r5, selected_mode
        CMP     r5, #-1
        BEQ     %FT30
        LDRB    r0, rate_count
        LDR     lr, selected_subclass
25
        SUBS    r0, r0, #1              ; If we run out of menu items then
        MOVCC   r0, #&FF                ;   no tick for this menu.
        BCC     %FT30

        LDR     r4, [lr, r0, LSL #2]
        TEQ     r4, r5
        BNE     %BT25
        BL      Menu_ChangeTick         ; Tick rate menu.
 |
20
 ]
30
        STRB    r0, menu_tick           ; Remember ticked item (or &FF).
        STR     r1, menu_handle
        SWI     XWimp_CreateMenu

        EXIT


;---------------------------------------------------------------------------
; Menu_ChangeTick
;
;       In:     r0 = item number to change
;               r1 -> menu
;
;       Invert the tick bit for the specified menu item.
;
Menu_ChangeTick
        Entry   "r0"

        Debug   menu,"Menu_ChangeTick",r0,r1

        ASSERT  mi_size=24
        MOV     r0, r0, LSL #3
        ADD     r0, r0, r0, LSL #1
        ADD     r0, r0, #m_headersize
        LDR     lr, [r1, r0]
        EOR     lr, lr, #mi_it_tick
        STR     lr, [r1, r0]

        EXIT


;---------------------------------------------------------------------------
; Menu_RemoveTick
;
;       In:     r1 -> menu
;       Out:    r0 corrupted
;
;       Untick menu item.
;
Menu_RemoveTick
        Entry

        TEQ     r1, #0
        LDRNEB  r0, menu_tick
        TEQNE   r0, #&FF                ; If last menu displayed was ticked then
        BLNE    Menu_ChangeTick         ;   remove the tick.

        EXIT


;---------------------------------------------------------------------------
; Menu_Selection
;
;       In:     r1 -> menu selection block
;       Out:    r0 corrupted
;
;       The Wimp has informed us of a menu selection.
;
Menu_Selection
        Entry   "r1,r2"

        Debug   menu,"Menu_Selection"

        MOV     r2, r1
        LDR     r1, menu_handle
        BL      Menu_Decode
        EXIT    VS

        MOV     r2, r1
        ADR     r1, user_data
        SWI     XWimp_GetPointerInfo
        EXIT    VS

        LDR     lr, [r1, #8]            ; Get button states.
        TST     lr, #button_right       ; If not adjust then
        BEQ     %FT10                   ;   let menu close.

        LDR     r1, menu_handle
        TEQ     r1, r2                  ; If menu is not there then
        BNE     %FT10                   ;   let menu close
        BL      Menu_Show               ; else display it again Sam!!
        EXIT

10
        LDR     r1, menu_handle
        BL      Menu_RemoveTick
        MOV     r1, #0
        STR     r1, menu_handle
        EXIT


;---------------------------------------------------------------------------
; Menu_Decode
;
;       In:     r1 -> menu definition
;               r2 -> menu selection block
;       Out:    r0 corrupted
;
;       Decode the given menu selection.
;
Menu_Decode
        ROUT
        Entry   "r1-r6"

        Debug   menu,"Menu_Decode"

        ADR     lr, m_iconbarmenu
        TEQ     r1, lr
        EXIT    EQ

 [ SelectFrameRate
        LDR     lr, m_ratemenu
        TEQ     r1, lr
        BNE     %FT10

        LDR     lr, [r2]                ; Get selected rate item (number to skip).
        LDR     r2, selected_subclass
        LDR     r2, [r2, lr, LSL #2]    ; Point to selected mode.

        LDR     lr, selected_mode
        TEQ     r2, lr                  ; If the mode hasn't changed then
        EXIT    EQ                      ;   nothing to do.

        STR     r2, selected_mode       ; Store updated selection.
        B       %FT20
10
 ]

        ADR     lr, m_coloursmenu
        TEQ     r1, lr                  ; If it's the colours menu then
        MOVEQ   r0, #1                  ;   step down class
        LDREQ   r3, [r2]                ;   get the selected colour item
        LDREQB  r4, selected_class      ;   get the resolution choice
        MOVNE   r0, #2                  ; else step down colour choice
        LDRNEB  r3, selected_colours    ;   get the colour choice
        LDRNE   r4, [r2]                ;   get the selected resolution item
        BLNE    Menu_ResolutionToClass  ;   convert to class.
        MOV     r6, #-1                 ; Don't care about frame rate.
        TEQ     r4, #&FF                ; If class not supported then
        MOVEQ   r4, #0                  ;   start at the bottom and work up.
        Debug   menu," colours,class =",r3,r4
        Push    "r0"                    ; Save flags in case we need to use non-menu modes.
        BL      Mode_FindSubClass
        Pull    "r0"
        Debug   menu," colours,class,mode =",r3,r4,r5

        ORRVS   r0, r0, #4              ; No mode in menus so try again but allow non-menu modes.
        BLVS    Mode_FindSubClass

        STRVC   r2, selected_subclass   ; Store selections.
        STRVCB  r3, selected_colours
        STRVCB  r4, selected_class
        STRVC   r5, selected_mode
        MOVVC   r2, r5
        MOVVC   r6, #-1                 ; Rate must come from mode, else it's "Unknown".
20
        BLVC    Mode_SetWindowIcons
        BLVC    Icon_Refresh

        EXIT


;---------------------------------------------------------------------------
; Menu_ClassToResolution
;
;       In:     r0 = index into mode_classlist
;
;       Out:    r0 = corresponding resolution menu item or &FF
;
;       Find the menu item for the given class.
;
Menu_ClassToResolution
        Entry   "r1,r2"

        LDR     lr, mode_classlist
        ADD     lr, lr, r0, LSL #2      ; lr = pointer to class list entry
        LDR     r1, mode_menulist       ; Try to find it in mode_menulist.
        LDRB    r0, resolution_count
10
        SUBS    r0, r0, #1
        MOVCC   r0, #&FF
        EXIT    CC

        LDR     r2, [r1, r0, LSL #2]
        TEQ     r2, lr
        BNE     %BT10

        EXIT


;---------------------------------------------------------------------------
; Menu_ResolutionToClass
;
;       In:     r4 = resolution menu item
;
;       Out:    r4 = corresponding index into mode_classlist
;
;       Find the class for the given resolution menu item.
;
Menu_ResolutionToClass
        Entry

        LDR     lr, mode_menulist
        LDR     lr, [lr, r4, LSL #2]
        LDR     r4, mode_classlist
        SUB     r4, lr, r4
        MOV     r4, r4, LSR #2

        EXIT


        END