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

Last change on this file since 592 was 293, checked in by krille_n_@…, 13 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.