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

Last change on this file since 604 was 604, checked in by krille_n_, 3 years ago

Changes:

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