source: xtideuniversalbios/trunk/Configurator/Src/Libraries/menu/menuloop.asm @ 2

Last change on this file since 2 was 2, checked in by aitotat, 14 years ago
File size: 9.6 KB
Line 
1; File name     :   menuloop.asm
2; Project name  :   Menu library
3; Created date  :   11.11.2009
4; Last update   :   10.12.2009
5; Author        :   Tomi Tilli
6; Description   :   ASM library to menu system.
7;                   Contains event dispatching loop.
8
9;--------------- Equates -----------------------------
10
11; BIOS scan codes
12KEY_ENTER       EQU     1Ch
13KEY_ESC         EQU     01h
14KEY_UP          EQU     48h
15KEY_DOWN        EQU     50h
16KEY_PGUP        EQU     49h
17KEY_PGDN        EQU     51h
18KEY_HOME        EQU     47h
19KEY_END         EQU     4Fh
20CNT_MENU_KEYS   EQU     8       ; Number of menukeys
21
22
23;-------------- Private global variables -------------
24; Section containing initialized data
25;SECTION .data
26
27
28;-------------- Public functions ---------------------
29; Section containing code
30SECTION .text
31
32
33;--------------------------------------------------------------------
34; Waits keyboard input, updates timeout and dispatch event for
35; user handler.
36;   Parameters:
37;       SS:BP:  Ptr to MENUVARS
38;   Returns:
39;       Nothing
40;   Corrupts registers:
41;       AX, BX, CX, DX
42;--------------------------------------------------------------------
43ALIGN JUMP_ALIGN
44MenuLoop_Enter:
45    ; Get current time for timeout
46    call    Menu_GetTime                    ; Get system time ticks to CX:DX
47    mov     [bp+MENUVARS.wTimeLast], dx     ; Store last read time
48
49    ; Check if menu operation should be continued
50ALIGN JUMP_ALIGN
51.CheckExit:
52    test    BYTE [bp+MENUVARS.bFlags], FLG_MNU_EXIT
53    jnz     .Return                         ; Return if exit flag set
54
55    ; Check if keystroke available
56    call    Keys_GetStroke                  ; Get keystroke to AX
57    jz      .CheckTimeout                   ; If no keystroke, jump to check timeout
58    call    MenuLoop_ProcessKey             ; Convert keystroke to events
59
60    ; Check if timeout needs updating
61ALIGN JUMP_ALIGN
62.CheckTimeout:
63    cmp     WORD [bp+MENUVARS.wTimeInit], 0 ; Timeout enabled?
64    jz      .CheckExit                      ;  If not, loop
65    call    Menu_GetTime                    ; Get system time ticks to CX:DX
66    mov     cx, dx                          ; Copy time loword to CX
67    sub     dx, [bp+MENUVARS.wTimeLast]     ; Has time changed?
68    je      .CheckExit                      ;  If not, loop
69
70    ; Update timeout
71    mov     [bp+MENUVARS.wTimeLast], cx     ; Store last update time
72    sub     [bp+MENUVARS.wTimeout], dx      ; Update timeout
73    ja      .PrintTimeout                   ;  If time left, just print new value
74    call    MenuLoop_SendSelEvent           ; Send selection event
75
76    ; Print timeout value
77ALIGN JUMP_ALIGN
78.PrintTimeout:
79    call    MenuDraw_Timeout
80    xor     dx, dx
81    call    MenuCrsr_PointBelowBrdr
82    jmp     .CheckExit
83
84ALIGN JUMP_ALIGN
85.Return:
86    ret
87
88
89;--------------------------------------------------------------------
90; Sends Menu event to user handler (MENUVARS.fnEvent).
91; MenuLoop_SendSelEvent     Sends Menuitem Selected event to user event handler
92; MenuLoop_SendEvent        Sends any event to user event handler
93;   Parameters:
94;       BX:     Event code
95;       DX:     Event parameter (event specific)
96;       SS:BP:  Ptr to MENUVARS
97;   Returns:
98;       AH:     Event specific or unused
99;       AL:     1=Event processed
100;               0=Event not processed (default action if any)
101;   Corrupts registers:
102;       BX, CX, DX
103;--------------------------------------------------------------------
104ALIGN JUMP_ALIGN
105MenuLoop_SendSelEvent:
106    mov     bx, EVNT_MNU_SELSET
107ALIGN JUMP_ALIGN
108MenuLoop_SendEvent:
109    mov     cx, [bp+MENUVARS.wItemSel]
110    call    [bp+MENUVARS.fnEvent]
111    ret
112
113
114;-------------- Private functions ---------------------
115
116
117;--------------------------------------------------------------------
118; Processed menu key input.
119; Menu keys will be handled and other keys dispatched as key events.
120;   Parameters:
121;       AH:     BIOS Scan Code for key
122;       AL:     ASCII character
123;       SS:BP:  Ptr to MENUVARS
124;   Returns:
125;       Nothing
126;   Corrupts registers:
127;       AX, BX, CX, DX
128;--------------------------------------------------------------------
129ALIGN JUMP_ALIGN
130MenuLoop_ProcessKey:
131    push    es
132    push    di
133
134    ; Check if wanted key
135    push    cs
136    pop     es                  ; Copy CS to ES
137    mov     cx, CNT_MENU_KEYS   ; Load number of menu keys
138    mov     di, .rgbKeyToIdx    ; Load offset to translation table
139    xchg    al, ah              ; Scan code to AL
140    cld                         ; SCASB to increment DI
141    repne scasb                 ; Compare [ES:DI] to AL until match
142    jne     .Dispatch           ; If not menukey, jump to dispatch
143
144    ; Jump to process menu key
145    mov     di, CNT_MENU_KEYS-1 ; Convert CX... 
146    sub     di, cx              ; ...to lookup index
147    shl     di, 1               ; Prepare for word lookup
148    jmp     [cs:di+.rgwMenuKeyJmp]
149
150    ; Dispatch key event
151ALIGN JUMP_ALIGN
152.Dispatch:
153    xchg    al, ah              ; Restore AX
154    mov     bx, EVNT_MNU_KEY
155    mov     dx, ax              ; Copy keys to DX
156    call    MenuLoop_SendEvent
157ALIGN JUMP_ALIGN
158.Return:
159    pop     di
160    pop     es
161    ret
162
163    ;;;;;;;;;;;;;;;;;;;;;
164    ; Menu key handlers ;
165    ;;;;;;;;;;;;;;;;;;;;;
166
167    ; ENTER pressed
168ALIGN JUMP_ALIGN
169.KeyEnter:
170    call    MenuLoop_SendSelEvent           ; Send selection event
171    jmp     .Return
172
173    ; ESC pressed
174ALIGN JUMP_ALIGN
175.KeyEsc:
176    call    Menu_Exit
177    jc      .Return                         ; User cancelled exit
178    mov     WORD [bp+MENUVARS.wItemSel], -1
179    jmp     .Return
180
181    ; UP pressed
182ALIGN JUMP_ALIGN
183.KeyUp:
184%ifdef USE_MENU_DIALOGS
185    test    BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW   ; Message dialog mode?
186    jnz     .TextScrollUp                   ;  If so, go to text scrolling
187%endif
188    mov     ax, [bp+MENUVARS.wItemSel]      ; Load selected index 
189    test    ax, ax                          ; Already at top?
190    jz      .KeyEnd                         ;  If so, go to end
191    mov     dx, ax                          ; Copy selected index to DX
192    dec     ax                              ; Decrement menuitem index
193    mov     [bp+MENUVARS.wItemSel], ax      ; Store new index
194    cmp     ax, [bp+MENUVARS.wItemTop]      ; Need to scroll?
195    jae     .DrawSelection                  ;  If not, go to draw selection
196    dec     WORD [bp+MENUVARS.wItemTop]     ; Scroll
197    jmp     .ScrollMenu
198
199%ifdef USE_MENU_DIALOGS
200ALIGN JUMP_ALIGN
201.TextScrollUp:
202    cmp     WORD [bp+MENUVARS.wItemTop], 0  ; Already at the top?
203    jz      .Return                         ;  If so, return
204    dec     WORD [bp+MENUVARS.wItemTop]
205    jmp     .ScrollMenu
206%endif
207
208    ; DOWN pressed
209ALIGN JUMP_ALIGN
210.KeyDown:
211%ifdef USE_MENU_DIALOGS
212    test    BYTE [bp+MENUVARS.bFlags], FLG_MNU_NOARRW   ; Message dialog mode?
213    jnz     .TextScrollDown                 ;  If so, go to text scrolling
214%endif
215    mov     ax, [bp+MENUVARS.wItemSel]      ; Load selected index
216    mov     dx, ax                          ; Copy selected index to DX
217    inc     ax                              ; Increment menuitem index
218    cmp     ax, [bp+MENUVARS.wItemCnt]      ; Already at bottom?
219    je      .KeyHome                        ;  If so, go to beginning
220    mov     [bp+MENUVARS.wItemSel], ax      ; Store new menuitem index
221    eMOVZX  bx, BYTE [bp+MENUVARS.bVisCnt]  ; Load number of visible items
222    add     bx, [bp+MENUVARS.wItemTop]      ; BX to one past last visible index
223    cmp     ax, bx                          ; Need to scroll?
224    jb      .DrawSelection                  ;  If not, go to draw selection
225    inc     WORD [bp+MENUVARS.wItemTop]     ; Scroll
226    jmp     .ScrollMenu
227
228%ifdef USE_MENU_DIALOGS
229ALIGN JUMP_ALIGN
230.TextScrollDown:
231    eMOVZX  ax, BYTE [bp+MENUVARS.bVisCnt]  ; Load visible items
232    add     ax, [bp+MENUVARS.wItemTop]      ; Add topmost menuitem index
233    cmp     ax, [bp+MENUVARS.wItemCnt]      ; Already at the bottom?
234    jae     .Return                         ;  If so, return
235    inc     WORD [bp+MENUVARS.wItemTop]
236    jmp     .ScrollMenu
237%endif
238
239    ; PGUP pressed
240ALIGN JUMP_ALIGN
241.KeyPgUp:
242    mov     ax, [bp+MENUVARS.wItemSel]      ; Load selected index
243    div     BYTE [bp+MENUVARS.bVisCnt]      ; AL=Current page index
244    sub     al, 1                           ; Decrement page
245    jc      .KeyHome                        ; Select first item if overflow
246    mul     BYTE [bp+MENUVARS.bVisCnt]      ; AX=Fist menuitem on page
247    mov     [bp+MENUVARS.wItemSel], ax
248    mov     [bp+MENUVARS.wItemTop], ax
249    jmp     .ScrollMenu
250
251    ; PGDN pressed
252ALIGN JUMP_ALIGN
253.KeyPgDn:
254    mov     ax, [bp+MENUVARS.wItemSel]      ; Load selected index
255    div     BYTE [bp+MENUVARS.bVisCnt]      ; AL=Current page index
256    inc     ax                              ; Increment page
257    mul     BYTE [bp+MENUVARS.bVisCnt]      ; AX=First menuitem on page
258    eMOVZX  bx, BYTE [bp+MENUVARS.bVisCnt]  ; Load number of visible items
259    add     bx, ax                          ; BX now one past last visible
260    cmp     bx, [bp+MENUVARS.wItemCnt]      ; Went over last?
261    jae     .KeyEnd                         ;  If so, select last menuitem
262    mov     [bp+MENUVARS.wItemSel], ax
263    mov     [bp+MENUVARS.wItemTop], ax
264    jmp     .ScrollMenu
265
266    ; HOME pressed
267ALIGN JUMP_ALIGN
268.KeyHome:
269    xor     ax, ax
270    mov     [bp+MENUVARS.wItemSel], ax
271    mov     [bp+MENUVARS.wItemTop], ax
272    jmp     .ScrollMenu
273
274    ; END pressed
275ALIGN JUMP_ALIGN
276.KeyEnd:
277    mov     ax, [bp+MENUVARS.wItemCnt]      ; Load number if menuitems
278    mov     bx, ax                          ; Copy menuitem count to BX
279    dec     ax                              ; Decrement for last index
280    mov     [bp+MENUVARS.wItemSel], ax      ; Store new selection
281    sub     bl, [bp+MENUVARS.bVisCnt]       ; BX to first menuitem to draw
282    sbb     bh, 0
283    mov     [bp+MENUVARS.wItemTop], bx      ; Store first menuitem to draw
284    jnc     .ScrollMenu 
285    mov     WORD [bp+MENUVARS.wItemTop], 0  ; Overflow, start with 0
286    ; Fall to .ScrollMenu
287
288    ; Menuitem selection changed, redraw all items
289ALIGN JUMP_ALIGN
290.ScrollMenu:
291    mov     bx, EVNT_MMU_SELCHG
292    call    MenuLoop_SendEvent
293    call    Menu_RestartTimeout
294    xor     cx, cx                          ; Invalidate...
295    dec     cx                              ; ...all menuitems
296    mov     dl, MFL_UPD_ITEM
297    call    Menu_Invalidate
298    jmp     .Return
299
300; Menuitem selection changed, only two items needs to be redrawn
301ALIGN JUMP_ALIGN
302.DrawSelection:
303    MINMAX_U ax, dx                         ; First menuitem to AX, next to DX
304    push    dx                              ; Store second to draw
305    push    ax                              ; Store first to draw
306    mov     bx, EVNT_MMU_SELCHG
307    call    MenuLoop_SendEvent
308    call    Menu_RestartTimeout
309    pop     cx                              ; First to draw to CX
310    call    MenuCrsr_PointNthItem           ; Set cursor position
311    call    MenuDraw_Item                   ; Draw first menuitem
312    pop     cx                              ; Second to draw to CX
313    call    MenuDraw_Item                   ; Draw second menuitem
314    jmp     .Return
315
316ALIGN WORD_ALIGN
317.rgwMenuKeyJmp:
318    dw      .KeyEnter   ; KEY_ENTER
319    dw      .KeyEsc     ; KEY_ESC
320    dw      .KeyUp      ; KEY_UP
321    dw      .KeyDown    ; KEY_DOWN
322    dw      .KeyPgUp    ; KEY_PGUP
323    dw      .KeyPgDn    ; KEY_PGDN
324    dw      .KeyHome    ; KEY_HOME
325    dw      .KeyEnd     ; KEY_END
326; Scan code to jump index translation table
327.rgbKeyToIdx:   
328    db  KEY_ENTER,  KEY_ESC,    KEY_UP,     KEY_DOWN,
329    db  KEY_PGUP,   KEY_PGDN,   KEY_HOME,   KEY_END
Note: See TracBrowser for help on using the repository browser.