source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm @ 600

Last change on this file since 600 was 600, checked in by aitotat, 6 years ago

Hotkeybar timer tick handler now keeps interrupts disabled and updates on every fourth call.

File size: 17.8 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   Hotkey Bar related functions.
3
4;
5; XTIDE Universal BIOS and Associated Tools
6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
12;
13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16; GNU General Public License for more details.
17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;
19
20; Section containing code
21SECTION .text
22
23
24;--------------------------------------------------------------------
25; Handler for INT 1Ch System Timer Tick.
26; Reads key presses and draws hotkey bar.
27;
28; HotkeyBar_TimerTickHandler
29;   Parameters:
30;       DS:     RAMVARS segment
31;       ES:     BDA segment (zero)
32;   Returns:
33;       Nothing
34;   Corrupts registers:
35;       AX, CX, DX, SI, DI
36;--------------------------------------------------------------------
37HotkeyBar_TimerTickHandler:
38    push    es
39    push    ds
40%ifdef USE_186
41    ePUSHA
42%else
43    push    di
44    push    si
45    push    dx
46    push    cx
47    push    ax
48%endif
49
50    ;!!! Keep interrupts disabled so there won't be another
51    ; timer tick call before we are ready
52
53    LOAD_BDA_SEGMENT_TO es, ax
54    call    RamVars_GetSegmentToDS
55
56    ; Call previous handler
57    pushf
58    call far [es:BOOTVARS.hotkeyVars+HOTKEYVARS.fpPrevTimerHandler]
59
60    ; Update Hotkeybar (process key input and draw) every fourth tick
61    test    BYTE [es:BDA.dwTimerTicks], 11b
62    jnz     SHORT .ReturnFromHandler
63    call    UpdateDuringDriveDetection
64
65.ReturnFromHandler:
66%ifdef USE_186
67    ePOPA
68%else
69    pop     ax
70    pop     cx
71    pop     dx
72    pop     si
73    pop     di
74%endif
75    pop     ds
76    pop     es
77    iret
78
79
80;--------------------------------------------------------------------
81; Scans key presses and draws any hotkey changes.
82;
83; HotkeyBar_UpdateDuringDriveDetection
84;   Parameters:
85;       DS:     RAMVARS segment
86;       ES:     BDA segment (zero)
87;   Returns:
88;       Nothing
89;   Corrupts registers:
90;       AX, CX, DX, SI, DI
91;--------------------------------------------------------------------
92UpdateDuringDriveDetection:
93    call    ScanHotkeysFromKeyBufferAndStoreToBootvars
94
95    ; If ESC pressed, abort detection by forcing timeout
96    cmp     al, ESC_SCANCODE
97    jne     SHORT .ContinueDrawing
98    mov     BYTE [RAMVARS.bTimeoutTicksLeft], 0
99.ContinueDrawing:
100   
101    ; Fall to HotkeyBar_DrawToTopOfScreen
102
103
104;--------------------------------------------------------------------
105; HotkeyBar_DrawToTopOfScreen
106;   Parameters:
107;       DS:     RAMVARS segment
108;       ES:     BDA segment (zero)
109;   Returns:
110;       Nothing
111;   Corrupts registers:
112;       AX, CX, DX, SI, DI
113;--------------------------------------------------------------------
114HotkeyBar_DrawToTopOfScreen:
115    ; Store current screen coordinates to be restored
116    ; when Hotkey Bar is rendered
117    call    DetectPrint_GetSoftwareCoordinatesToAX
118    push    ax
119
120    call    MoveCursorToScreenTopLeftCorner
121    ; Fall to .PrintFloppyDriveHotkeys
122
123;--------------------------------------------------------------------
124; .PrintFloppyDriveHotkeys
125;   Parameters:
126;       DS:     RAMVARS segment
127;       ES:     BDA segment (zero)
128;   Returns:
129;       Nothing
130;   Corrupts registers:
131;       AX, CX, DX, SI, DI
132;--------------------------------------------------------------------
133.PrintFloppyDriveHotkeys:
134    call    FloppyDrive_GetCountToAX
135    xchg    cx, ax      ; Any Floppy Drives?
136    jcxz    .SkipFloppyDriveHotkeys
137
138    mov     ax, (ANGLE_QUOTE_RIGHT << 8) | DEFAULT_FLOPPY_DRIVE_LETTER
139    mov     cl, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFddLetter]
140    mov     di, g_szFDD
141
142    ; Clear CH if floppy drive is selected for boot
143    mov     ch, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags]
144    ;and        ch, FLG_HOTKEY_HD_FIRST; Not needed until more flags added
145    call    FormatDriveHotkeyString
146
147.SkipFloppyDriveHotkeys:
148    ; Fall to .PrintHardDriveHotkeys
149
150;--------------------------------------------------------------------
151; .PrintHardDriveHotkeys
152;   Parameters:
153;       DS:     RAMVARS segment
154;       ES:     BDA segment (zero)
155;   Returns:
156;       Nothing
157;   Corrupts registers:
158;       AX, CX, DX, SI, DI
159;--------------------------------------------------------------------
160    call    BootVars_GetLetterForFirstHardDriveToAX
161    mov     ah, ANGLE_QUOTE_RIGHT
162    mov     cx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wHddLetterAndFlags]  ; Letter to CL, flags to CH
163    ;and        ch, FLG_HOTKEY_HD_FIRST ; Not needed until more flags added
164    xor     ch, FLG_HOTKEY_HD_FIRST     ; Clear CH if HD is selected for boot, set otherwise
165    mov     di, g_szHDD
166    call    FormatDriveHotkeyString
167    ; Fall to .PrintBootMenuHotkey
168
169;--------------------------------------------------------------------
170; .PrintBootMenuHotkey
171;   Parameters:
172;       ES:     BDA segment (zero)
173;   Returns:
174;       Nothing
175;   Corrupts registers:
176;       AX, CX, DX, SI, DI
177;--------------------------------------------------------------------
178.PrintBootMenuHotkey:
179%ifdef MODULE_BOOT_MENU
180    mov     ax, BOOT_MENU_HOTKEY_SCANCODE | ('2' << 8)
181    mov     di, g_szBootMenu
182    call    FormatFunctionHotkeyString
183%endif
184    ; Fall to .PrintComDetectHotkey
185
186;--------------------------------------------------------------------
187; .PrintComDetectHotkey
188;   Parameters:
189;       ES:     BDA segment (zero)
190;   Returns:
191;       Nothing
192;   Corrupts registers:
193;       AX, CX, DX, SI, DI
194;--------------------------------------------------------------------
195.PrintComDetectHotkey:
196%ifdef MODULE_SERIAL
197    mov     ax, COM_DETECT_HOTKEY_SCANCODE | ('6' << 8)
198    mov     di, g_szHotComDetect
199    call    FormatFunctionHotkeyString
200%endif
201    ; Fall to .PrintRomBootHotkey
202
203;--------------------------------------------------------------------
204; .PrintRomBootHotkey
205;   Parameters:
206;       ES:     BDA segment (zero)
207;   Returns:
208;       Nothing
209;   Corrupts registers:
210;       AX, CX, DX, SI, DI
211;--------------------------------------------------------------------
212.PrintRomBootHotkey:
213    mov     ax, ROM_BOOT_HOTKEY_SCANCODE | ('8' << 8)
214    mov     di, g_szRomBoot
215    call    FormatFunctionHotkeyString
216    ; Fall to .EndHotkeyBarRendering
217
218;--------------------------------------------------------------------
219; .EndHotkeyBarRendering
220;   Parameters:
221;       Stack:  Screen coordinates before drawing Hotkey Bar
222;   Returns:
223;       Nothing
224;   Corrupts registers:
225;       AX, CX, DI
226;--------------------------------------------------------------------
227.EndHotkeyBarRendering:
228    call    HotkeyBar_ClearRestOfTopRow
229    pop     ax
230    jmp     SHORT HotkeyBar_RestoreCursorCoordinatesFromAX
231
232
233;--------------------------------------------------------------------
234; HotkeyBar_ClearRestOfTopRow
235;   Parameters:
236;       Nothing
237;   Returns:
238;       Nothing
239;   Corrupts registers:
240;       AX, CX, DI
241;--------------------------------------------------------------------
242HotkeyBar_ClearRestOfTopRow:
243    CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
244    eMOVZX  cx, al
245    CALL_DISPLAY_LIBRARY GetSoftwareCoordinatesToAX
246    sub     cl, al
247    mov     al, ' '
248    JMP_DISPLAY_LIBRARY PrintRepeatedCharacterFromALwithCountInCX
249
250
251;--------------------------------------------------------------------
252; FormatDriveHotkeyString
253;   Parameters:
254;       CH:         Zero if letter in CL is selected for boot
255;       CL:         Drive letter hotkey from BOOTVARS
256;       AL:         First character for drive key string
257;       AH:         Second character for drive key string (ANGLE_QUOTE_RIGHT)
258;       SI:         Offset to hotkey description string
259;       ES:         BDA segment (zero)
260;   Returns:
261;       Nothing
262;   Corrupts registers:
263;       AX, CX, DX, SI, DI
264;--------------------------------------------------------------------
265FormatDriveHotkeyString:
266    ; Invalid scancodes are filtered on HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
267    ; so here we have either drive letter or function key pressed. If latter, draw
268    ; drive letters as unselected
269    cmp     BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], FIRST_FUNCTION_KEY_SCANCODE
270    jae     SHORT GetNonSelectedHotkeyDescriptionAttributeToDX
271
272    ; Drive selected to boot from?
273    test    ch, ch
274    jnz     SHORT GetNonSelectedHotkeyDescriptionAttributeToDX
275    jmp     SHORT GetSelectedHotkeyDescriptionAttributeToDX
276
277
278;--------------------------------------------------------------------
279; FormatFunctionHotkeyString
280;   Parameters:
281;       AL:         Scancode of function key, to know which if any to show as selected
282;                   Later replaced with an 'F' for the call to the output routine
283;       AH:         Second character for drive key string
284;       SI:         Offset to hotkey description string
285;       ES:         BDA segment (zero)
286;   Returns:
287;       Nothing
288;   Corrupts registers:
289;       AX, CX, DX, SI, DI
290;--------------------------------------------------------------------
291FormatFunctionHotkeyString:
292    xor     cx, cx      ; Null character, eaten in output routines
293
294    cmp     [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], al
295    mov     al, 'F'     ; Replace scancode with character for output
296
297%ifdef MODULE_BOOT_MENU
298
299GetSelectedHotkeyDescriptionAttributeToDX:
300    mov     si, ATTRIBUTE_CHARS.cHighlightedItem    ; Selected hotkey
301    je      SHORT GetDescriptionAttributeToDX       ; From compare with bScancode above and from FormatDriveHotkeyString
302
303GetNonSelectedHotkeyDescriptionAttributeToDX:
304    mov     si, ATTRIBUTE_CHARS.cItem               ; Unselected hotkey
305
306    ; Display Library should not be called like this
307GetDescriptionAttributeToDX:
308    xchg    dx, ax
309    call    MenuAttribute_GetToAXfromTypeInSI
310    xchg    dx, ax                  ; DX = Description attribute
311    ;;  fall through to PushHotkeyParamsAndFormat
312
313
314%else ; if no MODULE_BOOT_MENU - No boot menu so use simpler attributes
315
316GetSelectedHotkeyDescriptionAttributeToDX:
317    mov     dx, (COLOR_ATTRIBUTE(COLOR_YELLOW, COLOR_CYAN) << 8) | MONO_REVERSE_BLINK
318    je      SHORT SelectAttributeFromDHorDLbasedOnVideoMode     ; From compare with bScancode above and from FormatDriveHotkeyString
319
320GetNonSelectedHotkeyDescriptionAttributeToDX:
321    mov     dx, (COLOR_ATTRIBUTE(COLOR_BLACK, COLOR_CYAN) << 8) | MONO_REVERSE
322
323SelectAttributeFromDHorDLbasedOnVideoMode:
324    mov     ch, [es:BDA.bVidMode]       ; We only need to preserve CL
325    shr     ch, 1
326    jnc     SHORT .AttributeLoadedToDL  ; Black & White modes
327    shr     ch, 1
328    jnz     SHORT .AttributeLoadedToDL  ; MDA
329    mov     dl, dh
330.AttributeLoadedToDL:
331    ;;  fall through to PushHotkeyParamsAndFormat
332
333%endif ; MODULE_BOOT_MENU
334
335
336;--------------------------------------------------------------------
337; PushHotkeyParamsAndFormat
338;   Parameters:
339;       AL:         First character
340;       AH:         Second character
341;       DX:         Description Attribute
342;       CX:         Description string parameter
343;       CS:DI:      Description string
344;   Returns:
345;       Nothing
346;   Corrupts registers:
347;       AX, SI, DI
348;--------------------------------------------------------------------
349PushHotkeyParamsAndFormat:
350    push    bp
351    mov     bp, sp
352
353    mov     si, MONO_BRIGHT
354
355    push    si              ; Key attribute
356    push    ax              ; First Character
357    mov     al, ah
358    push    ax              ; Second Character
359
360    push    dx              ; Description attribute
361    push    di              ; Description string
362    push    cx              ; Description string parameter
363
364    push    si              ; Key attribute for last space
365
366    mov     si, g_szHotkey
367    jmp     DetectPrint_FormatCSSIfromParamsInSSBP
368
369
370;--------------------------------------------------------------------
371; MoveCursorToScreenTopLeftCorner
372;   Parameters:
373;       Nothing
374;   Returns:
375;       Nothing
376;   Corrupts registers:
377;       AX, DI
378;--------------------------------------------------------------------
379MoveCursorToScreenTopLeftCorner:
380    xor     ax, ax          ; Top left corner (0, 0)
381    ; Fall to HotkeyBar_RestoreCursorCoordinatesFromAX
382
383
384;--------------------------------------------------------------------
385; HotkeyBar_RestoreCursorCoordinatesFromAX
386;   Parameters:
387;       Nothing
388;   Returns:
389;       Nothing
390;   Corrupts registers:
391;       AX, DI
392;--------------------------------------------------------------------
393HotkeyBar_RestoreCursorCoordinatesFromAX:
394    JMP_DISPLAY_LIBRARY SetCursorCoordinatesFromAX
395
396
397;--------------------------------------------------------------------
398; HotkeyBar_StoreDefaultDriveLettersToHotkeyVars
399;   Parameters:
400;       ES:     BDA Segment
401;   Returns:
402;       Nothing
403;   Corrupts registers:
404;       AX
405;--------------------------------------------------------------------
406HotkeyBar_StoreDefaultDriveLettersToHotkeyVars:
407    call    BootVars_GetLetterForFirstHardDriveToAX
408    mov     ah, DEFAULT_FLOPPY_DRIVE_LETTER
409    xchg    al, ah
410    mov     [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wFddAndHddLetters], ax
411    ret
412
413
414;--------------------------------------------------------------------
415; HotkeyBar_InitializeVariables
416;   Parameters:
417;       DS:     RAMVARS Segment
418;       ES:     BDA Segment
419;   Returns:
420;       Nothing
421;   Corrupts registers:
422;       AX, CX, DX, DI
423;--------------------------------------------------------------------
424HotkeyBar_InitializeVariables:
425    push    ds
426    push    es
427    pop     ds
428
429    ; Store system 1Ch Timer Tick handler and install our hotkeybar handler
430    mov     ax, [SYSTEM_TIMER_TICK*4]
431    mov     [BOOTVARS.hotkeyVars+HOTKEYVARS.fpPrevTimerHandler], ax
432    mov     ax, [SYSTEM_TIMER_TICK*4+2]
433    mov     [BOOTVARS.hotkeyVars+HOTKEYVARS.fpPrevTimerHandler+2], ax
434    mov     al, SYSTEM_TIMER_TICK
435    mov     si, HotkeyBar_TimerTickHandler
436    call    Interrupts_InstallHandlerToVectorInALFromCSSI
437
438    ; Store time when hotkeybar is displayed
439    ; (it will be displayed after initialization is complete)
440    call    TimerTicks_ReadFromBdaToAX
441    mov     [BOOTVARS.hotkeyVars+HOTKEYVARS.wTimeWhenDisplayed], ax
442
443    pop     ds
444
445    ; Initialize HOTKEYVARS by storing default drives to boot from
446    call    HotkeyBar_StoreDefaultDriveLettersToHotkeyVars
447    mov     dl, [cs:ROMVARS.bBootDrv]
448    ; Fall to HotkeyBar_StoreHotkeyToBootvarsForDriveNumberInDL
449
450
451;--------------------------------------------------------------------
452; HotkeyBar_StoreHotkeyToBootvarsForDriveNumberInDL
453;   Parameters:
454;       DS:     RAMVARS segment
455;       ES:     BDA segment (zero)
456;       DL:     Drive Number
457;   Returns:
458;       Nothing
459;   Corrupts registers:
460;       AX, CX, DL, DI
461;--------------------------------------------------------------------
462HotkeyBar_StoreHotkeyToBootvarsForDriveNumberInDL:
463    call    DriveXlate_ConvertDriveNumberFromDLtoDriveLetter
464    ; Fall to StoreHotkeyToBootvarsForDriveLetterInDL
465
466
467;--------------------------------------------------------------------
468; StoreHotkeyToBootvarsForDriveLetterInDL
469;   Parameters:
470;       DS:     RAMVARS segment
471;       ES:     BDA segment (zero)
472;       DL:     Drive Letter ('A'...)
473;   Returns:
474;       Nothing
475;   Corrupts registers:
476;       AX, CX, DI
477;--------------------------------------------------------------------
478StoreHotkeyToBootvarsForDriveLetterInDL:
479    eMOVZX  ax, dl
480    or      al, 32  ; Upper case drive letter to lower case keystroke
481    jmp     SHORT HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
482
483
484;--------------------------------------------------------------------
485; ScanHotkeysFromKeyBufferAndStoreToBootvars
486;   Parameters:
487;       DS:     RAMVARS segment
488;       ES:     BDA segment (zero)
489;   Returns:
490;       AL:     Last scancode value
491;   Corrupts registers:
492;       AH, CX
493;--------------------------------------------------------------------
494ScanHotkeysFromKeyBufferAndStoreToBootvars:
495    call    Keyboard_GetKeystrokeToAX
496    jz      SHORT NoHotkeyToProcess
497
498    ; Prepare to read another key from buffer
499    ePUSH_T cx, ScanHotkeysFromKeyBufferAndStoreToBootvars
500    ; Fall to HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
501
502
503;--------------------------------------------------------------------
504; HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
505;   Parameters:
506;       AL:     Hotkey ASCII code
507;       AH:     Hotkey Scancode
508;       DS:     RAMVARS segment
509;       ES:     BDA segment (zero)
510;   Returns:
511;       AL:     Last scancode seen
512;       CF:     Set if valid hotkey in AL
513;               Clear if scancode in AL is not for any hotkey
514;   Corrupts registers:
515;       AH, CX, DI
516;--------------------------------------------------------------------
517HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX:
518    mov     di, BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode
519
520    ; All scancodes are saved, even if it wasn't a drive letter,
521    ; which also covers our function key case.  Invalid function keys
522    ; will not do anything (won't be printed, won't be accepted as input)
523    mov     [es:di], ah
524
525    ; Drive letter hotkeys remaining, allow 'a' to 'z'
526    call    Char_IsLowerCaseLetterInAL
527    jnc     SHORT .KeystrokeIsNotValidDriveLetter
528    and     al, ~32                 ; We want to print upper case letters
529
530    ; Clear HD First flag to assume Floppy Drive hotkey
531    dec     di
532    and     BYTE [es:di], ~FLG_HOTKEY_HD_FIRST
533
534    ; Determine if Floppy or Hard Drive hotkey
535    xchg    cx, ax
536    call    BootVars_GetLetterForFirstHardDriveToAX
537    cmp     cl, al
538    jb      SHORT .StoreDriveLetter ; Store Floppy Drive letter
539
540    ; Store Hard Drive letter
541    or      BYTE [es:di], FLG_HOTKEY_HD_FIRST
542
543.StoreDriveLetter:
544    sbb     di, BYTE 1              ; Sub CF if Floppy Drive
545    xchg    ax, cx
546    stosb
547    stc                             ; Valid hotkey scancode returned in AL
548
549.KeystrokeIsNotValidDriveLetter:
550NoHotkeyToProcess:
551    mov     al, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode]
552    ret
553
554
555;--------------------------------------------------------------------
556; HotkeyBar_GetBootDriveNumbersToDX
557;   Parameters:
558;       DS:     RAMVARS segment
559;       ES:     BDA segment (zero)
560;   Returns:
561;       DX:     Drives selected as boot device, DL is primary
562;   Corrupts registers:
563;       AX
564;--------------------------------------------------------------------
565HotkeyBar_GetBootDriveNumbersToDX:
566    mov     dx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wFddAndHddLetters]
567
568    ; HotkeyBar_GetBootDriveNumbersToDX is called when all drives are detected and
569    ; drive letters are known.
570    ; Replace unavailable hard drive letter with first hard drive.
571    ; If we have boot menu, it will be displayed instead.
572%ifndef MODULE_BOOT_MENU
573    call    BootVars_GetLetterForFirstHardDriveToAX
574    mov     ah, al
575    add     al, [es:BDA.bHDCount]   ; AL now contains first unavailable HD letter
576    cmp     dh, al                  ; Unavailable drive?
577    jb      SHORT .ValidHardDriveLetterInDH
578    mov     dh, ah                  ; Replace unavailable drive with first drive
579.ValidHardDriveLetterInDH:
580%endif
581
582    test    BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags], FLG_HOTKEY_HD_FIRST
583    jnz     SHORT .noflip
584    xchg    dl, dh
585.noflip:
586    call    DriveXlate_ConvertDriveLetterInDLtoDriveNumber
587    xchg    dl, dh
588    ; Fall to HotkeyBar_FallThroughTo_DriveXlate_ConvertDriveLetterInDLtoDriveNumber
589
590HotkeyBar_FallThroughTo_DriveXlate_ConvertDriveLetterInDLtoDriveNumber:
591
Note: See TracBrowser for help on using the repository browser.