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

Last change on this file was 293, checked in by krille_n_@…, 12 years ago

Commit 1/2 (Library, Configurators and Serial Server):

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