OpenCores
URL https://opencores.org/ocsvn/next186_soc_pc/next186_soc_pc/trunk

Subversion Repositories next186_soc_pc

[/] [next186_soc_pc/] [trunk/] [SW/] [BIOS_Next186/] [BIOS_Next186.asm] - Diff between revs 3 and 4

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 3 Rev 4
; This file is part of the Next186 SoC PC project
; This file is part of the Next186 SoC PC project
; http://opencores.org/project,next186
; http://opencores.org/project,next186
; Filename: BIOS_Next186.asm
; Filename: BIOS_Next186.asm
; Description: Part of the Next186 SoC PC project, ROM BIOS code
; Description: Part of the Next186 SoC PC project, ROM BIOS code
; Version 1.0
; Version 1.0
; Creation date: Feb-Jun 2013
; Creation date: Feb-Jun 2013
; Author: Nicolae Dumitrache
; Author: Nicolae Dumitrache
; e-mail: ndumitrache@opencores.org
; e-mail: ndumitrache@opencores.org
; -------------------------------------------------------------------------------------
; -------------------------------------------------------------------------------------
; Copyright (C) 2013 Nicolae Dumitrache
; Copyright (C) 2013 Nicolae Dumitrache
; This source file may be used and distributed without
; This source file may be used and distributed without
; restriction provided that this copyright statement is not
; restriction provided that this copyright statement is not
; removed from the file and that any derivative work contains
; removed from the file and that any derivative work contains
; the original copyright notice and the associated disclaimer.
; the original copyright notice and the associated disclaimer.
; This source file is free software; you can redistribute it
; This source file is free software; you can redistribute it
; and/or modify it under the terms of the GNU Lesser General
; and/or modify it under the terms of the GNU Lesser General
; Public License as published by the Free Software Foundation;
; Public License as published by the Free Software Foundation;
; either version 2.1 of the License, or (at your option) any
; either version 2.1 of the License, or (at your option) any
; later version.
; later version.
; This source is distributed in the hope that it will be
; This source is distributed in the hope that it will be
; useful, but WITHOUT ANY WARRANTY; without even the implied
; useful, but WITHOUT ANY WARRANTY; without even the implied
; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
; PURPOSE. See the GNU Lesser General Public License for more
; PURPOSE. See the GNU Lesser General Public License for more
; details.
; details.
; You should have received a copy of the GNU Lesser General
; You should have received a copy of the GNU Lesser General
; Public License along with this source; if not, download it
; Public License along with this source; if not, download it
; from http://www.opencores.org/lgpl.shtml
; from http://www.opencores.org/lgpl.shtml
; -----------------------------------------------------------------------
; -----------------------------------------------------------------------
; Additional Comments:
; Additional Comments:
; Assembled with MASM v6.14.8444
; Assembled with MASM v6.14.8444
; Next186 SoC PC have no ROM, only RAM. The bootstrap code is the initial value of cache
; Next186 SoC PC have no ROM, only RAM. The bootstrap code is the initial value of cache
;  (last half 1K = 4 lines of 256bytes each), initially marked as "dirty", in order to
;  (last half 1K = 4 lines of 256bytes each), initially marked as "dirty", in order to
;  be saved in RAM at first flush
;  be saved in RAM at first flush
; The bootstrap code may load the BIOS from SD, or from RS232, and place it at F000:E000
; The bootstrap code may load the BIOS from SD, or from RS232, and place it at F000:E000
.186
.186
.model tiny
.model tiny
.code
.code
SCANCODE1   equ 1
SCANCODE1   equ 1
;-------------------------- BIOS data area (BDA) -----------------
;-------------------------- BIOS data area (BDA) -----------------
;40:0000   2  Base port address of first RS-232 adapter (COM1) See COM Ports
;40:0000   2  Base port address of first RS-232 adapter (COM1) See COM Ports
;40:0002   2  Port of COM2
;40:0002   2  Port of COM2
;40:0004   2  Port of COM3
;40:0004   2  Port of COM3
;40:0006   2  Port of COM4
;40:0006   2  Port of COM4
;40:0008   2  Base port addr of first parallel printer (LPT1)  Printer Ports
;40:0008   2  Base port addr of first parallel printer (LPT1)  Printer Ports
;40:000A   2  Port of LPT2
;40:000A   2  Port of LPT2
;40:000C   2  Port of LPT3
;40:000C   2  Port of LPT3
;40:000E   2  Port of LPT4
;40:000E   2  Port of LPT4
;40:0010   2  Equipment/hardware installed/active; see Equipment List
;40:0010   2  Equipment/hardware installed/active; see Equipment List
;40:0012   1  Errors in PCjr infrared keyboard link
;40:0012   1  Errors in PCjr infrared keyboard link
;40:0013   2  Total memory in K-bytes (same as obtained via INT 12H)
;40:0013   2  Total memory in K-bytes (same as obtained via INT 12H)
;40:0015   2  Scratch pad for manufacturing error tests
;40:0015   2  Scratch pad for manufacturing error tests
;
;
;40:0017   2  Keyboard status bits; see Keyboard Shift Status Flags
;40:0017   2  Keyboard status bits; see Keyboard Shift Status Flags
;40:0019   1  Current (accumulating) value of Alt+numpad pseudo-key input;
;40:0019   1  Current (accumulating) value of Alt+numpad pseudo-key input;
;             normally 0.  When [Alt] is released, value is stored in
;             normally 0.  When [Alt] is released, value is stored in
;             keyboard buffer at 001e.
;             keyboard buffer at 001e.
;40:001a   2  Addr of keyboard buffer head (keystroke at that addr is next)
;40:001a   2  Addr of keyboard buffer head (keystroke at that addr is next)
;40:001c   2  Address of keyboard buffer tail
;40:001c   2  Address of keyboard buffer tail
;40:001e  32  Keyboard buffer.  BIOS stores keystrokes here (head and tail
;40:001e  32  Keyboard buffer.  BIOS stores keystrokes here (head and tail
;             point to addresses from 041eH to 043dH inclusive).
;             point to addresses from 041eH to 043dH inclusive).
;
;
;40:003e   1  Diskette drive needs recalibration (bit 0=A, bit 1=B, etc.)
;40:003e   1  Diskette drive needs recalibration (bit 0=A, bit 1=B, etc.)
;             bits 4-5 indicate which drive is currently selected
;             bits 4-5 indicate which drive is currently selected
;40:003f   1  Diskette motor is running (bit 0=drive A, bit 1=B, etc.)
;40:003f   1  Diskette motor is running (bit 0=drive A, bit 1=B, etc.)
;40:0040   1  Time until motor off. INT 08H turns motor off when this is 0.
;40:0040   1  Time until motor off. INT 08H turns motor off when this is 0.
;40:0041   1  Diskette error status; same as status returned by INT 13H
;40:0041   1  Diskette error status; same as status returned by INT 13H
;40:0042   7  Diskette controller status information area
;40:0042   7  Diskette controller status information area
;
;
;40:0049   1  Current active video mode.  See Video Modes and INT 10H.
;40:0049   1  Current active video mode.  See Video Modes and INT 10H.
;40:004a   2  Screen width in text columns
;40:004a   2  Screen width in text columns
;40:004c   2  Length (in bytes) of video area (regen size)
;40:004c   2  Length (in bytes) of video area (regen size)
;40:004e   2  Offset from video segment of active video memory page
;40:004e   2  Offset from video segment of active video memory page
;40:0050  16  Cursor location (8 byte-pairs; low byte=clm, hi byte=row)
;40:0050  16  Cursor location (8 byte-pairs; low byte=clm, hi byte=row)
;40:0060   2  Cursor size/shape.  Low byte=end scan line; hi byte=start line.
;40:0060   2  Cursor size/shape.  Low byte=end scan line; hi byte=start line.
;40:0062   1  Current active video page number
;40:0062   1  Current active video page number
;40:0063   2  Port address for 6845 video controller chip; see CGA I/O Ports
;40:0063   2  Port address for 6845 video controller chip; see CGA I/O Ports
;40:0065   1  Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
;40:0065   1  Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
;40:0066   1  Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
;40:0066   1  Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
;
;
;40:0067   5  Cassette data area or POST data area
;40:0067   5  Cassette data area or POST data area
;               40:0067: 1 byte mouse buffer counter (DataCounter)
;               40:0067: 1 byte mouse buffer counter (DataCounter)
;               40:0068: 1 byte mouse packet size (PacketSize): 0 for 3 bytes, 1 for 4 bytes (Intellimouse)
;               40:0068: 1 byte mouse packet size (PacketSize): 0 for 3 bytes, 1 for 4 bytes (Intellimouse)
;               40:0069: 1 byte palette paging status
;               40:0069: 1 byte palette paging status
;               40:006a: 1 byte PalPagingCounter - guards pal paging re-entrance
;               40:006a: 1 byte PalPagingCounter - guards pal paging re-entrance
;
;
;40:006c   4  Timer tick counter (count of 55ms ticks since CPU reset)
;40:006c   4  Timer tick counter (count of 55ms ticks since CPU reset)
;40:0070   1  Timer overflow flag (timer has rolled over 24 hr)
;40:0070   1  Timer overflow flag (timer has rolled over 24 hr)
;40:0071   1  Ctrl-Break flag.  Bit 7=1 when break was pressed.  This never
;40:0071   1  Ctrl-Break flag.  Bit 7=1 when break was pressed.  This never
;             gets reset unless you do it yourself.
;             gets reset unless you do it yourself.
;
;
;40:0072   2  1234H means Ctrl+Alt+Del reboot is in progress.  BIOS checks
;40:0072   2  1234H means Ctrl+Alt+Del reboot is in progress.  BIOS checks
;             this to avoid doing a "cold boot" with the time-consuming POST
;             this to avoid doing a "cold boot" with the time-consuming POST
;             4321H means reset, preserving memory
;             4321H means reset, preserving memory
;             5678H, 9abcH, and abcdH (are internal PC Convertible codes)
;             5678H, 9abcH, and abcdH (are internal PC Convertible codes)
;
;
;40:0074   4  PCjr diskette or AT hard disk control area
;40:0074   4  PCjr diskette or AT hard disk control area
;  (0074)   1 Status of last fixed-disk drive operation
;  (0074)   1 Status of last fixed-disk drive operation
;  (0075)   1 Number of hard disk drives for AT
;  (0075)   1 Number of hard disk drives for AT
;  (0077)   1 Hard disk port for XT.  See XT Hard Disk Ports.
;  (0077)   1 Hard disk port for XT.  See XT Hard Disk Ports.
;40:0078   4  Printer time-out values (478H=Lpt1, 478H=Lpt2...)
;40:0078   4  Printer time-out values (478H=Lpt1, 478H=Lpt2...)
;40:007c   4  RS-232 time-out values  (47cH=Com1, 47dH=Com2...)
;40:007c   4  RS-232 time-out values  (47cH=Com1, 47dH=Com2...)
;
;
;40:0080   2  AT PS/2 keyboard buffer offset start address (usually 01eH)
;40:0080   2  AT PS/2 keyboard buffer offset start address (usually 01eH)
;40:0082   2                                   end address (usually 003eH)
;40:0082   2                                   end address (usually 003eH)
;
;
;40:0084   1  EGA text rows-1  (maximum valid row value)
;40:0084   1  EGA text rows-1  (maximum valid row value)
;40:0085   2  EGA bytes per character (scan-lines/char used in active mode)
;40:0085   2  EGA bytes per character (scan-lines/char used in active mode)
;40:0087   1  EGA flags; see EgaMiscInfoRec
;40:0087   1  EGA flags; see EgaMiscInfoRec
;40:0088   1  EGA flags; see EgaMiscInfo2Rec
;40:0088   1  EGA flags; see EgaMiscInfo2Rec
;40:0089   1  VGA flags; see VgaFlagsRec
;40:0089   1  VGA flags; see VgaFlagsRec
;             See also:  EGA/VGA Data Areas
;             See also:  EGA/VGA Data Areas
;
;
;40:008b   1  AT PS/2 Media control: data rate, step rate
;40:008b   1  AT PS/2 Media control: data rate, step rate
;40:008c   1  AT PS/2 Hard disk drive controller status
;40:008c   1  AT PS/2 Hard disk drive controller status
;40:008d   1  AT PS/2 Hard disk drive error status
;40:008d   1  AT PS/2 Hard disk drive error status
;40:008e   1  AT PS/2 Hard disk drive interrupt control
;40:008e   1  AT PS/2 Hard disk drive interrupt control
;
;
;40:0090   1  AT PS/2 Disk media state bits for drive 0
;40:0090   1  AT PS/2 Disk media state bits for drive 0
;40:0091   1                                for drive 1
;40:0091   1                                for drive 1
;40:0092   1  AT PS/2 Disk operation started flag for drive 0
;40:0092   1  AT PS/2 Disk operation started flag for drive 0
;40:0093   1                                      for drive 1
;40:0093   1                                      for drive 1
;40:0094   1  AT PS/2 Present cylinder number for drive 0
;40:0094   1  AT PS/2 Present cylinder number for drive 0
;40:0095   1                                  for drive 1
;40:0095   1                                  for drive 1
        ; 2 - Number of 512bytes sectors of HD0
        ; 2 - Number of 512bytes sectors of HD0
;
;
;40:0096   1  AT Keyboard flag bit 4=1 (10H) if 101-key keyboard is attached
;40:0096   1  AT Keyboard flag bit 4=1 (10H) if 101-key keyboard is attached
;40:0097   1  AT Keyboard flag for LED 'key lock' display
;40:0097   1  AT Keyboard flag for LED 'key lock' display
;             bits 0-2 are ScrollLock, NumLock, CapsLock
;             bits 0-2 are ScrollLock, NumLock, CapsLock
;
;
;40:0098   4  AT Pointer to 8-bit user wait flag; see INT 15H 86H
;40:0098   4  AT Pointer to 8-bit user wait flag; see INT 15H 86H
;40:009c   4  AT Microseconds before user wait is done
;40:009c   4  AT Microseconds before user wait is done
;40:00a0   1  AT User wait activity flag:
;40:00a0   1  AT User wait activity flag:
;                01H=busy, 80H=posted, 00H=acknowledged
;                01H=busy, 80H=posted, 00H=acknowledged
;
;
;40:00a1   7  AT Reserved for network adapters
;40:00a1   7  AT Reserved for network adapters
;               40:00a1: 4 bytes far pointer to mouse callback (HandlerPtr)
;               40:00a1: 4 bytes far pointer to mouse callback (HandlerPtr)
;               40:00a5: 3 bytes mouse buffer (DataBuffer)
;               40:00a5: 3 bytes mouse buffer (DataBuffer)
;
;
;40:00a8   4  EGA Address of table of pointers; see EgaSavePtrRec
;40:00a8   4  EGA Address of table of pointers; see EgaSavePtrRec
;40:00ac  68  Reserved
;40:00ac  68  Reserved
;40:00f0  16  (IAC) Inter-Aapplication Communication area.  Programs may use
;40:00f0  16  (IAC) Inter-Aapplication Communication area.  Programs may use
;             this area to store status, etc.  Might get overwritten by
;             this area to store status, etc.  Might get overwritten by
;             another program.
;             another program.
; http://www.ctyme.com/intr/int.htm
; http://www.ctyme.com/intr/int.htm
; video memory: 8 physical segments at 0a000h, 0b000h, 0c000h, 0d000h, 0e000h, 0f000h, 10000h, 11000h
; video memory: 8 physical segments at 0a000h, 0b000h, 0c000h, 0d000h, 0e000h, 0f000h, 10000h, 11000h
; Memory segments mapping
; Memory segments mapping
; 1Mb virtual seg address   physical seg address
; 1Mb virtual seg address   physical seg address
;       0000h                   0000h
;       0000h                   0000h
;       1000h                   1000h
;       1000h                   1000h
;       2000h                   2000h
;       2000h                   2000h
;       3000h                   3000h
;       3000h                   3000h
;       4000h                   4000h
;       4000h                   4000h
;       5000h                   5000h
;       5000h                   5000h
;       6000h                   6000h
;       6000h                   6000h
;       7000h                   7000h
;       7000h                   7000h
;       8000h                   8000h
;       8000h                   8000h
;       9000h                   9000h
;       9000h                   9000h
;       a000h                   a000h       - video
;       a000h                   a000h       - video
;       b000h                   b000h       - video
;       b000h                   b000h       - video
;       c000h                   12000h
;       c000h                   12000h
;       d000h                   13000h
;       d000h                   13000h
;       e000h                   14000h
;       e000h                   14000h
;       f000h                   15000h
;       f000h                   15000h
        org 0e000h
        org 0e000h
bios:
bios:
biosmsg     db 'Next186 Spartan3AN SoC PC BIOS (C) 2013 Nicolae Dumitrache', 0
biosmsg     db 'Next186 Spartan3AN SoC PC BIOS (C) 2013 Nicolae Dumitrache', 0
msgmb       db 'MB SD Card', 13, 10, 0
msgmb       db 'MB SD Card', 13, 10, 0
msgkb       db 'PS2 KB detected', 13, 10, 0
msgkb       db 'PS2 KB detected', 13, 10, 0
; Graphics character set
; Graphics character set
font8x8:         ; TODO define and place font
font8x8:         ; TODO define and place font
font8x16:        ; TODO define and place font
font8x16:        ; TODO define and place font
        org 0e05bh
        org 0e05bh
coldboot:
coldboot:
warmboot:
warmboot:
        cli
        cli
        cld
        cld
        mov     ax, 30h
        mov     ax, 30h
        mov     ss, ax
        mov     ss, ax
        mov     sp, 100h
        mov     sp, 100h
        push    0
        push    0
        popf
        popf
        mov     al, 36h
        mov     al, 36h
        out     43h, al
        out     43h, al
        xor     ax, ax
        xor     ax, ax
        out     40h, al
        out     40h, al
        out     40h, al      ; 18Hz PIT CH0
        out     40h, al      ; 18Hz PIT CH0
        out     61h, al      ; speaker off
        out     61h, al      ; speaker off
        not     al
        not     al
        out     21h, al      ; disable all interrupts
        out     21h, al      ; disable all interrupts
; ------------------ MAP init
; ------------------ MAP init
        call    flush
        call    flush
        mov     ax, 15h     ; BIOS physical segment 15h mapped on virtual segment 0ch
        mov     ax, 15h     ; BIOS physical segment 15h mapped on virtual segment 0ch
        out     8ch, ax
        out     8ch, ax
        push    0c000h
        push    0c000h
        pop     es
        pop     es
        push    0f000h
        push    0f000h
        pop     ds
        pop     ds
        xor     si, si
        xor     si, si
        xor     di, di
        xor     di, di
        mov     cx, 8000h
        mov     cx, 8000h
        rep     movsw       ; copy BIOS virtual segment 0fh over physical segment 15h
        rep     movsw       ; copy BIOS virtual segment 0fh over physical segment 15h
        call    flush
        call    flush
        mov     dx, 80h
        mov     dx, 80h
        xor     ax, ax
        xor     ax, ax
mapi:
mapi:
        out     dx, ax
        out     dx, ax
        inc     ax
        inc     ax
        inc     dx
        inc     dx
        cmp     al, 0ch
        cmp     al, 0ch
        jne     short mapi1
        jne     short mapi1
        add     al, 6
        add     al, 6
mapi1:
mapi1:
        cmp     al, 16h
        cmp     al, 16h
        jne     short mapi
        jne     short mapi
; -------------------- Interrupt table init
; -------------------- Interrupt table init
        push    0
        push    0
        pop     ds
        pop     ds
        push    ds
        push    ds
        pop     es
        pop     es
        xor     si, si
        xor     si, si
        mov     di, 4
        mov     di, 4
        mov     word ptr [si], offset defint
        mov     word ptr [si], offset defint
        mov     word ptr [si+2], cs
        mov     word ptr [si+2], cs
        mov     cx, 256-2
        mov     cx, 256-2
        rep     movsw
        rep     movsw
        mov     word ptr ds:[7*4], offset int07
        mov     word ptr ds:[7*4], offset int07
        mov     word ptr ds:[8*4], offset int08
        mov     word ptr ds:[8*4], offset int08
        mov     word ptr ds:[9*4], offset int09
        mov     word ptr ds:[9*4], offset int09
        mov     word ptr ds:[10h*4], offset int10
        mov     word ptr ds:[10h*4], offset int10
        mov     word ptr ds:[11h*4], offset int11
        mov     word ptr ds:[11h*4], offset int11
        mov     word ptr ds:[12h*4], offset int12
        mov     word ptr ds:[12h*4], offset int12
        mov     word ptr ds:[13h*4], offset int13
        mov     word ptr ds:[13h*4], offset int13
        mov     word ptr ds:[15h*4], offset int15
        mov     word ptr ds:[15h*4], offset int15
        mov     word ptr ds:[16h*4], offset int16
        mov     word ptr ds:[16h*4], offset int16
        mov     word ptr ds:[18h*4], offset int18
        mov     word ptr ds:[18h*4], offset int18
        mov     word ptr ds:[19h*4], offset int19
        mov     word ptr ds:[19h*4], offset int19
        mov     word ptr ds:[1ah*4], offset int1a
        mov     word ptr ds:[1ah*4], offset int1a
        mov     word ptr ds:[70h*4], offset int70
        mov     word ptr ds:[70h*4], offset int70
        mov     word ptr ds:[74h*4], offset int74
        mov     word ptr ds:[74h*4], offset int74
; ------------------- BDA init
; ------------------- BDA init
        push    40h
        push    40h
        pop     ds
        pop     ds
        push    ds
        push    ds
        pop     es
        pop     es
        xor     di, di
        xor     di, di
        xor     si, si
        xor     si, si
        xor     ax, ax
        xor     ax, ax
        mov     cl, 80h
        mov     cl, 80h
        rep     stosw
        rep     stosw
        mov     byte ptr [si+10h], 24h   ; equipment word (color 80x25, PS2 mouse present)
        mov     byte ptr [si+10h], 24h   ; equipment word (color 80x25, PS2 mouse present)
        mov     word ptr [si+13h], 640   ; memory size in KB
        mov     word ptr [si+13h], 640   ; memory size in KB
        add     word ptr [si+1ah], 1eh   ; next char pointer in kb buffer
        add     word ptr [si+1ah], 1eh   ; next char pointer in kb buffer
        add     word ptr [si+1ch], 1eh   ; last char pointer in kb buffer
        add     word ptr [si+1ch], 1eh   ; last char pointer in kb buffer
        mov     word ptr [si+60h], 0e0fh ; cursor shape
        mov     word ptr [si+60h], 0e0fh ; cursor shape
        mov     word ptr [si+63h], 3d4h  ; video port address
        mov     word ptr [si+63h], 3d4h  ; video port address
        add     word ptr [si+80h], 1eh   ; start kb buffer
        add     word ptr [si+80h], 1eh   ; start kb buffer
        add     word ptr [si+82h], 3eh   ; end kb buffer
        add     word ptr [si+82h], 3eh   ; end kb buffer
        mov     word ptr [si+87h], 0940h ; video adapter options (512Kb video)
        mov     word ptr [si+87h], 0940h ; video adapter options (512Kb video)
        mov     word ptr [si+89h], 0b71h ; VGA video flags: 400 line text mode, default palette loading on (0), blinking on
        mov     word ptr [si+89h], 0b71h ; VGA video flags: 400 line text mode, default palette loading on (0), blinking on
        mov     byte ptr [si+96h], 10h   ; 101 keyboard installed
        mov     byte ptr [si+96h], 10h   ; 101 keyboard installed
; ------------------- Graph mode init
; ------------------- Graph mode init
        mov     ax, 3
        mov     ax, 3
        int     10h
        int     10h
 ; ------------------- KB init ----------------
 ; ------------------- KB init ----------------
        mov     al, 0aeh
        mov     al, 0aeh
        out     64h, al     ; enable kb
        out     64h, al     ; enable kb
        mov     al, 0a7h
        mov     al, 0a7h
        out     64h, al     ; disable mouse
        out     64h, al     ; disable mouse
        mov     cx, 25
        mov     cx, 25
kbi1:
kbi1:
        call    getps2byte
        call    getps2byte
        loop    short kbi1  ; wait for kb timeout
        loop    short kbi1  ; wait for kb timeout
        mov     ah, 0ffh    ; reset kb
        mov     ah, 0ffh    ; reset kb
        clc                 ; kb command
        clc                 ; kb command
        call    sendcmd
        call    sendcmd
        jc      short nokb
        jc      short nokb
        mov     cl, 25
        mov     cl, 25
kbi2:
kbi2:
        dec     cx
        dec     cx
        jcxz    short nokb
        jcxz    short nokb
        call    getps2byte
        call    getps2byte
        jc      short kbi2  ; wait for BAT
        jc      short kbi2  ; wait for BAT
        cmp     al, 0aah
        cmp     al, 0aah
        jne     short nokb
        jne     short nokb
        mov     ah, 0f2h    ; kb id
        mov     ah, 0f2h    ; kb id
        call    sendcmd     ; CF = 0
        call    sendcmd     ; CF = 0
        jc      short nokb
        jc      short nokb
        call    getps2byte
        call    getps2byte
        cmp     al, 0abh
        cmp     al, 0abh
        jne     short nokb
        jne     short nokb
        call    getps2byte
        call    getps2byte
        cmp     al, 83h
        cmp     al, 83h
; set scan code 1
; set scan code 1
IFDEF SCANCODE1
IFDEF SCANCODE1
        jne     short nokb
        jne     short nokb
        mov     ah, 0f0h    ; kb scan set
        mov     ah, 0f0h    ; kb scan set
        call    sendcmd
        call    sendcmd
        jc      short nokb
        jc      short nokb
        mov     ah, 1       ; scan set 1
        mov     ah, 1       ; scan set 1
        call    sendcmd
        call    sendcmd
        jnc     short kbok
        jnc     short kbok
ELSE
ELSE
        je     short kbok
        je     short kbok
ENDIF
ENDIF
nokb:
nokb:
        mov     byte ptr KbdFlags3, 0   ; kb not present
        mov     byte ptr KbdFlags3, 0   ; kb not present
kbok:
kbok:
        mov     al, 0adh
        mov     al, 0adh
        out     64h, al      ; disable kb interface
        out     64h, al      ; disable kb interface
; ------------------- Mouse init ----------------
; ------------------- Mouse init ----------------
        mov     al, 0a8h
        mov     al, 0a8h
        out     64h, al      ; enable mouse
        out     64h, al      ; enable mouse
mousei0:
mousei0:
        call    getps2byte
        call    getps2byte
        jnc     short mousei0
        jnc     short mousei0
        mov     ah, 0ffh
        mov     ah, 0ffh
        call    sendcmd      ; reset mouse (CF = 1)
        call    sendcmd      ; reset mouse (CF = 1)
        jc      short nomouse
        jc      short nomouse
        mov     cl, 25
        mov     cl, 25
mousei1:
mousei1:
        dec     cx
        dec     cx
        jcxz    short nomouse
        jcxz    short nomouse
        call    getps2byte
        call    getps2byte
        jc      short mousei1
        jc      short mousei1
        cmp     al, 0aah     ; BAT
        cmp     al, 0aah     ; BAT
        jne     short nomouse
        jne     short nomouse
        call    getps2byte
        call    getps2byte
        cmp     al, 0        ; mouse ID
        cmp     al, 0        ; mouse ID
        je      short mouseok
        je      short mouseok
nomouse:
nomouse:
        mov     al, 0a7h
        mov     al, 0a7h
        out     64h, al      ; disable mouse
        out     64h, al      ; disable mouse
        and     byte ptr EquipmentWord, not 4 ; ps2 mouse not present in equipement word
        and     byte ptr EquipmentWord, not 4 ; ps2 mouse not present in equipement word
mouseok:
mouseok:
        call    enableKbIfPresent
        call    enableKbIfPresent
        mov     al, 20h
        mov     al, 20h
        out     64h, al
        out     64h, al
        in      al, 60h
        in      al, 60h
        or      al, 3
        or      al, 3
        mov     ah, al
        mov     ah, al
        mov     al, 60h
        mov     al, 60h
        out     64h, al
        out     64h, al
        mov     al, ah
        mov     al, ah
        out     60h, al     ; enable 8042 mouse and kb interrupts
        out     60h, al     ; enable 8042 mouse and kb interrupts
        mov     ax,1000-1   ; 1ms
        mov     ax,1000-1   ; 1ms
        out     70h, ax     ; set RTC frequency
        out     70h, ax     ; set RTC frequency
        mov     al, 0e4h
        mov     al, 0e4h
        out     21h, al     ; enable all PIC interrupts (8h, 9h, 70h, 74h)
        out     21h, al     ; enable all PIC interrupts (8h, 9h, 70h, 74h)
        sti                 ; enable CPU interrupts
        sti                 ; enable CPU interrupts
; ---------------------   HDD init
; ---------------------   HDD init
        call    sdinit
        call    sdinit
        mov     HDSize, ax
        mov     HDSize, ax
        push    cs
        push    cs
        pop     es
        pop     es
        mov     si, offset biosmsg
        mov     si, offset biosmsg
        call    prts
        call    prts
        mov     si, offset bioscont
        mov     si, offset bioscont
        call    prts
        call    prts
        mov     ax, HDSize
        mov     ax, HDSize
        shr     ax, 1
        shr     ax, 1
        call    dispAX
        call    dispAX
        mov     si, offset msgmb
        mov     si, offset msgmb
        call    prts
        call    prts
        test    byte ptr KbdFlags3, 10h
        test    byte ptr KbdFlags3, 10h
        jz      nokbmsg
        jz      nokbmsg
        mov     si, offset msgkb
        mov     si, offset msgkb
        call    prts
        call    prts
nokbmsg:
nokbmsg:
        test    byte ptr EquipmentWord, 4
        test    byte ptr EquipmentWord, 4
        jz      nomousemsg
        jz      nomousemsg
        mov     si, offset msgmouse
        mov     si, offset msgmouse
        call    prts
        call    prts
nomousemsg:
nomousemsg:
;-------------- HD bootstrap
;-------------- HD bootstrap
        mov     ax, 305h
        mov     ax, 305h
        xor     bx, bx
        xor     bx, bx
        int     16h     ; set typematic rate and delay to fastest
        int     16h     ; set typematic rate and delay to fastest
        int     19h
        int     19h
msgmouse    db 'PS2 Mouse detected', 13, 10, 0
msgmouse    db 'PS2 Mouse detected', 13, 10, 0
bioscont    db 13, 10, 'CPU: 80186 33Mhz (33MIPS, 66Mhz 32bit bus)', 13, 10
bioscont    db 13, 10, 'CPU: 80186 33Mhz (33MIPS, 66Mhz 32bit bus)', 13, 10
            db 'RAM: 64MB DDR2 133Mhz', 13, 10
            db 'RAM: 64MB DDR2 133Mhz', 13, 10
            db 'Cache: 8x256 bytes data/inst', 13, 10
            db 'Cache: 8x256 bytes data/inst', 13, 10
            db 'HD0: ', 0
            db 'HD0: ', 0
; ---------------------------- INT 07 ---------------------
; ---------------------------- INT 07 ---------------------
int07 proc near ; coprocessor ESC sequence
int07 proc near ; coprocessor ESC sequence
        push    ax
        push    ax
        push    bx
        push    bx
        push    ds
        push    ds
        push    bp
        push    bp
        mov     bp, sp
        mov     bp, sp
        lds     bx, [bp+8]
        lds     bx, [bp+8]
int07_pfx:
int07_pfx:
        mov     al, [bx]
        mov     al, [bx]
        inc     bx
        inc     bx
        and     al, 0f8h
        and     al, 0f8h
        cmp     al, 0d8h        ; ESC code
        cmp     al, 0d8h        ; ESC code
        jne     short int07_pfx
        jne     short int07_pfx
        cmp     byte ptr [bx], 0c0h ; mod reg r/m of ESC 8087 instruction
        cmp     byte ptr [bx], 0c0h ; mod reg r/m of ESC 8087 instruction
        sbb     al, al
        sbb     al, al
        and     al, [bx]
        and     al, [bx]
        and     ax, 0c7h
        and     ax, 0c7h
        cmp     al, 6
        cmp     al, 6
        jne     int072
        jne     int072
        mov     al, 80h
        mov     al, 80h
int072:
int072:
        shr     al, 6
        shr     al, 6
        inc     ax
        inc     ax
        add     ax, bx
        add     ax, bx
        mov     [bp+8], ax
        mov     [bp+8], ax
        pop     bp
        pop     bp
        pop     ds
        pop     ds
        pop     bx
        pop     bx
        pop     ax
        pop     ax
        iret
        iret
int07 endp
int07 endp
; ---------------------------- INT 08 ---------------------
; ---------------------------- INT 08 ---------------------
int08 proc near
int08 proc near
        push    ds
        push    ds
        push    bx
        push    bx
        push    40h
        push    40h
        pop     ds
        pop     ds
        mov     bx, 6ch
        mov     bx, 6ch
        add     word ptr [bx], 1
        add     word ptr [bx], 1
        adc     word ptr [bx+2], 0
        adc     word ptr [bx+2], 0
        cmp     word ptr [bx+2], 18h
        cmp     word ptr [bx+2], 18h
        jne     short int081
        jne     short int081
        cmp     word ptr [bx], 0b0h
        cmp     word ptr [bx], 0b0h
        jne     short int081
        jne     short int081
        mov     word ptr [bx], 0
        mov     word ptr [bx], 0
        mov     word ptr [bx+2], 0
        mov     word ptr [bx+2], 0
        mov     byte ptr [bx+4], 1
        mov     byte ptr [bx+4], 1
int081:
int081:
        int     1ch
        int     1ch
        sti
        sti
        push    ax
        push    ax
        mov     ah, 4
        mov     ah, 4
kloop:
kloop:
        in      al, 64h
        in      al, 64h
        test    al, 1
        test    al, 1
        jz      short nokey
        jz      short nokey
        dec     ah
        dec     ah
        jnz     short kloop
        jnz     short kloop
        test    al, 20h
        test    al, 20h
        jz      short kbdata
        jz      short kbdata
        int     74h
        int     74h
        jmp     short nokey
        jmp     short nokey
kbdata:
kbdata:
        int     9h
        int     9h
nokey:
nokey:
        pop     ax
        pop     ax
        pop     bx
        pop     bx
        pop     ds
        pop     ds
        iret
        iret
int08 endp
int08 endp
; --------------------- INT 09 - keyboard ------------------
; --------------------- INT 09 - keyboard ------------------
KbdFlags1       equ     
KbdFlags1       equ     
KbdFlags2       equ     
KbdFlags2       equ     
AltKpd          equ     
AltKpd          equ     
CtrlBreak       equ     
CtrlBreak       equ     
KbdFlags3       equ     
KbdFlags3       equ     
KbdFlags4       equ     
KbdFlags4       equ     
; Bits for the KbdFlags1
; Bits for the KbdFlags1
RShfDown        equ     1
RShfDown        equ     1
LShfDown        equ     2
LShfDown        equ     2
CtrlDown        equ     4
CtrlDown        equ     4
AltDown         equ     8
AltDown         equ     8
ScrLock         equ     10h
ScrLock         equ     10h
NumLock         equ     20h
NumLock         equ     20h
CapsLock        equ     40h
CapsLock        equ     40h
Insert          equ     80h
Insert          equ     80h
; Bits for the KbdFlags2
; Bits for the KbdFlags2
LCtrDown        equ     1
LCtrDown        equ     1
LAltDown        equ     2
LAltDown        equ     2
SysReqDown      equ     4
SysReqDown      equ     4
Pause           equ     8
Pause           equ     8
ScrLockDown     equ     10h
ScrLockDown     equ     10h
NumLockDown     equ     20h
NumLockDown     equ     20h
CapsLockDown    equ     40h
CapsLockDown    equ     40h
InsDown         equ     80h
InsDown         equ     80h
; Bits for the KbdFlags3
; Bits for the KbdFlags3
LastE1          equ     1
LastE1          equ     1
LastE0          equ     2
LastE0          equ     2
RCtrDown        equ     4
RCtrDown        equ     4
RAltDown        equ     8
RAltDown        equ     8
LastF0          equ     20h
LastF0          equ     20h
; Bits for the KbdFlags4
; Bits for the KbdFlags4
ScrLockLED      equ     1
ScrLockLED      equ     1
NumLockLED      equ     2
NumLockLED      equ     2
CapsLockLED     equ     4
CapsLockLED     equ     4
SetRepeat       equ     8       ; Set auto repeat command in progress
SetRepeat       equ     8       ; Set auto repeat command in progress
AckReceived     equ     10h
AckReceived     equ     10h
LEDUpdate       equ     40h
LEDUpdate       equ     40h
IFDEF SCANCODE1
IFDEF SCANCODE1
int09 proc near
int09 proc near
        pusha
        pusha
        push    ds
        push    ds
        push    es
        push    es
        push    40h
        push    40h
        pop     ds
        pop     ds
        in      al, 60h         ; al contains the scan code
        in      al, 60h         ; al contains the scan code
        mov     dx, KbdFlags1
        mov     dx, KbdFlags1
        mov     cx, KbdFlags3
        mov     cx, KbdFlags3
        cmp     al, 0fah        ; ACK
        cmp     al, 0fah        ; ACK
        jne     short noACK
        jne     short noACK
; ------------ manage ACK response
; ------------ manage ACK response
        test    ch, LEDUpdate
        test    ch, LEDUpdate
        jz      short ToggleACK ; no LED update
        jz      short ToggleACK ; no LED update
        test    ch, AckReceived
        test    ch, AckReceived
        jnz     short SecondACK ; second ACK received
        jnz     short SecondACK ; second ACK received
        mov     ah, ch          ; LED update command sent, ACK received, need to send second byte
        mov     ah, ch          ; LED update command sent, ACK received, need to send second byte
        and     ah, ScrLockLED or NumLockLED or CapsLockLED
        and     ah, ScrLockLED or NumLockLED or CapsLockLED
        mov     bl, 0
        mov     bl, 0
        call    sendps2byte
        call    sendps2byte
        jmp     short ToggleACK
        jmp     short ToggleACK
SecondACK:
SecondACK:
        xor     ch, LEDUpdate   ; second ACK, clear LED update bit
        xor     ch, LEDUpdate   ; second ACK, clear LED update bit
ToggleACK:
ToggleACK:
        xor     ch, AckReceived ; toggle ACK bit
        xor     ch, AckReceived ; toggle ACK bit
SetFlags1:
SetFlags1:
        jmp     SetFlags
        jmp     SetFlags
; ------------ no ACK
; ------------ no ACK
noACK:
noACK:
        mov     ah,4fh
        mov     ah,4fh
        stc
        stc
        int     15h
        int     15h
        jnc     int09Exit
        jnc     int09Exit
        cmp     al, 0e0h
        cmp     al, 0e0h
        jne     short noE0
        jne     short noE0
        or      cl, LastE0
        or      cl, LastE0
        jmp     short SetFlags1
        jmp     short SetFlags1
noE0:
noE0:
        cmp     al, 0e1h
        cmp     al, 0e1h
        jne     short noE1
        jne     short noE1
        or      cl, LastE1
        or      cl, LastE1
        jmp     short SetFlags1
        jmp     short SetFlags1
noE1:
noE1:
        cmp     al, 53h     ; is DEL?
        cmp     al, 53h     ; is DEL?
        jne     short noDEL
        jne     short noDEL
        mov     ah, dl
        mov     ah, dl
        and     ah, CtrlDown or AltDown
        and     ah, CtrlDown or AltDown
        cmp     ah, CtrlDown or AltDown
        cmp     ah, CtrlDown or AltDown
        jne     NormalKey   ; is DEL, but no CTRL+ALt+DEL
        jne     NormalKey   ; is DEL, but no CTRL+ALt+DEL
        mov     word ptr ds:[72h], 1234h    ; warm boot flag
        mov     word ptr ds:[72h], 1234h    ; warm boot flag
        db      0eah
        db      0eah
        dw      0, 0ffffh       ; reboot
        dw      0, 0ffffh       ; reboot
noDEL:
noDEL:
        test    cl, LastE0
        test    cl, LastE0
        jnz     short noRSUp    ; ignore fake shifts
        jnz     short noRSUp    ; ignore fake shifts
        cmp     al, 2ah         ; left shift
        cmp     al, 2ah         ; left shift
        jne     short noLSDown
        jne     short noLSDown
        or      dl, LShfDown
        or      dl, LShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noLSDown:
noLSDown:
        cmp     al, 2ah or 80h
        cmp     al, 2ah or 80h
        jne     short noLSUp
        jne     short noLSUp
        and     dl, not LShfDown
        and     dl, not LShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noLSUp:
noLSUp:
        cmp     al, 36h         ; right shift
        cmp     al, 36h         ; right shift
        jne     short noRSDown
        jne     short noRSDown
        or      dl, RShfDown
        or      dl, RShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noRSDown:
noRSDown:
        cmp     al, 36h or 80h
        cmp     al, 36h or 80h
        jne     short noRSUP
        jne     short noRSUP
        and     dl, not RShfDown
        and     dl, not RShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noRSUp:
noRSUp:
        cmp     al, 38h         ; ALT
        cmp     al, 38h         ; ALT
        jne     short noALTDown
        jne     short noALTDown
        test    cl, LastE0
        test    cl, LastE0
        jz      short LALTDn
        jz      short LALTDn
        or      cl, RAltDown
        or      cl, RAltDown
        or      dl, AltDown
        or      dl, AltDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
LALTDn:
LALTDn:
        or      dx, (LAltDown shl 8) or AltDown
        or      dx, (LAltDown shl 8) or AltDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noALTDown:
noALTDown:
        cmp     al, 38h or 80h
        cmp     al, 38h or 80h
        jne     short noALTUp
        jne     short noALTUp
        test    cl, LastE0
        test    cl, LastE0
        jz      short LALTUp
        jz      short LALTUp
        and     cl, not RAltDown
        and     cl, not RAltDown
        and     dl, not AltDown
        and     dl, not AltDown
        jmp     short ALTup
        jmp     short ALTup
LALTUp:
LALTUp:
        and     dx, not ((LAltDown shl 8) or AltDown)
        and     dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
ALTUp:
        xor     ax, ax
        xor     ax, ax
        xchg    al, AltKpd
        xchg    al, AltKpd
        test    al, al
        test    al, al
        jz      short SetFlagsKey2
        jz      short SetFlagsKey2
        jmp     pushKey
        jmp     pushKey
noALTUp:
noALTUp:
        cmp     al, 1dh         ; CTL
        cmp     al, 1dh         ; CTL
        jne     short noCTLDown
        jne     short noCTLDown
        test    cl, lastE0
        test    cl, lastE0
        jz      short LCTLDn
        jz      short LCTLDn
        or      cl, RCtrDown
        or      cl, RCtrDown
        or      dl, CtrlDown
        or      dl, CtrlDown
SetFlagsKey2:
SetFlagsKey2:
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
LCTLDn:
LCTLDn:
        or      dx, (LCtrDown shl 8) or CtrlDown
        or      dx, (LCtrDown shl 8) or CtrlDown
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
noCTLDown:
noCTLDown:
        cmp     al, 1dh or 80h
        cmp     al, 1dh or 80h
        jne     short noCTLUp
        jne     short noCTLUp
        test    cl, LastE0
        test    cl, LastE0
        jz      short LCTLUp
        jz      short LCTLUp
        and     cl, not RCtrDown
        and     cl, not RCtrDown
        and     dl, not CtrlDown
        and     dl, not CtrlDown
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
LCTLUp:
LCTLUp:
        and     dx,  not ((LCtrDown shl 8) or CtrlDown)
        and     dx,  not ((LCtrDown shl 8) or CtrlDown)
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
noCTLUp:
noCTLUp:
        mov     bx, 3a00h + CapsLock
        mov     bx, 3a00h + CapsLock
        call    KeyLock
        call    KeyLock
        jnc     short SetFlagsKey1
        jnc     short SetFlagsKey1
        mov     bx, 4600h + ScrLock
        mov     bx, 4600h + ScrLock
        push    dx          ; save ScrLock state bit (dl)
        push    dx          ; save ScrLock state bit (dl)
        call    KeyLock
        call    KeyLock
        pop     bx          ; restore ScrLock state bit (bl)
        pop     bx          ; restore ScrLock state bit (bl)
        jc      short noScrLock
        jc      short noScrLock
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short SetFlagsKey1; no break, just ScollLock
        jz      short SetFlagsKey1; no break, just ScollLock
        mov     dl, bl      ; restore ScrLock flag
        mov     dl, bl      ; restore ScrLock flag
        test    bh, ScrLockDown
        test    bh, ScrLockDown
        jnz     short SetFlagsKey1
        jnz     short SetFlagsKey1
        mov     byte ptr CtrlBreak, 80h   ; CTRL+BREAK flag
        mov     byte ptr CtrlBreak, 80h   ; CTRL+BREAK flag
        mov     ax, Buffer
        mov     ax, Buffer
        mov     HeadPtr, ax
        mov     HeadPtr, ax
        mov     TailPtr, ax
        mov     TailPtr, ax
        int     1bh
        int     1bh
        xor     ax, ax
        xor     ax, ax
        jmp     pushkey
        jmp     pushkey
noScrLock:
noScrLock:
        test    cl, LastE0  ; INS
        test    cl, LastE0  ; INS
        jnz     short testINS
        jnz     short testINS
        test    dl, RShfDown or LShfDown
        test    dl, RShfDown or LShfDown
        jnz     short testINS
        jnz     short testINS
        test    dl, NumLock
        test    dl, NumLock
        jnz     short NoIns
        jnz     short NoIns
testINS:
testINS:
        mov     bx, 5200h + Insert
        mov     bx, 5200h + Insert
        call    KeyLock
        call    KeyLock
noIns:
noIns:
        mov     bx, 4500h + NumLock
        mov     bx, 4500h + NumLock
        push    dx          ; save NumLock state bit (dl)
        push    dx          ; save NumLock state bit (dl)
        call    KeyLock
        call    KeyLock
        pop     bx          ; restore NumLock state bit (bl)
        pop     bx          ; restore NumLock state bit (bl)
        jc      short NormalKey   ; CTRL+NumLock = Pause
        jc      short NormalKey   ; CTRL+NumLock = Pause
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short SetFlagsKey1
        jz      short SetFlagsKey1
        mov     dl, bl      ; restore NumLock flag
        mov     dl, bl      ; restore NumLock flag
        or      dh, Pause   ; set Pause bit
        or      dh, Pause   ; set Pause bit
SetFlagsKey1:
SetFlagsKey1:
        jmp     SetFlagsKey
        jmp     SetFlagsKey
E0Key:
E0Key:
        mov     di, offset E0KeyList
        mov     di, offset E0KeyList
        push    cx
        push    cx
        mov     cx, E0KeyIndex - E0KeyList
        mov     cx, E0KeyIndex - E0KeyList
        cld
        cld
        push    cs
        push    cs
        pop     es
        pop     es
        repne   scasb
        repne   scasb
        pop     cx
        pop     cx
        jne     short SetFlagsKey
        jne     short SetFlagsKey
        mov     al, es:[di + E0KeyIndex - E0KeyList - 1]
        mov     al, es:[di + E0KeyIndex - E0KeyList - 1]
        jmp     short KeyDown
        jmp     short KeyDown
NormalKey:
NormalKey:
        test    al, 80h
        test    al, 80h
        jnz     short SetFlagsKey ; key up
        jnz     short SetFlagsKey ; key up
        test    cl, LastE0
        test    cl, LastE0
        jnz     short E0Key
        jnz     short E0Key
        cmp     al, 59h
        cmp     al, 59h
        sbb     ah, ah
        sbb     ah, ah
        and     al, ah
        and     al, ah
        mov     bx, offset KeyIndex
        mov     bx, offset KeyIndex
        xlat    cs:[bx]
        xlat    cs:[bx]
KeyDown:
KeyDown:
        xor     bx, bx
        xor     bx, bx
        test    dl, RShfDown or LShfDown
        test    dl, RShfDown or LShfDown
        jz      short noShift
        jz      short noShift
        mov     bl, 2
        mov     bl, 2
noShift:
noShift:
        cmp     al, 26
        cmp     al, 26
        ja      short noCaps
        ja      short noCaps
        test    dl, CapsLock
        test    dl, CapsLock
        jz      short noNum
        jz      short noNum
        xor     bl, 2
        xor     bl, 2
        jmp     short noNum
        jmp     short noNum
noCaps:
noCaps:
        cmp     al, 37
        cmp     al, 37
        ja      short noNum
        ja      short noNum
        test    dl, NumLock
        test    dl, NumLock
        jnz     short NumDown
        jnz     short NumDown
        mov     bl, 2
        mov     bl, 2
NumDown:
NumDown:
        xor     bl, 2
        xor     bl, 2
noNum:
noNum:
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short noCtrl
        jz      short noCtrl
        mov     bl, 4
        mov     bl, 4
noCtrl:
noCtrl:
        test    dl, AltDown
        test    dl, AltDown
        jz      short noAlt
        jz      short noAlt
        mov     bl, 6
        mov     bl, 6
noAlt:
noAlt:
        cbw
        cbw
        shl     ax, 3
        shl     ax, 3
        add     bx, ax
        add     bx, ax
        mov     ax, cs:KeyCode[bx]
        mov     ax, cs:KeyCode[bx]
        cmp     ax, 000ah
        cmp     ax, 000ah
        ja      short pushKey
        ja      short pushKey
        dec     ax
        dec     ax
        js      short SetFlagsKey     ; ax was 0
        js      short SetFlagsKey     ; ax was 0
        mov     ah, AltKpd
        mov     ah, AltKpd
        aad
        aad
        mov     AltKpd, al
        mov     AltKpd, al
        jmp     short SetFlagsKey
        jmp     short SetFlagsKey
pushKey:
pushKey:
        push    cx
        push    cx
        mov     cx, ax
        mov     cx, ax
        mov     ah, 5
        mov     ah, 5
        int     16h
        int     16h
        pop     cx
        pop     cx
        and     dh, not Pause    ; clear Pause bit
        and     dh, not Pause    ; clear Pause bit
SetFlagsKey:
SetFlagsKey:
        and     cl, not (LastE0 or LastE1)    ; not prefix key code, clear all prefixes
        and     cl, not (LastE0 or LastE1)    ; not prefix key code, clear all prefixes
SetFlags:
SetFlags:
        mov     al, dl
        mov     al, dl
        shr     al, 4
        shr     al, 4
        xor     al, ch
        xor     al, ch
        and     al, 7
        and     al, 7
        jz      short SF1   ; no LEDs to update
        jz      short SF1   ; no LEDs to update
        test    ch, SetRepeat or AckReceived or LEDUpdate
        test    ch, SetRepeat or AckReceived or LEDUpdate
        jnz     short SF1   ; can not update LEDS, so just write the flags and exit
        jnz     short SF1   ; can not update LEDS, so just write the flags and exit
        or      al, LEDUpdate
        or      al, LEDUpdate
        xor     ch, al      ; insert the LEDs in KbdFlags4
        xor     ch, al      ; insert the LEDs in KbdFlags4
        mov     ah, 0edh    ; set LED
        mov     ah, 0edh    ; set LED
        mov     bl, 0
        mov     bl, 0
        call    sendps2byte
        call    sendps2byte
SF1:
SF1:
        mov     KbdFlags1, dx
        mov     KbdFlags1, dx
        mov     KbdFlags3, cx
        mov     KbdFlags3, cx
int09Exit:
int09Exit:
        pop     es
        pop     es
        pop     ds
        pop     ds
        popa
        popa
        iret
        iret
int09 endp
int09 endp
ELSE    ; SCANCODE2
ELSE    ; SCANCODE2
int09 proc near
int09 proc near
        pusha
        pusha
        push    ds
        push    ds
        push    es
        push    es
        push    40h
        push    40h
        pop     ds
        pop     ds
        in      al, 60h         ; al contains the scan code
        in      al, 60h         ; al contains the scan code
        mov     dx, KbdFlags1
        mov     dx, KbdFlags1
        mov     cx, KbdFlags3
        mov     cx, KbdFlags3
        cmp     al, 0fah        ; ACK
        cmp     al, 0fah        ; ACK
        jne     short noACK
        jne     short noACK
; ------------ manage ACK response
; ------------ manage ACK response
        test    ch, LEDUpdate
        test    ch, LEDUpdate
        jz      short ToggleACK ; no LED update
        jz      short ToggleACK ; no LED update
        test    ch, AckReceived
        test    ch, AckReceived
        jnz     short SecondACK ; second ACK received
        jnz     short SecondACK ; second ACK received
        mov     ah, ch          ; LED update command sent, ACK received, need to send second byte
        mov     ah, ch          ; LED update command sent, ACK received, need to send second byte
        and     ah, ScrLockLED or NumLockLED or CapsLockLED
        and     ah, ScrLockLED or NumLockLED or CapsLockLED
        mov     bl, 0
        mov     bl, 0
        call    sendps2byte
        call    sendps2byte
        jmp     short ToggleACK
        jmp     short ToggleACK
SecondACK:
SecondACK:
        xor     ch, LEDUpdate   ; second ACK, clear LED update bit
        xor     ch, LEDUpdate   ; second ACK, clear LED update bit
ToggleACK:
ToggleACK:
        xor     ch, AckReceived ; toggle ACK bit
        xor     ch, AckReceived ; toggle ACK bit
SetFlags1:
SetFlags1:
        jmp     SetFlags
        jmp     SetFlags
; ------------ no ACK
; ------------ no ACK
noACK:
noACK:
        cmp     al, 0e0h
        cmp     al, 0e0h
        jne     short noE0
        jne     short noE0
        or      cl, LastE0
        or      cl, LastE0
        jmp     short SetFlags1
        jmp     short SetFlags1
noE0:
noE0:
        cmp     al, 0e1h
        cmp     al, 0e1h
        jne     short noE1
        jne     short noE1
        or      cl, LastE1
        or      cl, LastE1
        jmp     short SetFlags1
        jmp     short SetFlags1
noE1:
noE1:
        cmp     al, 0f0h
        cmp     al, 0f0h
        jne     short noF0
        jne     short noF0
        or      cl, LastF0
        or      cl, LastF0
        jmp     short SetFlags1
        jmp     short SetFlags1
noF0:
noF0:
        cmp     al, 71h     ; is DEL?
        cmp     al, 71h     ; is DEL?
        jne     short noDEL
        jne     short noDEL
        mov     ah, dl
        mov     ah, dl
        and     ah, CtrlDown or AltDown
        and     ah, CtrlDown or AltDown
        cmp     ah, CtrlDown or AltDown
        cmp     ah, CtrlDown or AltDown
        je      short noF01
        je      short noF01
NormalKey1:
NormalKey1:
        jmp     NormalKey
        jmp     NormalKey
noF01:
noF01:
        mov     word ptr ds:[72h], 1234h    ; warm boot flag
        mov     word ptr ds:[72h], 1234h    ; warm boot flag
        db      0eah
        db      0eah
        dw      0, 0ffffh       ; reboot
        dw      0, 0ffffh       ; reboot
noDEL:
noDEL:
        cmp     al, 83h         ; is F7
        cmp     al, 83h         ; is F7
        je      short NormalKey1
        je      short NormalKey1
        ja      short SetFlags1
        ja      short SetFlags1
        test    cl, LastF0      ; key up?
        test    cl, LastF0      ; key up?
        jz      short noKeyUp
        jz      short noKeyUp
        or      al, 80h         ; key up flag
        or      al, 80h         ; key up flag
noKeyUp:
noKeyUp:
        test    cl, LastE0
        test    cl, LastE0
        jnz     short noRSUp    ; ignore fake shifts
        jnz     short noRSUp    ; ignore fake shifts
        cmp     al, 12h         ; left shift
        cmp     al, 12h         ; left shift
        jne     short noLSDown
        jne     short noLSDown
        or      dl, LShfDown
        or      dl, LShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noLSDown:
noLSDown:
        cmp     al, 12h or 80h
        cmp     al, 12h or 80h
        jne     short noLSUp
        jne     short noLSUp
        and     dl, not LShfDown
        and     dl, not LShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noLSUp:
noLSUp:
        cmp     al, 59h         ; right shift
        cmp     al, 59h         ; right shift
        jne     short noRSDown
        jne     short noRSDown
        or      dl, RShfDown
        or      dl, RShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noRSDown:
noRSDown:
        cmp     al, 59h or 80h
        cmp     al, 59h or 80h
        jne     short noRSUP
        jne     short noRSUP
        and     dl, not RShfDown
        and     dl, not RShfDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noRSUp:
noRSUp:
        cmp     al, 11h         ; ALT
        cmp     al, 11h         ; ALT
        jne     short noALTDown
        jne     short noALTDown
        test    cl, LastE0
        test    cl, LastE0
        jz      short LALTDn
        jz      short LALTDn
        or      cl, RAltDown
        or      cl, RAltDown
        or      dl, AltDown
        or      dl, AltDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
LALTDn:
LALTDn:
        or      dx, (LAltDown shl 8) or AltDown
        or      dx, (LAltDown shl 8) or AltDown
        jmp     short SetFlagsKey2
        jmp     short SetFlagsKey2
noALTDown:
noALTDown:
        cmp     al, 11h or 80h
        cmp     al, 11h or 80h
        jne     short noALTUp
        jne     short noALTUp
        test    cl, LastE0
        test    cl, LastE0
        jz      short LALTUp
        jz      short LALTUp
        and     cl, not RAltDown
        and     cl, not RAltDown
        and     dl, not AltDown
        and     dl, not AltDown
        jmp     short ALTup
        jmp     short ALTup
LALTUp:
LALTUp:
        and     dx, not ((LAltDown shl 8) or AltDown)
        and     dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
ALTUp:
        xor     ax, ax
        xor     ax, ax
        xchg    al, AltKpd
        xchg    al, AltKpd
        test    al, al
        test    al, al
        jz      short SetFlagsKey2
        jz      short SetFlagsKey2
        jmp     pushKey
        jmp     pushKey
noALTUp:
noALTUp:
        cmp     al, 14h         ; CTL
        cmp     al, 14h         ; CTL
        jne     short noCTLDown
        jne     short noCTLDown
        test    cl, lastE0
        test    cl, lastE0
        jz      short LCTLDn
        jz      short LCTLDn
        or      cl, RCtrDown
        or      cl, RCtrDown
        or      dl, CtrlDown
        or      dl, CtrlDown
SetFlagsKey2:
SetFlagsKey2:
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
LCTLDn:
LCTLDn:
        or      dx, (LCtrDown shl 8) or CtrlDown
        or      dx, (LCtrDown shl 8) or CtrlDown
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
noCTLDown:
noCTLDown:
        cmp     al, 14h or 80h
        cmp     al, 14h or 80h
        jne     short noCTLUp
        jne     short noCTLUp
        test    cl, LastE0
        test    cl, LastE0
        jz      short LCTLUp
        jz      short LCTLUp
        and     cl, not RCtrDown
        and     cl, not RCtrDown
        and     dl, not CtrlDown
        and     dl, not CtrlDown
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
LCTLUp:
LCTLUp:
        and     dx,  not ((LCtrDown shl 8) or CtrlDown)
        and     dx,  not ((LCtrDown shl 8) or CtrlDown)
        jmp     short SetFlagsKey1
        jmp     short SetFlagsKey1
noCTLUp:
noCTLUp:
        mov     bx, 5800h + CapsLock
        mov     bx, 5800h + CapsLock
        call    KeyLock
        call    KeyLock
        jnc     short SetFlagsKey1
        jnc     short SetFlagsKey1
        mov     bx, 7e00h + ScrLock
        mov     bx, 7e00h + ScrLock
        push    dx          ; save ScrLock state bit (dl)
        push    dx          ; save ScrLock state bit (dl)
        call    KeyLock
        call    KeyLock
        pop     bx          ; restore ScrLock state bit (bl)
        pop     bx          ; restore ScrLock state bit (bl)
        jc      short noScrLock
        jc      short noScrLock
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short SetFlagsKey1; no break, just ScollLock
        jz      short SetFlagsKey1; no break, just ScollLock
        mov     dl, bl      ; restore ScrLock flag
        mov     dl, bl      ; restore ScrLock flag
        test    bh, ScrLockDown
        test    bh, ScrLockDown
        jnz     short SetFlagsKey1
        jnz     short SetFlagsKey1
        mov     byte ptr CtrlBreak, 80h   ; CTRL+BREAK flag
        mov     byte ptr CtrlBreak, 80h   ; CTRL+BREAK flag
        mov     ax, Buffer
        mov     ax, Buffer
        mov     HeadPtr, ax
        mov     HeadPtr, ax
        mov     TailPtr, ax
        mov     TailPtr, ax
        int     1bh
        int     1bh
        xor     ax, ax
        xor     ax, ax
        jmp     pushkey
        jmp     pushkey
noScrLock:
noScrLock:
        test    cl, LastE0  ; INS
        test    cl, LastE0  ; INS
        jnz     short testINS
        jnz     short testINS
        test    dl, RShfDown or LShfDown
        test    dl, RShfDown or LShfDown
        jnz     short testINS
        jnz     short testINS
        test    dl, NumLock
        test    dl, NumLock
        jnz     short NoIns
        jnz     short NoIns
testINS:
testINS:
        mov     bx, 7000h + Insert
        mov     bx, 7000h + Insert
        call    KeyLock
        call    KeyLock
noIns:
noIns:
        mov     bx, 7700h + NumLock
        mov     bx, 7700h + NumLock
        push    dx          ; save NumLock state bit (dl)
        push    dx          ; save NumLock state bit (dl)
        call    KeyLock
        call    KeyLock
        pop     bx          ; restore NumLock state bit (bl)
        pop     bx          ; restore NumLock state bit (bl)
        jc      short noPause
        jc      short noPause
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short SetFlagsKey1
        jz      short SetFlagsKey1
        mov     dl, bl      ; restore NumLock flag
        mov     dl, bl      ; restore NumLock flag
        or      dh, Pause   ; set Pause bit
        or      dh, Pause   ; set Pause bit
SetFlagsKey1:
SetFlagsKey1:
        jmp     SetFlagsKey
        jmp     SetFlagsKey
E0Key:
E0Key:
        mov     di, offset E0KeyList
        mov     di, offset E0KeyList
        push    cx
        push    cx
        mov     cx, E0KeyIndex - E0KeyList
        mov     cx, E0KeyIndex - E0KeyList
        cld
        cld
        push    cs
        push    cs
        pop     es
        pop     es
        repne   scasb
        repne   scasb
        pop     cx
        pop     cx
        jne     short SetFlagsKey
        jne     short SetFlagsKey
        mov     al, es:[di + E0KeyIndex - E0KeyList - 1]
        mov     al, es:[di + E0KeyIndex - E0KeyList - 1]
        jmp     short KeyDown
        jmp     short KeyDown
noPause:
noPause:
        and     al, 07fh    ; delete up bit
        and     al, 07fh    ; delete up bit
NormalKey:
NormalKey:
        test    cl, LastF0
        test    cl, LastF0
        jnz     short SetFlagsKey ; key up
        jnz     short SetFlagsKey ; key up
        test    cl, LastE0
        test    cl, LastE0
        jnz     short E0Key
        jnz     short E0Key
        mov     bx, offset KeyIndex
        mov     bx, offset KeyIndex
        xlat    cs:[bx]
        xlat    cs:[bx]
KeyDown:
KeyDown:
        xor     bx, bx
        xor     bx, bx
        test    dl, RShfDown or LShfDown
        test    dl, RShfDown or LShfDown
        jz      short noShift
        jz      short noShift
        mov     bl, 2
        mov     bl, 2
noShift:
noShift:
        cmp     al, 26
        cmp     al, 26
        ja      short noCaps
        ja      short noCaps
        test    dl, CapsLock
        test    dl, CapsLock
        jz      short noNum
        jz      short noNum
        xor     bl, 2
        xor     bl, 2
        jmp     short noNum
        jmp     short noNum
noCaps:
noCaps:
        cmp     al, 37
        cmp     al, 37
        ja      short noNum
        ja      short noNum
        test    dl, NumLock
        test    dl, NumLock
        jnz     short NumDown
        jnz     short NumDown
        mov     bl, 2
        mov     bl, 2
NumDown:
NumDown:
        xor     bl, 2
        xor     bl, 2
noNum:
noNum:
        test    dl, CtrlDown
        test    dl, CtrlDown
        jz      short noCtrl
        jz      short noCtrl
        mov     bl, 4
        mov     bl, 4
noCtrl:
noCtrl:
        test    dl, AltDown
        test    dl, AltDown
        jz      short noAlt
        jz      short noAlt
        mov     bl, 6
        mov     bl, 6
noAlt:
noAlt:
        cbw
        cbw
        shl     ax, 3
        shl     ax, 3
        add     bx, ax
        add     bx, ax
        mov     ax, cs:KeyCode[bx]
        mov     ax, cs:KeyCode[bx]
        cmp     ax, 000ah
        cmp     ax, 000ah
        ja      short pushKey
        ja      short pushKey
        dec     ax
        dec     ax
        js      short SetFlagsKey     ; ax was 0
        js      short SetFlagsKey     ; ax was 0
        mov     ah, AltKpd
        mov     ah, AltKpd
        aad
        aad
        mov     AltKpd, al
        mov     AltKpd, al
        jmp     short SetFlagsKey
        jmp     short SetFlagsKey
pushKey:
pushKey:
        push    cx
        push    cx
        mov     cx, ax
        mov     cx, ax
        mov     al, ah      ; scan code
        mov     al, ah      ; scan code
        mov     ah,4fh
        mov     ah,4fh
        stc
        stc
        int     15h
        int     15h
        jnc     nopush
        jnc     nopush
        mov     ah, 5
        mov     ah, 5
        int     16h
        int     16h
nopush:
nopush:
        pop     cx
        pop     cx
        and     dh, not Pause    ; clear Pause bit
        and     dh, not Pause    ; clear Pause bit
SetFlagsKey:
SetFlagsKey:
        and     cl, not (LastE0 or LastE1 or LastF0)    ; not prefix key code, clear all prefixes
        and     cl, not (LastE0 or LastE1 or LastF0)    ; not prefix key code, clear all prefixes
SetFlags:
SetFlags:
        mov     al, dl
        mov     al, dl
        shr     al, 4
        shr     al, 4
        xor     al, ch
        xor     al, ch
        and     al, 7
        and     al, 7
        jz      short SF1   ; no LEDs to update
        jz      short SF1   ; no LEDs to update
        test    ch, SetRepeat or AckReceived or LEDUpdate
        test    ch, SetRepeat or AckReceived or LEDUpdate
        jnz     short SF1   ; can not update LEDS, so just write the flags and exit
        jnz     short SF1   ; can not update LEDS, so just write the flags and exit
        or      al, LEDUpdate
        or      al, LEDUpdate
        xor     ch, al      ; insert the LEDs in KbdFlags4
        xor     ch, al      ; insert the LEDs in KbdFlags4
        mov     ah, 0edh    ; set LED
        mov     ah, 0edh    ; set LED
        mov     bl, 0
        mov     bl, 0
        call    sendps2byte
        call    sendps2byte
SF1:
SF1:
        mov     KbdFlags1, dx
        mov     KbdFlags1, dx
        mov     KbdFlags3, cx
        mov     KbdFlags3, cx
int09Exit:
int09Exit:
        pop     es
        pop     es
        pop     ds
        pop     ds
        popa
        popa
        iret
        iret
int09 endp
int09 endp
ENDIF
ENDIF
KeyLock proc near   ; input: BH = expected scan code, al = scan code, BL = key lock flag. Returns CF=1 to continue, CF=0 to exit
KeyLock proc near   ; input: BH = expected scan code, al = scan code, BL = key lock flag. Returns CF=1 to continue, CF=0 to exit
        xor     bh, al
        xor     bh, al
        jnz     short s2
        jnz     short s2
        mov     ah, dh
        mov     ah, dh
        or      dh, bl      ; set flag
        or      dh, bl      ; set flag
        xor     ah, dh      ; get flag difference
        xor     ah, dh      ; get flag difference
        xor     dl, ah      ; toggle only if key was not already down
        xor     dl, ah      ; toggle only if key was not already down
        ret
        ret
s2:     cmp     bh, 80h
s2:     cmp     bh, 80h
        stc
        stc
        jne     short exit
        jne     short exit
        xor     dh, bl      ; key up
        xor     dh, bl      ; key up
exit:
exit:
        ret
        ret
KeyLock endp
KeyLock endp
; --------------------- INT 10h - Video ----------------
; --------------------- INT 10h - Video ----------------
ActiveVideoMode     equ   ; 1  byte
ActiveVideoMode     equ   ; 1  byte
ScreenWidth         equ   ; 2  Screen width in text columns
ScreenWidth         equ   ; 2  Screen width in text columns
RegenLength         equ   ; 2  Length (in bytes) of video area (regen size)
RegenLength         equ   ; 2  Length (in bytes) of video area (regen size)
PageOffset          equ   ; 2  Offset from video segment of active video memory page
PageOffset          equ   ; 2  Offset from video segment of active video memory page
CursorPos           equ   ; 16 Cursor location (8 byte-pairs; low byte=col, hi byte=row)
CursorPos           equ   ; 16 Cursor location (8 byte-pairs; low byte=col, hi byte=row)
CursorShape         equ   ; 2  Cursor size/shape.  Low byte=end scan line; hi byte=start line.
CursorShape         equ   ; 2  Cursor size/shape.  Low byte=end scan line; hi byte=start line.
ActivePage          equ   ; 1  Current active video page number
ActivePage          equ   ; 1  Current active video page number
PortAddress         equ   ; 2  Port address for 6845 video controller chip; see CGA I/O Ports
PortAddress         equ   ; 2  Port address for 6845 video controller chip; see CGA I/O Ports
CrtMode             equ   ; 1  Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
CrtMode             equ   ; 1  Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
CrtPalette          equ   ; 1  Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
CrtPalette          equ   ; 1  Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
ScreenRows          equ   ; 1  EGA text rows-1  (maximum valid row value)
ScreenRows          equ   ; 1  EGA text rows-1  (maximum valid row value)
ScanLinesChar       equ   ; 2  EGA bytes per character (scan-lines/char used in active mode)
ScanLinesChar       equ   ; 2  EGA bytes per character (scan-lines/char used in active mode)
EgaMiscInfo         equ   ; 1  EGA flags; see EgaMiscInfoRec
EgaMiscInfo         equ   ; 1  EGA flags; see EgaMiscInfoRec
EgaMiscInfo2        equ   ; 1  EGA flags; see EgaMiscInfo2Rec
EgaMiscInfo2        equ   ; 1  EGA flags; see EgaMiscInfo2Rec
VgaFlags            equ   ; 1  VGA flags; see VgaFlagsRec
VgaFlags            equ   ; 1  VGA flags; see VgaFlagsRec
VgaFlags2           equ   ; 1  VGA flags2
VgaFlags2           equ   ; 1  VGA flags2
PalPaging           equ   ; 1  Palette paging status: bit7=0 for 4x64, 1 for 16x16. bit3:0=active page
PalPaging           equ   ; 1  Palette paging status: bit7=0 for 4x64, 1 for 16x16. bit3:0=active page
PalPagingCounter    equ   ; 1  Palette paging counter
PalPagingCounter    equ   ; 1  Palette paging counter
int10 proc near
int10 proc near
        sti                     ; no interrupt reentrant
        sti                     ; no interrupt reentrant
        cld
        cld
        push    ds
        push    ds
        push    si
        push    si
        push    40h
        push    40h
        pop     ds
        pop     ds
        cmp     ah, 4fh
        cmp     ah, 4fh
        je      short svga
        je      short svga
        cmp     ah, 1ch
        cmp     ah, 1ch
        ja      short exit
        ja      short exit
        mov     si, ax
        mov     si, ax
        shr     si, 7
        shr     si, 7
        and     si, 1feh
        and     si, 1feh
        call    cs:vidtbl[si]
        call    cs:vidtbl[si]
exit:
exit:
        pop     si
        pop     si
        pop     ds
        pop     ds
        iret
        iret
svga:
svga:
        cmp     al, 5
        cmp     al, 5
        je      short VESAMemControl
        je      short VESAMemControl
        cmp     al, 1
        cmp     al, 1
        jb      short VESAGetInfo
        jb      short VESAGetInfo
        je      short VESAGetModeInfo
        je      short VESAGetModeInfo
        cmp     al, 3
        cmp     al, 3
        jb      short VESASetMode
        jb      short VESASetMode
        je      short VESAGetMode
        je      short VESAGetMode
        mov     ax, 100h
        mov     ax, 100h
        jmp     short exit
        jmp     short exit
; ---------------- VESA fn00
; ---------------- VESA fn00
VESAGetInfo:
VESAGetInfo:
        push    cx
        push    cx
        push    di
        push    di
        mov     si, offset VESAInfo
        mov     si, offset VESAInfo
        mov     cx, 10
        mov     cx, 10
        rep     movsw es:[di], cs:[si]
        rep     movsw es:[di], cs:[si]
        mov     cl, 118     ; 236 bytes 0
        mov     cl, 118     ; 236 bytes 0
VESASupportedClear:
VESASupportedClear:
        xor     ax, ax
        xor     ax, ax
        rep     stosw
        rep     stosw
        pop     di
        pop     di
        pop     cx
        pop     cx
VESASupported:
VESASupported:
        mov     ah, 0       ; success
        mov     ah, 0       ; success
VESASupportedErr:
VESASupportedErr:
        mov     al, 4fh
        mov     al, 4fh
        jmp     short exit
        jmp     short exit
; ---------------- VESA fn01
; ---------------- VESA fn01
VESAGetModeInfo:
VESAGetModeInfo:
        cmp     cx, 101h
        cmp     cx, 101h
VESAGetModeInfo1:
VESAGetModeInfo1:
        mov     ah, 1       ; error
        mov     ah, 1       ; error
        jne     short VESASupportedErr
        jne     short VESASupportedErr
        push    cx
        push    cx
        push    di
        push    di
        mov     cx, 9
        mov     cx, 9
        mov     si, offset VESAModeInfo
        mov     si, offset VESAModeInfo
        rep     movsw es:[di], cs:[si]
        rep     movsw es:[di], cs:[si]
        mov     cl, 119
        mov     cl, 119
        jmp     short VESASupportedClear
        jmp     short VESASupportedClear
; ---------------- VESA fn02
; ---------------- VESA fn02
VESASetMode:
VESASetMode:
        imul    ax, bx, 2
        imul    ax, bx, 2
        cmp     ax, 101h*2
        cmp     ax, 101h*2
        jne     short VESASetMode1
        jne     short VESASetMode1
        lea     ax, [bx+23ffh]
        lea     ax, [bx+23ffh]
        xchg    ah, al
        xchg    ah, al
        int     10h
        int     10h
        jmp     short VESASupported
        jmp     short VESASupported
VESASetMode1:
VESASetMode1:
        mov     al, bl
        mov     al, bl
        mov     ah, 0
        mov     ah, 0
        int     10h
        int     10h
        jmp     short VESASupported
        jmp     short VESASupported
; ---------------- VESA fn03
; ---------------- VESA fn03
VESAGetMode:
VESAGetMode:
        mov     bh, EgaMiscInfo
        mov     bh, EgaMiscInfo
        and     bh, 80h
        and     bh, 80h
        mov     bl, ActiveVideoMode
        mov     bl, ActiveVideoMode
        cmp     bl, 25h
        cmp     bl, 25h
        je      short VESAGetMode1
        je      short VESAGetMode1
        or      bl, bh
        or      bl, bh
        mov     bh, 0
        mov     bh, 0
        jmp     short VESASupported
        jmp     short VESASupported
VESAGetMode1:
VESAGetMode1:
        add     bx, 257-25
        add     bx, 257-25
        jmp     short VESASupported
        jmp     short VESASupported
; ---------------- VESA fn05
; ---------------- VESA fn05
VESAMemControl:
VESAMemControl:
        test    bx, not 101h                ; BX validation
        test    bx, not 101h                ; BX validation
        jnz     short VESAGetModeInfo1      ; error
        jnz     short VESAGetModeInfo1      ; error
        push    cs
        push    cs
        call    VESAMemControlCB
        call    VESAMemControlCB
        jmp     short VESASupported
        jmp     short VESASupported
VESAMemControlCB:
VESAMemControlCB:
        push    ax
        push    ax
        push    dx
        push    dx
        mov     ax, bx
        mov     ax, bx
        and     ax, 1
        and     ax, 1
        add     al, 8ah
        add     al, 8ah
        xchg    ax, dx
        xchg    ax, dx
        and     ax, 7
        and     ax, 7
        add     al, 0ah
        add     al, 0ah
        test    bh, bh
        test    bh, bh
        jnz     getpageinfo
        jnz     getpageinfo
        call    flush
        call    flush
        out     dx, ax
        out     dx, ax
        pop     dx
        pop     dx
        pop     ax
        pop     ax
        retf
        retf
getpageinfo:
getpageinfo:
        in      ax, dx
        in      ax, dx
        sub     al, 0ah
        sub     al, 0ah
        and     ax, 7
        and     ax, 7
        xchg    ax, dx
        xchg    ax, dx
        pop     ax
        pop     ax
        pop     ax
        pop     ax
        retf
        retf
VESAInfo    db  'VESA'
VESAInfo    db  'VESA'
            dw  100h, VESAOEM, 0f000h, 2, 0, VESAModes, 0f000h, 8
            dw  100h, VESAOEM, 0f000h, 2, 0, VESAModes, 0f000h, 8
VESAOEM     db  'Nicolae Dumitrache', 0
VESAOEM     db  'Nicolae Dumitrache', 0
VESAModes   dw  101h, 0ffffh
VESAModes   dw  101h, 0ffffh
VESAModeInfo:
VESAModeInfo:
;Bit(s)  Description - mode attributes
;Bit(s)  Description - mode attributes
;0      mode supported by present hardware configuration
;0      mode supported by present hardware configuration
;1      optional information available (must be =1 for VBE v1.2+)
;1      optional information available (must be =1 for VBE v1.2+)
;2      BIOS output supported
;2      BIOS output supported
;3      set if color, clear if monochrome
;3      set if color, clear if monochrome
;4      set if graphics mode, clear if text mode
;4      set if graphics mode, clear if text mode
;---VBE v2.0+ ---
;---VBE v2.0+ ---
;5      mode is not VGA-compatible
;5      mode is not VGA-compatible
;6      bank-switched mode not supported
;6      bank-switched mode not supported
;7      linear framebuffer mode supported
;7      linear framebuffer mode supported
;8      double-scan mode available (e.g. 320x200 and 320x240)
;8      double-scan mode available (e.g. 320x200 and 320x240)
;---VBE v3.0 ---
;---VBE v3.0 ---
;9      interlaced mode available
;9      interlaced mode available
;10     hardware supports triple buffering
;10     hardware supports triple buffering
;11     hardware supports stereoscopic display
;11     hardware supports stereoscopic display
;12     dual display start address support
;12     dual display start address support
;13-15  reserved
;13-15  reserved
        dw  0000000010011001b
        dw  0000000010011001b
;Bit(s)  Description - window attributes
;Bit(s)  Description - window attributes
;0      exists
;0      exists
;1      readable
;1      readable
;2      writable
;2      writable
;3-7    reserved
;3-7    reserved
        db  00000111b, 00000111b
        db  00000111b, 00000111b
        dw  64, 64, 0a000h, 0b000h, VESAMemControlCB, 0f000h, 640
        dw  64, 64, 0a000h, 0b000h, VESAMemControlCB, 0f000h, 640
; --------------- fn 00h, set video mode
; --------------- fn 00h, set video mode
setmode:
setmode:
        pusha
        pusha
        push    es
        push    es
        add     al, al      ; CF = cls bit
        add     al, al      ; CF = cls bit
        rcl     byte ptr EgaMiscInfo, 1
        rcl     byte ptr EgaMiscInfo, 1
        ror     byte ptr EgaMiscInfo, 1
        ror     byte ptr EgaMiscInfo, 1
        cmp     al, 3*2
        cmp     al, 3*2
        ja      short setmode1
        ja      short setmode1
        mov     al, 0b6h        ; reset sound generator
        mov     al, 0b6h        ; reset sound generator
        out     43h, al
        out     43h, al
        mov     al, 0
        mov     al, 0
        out     42h, al
        out     42h, al
        out     42h, al
        out     42h, al
        mov     ax, 0806h   ; text mode (80x25, 16 colors), flash enabled
        mov     ax, 0806h   ; text mode (80x25, 16 colors), flash enabled
        mov     word ptr ScreenWidth, 80
        mov     word ptr ScreenWidth, 80
        mov     word ptr RegenLength, 1000h
        mov     word ptr RegenLength, 1000h
        mov     byte ptr ScreenRows, 25-1
        mov     byte ptr ScreenRows, 25-1
        mov     word ptr ScanLinesChar, 16
        mov     word ptr ScanLinesChar, 16
        mov     bx, 0b800h  ; segment
        mov     bx, 0b800h  ; segment
        mov     cx, 4000h   ; video len/2
        mov     cx, 4000h   ; video len/2
        mov     si, 0720h   ; clear value
        mov     si, 0720h   ; clear value
        jmp     short setmode2
        jmp     short setmode2
setmode1:
setmode1:
        cmp     al, 13h*2
        cmp     al, 13h*2
        jne     short setmode3
        jne     short setmode3
        mov     ah, 41h     ; graphic mode, 320x200, 256 colors
        mov     ah, 41h     ; graphic mode, 320x200, 256 colors
        mov     word ptr ScreenWidth, 40
        mov     word ptr ScreenWidth, 40
        mov     word ptr RegenLength, 2000h
        mov     word ptr RegenLength, 2000h
        jmp     short setmode21
        jmp     short setmode21
setmode3:
setmode3:
        cmp     al, 25h*2
        cmp     al, 25h*2
        jne     short setmodeexit
        jne     short setmodeexit
        mov     ah, 1       ; graphic mode, 640x400, 256 colors
        mov     ah, 1       ; graphic mode, 640x400, 256 colors
        mov     word ptr ScreenWidth, 80
        mov     word ptr ScreenWidth, 80
        mov     word ptr RegenLength, 2000h
        mov     word ptr RegenLength, 2000h
setmode21:
setmode21:
        mov     bx, 0a000h  ; segment
        mov     bx, 0a000h  ; segment
        mov     cx, 8000h   ; video len/2 - clears only the first segment (TODO clear full screen)
        mov     cx, 8000h   ; video len/2 - clears only the first segment (TODO clear full screen)
        xor     si, si      ; clear value
        xor     si, si      ; clear value
setmode2:
setmode2:
        shr     al, 1
        shr     al, 1
        mov     ActiveVideoMode, al
        mov     ActiveVideoMode, al
        push    ax
        push    ax
        push    cx
        push    cx
        push    ds
        push    ds
        pop     es
        pop     es
        xor     ax, ax
        xor     ax, ax
        mov     di, offset CursorPos
        mov     di, offset CursorPos
        mov     cx, 8
        mov     cx, 8
        rep     stosw           ; reset cursor position for all pages
        rep     stosw           ; reset cursor position for all pages
        mov     ax, 0500h
        mov     ax, 0500h
        int     10h             ; set page0
        int     10h             ; set page0
        pop     cx
        pop     cx
        pop     ax
        pop     ax
        test    byte ptr EgaMiscInfo, 80h
        test    byte ptr EgaMiscInfo, 80h
        jnz     short setmode4    ; no clear video memory
        jnz     short setmode4    ; no clear video memory
        mov     es, bx
        mov     es, bx
        xchg    ax, si
        xchg    ax, si
        xor     di, di
        xor     di, di
        rep     stosw
        rep     stosw
        xchg    ax, si
        xchg    ax, si
        call    palpageset
        call    palpageset
        mov     byte ptr PalPaging, cl  ; reset paging
        mov     byte ptr PalPaging, cl  ; reset paging
setmode4:
setmode4:
        mov     dx, 3c0h
        mov     dx, 3c0h
        mov     al, 10h
        mov     al, 10h
        out     dx, al
        out     dx, al
        mov     al, ah
        mov     al, ah
        out     dx, al          ; set video mode
        out     dx, al          ; set video mode
        mov     ax, 1123h
        mov     ax, 1123h
        int     10h             ; set ROM 8x8 font for graphics mode
        int     10h             ; set ROM 8x8 font for graphics mode
        mov     ah, 1
        mov     ah, 1
        xor     cx, cx
        xor     cx, cx
        int     10h             ; show cursor
        int     10h             ; show cursor
        test    byte ptr VgaFlags, 8     ; test default palette loading
        test    byte ptr VgaFlags, 8     ; test default palette loading
        jnz     short setmodeexit     ; no default palette
        jnz     short setmodeexit     ; no default palette
        mov     ax, 1012h
        mov     ax, 1012h
        xor     bx, bx
        xor     bx, bx
        mov     cx, 100h
        mov     cx, 100h
        mov     dx, offset default_pal
        mov     dx, offset default_pal
        push    cs
        push    cs
        pop     es
        pop     es
        int     10h             ; set default palette
        int     10h             ; set default palette
setmodeexit:
setmodeexit:
        pop     es
        pop     es
        popa
        popa
nullproc:
nullproc:
        ret
        ret
; --------------- fn 01h, set cursor shape and visibility (shape is ignored, always lines 14&15 of text mode char)
; --------------- fn 01h, set cursor shape and visibility (shape is ignored, always lines 14&15 of text mode char)
cursor:     ; CH bit 6 or 5 -> cursor off
cursor:     ; CH bit 6 or 5 -> cursor off
        push    ax
        push    ax
        push    dx
        push    dx
        mov     dx, 3d4h
        mov     dx, 3d4h
        mov     al, 0ah
        mov     al, 0ah
        out     dx, al
        out     dx, al
        mov     al, ch
        mov     al, ch
        shr     al, 1
        shr     al, 1
        or      al, ch
        or      al, ch
        inc     dx
        inc     dx
        out     dx, al
        out     dx, al
        pop     dx
        pop     dx
        pop     ax
        pop     ax
        ret
        ret
;---------------- fn 02h, set cursor pos
;---------------- fn 02h, set cursor pos
curpos:
curpos:
        push    ax
        push    ax
        push    bx
        push    bx
        mov     al, bh
        mov     al, bh
        shr     bx, 7
        shr     bx, 7
        and     bx, 0eh
        and     bx, 0eh
        mov     CursorPos[bx], dx
        mov     CursorPos[bx], dx
        cmp     byte ptr ActiveVideoMode, 3
        cmp     byte ptr ActiveVideoMode, 3
        jne     short curpos1
        jne     short curpos1
        cmp     al, ActivePage
        cmp     al, ActivePage
        jne     short curpos1
        jne     short curpos1
        push    dx
        push    dx
        xor     ax, ax
        xor     ax, ax
        xchg    al, dh
        xchg    al, dh
        imul    ax, 80
        imul    ax, 80
        add     ax, dx
        add     ax, dx
        mov     dx, 3d4h
        mov     dx, 3d4h
        push    ax
        push    ax
        mov     al, 0fh
        mov     al, 0fh
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        pop     ax
        pop     ax
        out     dx, al
        out     dx, al
        dec     dx
        dec     dx
        mov     al, 0eh
        mov     al, 0eh
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        mov     al, ah
        mov     al, ah
        out     dx, al
        out     dx, al
        pop     dx
        pop     dx
curpos1:
curpos1:
        pop     bx
        pop     bx
        pop     ax
        pop     ax
        ret
        ret
;---------------- fn 03h, get cursor pos
;---------------- fn 03h, get cursor pos
getcurpos:
getcurpos:
        push    bx
        push    bx
        shr     bx, 7
        shr     bx, 7
        and     bx, 0eh
        and     bx, 0eh
        mov     dx, CursorPos[bx]
        mov     dx, CursorPos[bx]
        mov     cx, CursorShape
        mov     cx, CursorShape
        pop     bx
        pop     bx
        ret
        ret
;---------------- fn 04h, light pen
;---------------- fn 04h, light pen
lightpen:
lightpen:
        mov     ah, 0   ; not triggered
        mov     ah, 0   ; not triggered
        ret
        ret
;---------------- fn 05h, set active video page
;---------------- fn 05h, set active video page
apage:
apage:
        pusha
        pusha
        call    flush
        call    flush
        and     al, 7
        and     al, 7
        mov     bh, al
        mov     bh, al
        mov     ActivePage, al
        mov     ActivePage, al
        mov     al, ActiveVideoMode
        mov     al, ActiveVideoMode
        cmp     al, 3
        cmp     al, 3
        jne     short apage1
        jne     short apage1
        mov     ax, 0ah
        mov     ax, 0ah
        out     8ah, ax
        out     8ah, ax
        inc     ax
        inc     ax
        out     8bh, ax
        out     8bh, ax
        mov     ah, 3
        mov     ah, 3
        int     10h        ; get cursor pos
        int     10h        ; get cursor pos
        mov     ah, 2
        mov     ah, 2
        int     10h        ; set cursor pos
        int     10h        ; set cursor pos
        mov     ax, 200h   ; page size / 8
        mov     ax, 200h   ; page size / 8
        jmp     short apage2
        jmp     short apage2
apage1:                    ; mode 13h and 25h
apage1:                    ; mode 13h and 25h
        mov     ax, 0ah
        mov     ax, 0ah
        add     al, bh
        add     al, bh
        out     8ah, ax
        out     8ah, ax
        inc     ax
        inc     ax
        cmp     al, 12h
        cmp     al, 12h
        jne     short apage4
        jne     short apage4
        mov     al, 0ah
        mov     al, 0ah
apage4: out     8bh, ax
apage4: out     8bh, ax
        mov     ax, 2000h  ; page size / 8
        mov     ax, 2000h  ; page size / 8
apage2:
apage2:
        shr     bx, 8      ; page number
        shr     bx, 8      ; page number
        mul     bx
        mul     bx
        push    ax
        push    ax
        shl     ax, 3
        shl     ax, 3
        mov     PageOffset, ax
        mov     PageOffset, ax
        mov     dx, 3d4h
        mov     dx, 3d4h
        mov     al, 0dh
        mov     al, 0dh
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        pop     ax
        pop     ax
        out     dx, al
        out     dx, al
        dec     dx
        dec     dx
        mov     al, 0ch
        mov     al, 0ch
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        mov     al, ah
        mov     al, ah
        out     dx, al
        out     dx, al
        popa
        popa
        ret
        ret
;---------------- fn 06h, scroll up / clr
;---------------- fn 06h, scroll up / clr
scrollup:
scrollup:
        pusha
        pusha
        push    es
        push    es
        xchg    cx, dx
        xchg    cx, dx
        sub     cx, dx
        sub     cx, dx
        inc     cx
        inc     cx
        cmp     byte ptr ActiveVideoMode, 13h
        cmp     byte ptr ActiveVideoMode, 13h
        jae     short scrollup1
        jae     short scrollup1
        call    scr_params
        call    scr_params
scrollup6:
scrollup6:
        push    0b800h          ; segment
        push    0b800h          ; segment
        pop     es
        pop     es
        add     dl, dl
        add     dl, dl
        add     di, di
        add     di, di
        add     di, PageOffset  ; di = top left corner address
        add     di, PageOffset  ; di = top left corner address
        xchg    ax, cx          ; ah = 0
        xchg    ax, cx          ; ah = 0
        test    bl, bl
        test    bl, bl
        jz      short scrollup3       ; clear
        jz      short scrollup3       ; clear
        sub     ah, bl
        sub     ah, bl
        jb      short scrollup3       ; clear
        jb      short scrollup3       ; clear
        add     si, di
        add     si, di
scrollup4:
scrollup4:
        mov     cl, al
        mov     cl, al
        rep     movsw es:[si], es:[di]
        rep     movsw es:[si], es:[di]
        add     si, dx
        add     si, dx
        add     di, dx
        add     di, dx
        dec     ah
        dec     ah
        jns     short scrollup4       ; ch = lines - 1
        jns     short scrollup4       ; ch = lines - 1
scrollup3:
scrollup3:
        add     ah, bl          ; clear rectangle: DI=address, ah=lines, al=columns, bh=attribute
        add     ah, bl          ; clear rectangle: DI=address, ah=lines, al=columns, bh=attribute
        xchg    ax, bx
        xchg    ax, bx
        mov     al, ' '
        mov     al, ' '
scrollup5:
scrollup5:
        mov     cl, bl
        mov     cl, bl
        rep     stosw
        rep     stosw
        add     di, dx
        add     di, dx
        dec     bh
        dec     bh
        jns     short scrollup5       ; ch = lines - 1
        jns     short scrollup5       ; ch = lines - 1
scrollexit:
scrollexit:
        pop     es
        pop     es
        popa
        popa
        ret
        ret
scrollup1:
scrollup1:
        ja     short scrollup2
        ja     short scrollup2
; TODO mode13h scroll up
; TODO mode13h scroll up
        jmp     short scrollexit
        jmp     short scrollexit
scrollup2:
scrollup2:
; TODO mode25h scroll up
; TODO mode25h scroll up
        jmp     short scrollexit
        jmp     short scrollexit
;---------------- fn 07h, scroll dn / clr
;---------------- fn 07h, scroll dn / clr
scrolldn:
scrolldn:
        std
        std
        pusha
        pusha
        push    es
        push    es
        neg     cx
        neg     cx
        add     cx, dx
        add     cx, dx
        inc     cx
        inc     cx
        cmp     byte ptr ActiveVideoMode, 13h
        cmp     byte ptr ActiveVideoMode, 13h
        jae     short scrolldn1
        jae     short scrolldn1
        call    scr_params
        call    scr_params
        neg     dx
        neg     dx
        neg     si
        neg     si
        jmp     short scrollup6
        jmp     short scrollup6
scrolldn1:
scrolldn1:
        ja     short scrolldn2
        ja     short scrolldn2
; TODO  mode13h scroll down
; TODO  mode13h scroll down
        jmp     short scrollexit
        jmp     short scrollexit
scrolldn2:
scrolldn2:
; TODO  mode25h scroll down
; TODO  mode25h scroll down
        jmp     short scrollexit
        jmp     short scrollexit
scr_params:
scr_params:
        mov     bl, al          ; lines
        mov     bl, al          ; lines
        xor     ax, ax
        xor     ax, ax
        xchg    al, dh
        xchg    al, dh
        imul    di, ax, 80
        imul    di, ax, 80
        add     di, dx
        add     di, dx
        mov     dl, 80          ; dh = 0
        mov     dl, 80          ; dh = 0
        sub     dl, cl
        sub     dl, cl
        mov     al, bl
        mov     al, bl
        imul    si, ax, 160
        imul    si, ax, 160
        ret
        ret
;---------------- fn 08h, read char/attr
;---------------- fn 08h, read char/attr
readchar:
readchar:
        push    bx
        push    bx
        mov     al, ActiveVideoMode
        mov     al, ActiveVideoMode
        cmp     al, 3
        cmp     al, 3
        xor     ax, ax
        xor     ax, ax
        jne     short readchar1
        jne     short readchar1
        call    mode3chaddr
        call    mode3chaddr
        mov     ax, [bx]
        mov     ax, [bx]
readcharexit:
readcharexit:
        pop     bx
        pop     bx
        ret
        ret
readchar1:
readchar1:
        cmp     al, 13h
        cmp     al, 13h
        jne     short readchar2
        jne     short readchar2
; TODO mode13h
; TODO mode13h
        jmp     short readcharexit
        jmp     short readcharexit
readchar2:
readchar2:
; TODO mode25h
; TODO mode25h
        jmp     short readcharexit
        jmp     short readcharexit
mode3chaddr:    ; returns current char address in mode3 in ds:bx. Input: bh=page, ds=40h
mode3chaddr:    ; returns current char address in mode3 in ds:bx. Input: bh=page, ds=40h
        push    ax
        push    ax
        and     bx, 700h
        and     bx, 700h
        lea     ax, [bx+0b800h]
        lea     ax, [bx+0b800h]
        shr     bx, 7
        shr     bx, 7
        mov     bx, CursorPos[bx]
        mov     bx, CursorPos[bx]
        mov     ds, ax
        mov     ds, ax
        xor     ax, ax
        xor     ax, ax
        xchg    al, bh
        xchg    al, bh
        imul    ax, 80
        imul    ax, 80
        add     bx, ax
        add     bx, ax
        add     bx, bx
        add     bx, bx
        pop     ax
        pop     ax
        ret
        ret
;---------------- fn 09h, write char/attr
;---------------- fn 09h, write char/attr
writecharattr:
writecharattr:
        push    ax
        push    ax
        push    es
        push    es
        push    bx
        push    bx
        push    cx
        push    cx
        cmp     byte ptr ActiveVideoMode, 3
        cmp     byte ptr ActiveVideoMode, 3
        jne     short writecharattr1
        jne     short writecharattr1
        mov     ah, bl
        mov     ah, bl
        call    mode3chaddr
        call    mode3chaddr
        push    ds
        push    ds
        pop     es
        pop     es
        xchg    di, bx
        xchg    di, bx
        rep     stosw
        rep     stosw
        xchg    di, bx
        xchg    di, bx
writecharattrexit:
writecharattrexit:
        pop     cx
        pop     cx
        pop     bx
        pop     bx
        pop     es
        pop     es
        pop     ax
        pop     ax
        ret
        ret
writecharattr1:
writecharattr1:
        cmp     byte ptr ActiveVideoMode, 13h
        cmp     byte ptr ActiveVideoMode, 13h
        jne     short writecharattr2
        jne     short writecharattr2
; TODO mode13h
; TODO mode13h
        jmp     short writecharattrexit
        jmp     short writecharattrexit
writecharattr2:
writecharattr2:
; TODO mode25h
; TODO mode25h
        jmp     short writecharattrexit
        jmp     short writecharattrexit
;---------------- fn 0ah, write char
;---------------- fn 0ah, write char
writechar:
writechar:
        jcxz    short writecharskip
        jcxz    short writecharskip
        push    bx
        push    bx
        push    cx
        push    cx
        cmp     byte ptr ActiveVideoMode, 3
        cmp     byte ptr ActiveVideoMode, 3
        jne     short writechar1
        jne     short writechar1
        call    mode3chaddr
        call    mode3chaddr
writechar3:
writechar3:
        mov     [bx], al
        mov     [bx], al
        add     bx, 2
        add     bx, 2
        loop    short writechar3
        loop    short writechar3
writecharexit:
writecharexit:
        pop     cx
        pop     cx
        pop     bx
        pop     bx
writecharskip:
writecharskip:
        ret
        ret
writechar1:
writechar1:
        cmp     byte ptr ActiveVideoMode, 13h
        cmp     byte ptr ActiveVideoMode, 13h
        jne     short writechar2
        jne     short writechar2
; TODO mode13h
; TODO mode13h
        jmp     short writecharexit
        jmp     short writecharexit
writechar2:
writechar2:
; TODO mode25h
; TODO mode25h
        jmp     short writecharexit
        jmp     short writecharexit
;---------------- fn 0eh, write char as TTY
;---------------- fn 0eh, write char as TTY
writecharTTY:
writecharTTY:
        push    ax
        push    ax
        push    bx
        push    bx
        push    dx
        push    dx
        mov     bl, ActivePage
        mov     bl, ActivePage
        mov     bh, 0
        mov     bh, 0
        add     bx, bx
        add     bx, bx
        mov     dx, CursorPos[bx]
        mov     dx, CursorPos[bx]
        shl     bx, 7
        shl     bx, 7
        mov     ah, 0ah
        mov     ah, 0ah
        call    tty
        call    tty
        mov     ah, 2       ; set cursor pos
        mov     ah, 2       ; set cursor pos
        int     10h
        int     10h
        pop     dx
        pop     dx
        pop     bx
        pop     bx
        pop     ax
        pop     ax
        ret
        ret
tty:    ; dx=xy, bh=page, al=char, bl=attr, ah=0ah(no attr) or 09h(with attr)
tty:    ; dx=xy, bh=page, al=char, bl=attr, ah=0ah(no attr) or 09h(with attr)
        test    word ptr KbdFlags2, Pause
        test    word ptr KbdFlags2, Pause
        jnz     short tty
        jnz     short tty
        push    cx
        push    cx
        cmp     al, 7
        cmp     al, 7
        je      short bell
        je      short bell
        cmp     al, 8
        cmp     al, 8
        je      short bs
        je      short bs
        cmp     al, 0ah
        cmp     al, 0ah
        je      short cr
        je      short cr
        cmp     al, 0dh
        cmp     al, 0dh
        je      short lf
        je      short lf
        mov     cx, 1
        mov     cx, 1
        int     10h         ; write char at cursor
        int     10h         ; write char at cursor
        inc     dx
        inc     dx
        cmp     dl, ScreenWidth
        cmp     dl, ScreenWidth
        jae     short crlf
        jae     short crlf
tty1:
tty1:
        pop     cx
        pop     cx
        ret
        ret
bell:
bell:
; TODO bell code
; TODO bell code
        jmp     short tty1
        jmp     short tty1
bs:
bs:
        sub     dl, 1
        sub     dl, 1
        adc     dl, 0
        adc     dl, 0
        jmp     short tty1
        jmp     short tty1
lf:
lf:
        mov     dl, 0
        mov     dl, 0
        jmp     short tty1
        jmp     short tty1
crlf:
crlf:
        mov     dl, 0
        mov     dl, 0
cr:
cr:
        inc     dh
        inc     dh
        cmp     dh, ScreenRows
        cmp     dh, ScreenRows
        jbe     short tty1
        jbe     short tty1
        dec     dh
        dec     dh
;        mov     ah, 8
;        mov     ah, 8
;        int     10h         ; read attribute at cursor pos
;        int     10h         ; read attribute at cursor pos
        push    bx          ; save active page in bh
        push    bx          ; save active page in bh
        push    dx
        push    dx
;        xchg    ax, bx
;        xchg    ax, bx
        mov     bh, 7       ; default attribute
        mov     bh, 7       ; default attribute
        mov     ax, 601h
        mov     ax, 601h
        mov     dh, ScreenRows
        mov     dh, ScreenRows
        mov     dl, ScreenWidth
        mov     dl, ScreenWidth
        dec     dx
        dec     dx
        xor     cx, cx
        xor     cx, cx
        int     10h         ; scroll up
        int     10h         ; scroll up
        pop     dx
        pop     dx
        pop     bx          ; restore active page in bh
        pop     bx          ; restore active page in bh
        jmp     short tty1
        jmp     short tty1
;---------------- fn 0fh, read video mode
;---------------- fn 0fh, read video mode
readmode:
readmode:
        mov     al, EgaMiscInfo
        mov     al, EgaMiscInfo
        and     al, 80h
        and     al, 80h
        or      al, ActiveVideoMode
        or      al, ActiveVideoMode
        mov     ah, ScreenWidth
        mov     ah, ScreenWidth
        mov     bh, ActivePage
        mov     bh, ActivePage
        ret
        ret
;---------------- fn 10h, palette
;---------------- fn 10h, palette
paltable    dw  setonereg, palexit, setallreg, setblink, palexit, palexit, palexit, readonereg, readoverscan, readallreg, palexit, palexit, palexit, palexit, palexit, palexit
paltable    dw  setonereg, palexit, setallreg, setblink, palexit, palexit, palexit, readonereg, readoverscan, readallreg, palexit, palexit, palexit, palexit, palexit, palexit
            dw  setoneDAC, palexit, setblockDAC, paging, palexit, readoneDAC, palexit, readblockDAC, setPELmask, getPELmask, getpaging, grayscale
            dw  setoneDAC, palexit, setblockDAC, paging, palexit, readoneDAC, palexit, readblockDAC, setPELmask, getPELmask, getpaging, grayscale
pal:
pal:
        cmp     al, 1bh
        cmp     al, 1bh
        ja      short palexit
        ja      short palexit
        mov     si, ax
        mov     si, ax
        add     si, si
        add     si, si
        add     byte ptr PalPagingCounter, ah   ; prevents  re-entrance on recursive  calls
        add     byte ptr PalPagingCounter, ah   ; prevents  re-entrance on recursive  calls
        call    palpage
        call    palpage
        call    cs:paltable[si-2000h]
        call    cs:paltable[si-2000h]
        call    palpage
        call    palpage
        sub     byte ptr PalPagingCounter, ah
        sub     byte ptr PalPagingCounter, ah
palexit:
palexit:
        ret
        ret
palpage:                    ; executes only if PalPagingCounter == ah
palpage:                    ; executes only if PalPagingCounter == ah
        cmp     byte ptr PalPagingCounter, ah
        cmp     byte ptr PalPagingCounter, ah
        jne     short palpageexit
        jne     short palpageexit
palpageset:
palpageset:
        test    byte ptr PalPaging, 0fh
        test    byte ptr PalPaging, 0fh
        jz      short palpageexit
        jz      short palpageexit
        pusha
        pusha
        mov     bl, byte ptr PalPaging
        mov     bl, byte ptr PalPaging
        add     bl, bl
        add     bl, bl
        jc      short page16
        jc      short page16
        shl     bl, 2
        shl     bl, 2
page16:
page16:
        shl     bx, 11  ; bh=target page, bl=0 page
        shl     bx, 11  ; bh=target page, bl=0 page
palpage1:
palpage1:
        mov     al, 15h
        mov     al, 15h
        int     10h     ; read 0 page DAC reg
        int     10h     ; read 0 page DAC reg
        push    cx
        push    cx
        push    dx
        push    dx
        xchg    bl, bh
        xchg    bl, bh
        int     10h     ; read target page DAC register
        int     10h     ; read target page DAC register
        xchg    bl, bh
        xchg    bl, bh
        mov     al, 10h
        mov     al, 10h
        int     10h     ; write 0 page DAC register
        int     10h     ; write 0 page DAC register
        pop     dx
        pop     dx
        pop     cx
        pop     cx
        xchg    bl, bh
        xchg    bl, bh
        int     10h     ; write target page DAC register
        int     10h     ; write target page DAC register
        xchg    bl, bh
        xchg    bl, bh
        add     bx, 101h; next DAC reg
        add     bx, 101h; next DAC reg
        test    bl, 0fh
        test    bl, 0fh
        jnz     short palpage1
        jnz     short palpage1
        popa
        popa
palpageexit:
palpageexit:
        ret
        ret
setonereg:
setonereg:
        cmp     bl, 10h
        cmp     bl, 10h
        jae     setonereg1
        jae     setonereg1
        pusha
        pusha
        call    colfrombits
        call    colfrombits
        mov     cl, al
        mov     cl, al
        call    colfrombits
        call    colfrombits
        mov     ch, al
        mov     ch, al
        call    colfrombits
        call    colfrombits
        mov     dh, al
        mov     dh, al
        mov     al, 10h
        mov     al, 10h
        int     10h
        int     10h
        popa
        popa
setonereg1:
setonereg1:
        ret
        ret
setallreg:
setallreg:
        pusha
        pusha
        mov     al, 0
        mov     al, 0
        mov     si, dx
        mov     si, dx
        mov     bl, 15
        mov     bl, 15
setallreg1:
setallreg1:
        mov     bh, es:[si+15]
        mov     bh, es:[si+15]
        int     10h
        int     10h
        dec     si
        dec     si
        dec     bl
        dec     bl
        jns     short setallreg1
        jns     short setallreg1
        popa
        popa
        ret
        ret
setblink:
setblink:
        pusha
        pusha
        cmp     byte ptr ActiveVideoMode, 3
        cmp     byte ptr ActiveVideoMode, 3
        jne     short setblink1
        jne     short setblink1
        mov     dx, 3c0h
        mov     dx, 3c0h
        mov     al, 10h
        mov     al, 10h
        out     dx, al
        out     dx, al
        mov     al, bl
        mov     al, bl
        and     al, 1
        and     al, 1
        shl     al, 3
        shl     al, 3
        out     dx, al          ; set video mode (0 or 8)
        out     dx, al          ; set video mode (0 or 8)
        shl     al, 2
        shl     al, 2
        xor     al, VgaFlags
        xor     al, VgaFlags
        and     al, 20h
        and     al, 20h
        xor     VgaFlags, al
        xor     VgaFlags, al
setblink1:
setblink1:
        popa
        popa
        ret
        ret
readonereg:
readonereg:
        cmp     bl, 10h
        cmp     bl, 10h
        jae     readonereg1
        jae     readonereg1
        push    ax
        push    ax
        push    cx
        push    cx
        push    dx
        push    dx
        mov     al, 15h
        mov     al, 15h
        int     10h
        int     10h
        mov     al, dh          ; al = R
        mov     al, dh          ; al = R
        and     al, 00110000b
        and     al, 00110000b
        shr     al, 2
        shr     al, 2
        add     al, 01111000b
        add     al, 01111000b
        and     al, 10000100b
        and     al, 10000100b
        mov     bh, al
        mov     bh, al
        xchg    ax, cx          ; ax = GB
        xchg    ax, cx          ; ax = GB
        and     ax, 0011000000110000b
        and     ax, 0011000000110000b
        shr     ax, 3
        shr     ax, 3
        shr     al, 1
        shr     al, 1
        add     ax, 0011110000011110b
        add     ax, 0011110000011110b
        and     ax, 0100001000100001b
        and     ax, 0100001000100001b
        or      bh, ah
        or      bh, ah
        or      bh, al
        or      bh, al
        rol     bh, 3
        rol     bh, 3
        pop     dx
        pop     dx
        pop     cx
        pop     cx
        pop     ax
        pop     ax
readonereg1:
readonereg1:
        ret
        ret
readallreg:
readallreg:
        pusha
        pusha
        mov     di, dx
        mov     di, dx
        mov     bl, 0
        mov     bl, 0
readllreg1:
readllreg1:
        mov     al, 7
        mov     al, 7
        int     10h
        int     10h
        mov     al, bh
        mov     al, bh
        stosb
        stosb
        inc     bx
        inc     bx
        cmp     bl, 16
        cmp     bl, 16
        jne     short readllreg1
        jne     short readllreg1
        mov     al, 0   ; overscan color
        mov     al, 0   ; overscan color
        stosb
        stosb
        popa
        popa
        ret
        ret
readoverscan:
readoverscan:
        mov     bh, 0
        mov     bh, 0
        ret
        ret
setoneDAC:
setoneDAC:
        push    ax
        push    ax
        push    dx
        push    dx
        xchg    ax, dx
        xchg    ax, dx
        mov     al, bl
        mov     al, bl
        mov     dx, 3c8h
        mov     dx, 3c8h
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        mov     al, ah
        mov     al, ah
        out     dx, al
        out     dx, al
        mov     al, ch
        mov     al, ch
        out     dx, al
        out     dx, al
        mov     al, cl
        mov     al, cl
        out     dx, al
        out     dx, al
        pop     dx
        pop     dx
        pop     ax
        pop     ax
        ret
        ret
setblockDAC:
setblockDAC:
        pusha
        pusha
        mov     si, dx
        mov     si, dx
        mov     dx, 3c8h
        mov     dx, 3c8h
        xchg    ax, bx
        xchg    ax, bx
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        imul    cx, 3
        imul    cx, 3
        rep     outsb dx, es:[si]
        rep     outsb dx, es:[si]
        popa
        popa
        ret
        ret
paging:
paging:
        push    bx
        push    bx
        test    bl, bl
        test    bl, bl
        mov     bl, PalPaging
        mov     bl, PalPaging
        jnz     short paging1
        jnz     short paging1
        add     bl, bl
        add     bl, bl
        ror     bx, 1
        ror     bx, 1
        jmp     short paging2
        jmp     short paging2
paging1:
paging1:
        and     bx, 0f80h       ; bl=old page, bh=new page
        and     bx, 0f80h       ; bl=old page, bh=new page
        or      bl, bh
        or      bl, bh
paging2:
paging2:
        mov     PalPaging, bl
        mov     PalPaging, bl
        pop     bx
        pop     bx
        ret
        ret
readoneDAC:
readoneDAC:
        push    ax
        push    ax
        push    dx
        push    dx
        mov     al, bl
        mov     al, bl
        mov     dx, 3c7h
        mov     dx, 3c7h
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        inc     dx
        inc     dx
        in      al, dx
        in      al, dx
        mov     ah, al
        mov     ah, al
        in      al, dx
        in      al, dx
        mov     ch, al
        mov     ch, al
        in      al, dx
        in      al, dx
        mov     cl, al
        mov     cl, al
        pop     dx
        pop     dx
        mov     dh, ah
        mov     dh, ah
        pop     ax
        pop     ax
        ret
        ret
readblockDAC:
readblockDAC:
        pusha
        pusha
        mov     di, dx
        mov     di, dx
        mov     dx, 3c7h
        mov     dx, 3c7h
        xchg    ax, bx
        xchg    ax, bx
        out     dx, al
        out     dx, al
        inc     dx
        inc     dx
        inc     dx
        inc     dx
        imul    cx, 3
        imul    cx, 3
        rep     insb
        rep     insb
        popa
        popa
        ret
        ret
setPELmask:
setPELmask:
        push    dx
        push    dx
        xchg    ax, bx
        xchg    ax, bx
        mov     dx, 3c6h
        mov     dx, 3c6h
        out     dx, al
        out     dx, al
        xchg    ax, bx
        xchg    ax, bx
        pop     dx
        pop     dx
        ret
        ret
getPELmask:
getPELmask:
        push    dx
        push    dx
        xchg    ax, bx
        xchg    ax, bx
        mov     dx, 3c6h
        mov     dx, 3c6h
        in      al, dx
        in      al, dx
        xchg    ax, bx
        xchg    ax, bx
        pop     dx
        pop     dx
        ret
        ret
getpaging:
getpaging:
        mov     bh, PalPaging
        mov     bh, PalPaging
        mov     bl, 0
        mov     bl, 0
        rol     bx, 1
        rol     bx, 1
        shr     bh, 1
        shr     bh, 1
        ret
        ret
grayscale:
grayscale:
        jcxz    short grayscale2
        jcxz    short grayscale2
        pusha
        pusha
        mov     bh, cl
        mov     bh, cl
grayscale1:
grayscale1:
        mov     al, 15h
        mov     al, 15h
        int     10h
        int     10h
        shr     dx, 8
        shr     dx, 8
        imul    si, dx, 77
        imul    si, dx, 77
        mov     dl, ch
        mov     dl, ch
        imul    dx, 151
        imul    dx, 151
        mov     ch, 0
        mov     ch, 0
        imul    cx, 28
        imul    cx, 28
        add     dx, si
        add     dx, si
        add     dx, cx
        add     dx, cx
        mov     ch, dh
        mov     ch, dh
        mov     cl, dh
        mov     cl, dh
        mov     al, 10h
        mov     al, 10h
        int     10h
        int     10h
        inc     bl
        inc     bl
        dec     bh
        dec     bh
        jne     short grayscale1
        jne     short grayscale1
        popa
        popa
grayscale2:
grayscale2:
        ret
        ret
colfrombits:    ; input: bh, output: al
colfrombits:    ; input: bh, output: al
        shr     bh, 1
        shr     bh, 1
        sbb     al, al
        sbb     al, al
        and     al, 2ah
        and     al, 2ah
        test    bh, 4
        test    bh, 4
        jz      short col1
        jz      short col1
        or      al, 15h
        or      al, 15h
col1:
col1:
        ret
        ret
;---------------- fn 11h, character generator
;---------------- fn 11h, character generator
loadUDF:
loadUDF:
        cmp     bx, 1000h
        cmp     bx, 1000h
        jne     loadUDFexit     ; only 16bytes chars and font block 0 supported
        jne     loadUDFexit     ; only 16bytes chars and font block 0 supported
        pusha
        pusha
        xchg    ax, dx
        xchg    ax, dx
        mov     dx, 03cbh
        mov     dx, 03cbh
        out     dx, ax
        out     dx, ax
        mov     si, bp
        mov     si, bp
        shl     cx, 4
        shl     cx, 4
        rep     outsb dx, es:[si]
        rep     outsb dx, es:[si]
        popa
        popa
loadUDFexit:
loadUDFexit:
        ret
        ret
chargen:
chargen:
        test    al, not 10h     ; test for 00h and 10h
        test    al, not 10h     ; test for 00h and 10h
        jz      short loadUDF
        jz      short loadUDF
        test    al, not 11h     ; test for 01h and 11h
        test    al, not 11h     ; test for 01h and 11h
        jz      short loadROMfont
        jz      short loadROMfont
        test    al, not 12h     ; test for 02h and 12h
        test    al, not 12h     ; test for 02h and 12h
        jz      short loadROMfont
        jz      short loadROMfont
        test    al, not 14h     ; test for 04h and 14h
        test    al, not 14h     ; test for 04h and 14h
        jz      short loadROMfont
        jz      short loadROMfont
        cmp     al, 20h
        cmp     al, 20h
        jb      loadUDFexit
        jb      loadUDFexit
        je      short set1f
        je      short set1f
        cmp     al, 21h
        cmp     al, 21h
        je      short setgrUDF
        je      short setgrUDF
        cmp     al, 24h
        cmp     al, 24h
        jbe     short setROMgrFont
        jbe     short setROMgrFont
        cmp     al, 30h
        cmp     al, 30h
        je      short getfontinfo
        je      short getfontinfo
        ret
        ret
loadROMFont:
loadROMFont:
        push    es
        push    es
        pusha
        pusha
        mov     bx, 1000h       ; 8x16 chars, block 0
        mov     bx, 1000h       ; 8x16 chars, block 0
        mov     cx, 100h        ; all chars
        mov     cx, 100h        ; all chars
        xor     dx, dx
        xor     dx, dx
        mov     bp, offset font8x16
        mov     bp, offset font8x16
        push    cs
        push    cs
        pop     es
        pop     es
        mov     al, 0
        mov     al, 0
;        int     10h             ; loadUDF
;        int     10h             ; loadUDF
        popa
        popa
        pop     es
        pop     es
        ret
        ret
set1f:
set1f:
        xor     si, si
        xor     si, si
        mov     ds, si
        mov     ds, si
        mov     [si+1fh*4], bp
        mov     [si+1fh*4], bp
        mov     [si+1fh*4+2], es
        mov     [si+1fh*4+2], es
        ret
        ret
setgrUDF:
setgrUDF:
        pusha
        pusha
        jcxz    short loadUDFexit
        jcxz    short loadUDFexit
        push    ds
        push    ds
        xor     si, si
        xor     si, si
        mov     ds, si
        mov     ds, si
        mov     [si+43h*4], bp
        mov     [si+43h*4], bp
        mov     [si+43h*4+2], es
        mov     [si+43h*4+2], es
        pop     ds
        pop     ds
        mov     ax, 200
        mov     ax, 200
        cmp     byte ptr ActiveVideoMode, 13h
        cmp     byte ptr ActiveVideoMode, 13h
        jb      short setgrUDFexit
        jb      short setgrUDFexit
        je      short setgrUDF1
        je      short setgrUDF1
        mov     ax, 480         ; mode 25h, 480 lines
        mov     ax, 480         ; mode 25h, 480 lines
setgrUDF1:
setgrUDF1:
        mov     ScanLinesChar, cx
        mov     ScanLinesChar, cx
        cwd
        cwd
        div     cx
        div     cx
        dec     ax
        dec     ax
        mov     ScreenRows, al
        mov     ScreenRows, al
setgrUDFexit:
setgrUDFexit:
        popa
        popa
        ret
        ret
setROMgrFont:
setROMgrFont:
        pusha
        pusha
        push    es
        push    es
        mov     cx, 8
        mov     cx, 8
        push    cs
        push    cs
        pop     es
        pop     es
        mov     bp, offset font8x8
        mov     bp, offset font8x8
        cmp     al, 23h
        cmp     al, 23h
        je      short setROMgrFont1
        je      short setROMgrFont1
        mov     bp, offset font8x16
        mov     bp, offset font8x16
setROMgrFont1:
setROMgrFont1:
        mov     al, 21h
        mov     al, 21h
        int     10h     ; set graphic UDF
        int     10h     ; set graphic UDF
        dec     ax
        dec     ax
        mov     bp, offset font8x8 + 128*8
        mov     bp, offset font8x8 + 128*8
        int     10h     ; set INT 1fh
        int     10h     ; set INT 1fh
        pop     es
        pop     es
        popa
        popa
        ret
        ret
getfontinfo:
getfontinfo:
        mov     cx, ScanLinesChar
        mov     cx, ScanLinesChar
        mov     dl, ScreenRows
        mov     dl, ScreenRows
        cmp     bh, 1
        cmp     bh, 1
        ja      short getfontinfo1
        ja      short getfontinfo1
        push    0
        push    0
        pop     ds
        pop     ds
        les     bp, ds:[1fh*4]
        les     bp, ds:[1fh*4]
        jb      short getfontinfoexit
        jb      short getfontinfoexit
        les     bp, ds:[43h*4]
        les     bp, ds:[43h*4]
        ret
        ret
getfontinfo1:
getfontinfo1:
        cmp     bh, 7
        cmp     bh, 7
        ja      short getfontinfoexit
        ja      short getfontinfoexit
        mov     si, bx
        mov     si, bx
        shr     si, 8
        shr     si, 8
        add     si, si
        add     si, si
        mov     bp, cs:fontinfo[si-4]
        mov     bp, cs:fontinfo[si-4]
        push    cs
        push    cs
        pop     es
        pop     es
getfontinfoexit:
getfontinfoexit:
        ret
        ret
fontinfo    dw  font8x16, font8x8, font8x8+128*8, font8x16, font8x16, font8x16
fontinfo    dw  font8x16, font8x8, font8x8+128*8, font8x16, font8x16, font8x16
;---------------- fn 12h, special functions
;---------------- fn 12h, special functions
special:
special:
        cmp     bl, 10h
        cmp     bl, 10h
        jne     short special1
        jne     short special1
        mov     cl, EgaMiscInfo2    ; cl = switch settings
        mov     cl, EgaMiscInfo2    ; cl = switch settings
        and     cx, 15              ; ch <- 0 (feature bits)
        and     cx, 15              ; ch <- 0 (feature bits)
        mov     bx, 3               ; bh <- 0 (color mode), bl = video memory size
        mov     bx, 3               ; bh <- 0 (color mode), bl = video memory size
        ret
        ret
special1:
special1:
        cmp     bl, 31h
        cmp     bl, 31h
        jne     short special2
        jne     short special2
        neg     al
        neg     al
        xor     al, VgaFlags
        xor     al, VgaFlags
        and     al, 8       ; transfer palette loading bit to VgaFlags
        and     al, 8       ; transfer palette loading bit to VgaFlags
        xor     VgaFlags, al
        xor     VgaFlags, al
        mov     al, 12h     ; supported function
        mov     al, 12h     ; supported function
        ret
        ret
special2:
special2:
        mov     al, 0       ; unsupported function
        mov     al, 0       ; unsupported function
        ret
        ret
;---------------- fn 13h, write string
;---------------- fn 13h, write string
writestr:
writestr:
        jcxz    short wstrexit
        jcxz    short wstrexit
        pusha
        pusha
        mov     si, bx
        mov     si, bx
        shr     si, 8
        shr     si, 8
        add     si, si
        add     si, si
        push    CursorPos[si]
        push    CursorPos[si]
        mov     ah, 9       ; write tty char/attribute
        mov     ah, 9       ; write tty char/attribute
wstr1:
wstr1:
        push    ax
        push    ax
        test    al, 2
        test    al, 2
        mov     al, es:[bp]
        mov     al, es:[bp]
        jz      short noattr
        jz      short noattr
        inc     bp
        inc     bp
        mov     bl, es:[bp]
        mov     bl, es:[bp]
noattr:
noattr:
        inc     bp
        inc     bp
        mov     CursorPos[si], dx
        mov     CursorPos[si], dx
        call    tty
        call    tty
        pop     ax
        pop     ax
        loop    short wstr1
        loop    short wstr1
        pop     CursorPos[si]
        pop     CursorPos[si]
        test    al, 1
        test    al, 1
        jz      short wstr2
        jz      short wstr2
        mov     ah, 2       ; set cursor pos
        mov     ah, 2       ; set cursor pos
        int     10h
        int     10h
wstr2:
wstr2:
        popa
        popa
wstrexit:
wstrexit:
        ret
        ret
;---------------- fn 1ah, get/set display combination code
;---------------- fn 1ah, get/set display combination code
getdcc:
getdcc:
        cmp     al, 1
        cmp     al, 1
        ja      short getdccexit
        ja      short getdccexit
        mov     al, ah
        mov     al, ah
        je      short setdcc
        je      short setdcc
        mov     bx, 08h
        mov     bx, 08h
dccval  label word
dccval  label word
setdcc:
setdcc:
        mov     cs:[dccval-2], bx
        mov     cs:[dccval-2], bx
getdccexit:
getdccexit:
        ret
        ret
;---------------- fn 1bh, query status
;---------------- fn 1bh, query status
querystatus:
querystatus:
        pusha
        pusha
        mov     ax, offset staticfunctable
        mov     ax, offset staticfunctable
        stosw
        stosw
        mov     ax, cs
        mov     ax, cs
        stosw
        stosw
        mov     si, offset ActiveVideoMode
        mov     si, offset ActiveVideoMode
        cmp     byte ptr [si], 13h
        cmp     byte ptr [si], 13h
        mov     cx, 33          ; info copied from BDA
        mov     cx, 33          ; info copied from BDA
        rep     movsb
        rep     movsb
        mov     ax, 8
        mov     ax, 8
        stosw                   ; display info (one VGA analog color monitor)
        stosw                   ; display info (one VGA analog color monitor)
        mov     bx, 208h        ; 400 scan lines, 8 pages
        mov     bx, 208h        ; 400 scan lines, 8 pages
        mov     al, 10h         ; 16 colors
        mov     al, 10h         ; 16 colors
        jb      short querystatus1     ; mode03h
        jb      short querystatus1     ; mode03h
        mov     bh, 0           ; scan lines code (0=200, 1=350, 2=400, 3=480), 8 pages
        mov     bh, 0           ; scan lines code (0=200, 1=350, 2=400, 3=480), 8 pages
        mov     ax, 100h        ; 256 colors
        mov     ax, 100h        ; 256 colors
        je      short querystatus1     ; mode13h
        je      short querystatus1     ; mode13h
        mov     bx, 301h        ; 480 scan lines, 1 page
        mov     bx, 301h        ; 480 scan lines, 1 page
querystatus1:
querystatus1:
        stosw
        stosw
        xchg    ax, bx
        xchg    ax, bx
        stosw
        stosw
        xor     ax, ax
        xor     ax, ax
        stosw                   ; font block info (45)
        stosw                   ; font block info (45)
        mov     al, VgaFlags
        mov     al, VgaFlags
        and     al, 00101111b
        and     al, 00101111b
        stosw
        stosw
        stosw
        stosw
        mov     al, EgaMiscInfo
        mov     al, EgaMiscInfo
        shr     al, 4
        shr     al, 4
        and     al, 7           ; video memory size
        and     al, 7           ; video memory size
        stosw
        stosw
        mov     al, 2
        mov     al, 2
        stosb                   ; color display attached
        stosb                   ; color display attached
        mov     cl, 6
        mov     cl, 6
        xor     ax, ax
        xor     ax, ax
        rep     stosw           ; 12 reserved bytes
        rep     stosw           ; 12 reserved bytes
        popa
        popa
        mov     al, ah          ; supported function
        mov     al, ah          ; supported function
        ret
        ret
staticfunctable db  00001100b   ; video mode 2h, 3h supported
staticfunctable db  00001100b   ; video mode 2h, 3h supported
                db  00000000b
                db  00000000b
                db  00001000b   ; video mode 13h supported
                db  00001000b   ; video mode 13h supported
                db  00000000b
                db  00000000b
                db  00100000b   ; video mode 25h supported
                db  00100000b   ; video mode 25h supported
                db  0, 0
                db  0, 0
                db  00000100b   ; 400 scanline supported
                db  00000100b   ; 400 scanline supported
                db  1           ; font blocks available in text mode
                db  1           ; font blocks available in text mode
                db  1           ; max active font blocks available in text mode
                db  1           ; max active font blocks available in text mode
;Bit(s)  Description
;Bit(s)  Description
;0      all modes on all displays function supported
;0      all modes on all displays function supported
;1      gray summing function supported
;1      gray summing function supported
;2      character font loading function supported
;2      character font loading function supported
;3      default palette loading enable/disable supported
;3      default palette loading enable/disable supported
;4      cursor emulation function supported
;4      cursor emulation function supported
;5      EGA palette present
;5      EGA palette present
;6      color palette present
;6      color palette present
;7      color-register paging function supported
;7      color-register paging function supported
;8      light pen supported (see AH=04h)
;8      light pen supported (see AH=04h)
;9      save/restore state function 1Ch supported
;9      save/restore state function 1Ch supported
;10     intensity/blinking function supported (see AX=1003h)
;10     intensity/blinking function supported (see AX=1003h)
;11     Display Combination Code supported (see #00039)
;11     Display Combination Code supported (see #00039)
;12-15  unused (0)
;12-15  unused (0)
                db  11101111b   ; miscellaneous function support flags
                db  11101111b   ; miscellaneous function support flags
                db  00001100b   ; miscellaneous function support flags
                db  00001100b   ; miscellaneous function support flags
                db  0, 0        ; reserved
                db  0, 0        ; reserved
                db  0           ; save pointer function flags
                db  0           ; save pointer function flags
                db  0           ; reserved
                db  0           ; reserved
vidtbl  dw  setmode, cursor, curpos, getcurpos, lightpen, apage, scrollup, scrolldn, readchar, writecharattr
vidtbl  dw  setmode, cursor, curpos, getcurpos, lightpen, apage, scrollup, scrolldn, readchar, writecharattr
        dw  writechar, nullproc, nullproc, nullproc, writecharTTY, readmode
        dw  writechar, nullproc, nullproc, nullproc, writecharTTY, readmode
        dw  pal, chargen, special, writestr, nullproc, nullproc, nullproc, nullproc, nullproc, nullproc, getdcc, querystatus, nullproc
        dw  pal, chargen, special, writestr, nullproc, nullproc, nullproc, nullproc, nullproc, nullproc, getdcc, querystatus, nullproc
int10 endp
int10 endp
; --------------------- INT 11h - Equipment ----------------
; --------------------- INT 11h - Equipment ----------------
EquipmentWord       equ     
EquipmentWord       equ     
int11   proc near
int11   proc near
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        mov     ax, EquipmentWord
        mov     ax, EquipmentWord
        pop     ds
        pop     ds
        iret
        iret
int11   endp
int11   endp
; --------------------- INT 12h - Memory size ----------------
; --------------------- INT 12h - Memory size ----------------
MemorySize       equ     
MemorySize       equ     
int12   proc near
int12   proc near
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        mov     ax, MemorySize
        mov     ax, MemorySize
        pop     ds
        pop     ds
        iret
        iret
int12   endp
int12   endp
; --------------------- INT 13h - Disk services ----------------
; --------------------- INT 13h - Disk services ----------------
HDLastError       equ     
HDLastError       equ     
HDOpStarted       equ         ; bit 3: in INT13h (all other bits must be 0)
HDOpStarted       equ         ; bit 3: in INT13h (all other bits must be 0)
HDSize            equ     
HDSize            equ     
int13   proc near
int13   proc near
        push    ds
        push    ds
        push    bp
        push    bp
        push    40h
        push    40h
        pop     ds
        pop     ds
        xor     byte ptr HDOpStarted, 8
        xor     byte ptr HDOpStarted, 8
        jz      short inINT13
        jz      short inINT13
        sti
        sti
        cld
        cld
        cmp     ah, 1ah
        cmp     ah, 1ah
        jbe     short Disk1
        jbe     short Disk1
        sub     ah, 41h-1bh     ; extensions
        sub     ah, 41h-1bh     ; extensions
        cmp     ah, 22h
        cmp     ah, 22h
        jbe     short Disk1
        jbe     short Disk1
        mov     ah, 1           ; bad command error
        mov     ah, 1           ; bad command error
        jmp     short exit
        jmp     short exit
inINT13:
inINT13:
        mov     ah, 0aah        ; drive not ready
        mov     ah, 0aah        ; drive not ready
        jmp     short exit2
        jmp     short exit2
Disk1:
Disk1:
        mov     bp, ax
        mov     bp, ax
        shr     bp, 7
        shr     bp, 7
        and     bp, 1feh
        and     bp, 1feh
        push    ds
        push    ds
        call    cs:disktbl[bp]
        call    cs:disktbl[bp]
        pop     ds
        pop     ds
exit:
exit:
        mov     HDLastError, ah
        mov     HDLastError, ah
exit2:
exit2:
        xor     byte ptr HDOpStarted, 8
        xor     byte ptr HDOpStarted, 8
        neg     ah              ; CF <- (AH != 0)
        neg     ah              ; CF <- (AH != 0)
exit1:
exit1:
        mov     bp, sp
        mov     bp, sp
        rcr     byte ptr [bp+8], 1
        rcr     byte ptr [bp+8], 1
        rol     byte ptr [bp+8], 1  ; insert error CF on stack
        rol     byte ptr [bp+8], 1  ; insert error CF on stack
        neg     ah
        neg     ah
        pop     bp
        pop     bp
        pop     ds
        pop     ds
        iret
        iret
disktbl dw      DiskReset, DiskGetStatus, DiskRead, DiskWrite, DiskVerify, DiskFormat, DiskFormat, DiskFormat, DiskGetParams, DiskInit, DiskRead, DiskWrite, DiskSeek, DiskRst, DiskReadSectBuffer, DiskWriteSectBuffer
disktbl dw      DiskReset, DiskGetStatus, DiskRead, DiskWrite, DiskVerify, DiskFormat, DiskFormat, DiskFormat, DiskGetParams, DiskInit, DiskRead, DiskWrite, DiskSeek, DiskRst, DiskReadSectBuffer, DiskWriteSectBuffer
        dw      DiskReady, DiskRecalibrate, DiskDiag, DiskDiag, DiskDiag, DiskGetType, DiskChanged, DiskSetDASDType, DiskSetMediaType, DiskPark, DiskFormat,  DiskExtInstCheck, DiskExtRead, DiskExtWrite, DiskExtVerify, DiskExtLock
        dw      DiskReady, DiskRecalibrate, DiskDiag, DiskDiag, DiskDiag, DiskGetType, DiskChanged, DiskSetDASDType, DiskSetMediaType, DiskPark, DiskFormat,  DiskExtInstCheck, DiskExtRead, DiskExtWrite, DiskExtVerify, DiskExtLock
        dw      DiskExtEject, DiskExtSeek, DiskExtGetParams
        dw      DiskExtEject, DiskExtSeek, DiskExtGetParams
DiskGetType:
DiskGetType:
        cmp     dl, 80h
        cmp     dl, 80h
        jne     short DiskReset ; ah=0, drive not present
        jne     short DiskReset ; ah=0, drive not present
        mov     cx, HDSize
        mov     cx, HDSize
        mov     dx, cx
        mov     dx, cx
        test    cx, cx
        test    cx, cx
        jz      short DiskReset ; ah=0, drive not present
        jz      short DiskReset ; ah=0, drive not present
        mov     ah, -3      ; HD present
        mov     ah, -3      ; HD present
        shr     cx, 6
        shr     cx, 6
        shl     dx, 10      ; CX:DX = HDSize * 1024
        shl     dx, 10      ; CX:DX = HDSize * 1024
DiskGetTypeexit:
DiskGetTypeexit:
        pop     ds          ; discard ret address
        pop     ds          ; discard ret address
        pop     ds          ; discard DS
        pop     ds          ; discard DS
        xor     byte ptr HDOpStarted, 8     ; CF <- 0
        xor     byte ptr HDOpStarted, 8     ; CF <- 0
        jmp     short   exit1
        jmp     short   exit1
DiskExtInstCheck:
DiskExtInstCheck:
        xchg    bl, bh
        xchg    bl, bh
        mov     ah, -1
        mov     ah, -1
        mov     cx, 1       ; extended disk access functions (AH=42h-44h,47h,48h) supported
        mov     cx, 1       ; extended disk access functions (AH=42h-44h,47h,48h) supported
        cmp     dl, 80h
        cmp     dl, 80h
        jne     short notready
        jne     short notready
        jmp     short DiskGetTypeexit
        jmp     short DiskGetTypeexit
DiskReset:
DiskReset:
DiskChanged:
DiskChanged:
DiskPark:
DiskPark:
        mov     ah, 0       ; success
        mov     ah, 0       ; success
        ret
        ret
DiskGetStatus:
DiskGetStatus:
        mov     ah, HDLastError
        mov     ah, HDLastError
        ret
        ret
DiskVerify:
DiskVerify:
        mov     bp, sdverify
        mov     bp, sdverify
        jmp     short   DiskRead1
        jmp     short   DiskRead1
DiskWrite:
DiskWrite:
        mov     bp, sdwrite
        mov     bp, sdwrite
        jmp     short   DiskRead1
        jmp     short   DiskRead1
DiskRead:
DiskRead:
        mov     bp, sdread
        mov     bp, sdread
DiskRead1:
DiskRead1:
        test    al, al
        test    al, al
        jz      short DiskReset
        jz      short DiskReset
        cmp     dl, 80h
        cmp     dl, 80h
        jne     short notready
        jne     short notready
        mov     ah, 4
        mov     ah, 4
        test    cl, 3fh
        test    cl, 3fh
        jz      short DiskReadend   ; bad sector 0
        jz      short DiskReadend   ; bad sector 0
        pusha
        pusha
        mov     ah, 0
        mov     ah, 0
        push    ax
        push    ax
        call    HCStoLBA
        call    HCStoLBA
        pop     cx
        pop     cx
        push    cx
        push    cx
        call    bp              ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=read sectors
        call    bp              ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=read sectors
        pop     cx
        pop     cx
        sub     cx, ax
        sub     cx, ax
        neg     cx              ; CF=1 if cx != 0
        neg     cx              ; CF=1 if cx != 0
        rcl     ah, 3           ; AH = 4*CF (sector not found / read error)
        rcl     ah, 3           ; AH = 4*CF (sector not found / read error)
        mov     ds, ax
        mov     ds, ax
        popa
        popa
        mov     ax, ds
        mov     ax, ds
DiskReadend:
DiskReadend:
        ret
        ret
HCStoLBA:       ; CX = {cyl[7:0], cyl[9:8], sect[5:0]}, DH = head. Returns DX:AX LBA
HCStoLBA:       ; CX = {cyl[7:0], cyl[9:8], sect[5:0]}, DH = head. Returns DX:AX LBA
        mov     al, ch
        mov     al, ch
        mov     ah, cl
        mov     ah, cl
        shr     ah, 6
        shr     ah, 6
        shr     dx, 8
        shr     dx, 8
        imul    dx, 63
        imul    dx, 63
        and     cx, 3fh
        and     cx, 3fh
        add     cx, dx
        add     cx, dx
        dec     cx
        dec     cx
        mov     dx, 255*63
        mov     dx, 255*63
        mul     dx
        mul     dx
        add     ax, cx
        add     ax, cx
        adc     dx, 0
        adc     dx, 0
        ret
        ret
;    unsigned int s = cs & 0x3f;
;    unsigned int s = cs & 0x3f;
;    unsigned int c = ((cs & 0xc0) << 2) | (cs >> 8);
;    unsigned int c = ((cs & 0xc0) << 2) | (cs >> 8);
;    return (c*255l + h)*63l + s - 1l;
;    return (c*255l + h)*63l + s - 1l;
DiskFormat:
DiskFormat:
DiskInit:
DiskInit:
DiskSeek:
DiskSeek:
DiskRst:
DiskRst:
DiskReady:
DiskReady:
DiskRecalibrate:
DiskRecalibrate:
DiskDiag:
DiskDiag:
DiskExtSeek:
DiskExtSeek:
        cmp     word ptr HDSize, 0
        cmp     word ptr HDSize, 0
        je      short notready
        je      short notready
        cmp     dl, 80h
        cmp     dl, 80h
        je      short DiskReset
        je      short DiskReset
notready:
notready:
        mov     ah, 0aah        ; disk not ready
        mov     ah, 0aah        ; disk not ready
        ret
        ret
DiskGetParams:
DiskGetParams:
        cmp     dl, 80h
        cmp     dl, 80h
        mov     ah, 7
        mov     ah, 7
        jne     short DiskReadend   ; ret
        jne     short DiskReadend   ; ret
        mov     bl, 0   ; ???
        mov     bl, 0   ; ???
        mov     ax, HDSize
        mov     ax, HDSize
        mov     dx, ax
        mov     dx, ax
        shl     ax, 10
        shl     ax, 10
        shr     dx, 6
        shr     dx, 6
        sub     ax, 30
        sub     ax, 30
        sbb     dx, 0
        sbb     dx, 0
        mov     cx, 63*255
        mov     cx, 63*255
        div     cx
        div     cx
        dec     ax
        dec     ax
        cmp     ax, 3feh
        cmp     ax, 3feh
        jbe     dgpok
        jbe     dgpok
        mov     ax, 3feh
        mov     ax, 3feh
dgpok:
dgpok:
        xchg    al, ah
        xchg    al, ah
        shl     al, 6
        shl     al, 6
        or      al, 3fh
        or      al, 3fh
        mov     cx, ax
        mov     cx, ax
        mov     dx, 0fe01h
        mov     dx, 0fe01h
        xor     ax, ax
        xor     ax, ax
        ret
        ret
DiskExtVerify:
DiskExtVerify:
        mov     bp, sdverify
        mov     bp, sdverify
        jmp     short DiskExtRead1
        jmp     short DiskExtRead1
DiskExtWrite:
DiskExtWrite:
        mov     bp, sdwrite
        mov     bp, sdwrite
        jmp     short DiskExtRead1
        jmp     short DiskExtRead1
DiskExtRead:
DiskExtRead:
        mov     bp, sdread
        mov     bp, sdread
DiskExtRead1:
DiskExtRead1:
        cmp     dl, 80h
        cmp     dl, 80h
        jne     short notready
        jne     short notready
        push    es
        push    es
        push    ax
        push    ax
        pusha
        pusha
        mov     bx, sp
        mov     bx, sp
        mov     ds, ss:[bx+26]
        mov     ds, ss:[bx+26]
        mov     cx, [si+2]
        mov     cx, [si+2]
        les     bx, [si+4]
        les     bx, [si+4]
        mov     ax, [si+8]
        mov     ax, [si+8]
        mov     dx, [si+10]
        mov     dx, [si+10]
        push    ds
        push    ds
        push    si
        push    si
        call    bp
        call    bp
        pop     si
        pop     si
        pop     ds
        pop     ds
        sub     ax, [si+2]
        sub     ax, [si+2]
        add     [si+2], ax
        add     [si+2], ax
        popa
        popa
        pop     ax
        pop     ax
        sbb     ah, ah
        sbb     ah, ah
        and     ah, 4
        and     ah, 4
        pop     es
        pop     es
        ret
        ret
DiskExtGetParams:
DiskExtGetParams:
        cmp     dl, 80h
        cmp     dl, 80h
        jne     short notready
        jne     short notready
        push    ax
        push    ax
        mov     ax, HDSize
        mov     ax, HDSize
        mov     bp, sp
        mov     bp, sp
        mov     ds, [bp+8]
        mov     ds, [bp+8]
        xor     bp, bp
        xor     bp, bp
        mov     word ptr [si], 1ah      ; size
        mov     word ptr [si], 1ah      ; size
        mov     word ptr [si+2], 0bh    ; flags
        mov     word ptr [si+2], 0bh    ; flags
        mov     word ptr [si+4], 1023   ; cylinders
        mov     word ptr [si+4], 1023   ; cylinders
        mov     word ptr [si+6], bp
        mov     word ptr [si+6], bp
        mov     word ptr [si+8], 255    ; heads
        mov     word ptr [si+8], 255    ; heads
        mov     word ptr [si+10], bp
        mov     word ptr [si+10], bp
        mov     word ptr [si+12], 63     ; sectors/track
        mov     word ptr [si+12], 63     ; sectors/track
        mov     word ptr [si+14], bp
        mov     word ptr [si+14], bp
        mov     word ptr [si+16], ax
        mov     word ptr [si+16], ax
        shl     word ptr [si+16], 10
        shl     word ptr [si+16], 10
        shr     ax, 6
        shr     ax, 6
        mov     word ptr [si+18], ax
        mov     word ptr [si+18], ax
        mov     word ptr [si+20], bp
        mov     word ptr [si+20], bp
        mov     word ptr [si+22], bp
        mov     word ptr [si+22], bp
        mov     word ptr [si+24], 512   ; bytes/sector
        mov     word ptr [si+24], 512   ; bytes/sector
        pop     ax
        pop     ax
        mov     ah, 0
        mov     ah, 0
        ret
        ret
DiskReadSectBuffer:
DiskReadSectBuffer:
DiskWriteSectBuffer:
DiskWriteSectBuffer:
DiskSetDASDType:
DiskSetDASDType:
DiskSetMediaType:
DiskSetMediaType:
DiskExtLock:
DiskExtLock:
DiskExtEject:
DiskExtEject:
        mov     ah, 1       ; unsupported fn
        mov     ah, 1       ; unsupported fn
        ret
        ret
int13   endp
int13   endp
; --------------------- INT 15h - Extended services ----------------
; --------------------- INT 15h - Extended services ----------------
UFPtr           equ     
UFPtr           equ     
WaitCount       equ     
WaitCount       equ     
UWaitFlag       equ     
UWaitFlag       equ     
HandlerPtr      equ      ; 4 bytes
HandlerPtr      equ      ; 4 bytes
DataBuffer      equ      ; 3 bytes
DataBuffer      equ      ; 3 bytes
DataCounter     equ      ; 1 byte
DataCounter     equ      ; 1 byte
PacketSize      equ      ; 1 byte, 0->3bytes, 1->4bytes
PacketSize      equ      ; 1 byte, 0->3bytes, 1->4bytes
FreeXMSKb       equ     (1024 - 16 - 6)*64
FreeXMSKb       equ     (1024 - 16 - 6)*64
; ------------ MovExt
; ------------ MovExt
IncSeg: ; DX = segment port address
IncSeg: ; DX = segment port address
        jnz     short SetSegExit
        jnz     short SetSegExit
        in      ax, dx
        in      ax, dx
        and     ax, 3ffh
        and     ax, 3ffh
        inc     ax
        inc     ax
        cmp     ax, 12h
        cmp     ax, 12h
        jne     short IncSeg1
        jne     short IncSeg1
        xor     ax, ax
        xor     ax, ax
IncSeg1:
IncSeg1:
        cmp     ax, 0ch
        cmp     ax, 0ch
        jne     short SetSeg2
        jne     short SetSeg2
SetSeg: ; DX = segment port address, ax = logical segment (0..1023)
SetSeg: ; DX = segment port address, ax = logical segment (0..1023)
        and     ax, 3ffh
        and     ax, 3ffh
        cmp     ax, 0ch
        cmp     ax, 0ch
        jb      short SetSeg1
        jb      short SetSeg1
        add     ax, 6
        add     ax, 6
SetSeg2:
SetSeg2:
        cmp     ax, 400h
        cmp     ax, 400h
        jb      short SetSeg1
        jb      short SetSeg1
        sub     ax, 400h - 0ch
        sub     ax, 400h - 0ch
SetSeg1:
SetSeg1:
        out     dx, ax
        out     dx, ax
SetSegExit:
SetSegExit:
        ret
        ret
MovSeg  equ     01h
MovSeg  equ     01h
savess  dw      0
savess  dw      0
savesp  dw      MovExt, 0 ; tmp stack
savesp  dw      MovExt, 0 ; tmp stack
; Log(idx) to Phy(val) segment map (1024segs): 0,1,2,3,4,5,6,7,8,9,a,b,12h,13h,...,3feh,3ffh,c,d,e,f,10h,11h, then wrap to 0,1,2,...
; Log(idx) to Phy(val) segment map (1024segs): 0,1,2,3,4,5,6,7,8,9,a,b,12h,13h,...,3feh,3ffh,c,d,e,f,10h,11h, then wrap to 0,1,2,...
MovExt:
MovExt:
        push    es
        push    es
        push    ds
        push    ds
        pusha
        pusha
        cli
        cli
        mov     cs:savess, ss
        mov     cs:savess, ss
        push    cs
        push    cs
        pop     ss
        pop     ss
        xchg    sp, cs:savesp
        xchg    sp, cs:savesp
        mov     dx, 80h + MovSeg + 1
        mov     dx, 80h + MovSeg + 1
        jcxz    short MovExt_exit
        jcxz    short MovExt_exit
        push    es
        push    es
        pop     ds
        pop     ds
        cld
        cld
        mov     al, [si+1ch]
        mov     al, [si+1ch]
        mov     ah, [si+1fh]
        mov     ah, [si+1fh]
        mov     bl, [si+14h]
        mov     bl, [si+14h]
        mov     bh, [si+17h]
        mov     bh, [si+17h]
        mov     di, [si+1ah]
        mov     di, [si+1ah]
        mov     si, [si+12h]
        mov     si, [si+12h]
        call    flush
        call    flush
        call    SetSeg      ; 02000h = destination, DX=82h
        call    SetSeg      ; 02000h = destination, DX=82h
        dec     dx
        dec     dx
        xchg    ax, bx
        xchg    ax, bx
        call    SetSeg      ; 01000h = source, DX=81h
        call    SetSeg      ; 01000h = source, DX=81h
        push    MovSeg shl 12
        push    MovSeg shl 12
        pop     ds
        pop     ds
        push    (MovSeg + 1) shl 12
        push    (MovSeg + 1) shl 12
        pop     es
        pop     es
        xor     bx, bx
        xor     bx, bx
        add     cx, cx
        add     cx, cx
        adc     bx, bx      ; BX:CX = bytes to transfer
        adc     bx, bx      ; BX:CX = bytes to transfer
; move from 01000h:si to 02000h:di, 2*cx bytes
; move from 01000h:si to 02000h:di, 2*cx bytes
MovExtLoop:
MovExtLoop:
        inc     dx          ; 82h
        inc     dx          ; 82h
        mov     ax, si
        mov     ax, si
        cmp     ax, di
        cmp     ax, di
        ja      short MovExt1
        ja      short MovExt1
        mov     ax, di
        mov     ax, di
MovExt1:
MovExt1:
        neg     ax
        neg     ax
        adc     bx, -1
        adc     bx, -1
        sub     cx, ax
        sub     cx, ax
        sbb     bx, 0
        sbb     bx, 0
        xchg    ax, cx      ; cx = bytes to move, bx:ax = bytes left for the next transfer
        xchg    ax, cx      ; cx = bytes to move, bx:ax = bytes left for the next transfer
        jns     short MovExt2   ; ax <= bx:cx
        jns     short MovExt2   ; ax <= bx:cx
        add     cx, ax
        add     cx, ax
        xor     ax, ax
        xor     ax, ax
        inc     bx
        inc     bx
MovExt2:
MovExt2:
        movsb               ; if CX = 0 transfer 10000h bytes
        movsb               ; if CX = 0 transfer 10000h bytes
        dec     cx
        dec     cx
        jz      short MovExt_next
        jz      short MovExt_next
        test    si, 1       ; read align
        test    si, 1       ; read align
        jz      short raligned
        jz      short raligned
        movsb
        movsb
        dec     cx
        dec     cx
raligned:
raligned:
        shr     cx, 1
        shr     cx, 1
        rep     movsw
        rep     movsw
        jnc     short MovExt_next
        jnc     short MovExt_next
        movsb
        movsb
MovExt_next:
MovExt_next:
        call    flush
        call    flush
        mov     cx, ax
        mov     cx, ax
        or      ax, bx
        or      ax, bx
        jz      short MovExt_exit  ; finalized
        jz      short MovExt_exit  ; finalized
        test    di, di
        test    di, di
        call    incseg      ; does nothing if ZF == 0, dx = 8bh
        call    incseg      ; does nothing if ZF == 0, dx = 8bh
        dec     dx          ; 81h
        dec     dx          ; 81h
        test    si, si
        test    si, si
        call    incseg      ; dx = 81h
        call    incseg      ; dx = 81h
        jmp     short MovExtLoop
        jmp     short MovExtLoop
MovExt_exit:
MovExt_exit:
        mov     ax, MovSeg + 1
        mov     ax, MovSeg + 1
        out     dx, ax      ; 82h
        out     dx, ax      ; 82h
        dec     ax
        dec     ax
        dec     dx
        dec     dx
        out     dx, ax      ; 81h
        out     dx, ax      ; 81h
        mov     ss, cs:savess
        mov     ss, cs:savess
        xchg    sp, cs:savesp
        xchg    sp, cs:savesp
        popa
        popa
        pop     ds
        pop     ds
        pop     es
        pop     es
        xor     ah, ah
        xor     ah, ah
        jmp     short exit_ax
        jmp     short exit_ax
MovExtProxy:
MovExtProxy:
        jmp     MovExt
        jmp     MovExt
int15:
int15:
        cmp     ah, 4fh
        cmp     ah, 4fh
        je      short exit_iret
        je      short exit_iret
        xchg    al, ah
        xchg    al, ah
        cmp     al, 80h
        cmp     al, 80h
        jb      short exit15; CF=1  for <80h
        jb      short exit15; CF=1  for <80h
        cmp     al, 83h
        cmp     al, 83h
        jb      short done  ; no error for 80, 81, 82
        jb      short done  ; no error for 80, 81, 82
        je      short SetEventWait; 83
        je      short SetEventWait; 83
        cmp     al, 86h
        cmp     al, 86h
        jb      short exit15; CF=1 for 84, 85
        jb      short exit15; CF=1 for 84, 85
        je      short Wait1 ; 86
        je      short Wait1 ; 86
        cmp     al, 88h
        cmp     al, 88h
        jb      short MovExtProxy ; 87
        jb      short MovExtProxy ; 87
        je      short ExtSize     ; 88
        je      short ExtSize     ; 88
        cmp     al, 90h
        cmp     al, 90h
        jb      short  exit15; CF=1 for 89..8f
        jb      short  exit15; CF=1 for 89..8f
        cmp     al, 92h
        cmp     al, 92h
        jb      short done  ; no error for 90, 91
        jb      short done  ; no error for 90, 91
        cmp     al, 0c0h
        cmp     al, 0c0h
        jb      short exit15; CF=1 for 92..bf
        jb      short exit15; CF=1 for 92..bf
        je      short GetConfig   ; c0
        je      short GetConfig   ; c0
        cmp     al, 0c2h
        cmp     al, 0c2h
        jb      short exit15; CF=1 for c1
        jb      short exit15; CF=1 for c1
        je      short Mouse ; c2
        je      short Mouse ; c2
done:
done:
        cmc                 ; CF=1 for >c2
        cmc                 ; CF=1 for >c2
exit15:
exit15:
        mov     ax, 8600h
        mov     ax, 8600h
exit_ax:
exit_ax:
        sti
        sti
        retf    2           ; discard flags (need to keep CF)
        retf    2           ; discard flags (need to keep CF)
exit_iret:
exit_iret:
        iret
        iret
; ------------ SetEventWait
; ------------ SetEventWait
SetEventWait:
SetEventWait:
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        xor     ah, 1
        xor     ah, 1
        jz      short cancel
        jz      short cancel
        test    ah, byte ptr UWaitFlag ; ah=1
        test    ah, byte ptr UWaitFlag ; ah=1
        jnz     short busy  ; CF=0
        jnz     short busy  ; CF=0
        mov     ax, 1000-1  ; 1ms
        mov     ax, 1000-1  ; 1ms
        out     70h, ax     ; restart RTC timer
        out     70h, ax     ; restart RTC timer
        mov     UFPtr[0], bx
        mov     UFPtr[0], bx
        mov     UFPtr[2], es
        mov     UFPtr[2], es
        add     ax, dx
        add     ax, dx
        adc     cx, 0
        adc     cx, 0
        mov     WaitCount[0], ax
        mov     WaitCount[0], ax
        mov     WaitCount[2], cx
        mov     WaitCount[2], cx
        mov     ah, 1       ; wait in progress
        mov     ah, 1       ; wait in progress
cancel:
cancel:
        mov     byte ptr UWaitFlag, ah
        mov     byte ptr UWaitFlag, ah
        int     70h
        int     70h
        stc                 ; no error
        stc                 ; no error
busy:
busy:
        cmc                 ; eror
        cmc                 ; eror
nowait:
nowait:
        pop     ds
        pop     ds
        jmp     short exit15
        jmp     short exit15
; ------------ Wait
; ------------ Wait
Wait1:
Wait1:
        push    es
        push    es
        push    bx
        push    bx
        mov     ax, 8300h
        mov     ax, 8300h
        push    4ah
        push    4ah
        pop     es
        pop     es
        xor     bx, bx      ; user wait flag address=0040:00a0
        xor     bx, bx      ; user wait flag address=0040:00a0
        int     15h         ; returns with IF = 1
        int     15h         ; returns with IF = 1
        jc      short wbusy
        jc      short wbusy
wloop:
wloop:
        hlt
        hlt
        test    byte ptr es:[bx], 80h
        test    byte ptr es:[bx], 80h
        jz      short wloop
        jz      short wloop
wbusy:
wbusy:
        pop     bx
        pop     bx
        pop     es
        pop     es
        jmp     short exit15
        jmp     short exit15
; ------------ ExtSize
; ------------ ExtSize
ExtSize:
ExtSize:
        mov     ax, FreeXMSKb
        mov     ax, FreeXMSKb
        jmp     short exit_ax
        jmp     short exit_ax
; ------------ GetConfig
; ------------ GetConfig
GetConfig:
GetConfig:
        xor     ax, ax
        xor     ax, ax
        push    cs
        push    cs
        pop     es
        pop     es
        mov     bx, offset SysParams
        mov     bx, offset SysParams
        jmp     short exit_ax
        jmp     short exit_ax
; ------------ Mouse
; ------------ Mouse
Mouse:
Mouse:
        push    ds
        push    ds
        push    dx
        push    dx
        push    40h
        push    40h
        pop     ds
        pop     ds
        test    byte ptr EquipmentWord, 4 ; ps2 mouse equipement word
        test    byte ptr EquipmentWord, 4 ; ps2 mouse equipement word
        jnz     short mouse_present
        jnz     short mouse_present
if_err:
if_err:
        mov     ax, 03a7h   ; interface error (no mouse present)
        mov     ax, 03a7h   ; interface error (no mouse present)
        out     64h, al     ; disable mouse
        out     64h, al     ; disable mouse
errexit:
errexit:
        stc                 ; error
        stc                 ; error
exitok:
exitok:
        pushf               ; save CF
        pushf               ; save CF
        in      al, 21h
        in      al, 21h
        and     al, not 10h
        and     al, not 10h
        out     21h, al     ; enable mouse interrupts
        out     21h, al     ; enable mouse interrupts
        call    enableKbIfPresent
        call    enableKbIfPresent
        popf
        popf
        pop     dx
        pop     dx
        pop     ds
        pop     ds
        jmp     exit_ax
        jmp     exit_ax
mouse_present:
mouse_present:
        mov     al, ah
        mov     al, ah
        mov     ah, 1       ; invalid function
        mov     ah, 1       ; invalid function
        cmp     al, 7
        cmp     al, 7
        ja      short errexit
        ja      short errexit
        push    ax
        push    ax
        in      al, 21h
        in      al, 21h
        or      al, 10h
        or      al, 10h
        out     21h, al     ; disable mouse interrupts
        out     21h, al     ; disable mouse interrupts
        sti                 ; allow interrupts for a short time, to flush possible pending KB/mouse requests
        sti                 ; allow interrupts for a short time, to flush possible pending KB/mouse requests
        mov     al, 0adh
        mov     al, 0adh
        out     64h, al     ; disable kb interface
        out     64h, al     ; disable kb interface
        pop     ax
        pop     ax
        cmp     al, 1
        cmp     al, 1
        cli                 ; from now on we are working with ints disabled, as the following code is highly non re-entrant
        cli                 ; from now on we are working with ints disabled, as the following code is highly non re-entrant
        jb      short en_dis
        jb      short en_dis
        je      short reset
        je      short reset
        cmp     al, 3
        cmp     al, 3
        jb      short sampling
        jb      short sampling
        je      short resolution
        je      short resolution
        cmp     al, 5
        cmp     al, 5
        jb      short gettype
        jb      short gettype
        je      short reset
        je      short reset
        cmp     al, 6
        cmp     al, 6
        je      short extend
        je      short extend
; ------------- set handler
; ------------- set handler
        mov     HandlerPtr[0], bx
        mov     HandlerPtr[0], bx
        mov     HandlerPtr[2], es
        mov     HandlerPtr[2], es
        jmp     short exit_success1
        jmp     short exit_success1
; ------------- enable/disable
; ------------- enable/disable
en_dis:
en_dis:
        mov     ax, 02f5h   ; ah = invalid input
        mov     ax, 02f5h   ; ah = invalid input
        sub     al, bh
        sub     al, bh
        cmp     bh, ah
        cmp     bh, ah
        jnc     short errexit
        jnc     short errexit
        mov     ah, al
        mov     ah, al
        call    sendcmd     ; enable/disable data reporting (CF = 1)
        call    sendcmd     ; enable/disable data reporting (CF = 1)
if_err1:
if_err1:
        jc      short if_err
        jc      short if_err
exit_success:
exit_success:
        mov     byte ptr DataCounter, 0
        mov     byte ptr DataCounter, 0
exit_success1:
exit_success1:
        xor     ah, ah      ; success
        xor     ah, ah      ; success
        jmp     short exitok
        jmp     short exitok
; ------------- reset
; ------------- reset
reset:
reset:
        mov     ah, 0f6h    ; set defaults
        mov     ah, 0f6h    ; set defaults
        stc                 ; mouse command
        stc                 ; mouse command
        call    sendcmd
        call    sendcmd
        jc      short if_err
        jc      short if_err
        mov     bx, 00aah
        mov     bx, 00aah
        mov     byte ptr PacketSize, bh ; 3bytes packet
        mov     byte ptr PacketSize, bh ; 3bytes packet
        jmp     short exit_success
        jmp     short exit_success
; ------------- sampling
; ------------- sampling
sampling:
sampling:
        cmp     bh, 6
        cmp     bh, 6
badparam:
badparam:
        mov     ah, 2       ; invalid input
        mov     ah, 2       ; invalid input
        ja      short errexit
        ja      short errexit
        shr     bx, 8
        shr     bx, 8
        mov     ah, cs:sample_tbl[bx]
        mov     ah, cs:sample_tbl[bx]
        push    ax
        push    ax
        mov     ah, 0f3h    ; st sample rate
        mov     ah, 0f3h    ; st sample rate
send2c:
send2c:
        stc
        stc
        call    sendcmd
        call    sendcmd
        pop     ax
        pop     ax
        jc      short if_err1
        jc      short if_err1
send1c:
send1c:
        stc
        stc
        call    sendcmd
        call    sendcmd
        jmp     short if_err1
        jmp     short if_err1
; ------------- resolution
; ------------- resolution
resolution:
resolution:
        cmp     bh, 3
        cmp     bh, 3
        ja      short badparam
        ja      short badparam
        push    bx
        push    bx
        mov     ah, 0e8h    ; set resolution
        mov     ah, 0e8h    ; set resolution
        jmp     short send2c
        jmp     short send2c
; ------------- gettype
; ------------- gettype
gettype:
gettype:
        mov     ah, 0f2h
        mov     ah, 0f2h
        stc
        stc
        call    sendcmd
        call    sendcmd
        jc      short if_err1
        jc      short if_err1
        call    getps2byte
        call    getps2byte
        jc      short if_err1
        jc      short if_err1
        mov     bh, al
        mov     bh, al
        neg     al          ; CF=1 if al != 0
        neg     al          ; CF=1 if al != 0
        adc     al, bh
        adc     al, bh
        mov     byte ptr PacketSize, al ; 3 or 4 bytes packet
        mov     byte ptr PacketSize, al ; 3 or 4 bytes packet
        jmp     short exit_success
        jmp     short exit_success
; ------------- extended commands
; ------------- extended commands
extend:
extend:
        test    bh, bh
        test    bh, bh
        jnz     short setscaling
        jnz     short setscaling
        mov     ah, 0e9h    ; status request
        mov     ah, 0e9h    ; status request
        stc
        stc
        call    sendcmd
        call    sendcmd
        jc      short if_err1
        jc      short if_err1
        call    getps2byte
        call    getps2byte
        jc      short if_err1
        jc      short if_err1
        mov     bl, al
        mov     bl, al
        call    getps2byte
        call    getps2byte
        jc      short if_err1
        jc      short if_err1
        mov     cl, al
        mov     cl, al
        call    getps2byte
        call    getps2byte
        jc      short if_err1
        jc      short if_err1
        pop     dx
        pop     dx
        push    ax          ; replace dx on stack
        push    ax          ; replace dx on stack
        jmp     short exit_success
        jmp     short exit_success
setscaling:
setscaling:
        cmp     bh, 2
        cmp     bh, 2
        ja      short badparam
        ja      short badparam
        mov     ah, 0e5h    ; set scaling 1:1 or 2:1
        mov     ah, 0e5h    ; set scaling 1:1 or 2:1
        add     ah, bh
        add     ah, bh
        jmp     short send1c
        jmp     short send1c
sample_tbl  db  10, 20, 40, 60, 80, 100, 200
sample_tbl  db  10, 20, 40, 60, 80, 100, 200
SysParams   db  8, 0, 0fch, 0, 0
SysParams   db  8, 0, 0fch, 0, 0
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Feature byte 1
; Feature byte 1
; b7: 1=DMA channel 3 used by hard disk
; b7: 1=DMA channel 3 used by hard disk
; b6: 1=2 interrupt controllers present
; b6: 1=2 interrupt controllers present
; b5: 1=RTC present
; b5: 1=RTC present
; b4: 1=BIOS calls int 15h/4Fh every key
; b4: 1=BIOS calls int 15h/4Fh every key
; b3: 1=wait for extern event supported (Int 15h/41h)
; b3: 1=wait for extern event supported (Int 15h/41h)
; b2: 1=extended BIOS data area used
; b2: 1=extended BIOS data area used
; b1: 0=AT or ESDI bus, 1=MicroChannel
; b1: 0=AT or ESDI bus, 1=MicroChannel
; b0: 1=Dual bus (MicroChannel + ISA)
; b0: 1=Dual bus (MicroChannel + ISA)
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
            db      10h
            db      10h
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Feature byte 2
; Feature byte 2
; b7: 1=32-bit DMA supported
; b7: 1=32-bit DMA supported
; b6: 1=int16h, function 9 supported
; b6: 1=int16h, function 9 supported
; b5: 1=int15h/C6h (get POS data) supported
; b5: 1=int15h/C6h (get POS data) supported
; b4: 1=int15h/C7h (get mem map info) supported
; b4: 1=int15h/C7h (get mem map info) supported
; b3: 1=int15h/C8h (en/dis CPU) supported
; b3: 1=int15h/C8h (en/dis CPU) supported
; b2: 1=non-8042 kb controller
; b2: 1=non-8042 kb controller
; b1: 1=data streaming supported
; b1: 1=data streaming supported
; b0: reserved
; b0: reserved
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
            db      44h
            db      44h
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Feature byte 3
; Feature byte 3
; b7: not used
; b7: not used
; b6: reserved
; b6: reserved
; b5: reserved
; b5: reserved
; b4: POST supports ROM-to-RAM enable/disable
; b4: POST supports ROM-to-RAM enable/disable
; b3: SCSI on system board
; b3: SCSI on system board
; b2: info panel installed
; b2: info panel installed
; b1: Initial Machine Load (IML) system - BIOS on disk
; b1: Initial Machine Load (IML) system - BIOS on disk
; b0: SCSI supported in IML
; b0: SCSI supported in IML
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
            db      0
            db      0
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Feature byte 4
; Feature byte 4
; b7: IBM private
; b7: IBM private
; b6: EEPROM present
; b6: EEPROM present
; b5-3: ABIOS presence (011 = not supported)
; b5-3: ABIOS presence (011 = not supported)
; b2: private
; b2: private
; b1: memory split above 16Mb supported
; b1: memory split above 16Mb supported
; b0: POSTEXT directly supported by POST
; b0: POSTEXT directly supported by POST
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
            db      0
            db      0
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Feature byte 5 (IBM)
; Feature byte 5 (IBM)
; b1: enhanced mouse
; b1: enhanced mouse
; b0: flash EPROM
; b0: flash EPROM
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
            db      0
            db      0
; --------------------- INT 16h - keyboard interface ----------------
; --------------------- INT 16h - keyboard interface ----------------
;       AH      Description
;       AH      Description
;       --      ------------------------------------------------
;       --      ------------------------------------------------
;       00h     Get a key from the keyboard, return code in AX.
;       00h     Get a key from the keyboard, return code in AX.
;       01h     Test for available key, ZF=1 if none, ZF=0 and
;       01h     Test for available key, ZF=1 if none, ZF=0 and
;               AX contains next key code if key available.
;               AX contains next key code if key available.
;       02h     Get shift status. Returns shift key status in AL.
;       02h     Get shift status. Returns shift key status in AL.
;       03h     Set Autorepeat rate. BH=0,1,2,3 (delay time in quarter seconds), BL=0..1Fh for 30 char/sec to 2 char/sec repeat rate.
;       03h     Set Autorepeat rate. BH=0,1,2,3 (delay time in quarter seconds), BL=0..1Fh for 30 char/sec to 2 char/sec repeat rate.
;       05h     Store scan code (in CX) in the type ahead buffer.
;       05h     Store scan code (in CX) in the type ahead buffer.
;       10h     Get a key (same as 00h in this implementation).
;       10h     Get a key (same as 00h in this implementation).
;       11h     Test for key (same as 01h).
;       11h     Test for key (same as 01h).
;       12h     Get extended key status. Returns status in AX.
;       12h     Get extended key status. Returns status in AX.
AltKpd          equ     
AltKpd          equ     
HeadPtr         equ     
HeadPtr         equ     
TailPtr         equ     
TailPtr         equ     
Buffer          equ     ;1eh
Buffer          equ     ;1eh
EndBuf          equ     ;3eh
EndBuf          equ     ;3eh
int16 proc near
int16 proc near
        push    ds
        push    ds
        push    si
        push    si
        push    40h
        push    40h
        pop     ds
        pop     ds
        xchg    al, ah          ;shorter opcodes for al than ah
        xchg    al, ah          ;shorter opcodes for al than ah
        dec     ax
        dec     ax
        test    al, 0EFh        ;Check for 01h and 11h
        test    al, 0EFh        ;Check for 01h and 11h
        jz      short TestKey   ;TestKey does not need cld
        jz      short TestKey   ;TestKey does not need cld
        inc     ax
        inc     ax
        cld
        cld
        test    al, 0EFh        ;Check for 0h and 10h
        test    al, 0EFh        ;Check for 0h and 10h
        jz      short GetKey
        jz      short GetKey
        cmp     al, 3           ;Check for 02h and 03h
        cmp     al, 3           ;Check for 02h and 03h
        jb      short GetStatus
        jb      short GetStatus
        je      short SetAutoRpt
        je      short SetAutoRpt
        cmp     al, 5           ;Check for StoreKey function.
        cmp     al, 5           ;Check for StoreKey function.
        je      short StoreKey
        je      short StoreKey
        cmp     al, 9           ;Get KB functionality
        cmp     al, 9           ;Get KB functionality
        je      short kbfunc
        je      short kbfunc
        cmp     al, 12h         ;Extended status call
        cmp     al, 12h         ;Extended status call
        je      short ExtStatus
        je      short ExtStatus
        cmp     al, 92h         ;stupid keyb.com
        cmp     al, 92h         ;stupid keyb.com
        jne     short Exit
        jne     short Exit
kbfunc:
kbfunc:
        mov     al, 24h         ;AL=20h (fn 10h, 12h supported, set typematic supported)
        mov     al, 24h         ;AL=20h (fn 10h, 12h supported, set typematic supported)
Exit:
Exit:
        pop     si
        pop     si
        pop     ds
        pop     ds
        iret                    ; unknown function, Restores flags.
        iret                    ; unknown function, Restores flags.
GetKey1:                        ; wait for interrupt
GetKey1:                        ; wait for interrupt
        hlt
        hlt
GetKey: ; ----------- fn 00h, 10h
GetKey: ; ----------- fn 00h, 10h
        mov     ah, 11h
        mov     ah, 11h
        int     16h             ;See if key is available (IF becomes 1 after this int)
        int     16h             ;See if key is available (IF becomes 1 after this int)
        jz      short GetKey1   ;Wait for keystroke.
        jz      short GetKey1   ;Wait for keystroke.
        cli                     ;Critical region! Ints off.
        cli                     ;Critical region! Ints off.
        mov     si, HeadPtr     ;Ptr to next character.
        mov     si, HeadPtr     ;Ptr to next character.
        lodsw                   ;Get the character, Bump up HeadPtr
        lodsw                   ;Get the character, Bump up HeadPtr
        cmp     si, EndBuf
        cmp     si, EndBuf
        jb      short noWrap
        jb      short noWrap
        mov     si, Buffer
        mov     si, Buffer
noWrap:
noWrap:
        mov     HeadPtr, si
        mov     HeadPtr, si
        jmp     short Exit
        jmp     short Exit
TestKey: ; ---------- fn 01h
TestKey: ; ---------- fn 01h
        mov     si, HeadPtr
        mov     si, HeadPtr
        cmp     si, TailPtr     ;ZF=1, if empty buffer
        cmp     si, TailPtr     ;ZF=1, if empty buffer
        lodsw                   ;BIOS returns avail keycode.
        lodsw                   ;BIOS returns avail keycode.
        sti                     ;Ints back on.
        sti                     ;Ints back on.
        pop     si
        pop     si
        pop     ds
        pop     ds
        retf    2               ;Pop flags (ZF is important!)
        retf    2               ;Pop flags (ZF is important!)
StoreKey: ; ---------- fn 05h - Inserts the value in CX into the type ahead buffer.
StoreKey: ; ---------- fn 05h - Inserts the value in CX into the type ahead buffer.
        mov     si, TailPtr     ;Address where we can put next key code.
        mov     si, TailPtr     ;Address where we can put next key code.
        mov     [si], cx        ;Store the key code away
        mov     [si], cx        ;Store the key code away
        inc     si
        inc     si
        inc     si              ;Move on to next entry in buf
        inc     si              ;Move on to next entry in buf
        cmp     si, EndBuf
        cmp     si, EndBuf
        jb      short NoWrap1
        jb      short NoWrap1
        mov     si, Buffer
        mov     si, Buffer
 NoWrap1:
 NoWrap1:
        mov     al, 1           ;no room
        mov     al, 1           ;no room
        cmp     si, HeadPtr     ;Data overrun?
        cmp     si, HeadPtr     ;Data overrun?
        je      short Exit      ;if so, ignore key entry.
        je      short Exit      ;if so, ignore key entry.
        mov     TailPtr, si
        mov     TailPtr, si
        dec     ax              ;al=0
        dec     ax              ;al=0
        jmp     short Exit
        jmp     short Exit
ExtStatus: ; ------- fn 12h - Retrieve the extended keyboard status and return it in AH, and the standard keyboard status in AL.
ExtStatus: ; ------- fn 12h - Retrieve the extended keyboard status and return it in AH, and the standard keyboard status in AL.
        mov     al, KbdFlags2
        mov     al, KbdFlags2
        and     al, 01110111b   ;Clear final sysreq field, and final right alt bit.
        and     al, 01110111b   ;Clear final sysreq field, and final right alt bit.
        test    al, 100b        ;Test cur sysreq bit.
        test    al, 100b        ;Test cur sysreq bit.
        jz      short NoSysReq  ;Skip if it's zero.
        jz      short NoSysReq  ;Skip if it's zero.
        sub     al, 10000100b   ;Set final sysreq bit, clear final right ctl bit.
        sub     al, 10000100b   ;Set final sysreq bit, clear final right ctl bit.
NoSysReq:
NoSysReq:
        mov     ah, KbdFlags3
        mov     ah, KbdFlags3
        and     ah, 1100b       ;Grab rt alt/ctrl bits.
        and     ah, 1100b       ;Grab rt alt/ctrl bits.
        or      ah, al          ;Merge into AH.
        or      ah, al          ;Merge into AH.
GetStatus: ; --------- fn 02h
GetStatus: ; --------- fn 02h
        mov     al, KbdFlags1   ;Just return Std Status.
        mov     al, KbdFlags1   ;Just return Std Status.
Exit1:
Exit1:
        jmp     short Exit
        jmp     short Exit
SetAutoRpt: ; ------ fn 03h
SetAutoRpt: ; ------ fn 03h
        cmp     ah, 5
        cmp     ah, 5
        jne     short Exit
        jne     short Exit
        push    dx
        push    dx
        shl     bh, 5
        shl     bh, 5
        and     bl, 1fh
        and     bl, 1fh
        or      bl, bh
        or      bl, bh
        and     bl, 7fh
        and     bl, 7fh
        mov     ah, 0           ; wait LED update progress to finalize
        mov     ah, 0           ; wait LED update progress to finalize
        call    WaitFlag        ; leaves with IF=0
        call    WaitFlag        ; leaves with IF=0
        jc      short timeout
        jc      short timeout
        or      byte ptr KbdFlags4, SetRepeat    ; set auto repeat in progress
        or      byte ptr KbdFlags4, SetRepeat    ; set auto repeat in progress
        mov     ah, 0f3h        ; set typematic rate and delay
        mov     ah, 0f3h        ; set typematic rate and delay
        push    bx
        push    bx
        xor     bl, bl          ; send to kb
        xor     bl, bl          ; send to kb
        call    sendps2byte
        call    sendps2byte
        pop     bx
        pop     bx
        jc      short timeout1  ; send timeout
        jc      short timeout1  ; send timeout
        mov     ah, SetRepeat or AckReceived ; test if ACK received
        mov     ah, SetRepeat or AckReceived ; test if ACK received
        call    WaitFlag
        call    WaitFlag
        jc      short timeout1
        jc      short timeout1
        mov     ah, bl
        mov     ah, bl
        xor     bl, bl          ; send to kb
        xor     bl, bl          ; send to kb
        call    sendps2byte     ; send data
        call    sendps2byte     ; send data
timeout1:
timeout1:
        and     byte ptr KbdFlags4, not SetRepeat
        and     byte ptr KbdFlags4, not SetRepeat
timeout:
timeout:
        pop     dx
        pop     dx
        jmp     short Exit1
        jmp     short Exit1
WaitFlag:   ; ah = desired KbdFlags4 & (AckReceived | LEDUpdate | SetRepeat)
WaitFlag:   ; ah = desired KbdFlags4 & (AckReceived | LEDUpdate | SetRepeat)
        mov     dx, 3dah
        mov     dx, 3dah
        mov     bh, 8*25    ; wait for max 25 * VGA frame time
        mov     bh, 8*25    ; wait for max 25 * VGA frame time
wf_loop:
wf_loop:
        cli
        cli
        mov     al, KbdFlags4
        mov     al, KbdFlags4
        and     al, AckReceived or LEDUpdate or SetRepeat
        and     al, AckReceived or LEDUpdate or SetRepeat
        cmp     al, ah
        cmp     al, ah
        je      short wf_ok ; flag ok, CF=0
        je      short wf_ok ; flag ok, CF=0
        sti
        sti
        in      al, dx      ; get vblank
        in      al, dx      ; get vblank
        xor     al, bh
        xor     al, bh
        and     al, 8h
        and     al, 8h
        sub     bh, al
        sub     bh, al
        jnc     short wf_loop     ; IBF - buffer full, no timeout
        jnc     short wf_loop     ; IBF - buffer full, no timeout
wf_ok:
wf_ok:
        ret
        ret
int16 endp
int16 endp
; --------------------- INT 18h - BIOS Basic ------------------
; --------------------- INT 18h - BIOS Basic ------------------
int18 proc near
int18 proc near
        push    cs
        push    cs
        pop     es
        pop     es
        mov     si, offset booterrmsg
        mov     si, offset booterrmsg
        call    prts
        call    prts
;-------------- RS232 bootstrap
;-------------- RS232 bootstrap
        mov     al, 0b4h
        mov     al, 0b4h
        out     43h, al
        out     43h, al
        mov     ax, 0f000h
        mov     ax, 0f000h
        out     42h, al
        out     42h, al
        out     42h, al      ; 18Hz PIT CH2
        out     42h, al      ; 18Hz PIT CH2
          mov ds,ax
          mov ds,ax
          mov es,ax
          mov es,ax
        mov si,100h
        mov si,100h
          call srecb
          call srecb
        cli
        cli
          mov bh,ah
          mov bh,ah
          call srecb
          call srecb
          mov bl,ah
          mov bl,ah
sloop:
sloop:
          call srecb
          call srecb
          mov [si],ah
          mov [si],ah
          inc si
          inc si
          dec bx
          dec bx
          jnz short sloop
          jnz short sloop
          db 0eah
          db 0eah
        dw 100h,0f000h
        dw 100h,0f000h
booterrmsg db   'No boot device available, waiting on RS232 (115200bps, f000:100) ...', 13, 10, 0
booterrmsg db   'No boot device available, waiting on RS232 (115200bps, f000:100) ...', 13, 10, 0
int18 endp
int18 endp
; --------------------- INT 19h - OS Bootstrap loader ------------------
; --------------------- INT 19h - OS Bootstrap loader ------------------
int19 proc near
int19 proc near
        mov     ax, 201h
        mov     ax, 201h
        mov     cx, 1
        mov     cx, 1
        mov     dx, 80h
        mov     dx, 80h
        push    0
        push    0
        pop     es
        pop     es
        mov     bx, 7c00h
        mov     bx, 7c00h
        int     13h
        int     13h
        jc      int19err
        jc      int19err
        db      0eah
        db      0eah
        dw      7c00h, 0     ; jmp far 0000h:7c00h
        dw      7c00h, 0     ; jmp far 0000h:7c00h
int19err:
int19err:
        int     18h
        int     18h
int19 endp
int19 endp
; --------------------- INT 1ah - Get System Time ------------------
; --------------------- INT 1ah - Get System Time ------------------
int1a proc near
int1a proc near
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        cmp     ah, 1
        cmp     ah, 1
        je      setclock
 
        ja      clockexit
        ja      clockexit
 
        je      setclock
        mov     dx, ds:[6ch]    ; read clock
        mov     dx, ds:[6ch]    ; read clock
        mov     cx, ds:[6eh]
        mov     cx, ds:[6eh]
        mov     al, ds:[70h]
        mov     al, ds:[70h]
 
clockexit1:
 
        mov     byte ptr ds:[70h], 0
clockexit:
clockexit:
        cmc     ; CF = 1 on error
        cmc     ; CF = 1 on error
clockexit1:
 
        pop     ds
        pop     ds
        sti
        sti
        retf    2
        retf    2
setclock:
setclock:
        mov     ds:[6ch], dx
        mov     ds:[6ch], dx
        mov     ds:[6eh], cx
        mov     ds:[6eh], cx
        jmp     short clockexit1    ; CF = 0
        stc
 
        jmp     short clockexit1
int1a endp
int1a endp
; --------------------- INT 70h - RTC ------------------
; --------------------- INT 70h - RTC ------------------
int70 proc near
int70 proc near
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        test    byte ptr UWaitFlag, 1    ; is wait in progress?
        test    byte ptr UWaitFlag, 1    ; is wait in progress?
        jz      short exit
        jz      short exit
        sub     word ptr WaitCount[0], 1000
        sub     word ptr WaitCount[0], 1000
        sbb     word ptr WaitCount[2], 0
        sbb     word ptr WaitCount[2], 0
        jnc     short exit
        jnc     short exit
        mov     byte ptr UWaitFlag, 0
        mov     byte ptr UWaitFlag, 0
        push    bx
        push    bx
        lds     bx, UFPtr
        lds     bx, UFPtr
        or      byte ptr [bx], 80h
        or      byte ptr [bx], 80h
        pop     bx
        pop     bx
exit:
exit:
        pop     ds
        pop     ds
        iret
        iret
int70 endp
int70 endp
; --------------------- INT 74h - mouse ------------------
; --------------------- INT 74h - mouse ------------------
int74 proc near
int74 proc near
        cld
        cld
        pusha
        pusha
        push    ds
        push    ds
        push    40h
        push    40h
        pop     ds
        pop     ds
        mov     ah, 0
        mov     ah, 0
        in      al, 60h
        in      al, 60h
        mov     bx, ax
        mov     bx, ax
        inc     byte ptr DataCounter
        inc     byte ptr DataCounter
        mov     al, DataCounter
        mov     al, DataCounter
        mov     si, ax
        mov     si, ax
        sub     al, 3
        sub     al, 3
        ja      short docall
        ja      short docall
        mov     DataBuffer[si-1], bl
        mov     DataBuffer[si-1], bl
        cmp     al, PacketSize
        cmp     al, PacketSize
        jne     short nocall
        jne     short nocall
        mov     bl, 0
        mov     bl, 0
docall:
docall:
        mov     byte ptr DataCounter, bh    ; BH=0
        mov     byte ptr DataCounter, bh    ; BH=0
        mov     si, offset DataBuffer-2
        mov     si, offset DataBuffer-2
        lodsw
        lodsw
        or      ax, [si-4]
        or      ax, [si-4]
        jz      short nocall
        jz      short nocall
        sti
        sti
        push    es
        push    es
        mov     ah, 0
        mov     ah, 0
        lodsb
        lodsb
        push    ax
        push    ax
        lodsb
        lodsb
        push    ax
        push    ax
        lodsb
        lodsb
        push    ax
        push    ax
        push    bx
        push    bx
        call    far ptr [si-7]
        call    far ptr [si-7]
        add     sp, 8
        add     sp, 8
        pop     es
        pop     es
nocall:
nocall:
        pop     ds
        pop     ds
        popa
        popa
        iret
        iret
int74 endp
int74 endp
; ----------------  serial receive byte 115200 bps --------------
; ----------------  serial receive byte 115200 bps --------------
srecb:  mov     ah, 80h
srecb:  mov     ah, 80h
        mov     dx, 3dah
        mov     dx, 3dah
        mov     cx, -5aeh ; (half start bit)
        mov     cx, -5aeh ; (half start bit)
srstb:  in      al, dx
srstb:  in      al, dx
          shr     al, 2
          shr     al, 2
          jc      short srstb
          jc      short srstb
        in      al, 42h ; lo counter
        in      al, 42h ; lo counter
        add     ch, al
        add     ch, al
        in      al, 42h ; hi counter, ignore
        in      al, 42h ; hi counter, ignore
l1:
l1:
        call    dlybit
        call    dlybit
          in      al, dx
          in      al, dx
        shr     al, 2
        shr     al, 2
          rcr     ah, 1
          rcr     ah, 1
          jnc     short l1
          jnc     short l1
dlybit:
dlybit:
        sub     cx, 0a5bh  ;  (full bit)
        sub     cx, 0a5bh  ;  (full bit)
dly1:
dly1:
        in      al, 42h
        in      al, 42h
        cmp     al, ch
        cmp     al, ch
        in      al, 42h
        in      al, 42h
        jnz     short dly1
        jnz     short dly1
        ret
        ret
; -------------------- KB/Mouse access ----------------
; -------------------- KB/Mouse access ----------------
sendps2byte proc near   ; ah=data, bl!=0 for mouse, 0 for kb. returns cf=1 if timeout (al = 8)
sendps2byte proc near   ; ah=data, bl!=0 for mouse, 0 for kb. returns cf=1 if timeout (al = 8)
; changes BH, AL
; changes BH, AL
        push    dx
        push    dx
        mov     dx, 3dah
        mov     dx, 3dah
        mov     bh, 8*5
        mov     bh, 8*5
sps2b2:
sps2b2:
        in      al, 64h
        in      al, 64h
        test    al, 2
        test    al, 2
        jz      short sps2b1; buffer empty
        jz      short sps2b1; buffer empty
        in      al, dx      ; get vblank
        in      al, dx      ; get vblank
        xor     al, bh
        xor     al, bh
        and     al, 8h
        and     al, 8h
        sub     bh, al
        sub     bh, al
        jnc     short sps2b2; IBF - buffer full, no timeout
        jnc     short sps2b2; IBF - buffer full, no timeout
        jmp     short exit  ; timeout, CF=1
        jmp     short exit  ; timeout, CF=1
sps2b1:
sps2b1:
        test    bl, bl      ; CF=0
        test    bl, bl      ; CF=0
        jz      short sps2_kb
        jz      short sps2_kb
        mov     al, 0d4h    ; next mouse
        mov     al, 0d4h    ; next mouse
        out     64h, al
        out     64h, al
sps2_kb:
sps2_kb:
        mov     al, ah
        mov     al, ah
        out     60h, al     ; send byte
        out     60h, al     ; send byte
exit:
exit:
        pop     dx
        pop     dx
        ret
        ret
sendps2byte endp
sendps2byte endp
getps2byte proc near    ; returns al=data, zf=0 for mouse, 1 for kb, cf=1 if timeout (al=8)
getps2byte proc near    ; returns al=data, zf=0 for mouse, 1 for kb, cf=1 if timeout (al=8)
; changes BH, DX, AL
; changes BH, DX, AL
        mov     dx, 3dah
        mov     dx, 3dah
        mov     bh, 8*5
        mov     bh, 8*5
gps2b2:
gps2b2:
        in      al, 64h
        in      al, 64h
        test    al, 1
        test    al, 1
        jnz     short gps2b1     ; OBF (buffer full), continue
        jnz     short gps2b1     ; OBF (buffer full), continue
        in      al, dx     ; get vblank
        in      al, dx     ; get vblank
        xor     al, bh
        xor     al, bh
        and     al, 8
        and     al, 8
        sub     bh, al
        sub     bh, al
        jnc     short gps2b2     ; buffer empty, no timeout
        jnc     short gps2b2     ; buffer empty, no timeout
        ret                ; timeout, CF=1
        ret                ; timeout, CF=1
gps2b1:
gps2b1:
        test    al, 20h    ; CF=0, ZF <- !MOBF
        test    al, 20h    ; CF=0, ZF <- !MOBF
        in      al, 60h    ; read byte (if IF=1, this data may be invalid)
        in      al, 60h    ; read byte (if IF=1, this data may be invalid)
        ret
        ret
getps2byte endp
getps2byte endp
sendcmd proc near     ; ah = command, CF=1 for mouse, CF=0 for kb. returns CF=1 on error
sendcmd proc near     ; ah = command, CF=1 for mouse, CF=0 for kb. returns CF=1 on error
        sbb     bl, bl      ; bl <- CF
        sbb     bl, bl      ; bl <- CF
        call    sendps2byte
        call    sendps2byte
        jc      short exit
        jc      short exit
retry:
retry:
        call    getps2byte
        call    getps2byte
        jc      short exit
        jc      short exit
        cmp     al, 0fah    ; ack (returns CF=1 on error, when al=8)
        cmp     al, 0fah    ; ack (returns CF=1 on error, when al=8)
        jne     short retry
        jne     short retry
exit:
exit:
        ret
        ret
sendcmd endp
sendcmd endp
enableKbIfPresent proc near ; input DS = 40h
enableKbIfPresent proc near ; input DS = 40h
; modify AL, flags
; modify AL, flags
        test    byte ptr KbdFlags3, 10h
        test    byte ptr KbdFlags3, 10h
        jz      short noenablekb
        jz      short noenablekb
        mov     al, 0aeh
        mov     al, 0aeh
        out     64h, al     ; enable kb interface
        out     64h, al     ; enable kb interface
noenablekb:
noenablekb:
        ret
        ret
enableKbIfPresent endp
enableKbIfPresent endp
; ----------------------- default interrupt handler ---------------
; ----------------------- default interrupt handler ---------------
defint  proc near
defint  proc near
        iret
        iret
defint  endp
defint  endp
; ------------------------------- flush --------------------------
; ------------------------------- flush --------------------------
flush:
flush:
        pop     cs:flushret
        pop     cs:flushret
flush_nostack:
flush_nostack:
        mov     cs:flushbh, bh
        mov     cs:flushbh, bh
        mov     bh, 7       ; flush all 7 cache lines (the 8th one is CS:IP)
        mov     bh, 7       ; flush all 7 cache lines (the 8th one is CS:IP)
flush1:
flush1:
        test    bl, cs:[bx + 0e000h]
        test    bl, cs:[bx + 0e000h]
        dec     bh
        dec     bh
        jnz     short flush1
        jnz     short flush1
        mov     bh, cs:flushbh
        mov     bh, cs:flushbh
        jmp     word ptr cs:flushret
        jmp     word ptr cs:flushret
flushret dw 0
flushret dw 0
flushbh  db 0
flushbh  db 0
; ------------------------------- misc --------------------------
; ------------------------------- misc --------------------------
dispAX:
dispAX:
        push    dx
        push    dx
        xor     dx, dx
        xor     dx, dx
        div     word ptr cs:ten
        div     word ptr cs:ten
        test    ax, ax
        test    ax, ax
        jz      dispAX1
        jz      dispAX1
        call    dispAX
        call    dispAX
dispAX1:
dispAX1:
        xchg    ax, dx
        xchg    ax, dx
        add     ax, 0e00h + '0'
        add     ax, 0e00h + '0'
        int     10h
        int     10h
        pop     dx
        pop     dx
        ret
        ret
ten     dw      10
ten     dw      10
prts:   ; es:si = string
prts:   ; es:si = string
        mov     ah, 0eh
        mov     ah, 0eh
        lodsb   es:[si]
        lodsb   es:[si]
        or      al, al
        or      al, al
        jz      short prtse
        jz      short prtse
        int     10h
        int     10h
        jmp     short prts
        jmp     short prts
prtse:
prtse:
        ret
        ret
;---------------------  read/write byte ----------------------
;---------------------  read/write byte ----------------------
sdrb:   mov al,0ffh
sdrb:   mov al,0ffh
sdsb:               ; in AL=byte, DX = 03dah, out AX=result
sdsb:               ; in AL=byte, DX = 03dah, out AX=result
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        in      ax, dx
        in      ax, dx
        ret
        ret
;---------------------  write block ----------------------
;---------------------  write block ----------------------
sdwblk proc near              ; in SI=data ptr, DX=03dah, CX=size
sdwblk proc near              ; in SI=data ptr, DX=03dah, CX=size
        shr     cx, 1
        shr     cx, 1
sdwblk1:
sdwblk1:
        lodsb
        lodsb
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        lodsb
        lodsb
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        add     ax, ax
        add     ax, ax
        out     dx, al
        out     dx, al
        loop    short sdwblk1
        loop    short sdwblk1
        ret
        ret
sdwblk endp
sdwblk endp
;---------------------  read block ----------------------
;---------------------  read block ----------------------
sdrblk proc near              ; in DI=data ptr, DX=03dah, CX=size. Returns CF = 0
sdrblk proc near              ; in DI=data ptr, DX=03dah, CX=size. Returns CF = 0
        mov     al, 0ffh
        mov     al, 0ffh
        out     dx, al
        out     dx, al
        shr     cx, 1         ; CF = 0
        shr     cx, 1         ; CF = 0
        out     dx, al
        out     dx, al
        jmp     short sdrblk2
        jmp     short sdrblk2
sdrblk1:
sdrblk1:
        out     dx, al
        out     dx, al
        mov     [di], ah
        mov     [di], ah
        out     dx, al
        out     dx, al
        inc     di
        inc     di
sdrblk2:
sdrblk2:
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        in      ax, dx
        in      ax, dx
        out     dx, al
        out     dx, al
        mov     [di], ah
        mov     [di], ah
        out     dx, al
        out     dx, al
        inc     di
        inc     di
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        nop
        nop
        out     dx, al
        out     dx, al
        in      ax, dx
        in      ax, dx
        loop    short sdrblk1
        loop    short sdrblk1
        mov     [di], ah
        mov     [di], ah
        inc     di
        inc     di
        ret
        ret
sdrblk endp
sdrblk endp
;---------------------  verify block ----------------------
;---------------------  verify block ----------------------
sdvblk:              ; in DI=data ptr, DX=03dah, CX=size. Returns CF=1 on error
sdvblk:              ; in DI=data ptr, DX=03dah, CX=size. Returns CF=1 on error
        push    bx
        push    bx
        xor     bl, bl
        xor     bl, bl
sdvblk1:
sdvblk1:
        call    sdrb
        call    sdrb
        sub     ah, [di]
        sub     ah, [di]
        or      bl, ah
        or      bl, ah
        inc     di
        inc     di
        loop    short sdvblk1
        loop    short sdvblk1
        neg     bl  ; CF=1 if BL != 0
        neg     bl  ; CF=1 if BL != 0
        pop     bx
        pop     bx
        ret
        ret
;---------------------  write command ----------------------
;---------------------  write command ----------------------
sdcmd8T:
sdcmd8T:
        call    sdrb
        call    sdrb
sdcmd:              ; in SI=6 bytes cmd buffer, DX=03dah, out AH = 0ffh on error
sdcmd:              ; in SI=6 bytes cmd buffer, DX=03dah, out AH = 0ffh on error
        mov     cx, 6
        mov     cx, 6
        call    sdwblk
        call    sdwblk
sdresp:
sdresp:
        xor     si, si
        xor     si, si
sdresp1:
sdresp1:
        call    sdrb
        call    sdrb
        inc     si
        inc     si
        jz      short sdcmd1
        jz      short sdcmd1
        cmp     ah, 0ffh
        cmp     ah, 0ffh
        je      short sdresp1
        je      short sdresp1
sdcmd1: ret
sdcmd1: ret
;---------------------  read ----------------------
;---------------------  read ----------------------
sdverify:
sdverify:
        push    sdvblk
        push    sdvblk
        jmp     short sdread1
        jmp     short sdread1
sdread:   ; DX:AX sector, ES:BX buffer, CX=sectors. returns AX=read sectors
sdread:   ; DX:AX sector, ES:BX buffer, CX=sectors. returns AX=read sectors
        push    sdrblk   ; push proc address (read or verify) on stack
        push    sdrblk   ; push proc address (read or verify) on stack
sdread1:
sdread1:
        push    ax
        push    ax
        mov     al, dl
        mov     al, dl
        push    ax
        push    ax
        mov     dl, 51h  ; CMD17
        mov     dl, 51h  ; CMD17
        cmp     cx, 1
        cmp     cx, 1
        je      short sdr1s
        je      short sdr1s
        inc     dx      ; CMD18 - multiple sectors
        inc     dx      ; CMD18 - multiple sectors
sdr1s:
sdr1s:
        push    dx
        push    dx
        mov     si, sp
        mov     si, sp
        mov     dx, 3dah
        mov     dx, 3dah
        mov     ah, 1
        mov     ah, 1
        out     dx, ax       ; CS on
        out     dx, ax       ; CS on
        mov     di, bx
        mov     di, bx
        mov     bx, cx
        mov     bx, cx
        mov     bp, cx       ; save sectors number
        mov     bp, cx       ; save sectors number
        push    ss
        push    ss
        pop     ds
        pop     ds
        call    sdcmd
        call    sdcmd
        add     sp, 6
        add     sp, 6
        or      ah, ah
        or      ah, ah
        jnz     short sdr11   ; error
        jnz     short sdr11   ; error
        push    es
        push    es
        pop     ds
        pop     ds
sdrms:
sdrms:
        mov     ax, di
        mov     ax, di
        shr     ax, 4
        shr     ax, 4
        mov     si, ds
        mov     si, ds
        add     ax, si
        add     ax, si
        mov     ds, ax
        mov     ds, ax
        and     di, 15
        and     di, 15
        call    sdresp     ; wait for 0feh token
        call    sdresp     ; wait for 0feh token
        cmp     ah, 0feh
        cmp     ah, 0feh
        jne     short sdr11; read token error
        jne     short sdr11; read token error
        mov     ch, 2      ; 512 byte sector
        mov     ch, 2      ; 512 byte sector
        pop     si
        pop     si
        call    si         ; sdrblk or sdvblk
        call    si         ; sdrblk or sdvblk
        push    si
        push    si
        pushf
        pushf
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        popf
        popf
        jc      short sdr3 ; verify error
        jc      short sdr3 ; verify error
        dec     bx
        dec     bx
        jnz     short sdrms; multiple sectors
        jnz     short sdrms; multiple sectors
sdr3:
sdr3:
        cmp     bp, 1
        cmp     bp, 1
        je      short sdr11; single sector
        je      short sdr11; single sector
        mov     si, offset SD_CMD12 ; stop transfer
        mov     si, offset SD_CMD12 ; stop transfer
        push    cs
        push    cs
        pop     ds
        pop     ds
        call    sdcmd
        call    sdcmd
sdr2:
sdr2:
        shr     ah, 1
        shr     ah, 1
        jnc     short sdr11
        jnc     short sdr11
        call    sdrb
        call    sdrb
        jmp     short sdr2
        jmp     short sdr2
sdr11:
sdr11:
        pop     ax         ; remove proc address from stack
        pop     ax         ; remove proc address from stack
sdr1:
sdr1:
        xor     ax, ax
        xor     ax, ax
        out     dx, ax
        out     dx, ax
        call    sdrb       ; 8T
        call    sdrb       ; 8T
        mov     ax, bp
        mov     ax, bp
        sub     ax, bx
        sub     ax, bx
        ret
        ret
;---------------------  write ----------------------
;---------------------  write ----------------------
sdwrite:   ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=wrote sectors
sdwrite:   ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=wrote sectors
        push    ax
        push    ax
        mov     al, dl
        mov     al, dl
        push    ax
        push    ax
        mov     dl, 58h  ; CMD24
        mov     dl, 58h  ; CMD24
        cmp     cx, 1
        cmp     cx, 1
        je      short sdw1s
        je      short sdw1s
        inc     dx      ; CMD25 - multiple sectors
        inc     dx      ; CMD25 - multiple sectors
sdw1s:
sdw1s:
        push    dx
        push    dx
        mov     si, sp
        mov     si, sp
        mov     dx, 3dah
        mov     dx, 3dah
        mov     ah, 1
        mov     ah, 1
        out     dx, ax       ; CS on
        out     dx, ax       ; CS on
        mov     bp, cx       ; save sectors number
        mov     bp, cx       ; save sectors number
        push    ss
        push    ss
        pop     ds
        pop     ds
        call    sdcmd
        call    sdcmd
        add     sp, 6
        add     sp, 6
        mov     si, bx
        mov     si, bx
        mov     bx, bp
        mov     bx, bp
        or      ah, ah
        or      ah, ah
        jnz     short sdr1   ; error
        jnz     short sdr1   ; error
        push    es
        push    es
        pop     ds
        pop     ds
sdwms:
sdwms:
        mov     ax, si
        mov     ax, si
        shr     ax, 4
        shr     ax, 4
        mov     di, ds
        mov     di, ds
        add     ax, di
        add     ax, di
        mov     ds, ax
        mov     ds, ax
        and     si, 15
        and     si, 15
        mov     al, 0feh      ; start token
        mov     al, 0feh      ; start token
        cmp     bp, 1
        cmp     bp, 1
        je      short sdw1s1
        je      short sdw1s1
        mov     al, 0fch   ; multiple sectors
        mov     al, 0fch   ; multiple sectors
sdw1s1:
sdw1s1:
        call    sdsb
        call    sdsb
        mov     ch, 2      ; 512 byte sector
        mov     ch, 2      ; 512 byte sector
        call    sdwblk
        call    sdwblk
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        call    sdrb       ; ignore CRC
        call    sdrb       ; read response byte xxx00101
        call    sdrb       ; read response byte xxx00101
        and     ah, 0eh
        and     ah, 0eh
        cmp     ah, 4
        cmp     ah, 4
        jne     short sdr1 ; write error
        jne     short sdr1 ; write error
sdwwait:
sdwwait:
        call    sdrb
        call    sdrb
        shr     ah, 1
        shr     ah, 1
        jnc     short sdwwait     ; wait write completion
        jnc     short sdwwait     ; wait write completion
        dec     bx
        dec     bx
        jnz     short sdwms       ; multiple sectors
        jnz     short sdwms       ; multiple sectors
        cmp     bp, 1
        cmp     bp, 1
        je      short sdr1
        je      short sdr1
        mov     al, 0fdh     ; multiple end transfer
        mov     al, 0fdh     ; multiple end transfer
        call    sdsb
        call    sdsb
sdwwait1:
sdwwait1:
        call    sdrb
        call    sdrb
        shr     ah, 1
        shr     ah, 1
        jnc     short sdwwait1     ; wait write completion
        jnc     short sdwwait1     ; wait write completion
        jmp     sdr1
        jmp     sdr1
;---------------------  init SD ----------------------
;---------------------  init SD ----------------------
sdinit  proc near       ; returns AX = num kilosectors
sdinit  proc near       ; returns AX = num kilosectors
        push    ds
        push    ds
        push    cx
        push    cx
        push    dx
        push    dx
        push    si
        push    si
        push    di
        push    di
        mov     dx, 3dah
        mov     dx, 3dah
        mov     cx, 10
        mov     cx, 10
sdinit1:                   ; send 80T
sdinit1:                   ; send 80T
        call    sdrb
        call    sdrb
        loop    short sdinit1
        loop    short sdinit1
        mov     ah, 1
        mov     ah, 1
        out     dx, ax       ; select SD
        out     dx, ax       ; select SD
        mov     si, offset SD_CMD0
        mov     si, offset SD_CMD0
        push    cs
        push    cs
        pop     ds
        pop     ds
        call    sdcmd
        call    sdcmd
        dec     ah
        dec     ah
        jnz     short sdexit ; error
        jnz     short sdexit ; error
        mov     si, offset SD_CMD8
        mov     si, offset SD_CMD8
        call    sdcmd8T
        call    sdcmd8T
        dec     ah
        dec     ah
        jnz     short sdexit ; error
        jnz     short sdexit ; error
        mov     cl, 4
        mov     cl, 4
        sub     sp, cx
        sub     sp, cx
        mov     di, sp
        mov     di, sp
        push    ss
        push    ss
        pop     ds
        pop     ds
        call    sdrblk
        call    sdrblk
        pop     ax
        pop     ax
        pop     ax
        pop     ax
        cmp     ah, 0aah
        cmp     ah, 0aah
        jne     short sdexit ; CMD8 error
        jne     short sdexit ; CMD8 error
repinit:
repinit:
        mov     si, offset SD_CMD55
        mov     si, offset SD_CMD55
        push    cs
        push    cs
        pop     ds
        pop     ds
        call    sdcmd8T
        call    sdcmd8T
        call    sdrb
        call    sdrb
        mov     si, offset SD_CMD41
        mov     si, offset SD_CMD41
        call    sdcmd
        call    sdcmd
        dec     ah
        dec     ah
        jz      short repinit
        jz      short repinit
        mov     si, offset SD_CMD58
        mov     si, offset SD_CMD58
        call    sdcmd8T
        call    sdcmd8T
        mov     cl, 4
        mov     cl, 4
        sub     sp, cx
        sub     sp, cx
        mov     di, sp
        mov     di, sp
        push    ss
        push    ss
        pop     ds
        pop     ds
        call    sdrblk
        call    sdrblk
        pop     ax
        pop     ax
        test    al, 40h     ; test OCR bit 30 (CCS)
        test    al, 40h     ; test OCR bit 30 (CCS)
        pop     ax
        pop     ax
        jz      short sdexit; no SDHC
        jz      short sdexit; no SDHC
        mov     si, offset SD_CMD9 ; get size info
        mov     si, offset SD_CMD9 ; get size info
        push    cs
        push    cs
        pop     ds
        pop     ds
        call    sdcmd8T
        call    sdcmd8T
        or      ah, ah
        or      ah, ah
        jnz     short sdexit
        jnz     short sdexit
        call    sdresp     ; wait for 0feh token
        call    sdresp     ; wait for 0feh token
        cmp     ah, 0feh
        cmp     ah, 0feh
        jne     short sdexit
        jne     short sdexit
        mov     cl, 18       ; 16bytes + 2bytes CRC
        mov     cl, 18       ; 16bytes + 2bytes CRC
        sub     sp, cx
        sub     sp, cx
        mov     di, sp
        mov     di, sp
        push    ss
        push    ss
        pop     ds
        pop     ds
        call    sdrblk
        call    sdrblk
        mov     cx, [di-10]
        mov     cx, [di-10]
        rol     cx, 8
        rol     cx, 8
        inc     cx
        inc     cx
        mov     sp, di
        mov     sp, di
sdexit:
sdexit:
        xor     ax, ax       ; raise CS
        xor     ax, ax       ; raise CS
        out     dx, ax
        out     dx, ax
        call    sdrb
        call    sdrb
        pop     di
        pop     di
        pop     si
        pop     si
        pop     dx
        pop     dx
        mov     ax, cx
        mov     ax, cx
        pop     cx
        pop     cx
        pop     ds
        pop     ds
        ret
        ret
sdinit endp
sdinit endp
SD_CMD0     db  40h, 0, 0, 0, 0, 95h
SD_CMD0     db  40h, 0, 0, 0, 0, 95h
SD_CMD8     db  48h, 0, 0, 1, 0aah, 087h
SD_CMD8     db  48h, 0, 0, 1, 0aah, 087h
SD_CMD9     db  49h, 0, 0, 0, 0, 0ffh
SD_CMD9     db  49h, 0, 0, 0, 0, 0ffh
SD_CMD12    db  4ch, 0, 0, 0, 0, 0ffh
SD_CMD12    db  4ch, 0, 0, 0, 0, 0ffh
SD_CMD41    db  69h, 40h, 0, 0, 0, 0ffh
SD_CMD41    db  69h, 40h, 0, 0, 0, 0ffh
SD_CMD55    db  77h, 0, 0, 0, 0, 0ffh
SD_CMD55    db  77h, 0, 0, 0, 0, 0ffh
SD_CMD58    db  7ah, 0, 0, 0, 0, 0ffh
SD_CMD58    db  7ah, 0, 0, 0, 0, 0ffh
default_pal:
default_pal:
        db  00h,00h,00h, 00h,00h,2ah, 00h,2ah,00h, 00h,2ah,2ah, 2ah,00h,00h, 2ah,00h,2ah, 2ah,15h,00h, 2ah,2ah,2ah
        db  00h,00h,00h, 00h,00h,2ah, 00h,2ah,00h, 00h,2ah,2ah, 2ah,00h,00h, 2ah,00h,2ah, 2ah,15h,00h, 2ah,2ah,2ah
        db  15h,15h,15h, 15h,15h,3fh, 15h,3fh,15h, 15h,3fh,3fh, 3fh,15h,15h, 3fh,15h,3fh, 3fh,3fh,15h, 3fh,3fh,3fh
        db  15h,15h,15h, 15h,15h,3fh, 15h,3fh,15h, 15h,3fh,3fh, 3fh,15h,15h, 3fh,15h,3fh, 3fh,3fh,15h, 3fh,3fh,3fh
        db  00h,00h,00h, 05h,05h,05h, 08h,08h,08h, 0bh,0bh,0bh, 0eh,0eh,0eh, 11h,11h,11h, 14h,14h,14h, 18h,18h,18h
        db  00h,00h,00h, 05h,05h,05h, 08h,08h,08h, 0bh,0bh,0bh, 0eh,0eh,0eh, 11h,11h,11h, 14h,14h,14h, 18h,18h,18h
        db  1ch,1ch,1ch, 20h,20h,20h, 24h,24h,24h, 28h,28h,28h, 2dh,2dh,2dh, 32h,32h,32h, 38h,38h,38h, 3fh,3fh,3fh
        db  1ch,1ch,1ch, 20h,20h,20h, 24h,24h,24h, 28h,28h,28h, 2dh,2dh,2dh, 32h,32h,32h, 38h,38h,38h, 3fh,3fh,3fh
        db  00h,00h,3fh, 10h,00h,3fh, 1fh,00h,3fh, 2fh,00h,3fh, 3fh,00h,3fh, 3fh,00h,2fh, 3fh,00h,1fh, 3fh,00h,10h
        db  00h,00h,3fh, 10h,00h,3fh, 1fh,00h,3fh, 2fh,00h,3fh, 3fh,00h,3fh, 3fh,00h,2fh, 3fh,00h,1fh, 3fh,00h,10h
        db  3fh,00h,00h, 3fh,10h,00h, 3fh,1fh,00h, 3fh,2fh,00h, 3fh,3fh,00h, 2fh,3fh,00h, 1fh,3fh,00h, 10h,3fh,00h
        db  3fh,00h,00h, 3fh,10h,00h, 3fh,1fh,00h, 3fh,2fh,00h, 3fh,3fh,00h, 2fh,3fh,00h, 1fh,3fh,00h, 10h,3fh,00h
        db  00h,3fh,00h, 00h,3fh,10h, 00h,3fh,1fh, 00h,3fh,2fh, 00h,3fh,3fh, 00h,2fh,3fh, 00h,1fh,3fh, 00h,10h,3fh
        db  00h,3fh,00h, 00h,3fh,10h, 00h,3fh,1fh, 00h,3fh,2fh, 00h,3fh,3fh, 00h,2fh,3fh, 00h,1fh,3fh, 00h,10h,3fh
        db  1fh,1fh,3fh, 27h,1fh,3fh, 2fh,1fh,3fh, 37h,1fh,3fh, 3fh,1fh,3fh, 3fh,1fh,37h, 3fh,1fh,2fh, 3fh,1fh,27h
        db  1fh,1fh,3fh, 27h,1fh,3fh, 2fh,1fh,3fh, 37h,1fh,3fh, 3fh,1fh,3fh, 3fh,1fh,37h, 3fh,1fh,2fh, 3fh,1fh,27h
        db  3fh,1fh,1fh, 3fh,27h,1fh, 3fh,2fh,1fh, 3fh,37h,1fh, 3fh,3fh,1fh, 37h,3fh,1fh, 2fh,3fh,1fh, 27h,3fh,1fh
        db  3fh,1fh,1fh, 3fh,27h,1fh, 3fh,2fh,1fh, 3fh,37h,1fh, 3fh,3fh,1fh, 37h,3fh,1fh, 2fh,3fh,1fh, 27h,3fh,1fh
        db  1fh,3fh,1fh, 1fh,3fh,27h, 1fh,3fh,2fh, 1fh,3fh,37h, 1fh,3fh,3fh, 1fh,37h,3fh, 1fh,2fh,3fh, 1fh,27h,3fh
        db  1fh,3fh,1fh, 1fh,3fh,27h, 1fh,3fh,2fh, 1fh,3fh,37h, 1fh,3fh,3fh, 1fh,37h,3fh, 1fh,2fh,3fh, 1fh,27h,3fh
        db  2dh,2dh,3fh, 31h,2dh,3fh, 36h,2dh,3fh, 3ah,2dh,3fh, 3fh,2dh,3fh, 3fh,2dh,3ah, 3fh,2dh,36h, 3fh,2dh,31h
        db  2dh,2dh,3fh, 31h,2dh,3fh, 36h,2dh,3fh, 3ah,2dh,3fh, 3fh,2dh,3fh, 3fh,2dh,3ah, 3fh,2dh,36h, 3fh,2dh,31h
        db  3fh,2dh,2dh, 3fh,31h,2dh, 3fh,36h,2dh, 3fh,3ah,2dh, 3fh,3fh,2dh, 3ah,3fh,2dh, 36h,3fh,2dh, 31h,3fh,2dh
        db  3fh,2dh,2dh, 3fh,31h,2dh, 3fh,36h,2dh, 3fh,3ah,2dh, 3fh,3fh,2dh, 3ah,3fh,2dh, 36h,3fh,2dh, 31h,3fh,2dh
        db  2dh,3fh,2dh, 2dh,3fh,31h, 2dh,3fh,36h, 2dh,3fh,3ah, 2dh,3fh,3fh, 2dh,3ah,3fh, 2dh,36h,3fh, 2dh,31h,3fh
        db  2dh,3fh,2dh, 2dh,3fh,31h, 2dh,3fh,36h, 2dh,3fh,3ah, 2dh,3fh,3fh, 2dh,3ah,3fh, 2dh,36h,3fh, 2dh,31h,3fh
        db  00h,00h,1ch, 07h,00h,1ch, 0eh,00h,1ch, 15h,00h,1ch, 1ch,00h,1ch, 1ch,00h,15h, 1ch,00h,0eh, 1ch,00h,07h
        db  00h,00h,1ch, 07h,00h,1ch, 0eh,00h,1ch, 15h,00h,1ch, 1ch,00h,1ch, 1ch,00h,15h, 1ch,00h,0eh, 1ch,00h,07h
        db  1ch,00h,00h, 1ch,07h,00h, 1ch,0eh,00h, 1ch,15h,00h, 1ch,1ch,00h, 15h,1ch,00h, 0eh,1ch,00h, 07h,1ch,00h
        db  1ch,00h,00h, 1ch,07h,00h, 1ch,0eh,00h, 1ch,15h,00h, 1ch,1ch,00h, 15h,1ch,00h, 0eh,1ch,00h, 07h,1ch,00h
        db  00h,1ch,00h, 00h,1ch,07h, 00h,1ch,0eh, 00h,1ch,15h, 00h,1ch,1ch, 00h,15h,1ch, 00h,0eh,1ch, 00h,07h,1ch
        db  00h,1ch,00h, 00h,1ch,07h, 00h,1ch,0eh, 00h,1ch,15h, 00h,1ch,1ch, 00h,15h,1ch, 00h,0eh,1ch, 00h,07h,1ch
        db  0eh,0eh,1ch, 11h,0eh,1ch, 15h,0eh,1ch, 18h,0eh,1ch, 1ch,0eh,1ch, 1ch,0eh,18h, 1ch,0eh,15h, 1ch,0eh,11h
        db  0eh,0eh,1ch, 11h,0eh,1ch, 15h,0eh,1ch, 18h,0eh,1ch, 1ch,0eh,1ch, 1ch,0eh,18h, 1ch,0eh,15h, 1ch,0eh,11h
        db  1ch,0eh,0eh, 1ch,11h,0eh, 1ch,15h,0eh, 1ch,18h,0eh, 1ch,1ch,0eh, 18h,1ch,0eh, 15h,1ch,0eh, 11h,1ch,0eh
        db  1ch,0eh,0eh, 1ch,11h,0eh, 1ch,15h,0eh, 1ch,18h,0eh, 1ch,1ch,0eh, 18h,1ch,0eh, 15h,1ch,0eh, 11h,1ch,0eh
        db  0eh,1ch,0eh, 0eh,1ch,11h, 0eh,1ch,15h, 0eh,1ch,18h, 0eh,1ch,1ch, 0eh,18h,1ch, 0eh,15h,1ch, 0eh,11h,1ch
        db  0eh,1ch,0eh, 0eh,1ch,11h, 0eh,1ch,15h, 0eh,1ch,18h, 0eh,1ch,1ch, 0eh,18h,1ch, 0eh,15h,1ch, 0eh,11h,1ch
        db  14h,14h,1ch, 16h,14h,1ch, 18h,14h,1ch, 1ah,14h,1ch, 1ch,14h,1ch, 1ch,14h,1ah, 1ch,14h,18h, 1ch,14h,16h
        db  14h,14h,1ch, 16h,14h,1ch, 18h,14h,1ch, 1ah,14h,1ch, 1ch,14h,1ch, 1ch,14h,1ah, 1ch,14h,18h, 1ch,14h,16h
        db  1ch,14h,14h, 1ch,16h,14h, 1ch,18h,14h, 1ch,1ah,14h, 1ch,1ch,14h, 1ah,1ch,14h, 18h,1ch,14h, 16h,1ch,14h
        db  1ch,14h,14h, 1ch,16h,14h, 1ch,18h,14h, 1ch,1ah,14h, 1ch,1ch,14h, 1ah,1ch,14h, 18h,1ch,14h, 16h,1ch,14h
        db  14h,1ch,14h, 14h,1ch,16h, 14h,1ch,18h, 14h,1ch,1ah, 14h,1ch,1ch, 14h,1ah,1ch, 14h,18h,1ch, 14h,16h,1ch
        db  14h,1ch,14h, 14h,1ch,16h, 14h,1ch,18h, 14h,1ch,1ah, 14h,1ch,1ch, 14h,1ah,1ch, 14h,18h,1ch, 14h,16h,1ch
        db  00h,00h,10h, 04h,00h,10h, 08h,00h,10h, 0ch,00h,10h, 10h,00h,10h, 10h,00h,0ch, 10h,00h,08h, 10h,00h,04h
        db  00h,00h,10h, 04h,00h,10h, 08h,00h,10h, 0ch,00h,10h, 10h,00h,10h, 10h,00h,0ch, 10h,00h,08h, 10h,00h,04h
        db  10h,00h,00h, 10h,04h,00h, 10h,08h,00h, 10h,0ch,00h, 10h,10h,00h, 0ch,10h,00h, 08h,10h,00h, 04h,10h,00h
        db  10h,00h,00h, 10h,04h,00h, 10h,08h,00h, 10h,0ch,00h, 10h,10h,00h, 0ch,10h,00h, 08h,10h,00h, 04h,10h,00h
        db  00h,10h,00h, 00h,10h,04h, 00h,10h,08h, 00h,10h,0ch, 00h,10h,10h, 00h,0ch,10h, 00h,08h,10h, 00h,04h,10h
        db  00h,10h,00h, 00h,10h,04h, 00h,10h,08h, 00h,10h,0ch, 00h,10h,10h, 00h,0ch,10h, 00h,08h,10h, 00h,04h,10h
        db  08h,08h,10h, 0ah,08h,10h, 0ch,08h,10h, 0eh,08h,10h, 10h,08h,10h, 10h,08h,0eh, 10h,08h,0ch, 10h,08h,0ah
        db  08h,08h,10h, 0ah,08h,10h, 0ch,08h,10h, 0eh,08h,10h, 10h,08h,10h, 10h,08h,0eh, 10h,08h,0ch, 10h,08h,0ah
        db  10h,08h,08h, 10h,0ah,08h, 10h,0ch,08h, 10h,0eh,08h, 10h,10h,08h, 0eh,10h,08h, 0ch,10h,08h, 0ah,10h,08h
        db  10h,08h,08h, 10h,0ah,08h, 10h,0ch,08h, 10h,0eh,08h, 10h,10h,08h, 0eh,10h,08h, 0ch,10h,08h, 0ah,10h,08h
        db  08h,10h,08h, 08h,10h,0ah, 08h,10h,0ch, 08h,10h,0eh, 08h,10h,10h, 08h,0eh,10h, 08h,0ch,10h, 08h,0ah,10h
        db  08h,10h,08h, 08h,10h,0ah, 08h,10h,0ch, 08h,10h,0eh, 08h,10h,10h, 08h,0eh,10h, 08h,0ch,10h, 08h,0ah,10h
        db  0bh,0bh,10h, 0ch,0bh,10h, 0dh,0bh,10h, 0fh,0bh,10h, 10h,0bh,10h, 10h,0bh,0fh, 10h,0bh,0dh, 10h,0bh,0ch
        db  0bh,0bh,10h, 0ch,0bh,10h, 0dh,0bh,10h, 0fh,0bh,10h, 10h,0bh,10h, 10h,0bh,0fh, 10h,0bh,0dh, 10h,0bh,0ch
        db  10h,0bh,0bh, 10h,0ch,0bh, 10h,0dh,0bh, 10h,0fh,0bh, 10h,10h,0bh, 0fh,10h,0bh, 0dh,10h,0bh, 0ch,10h,0bh
        db  10h,0bh,0bh, 10h,0ch,0bh, 10h,0dh,0bh, 10h,0fh,0bh, 10h,10h,0bh, 0fh,10h,0bh, 0dh,10h,0bh, 0ch,10h,0bh
        db  0bh,10h,0bh, 0bh,10h,0ch, 0bh,10h,0dh, 0bh,10h,0fh, 0bh,10h,10h, 0bh,0fh,10h, 0bh,0dh,10h, 0bh,0ch,10h
        db  0bh,10h,0bh, 0bh,10h,0ch, 0bh,10h,0dh, 0bh,10h,0fh, 0bh,10h,10h, 0bh,0fh,10h, 0bh,0dh,10h, 0bh,0ch,10h
        db  00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h
        db  00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h
IFDEF SCANCODE1 ; use SCANCODE1
IFDEF SCANCODE1 ; use SCANCODE1
KeyIndex:
KeyIndex:
        db      0, 82, 49, 50, 52, 51, 54, 55    ;0-7
        db      0, 82, 49, 50, 52, 51, 54, 55    ;0-7
        db 56, 57, 60, 59, 65, 68, 72, 47    ;8-f
        db 56, 57, 60, 59, 65, 68, 72, 47    ;8-f
        db      1,  5,  9, 13, 12, 18, 21, 23    ;10-17
        db      1,  5,  9, 13, 12, 18, 21, 23    ;10-17
        db 24, 26, 67, 70, 69,  0,  4,  3    ;18-1f
        db 24, 26, 67, 70, 69,  0,  4,  3    ;18-1f
        db      8, 11, 17, 16, 20, 22, 25, 64    ;20-27
        db      8, 11, 17, 16, 20, 22, 25, 64    ;20-27
        db 66, 48,  0, 71,  2,  7,  6, 10    ;28-2f
        db 66, 48,  0, 71,  2,  7,  6, 10    ;28-2f
        db 15, 14, 19, 58, 61, 62,  0, 87    ;30-37
        db 15, 14, 19, 58, 61, 62,  0, 87    ;30-37
        db      0, 53,  0, 40, 41, 39, 46, 38    ;38-3f
        db      0, 53,  0, 40, 41, 39, 46, 38    ;38-3f
        db 45, 90, 44, 79, 43,  0, 89, 29    ;40-47
        db 45, 90, 44, 79, 43,  0, 89, 29    ;40-47
        db 34, 36, 86, 28, 37, 33, 84, 27    ;48-4f
        db 34, 36, 86, 28, 37, 33, 84, 27    ;48-4f
        db 32, 35, 30, 31,  0,  0,      0, 83    ;50-57
        db 32, 35, 30, 31,  0,  0,      0, 83    ;50-57
        db 42
        db 42
E0KeyList:
E0KeyList:
        db      35h, 1ch, 4fh, 4bh, 47h, 52h, 53h, 50h, 4dh, 48h, 51h, 49h
        db      35h, 1ch, 4fh, 4bh, 47h, 52h, 53h, 50h, 4dh, 48h, 51h, 49h
ELSE    ; use SCANCODE2
ELSE    ; use SCANCODE2
KeyIndex:
KeyIndex:
        db      0, 79,  0, 38, 39, 40, 41, 42
        db      0, 79,  0, 38, 39, 40, 41, 42
        db      0, 43, 44, 45, 46, 47, 48,  0
        db      0, 43, 44, 45, 46, 47, 48,  0
        db      0,  0,  0,  0,  0,  1, 49,  0
        db      0,  0,  0,  0,  0,  1, 49,  0
        db      0,  0,  2,      3,  4,  5, 50,  0
        db      0,  0,  2,      3,  4,  5, 50,  0
        db      0,  6,  7,      8,  9, 51, 52,  0
        db      0,  6,  7,      8,  9, 51, 52,  0
        db      0, 53, 10, 11, 12, 13, 54,  0
        db      0, 53, 10, 11, 12, 13, 54,  0
        db      0, 14, 15, 16, 17, 18, 55,  0
        db      0, 14, 15, 16, 17, 18, 55,  0
        db      0,  0, 19, 20, 21, 56, 57,  0
        db      0,  0, 19, 20, 21, 56, 57,  0
        db      0, 58, 22, 23, 24, 59, 60,  0
        db      0, 58, 22, 23, 24, 59, 60,  0
        db      0, 61, 62, 25, 64, 26, 65,  0
        db      0, 61, 62, 25, 64, 26, 65,  0
        db      0,  0, 66,      0, 67, 68,      0,  0
        db      0,  0, 66,      0, 67, 68,      0,  0
        db      0,  0, 69, 70,  0, 71,  0,  0
        db      0,  0, 69, 70,  0, 71,  0,  0
        db      0,  0,  0,      0,  0,  0, 72,  0
        db      0,  0,  0,      0,  0,  0, 72,  0
        db      0, 27,  0, 28, 29,  0,  0,  0
        db      0, 27,  0, 28, 29,  0,  0,  0
        db 30, 31, 32, 37, 33, 34, 82,  0
        db 30, 31, 32, 37, 33, 34, 82,  0
        db 83, 84, 35, 86, 87, 36, 89,  0
        db 83, 84, 35, 86, 87, 36, 89,  0
        db      0,  0,  0,      90
        db      0,  0,  0,      90
E0KeyList:
E0KeyList:
        db      4ah, 5ah, 69h, 6bh, 6ch, 70h, 71h, 72h, 74h, 75h, 7ah, 7dh
        db      4ah, 5ah, 69h, 6bh, 6ch, 70h, 71h, 72h, 74h, 75h, 7ah, 7dh
ENDIF
ENDIF
E0KeyIndex:
E0KeyIndex:
        db      63,  69,  73,  74,  75,  76,  77,  78,  80,  81,  85,  88
        db      63,  69,  73,  74,  75,  76,  77,  78,  80,  81,  85,  88
KeyCode:
KeyCode:
; Keys affected by CapsLock
; Keys affected by CapsLock
;               norm   shft   ctrl   alt
;               norm   shft   ctrl   alt
        dw      0000h, 0000h, 0000h, 0000h ;17 - <0>
        dw      0000h, 0000h, 0000h, 0000h ;17 - <0>
        dw      1071h, 1051h, 1011h, 1000h ;15 - Q, (E0)PrevTrack <1>
        dw      1071h, 1051h, 1011h, 1000h ;15 - Q, (E0)PrevTrack <1>
        dw      2c7ah, 2c5ah, 2c1ah, 2c00h ;1a - Z <2>
        dw      2c7ah, 2c5ah, 2c1ah, 2c00h ;1a - Z <2>
        dw      1f73h, 1f53h, 1f13h, 1f00h ;1b - S <3>
        dw      1f73h, 1f53h, 1f13h, 1f00h ;1b - S <3>
        dw      1e61h, 1e41h, 1e01h, 1e00h ;1c - A <4>
        dw      1e61h, 1e41h, 1e01h, 1e00h ;1c - A <4>
        dw      1177h, 1157h, 1117h, 1100h ;1d - W <5>
        dw      1177h, 1157h, 1117h, 1100h ;1d - W <5>
        dw      2e63h, 2e43h, 2e03h, 2e00h ;21 - C, (E0)Volume Down <6>
        dw      2e63h, 2e43h, 2e03h, 2e00h ;21 - C, (E0)Volume Down <6>
        dw      2d78h, 2d58h, 2d18h, 2d00h ;22 - X <7>
        dw      2d78h, 2d58h, 2d18h, 2d00h ;22 - X <7>
        dw      2064h, 2044h, 2004h, 2000h ;23 - D, (E0)Mute <8>
        dw      2064h, 2044h, 2004h, 2000h ;23 - D, (E0)Mute <8>
        dw      1265h, 1245h, 1205h, 1200h ;24 - E <9>
        dw      1265h, 1245h, 1205h, 1200h ;24 - E <9>
        dw      2f76h, 2f56h, 2f16h, 2f00h ;2a - V <10>
        dw      2f76h, 2f56h, 2f16h, 2f00h ;2a - V <10>
        dw      2166h, 2146h, 2106h, 2100h ;2b - F, (E0)Calculator <11>
        dw      2166h, 2146h, 2106h, 2100h ;2b - F, (E0)Calculator <11>
        dw      1474h, 1454h, 1414h, 1400h ;2c - T <12>
        dw      1474h, 1454h, 1414h, 1400h ;2c - T <12>
        dw      1372h, 1352h, 1312h, 1300h ;2d - R <13>
        dw      1372h, 1352h, 1312h, 1300h ;2d - R <13>
        dw      316eh, 314eh, 310eh, 3100h ;31 - N <14>
        dw      316eh, 314eh, 310eh, 3100h ;31 - N <14>
        dw      3062h, 3042h, 3002h, 3000h ;32 - B, (E0)Volume Up <15>
        dw      3062h, 3042h, 3002h, 3000h ;32 - B, (E0)Volume Up <15>
        dw      2368h, 2348h, 2308h, 2300h ;33 - H <16>
        dw      2368h, 2348h, 2308h, 2300h ;33 - H <16>
        dw      2267h, 2247h, 2207h, 2200h ;34 - G, (E0)Play/Pause <17>
        dw      2267h, 2247h, 2207h, 2200h ;34 - G, (E0)Play/Pause <17>
        dw      1579h, 1559h, 1519h, 1500h ;35 - Y <18>
        dw      1579h, 1559h, 1519h, 1500h ;35 - Y <18>
        dw      326dh, 324dh, 320dh, 3200h ;3a - M, (E0)WWW Home <19>
        dw      326dh, 324dh, 320dh, 3200h ;3a - M, (E0)WWW Home <19>
        dw      246ah, 244ah, 240ah, 2400h ;3b - J, (E0)Stop <20>
        dw      246ah, 244ah, 240ah, 2400h ;3b - J, (E0)Stop <20>
        dw      1675h, 1655h, 1615h, 1600h ;3c - U <21>
        dw      1675h, 1655h, 1615h, 1600h ;3c - U <21>
        dw      256bh, 254bh, 250bh, 2500h ;42 - K <22>
        dw      256bh, 254bh, 250bh, 2500h ;42 - K <22>
        dw      1769h, 1749h, 1709h, 1700h ;43 - I <23>
        dw      1769h, 1749h, 1709h, 1700h ;43 - I <23>
        dw      186fh, 184fh, 180fh, 1800h ;44 - O <24>
        dw      186fh, 184fh, 180fh, 1800h ;44 - O <24>
        dw      266ch, 264ch, 260ch, 2600h ;4b - L <25>
        dw      266ch, 264ch, 260ch, 2600h ;4b - L <25>
        dw      1970h, 1950h, 1910h, 1900h ;4d - P, (E0)Next Track <26>
        dw      1970h, 1950h, 1910h, 1900h ;4d - P, (E0)Next Track <26>
; keys affected by NumLock
; keys affected by NumLock
        dw      4f00h, 4f31h, 7500h, 0002h ;69 - KP1 <27>
        dw      4f00h, 4f31h, 7500h, 0002h ;69 - KP1 <27>
        dw      4b00h, 4b34h, 7300h, 0005h ;6b - KP4 <28>
        dw      4b00h, 4b34h, 7300h, 0005h ;6b - KP4 <28>
        dw      4700h, 4737h, 7700h, 0008h ;6c - KP7 <29>
        dw      4700h, 4737h, 7700h, 0008h ;6c - KP7 <29>
        dw      5200h, 5230h, 9200h, 0001h ;70 - KP0 <30>
        dw      5200h, 5230h, 9200h, 0001h ;70 - KP0 <30>
        dw      5300h, 532eh, 9300h, 0000h ;71 - KP. <31>
        dw      5300h, 532eh, 9300h, 0000h ;71 - KP. <31>
        dw      5000h, 5032h, 9100h, 0003h ;72 - KP2 <32>
        dw      5000h, 5032h, 9100h, 0003h ;72 - KP2 <32>
        dw      4d00h, 4d36h, 7400h, 0007h ;74 - KP6 <33>
        dw      4d00h, 4d36h, 7400h, 0007h ;74 - KP6 <33>
        dw      4800h, 4838h, 8d00h, 0009h ;75 - KP8 <34>
        dw      4800h, 4838h, 8d00h, 0009h ;75 - KP8 <34>
        dw      5100h, 5133h, 7600h, 0004h ;7a - KP3 <35>
        dw      5100h, 5133h, 7600h, 0004h ;7a - KP3 <35>
        dw      4900h, 4939h, 8400h, 000ah ;7d - KP9 <36>
        dw      4900h, 4939h, 8400h, 000ah ;7d - KP9 <36>
        dw      4c00h, 4c35h, 8f00h, 0006h ;73 - KP5 --- on VMWare, it does not send 4c00 <37>
        dw      4c00h, 4c35h, 8f00h, 0006h ;73 - KP5 --- on VMWare, it does not send 4c00 <37>
; keys unaffected by CapsLock or N
; keys unaffected by CapsLock or N
        dw      3f00h, 5800h, 6200h, 6c00h ;03 - F5 <38>
        dw      3f00h, 5800h, 6200h, 6c00h ;03 - F5 <38>
        dw      3d00h, 5600h, 6000h, 6a00h ;04 - F3 <39>
        dw      3d00h, 5600h, 6000h, 6a00h ;04 - F3 <39>
        dw      3b00h, 5400h, 5e00h, 6800h ;05 - F1 <40>
        dw      3b00h, 5400h, 5e00h, 6800h ;05 - F1 <40>
        dw      3c00h, 5500h, 5f00h, 6900h ;06 - F2 <41>
        dw      3c00h, 5500h, 5f00h, 6900h ;06 - F2 <41>
        dw      8600h, 8800h, 8a00h, 8c00h ;07 - F12 <42>
        dw      8600h, 8800h, 8a00h, 8c00h ;07 - F12 <42>
        dw      4400h, 5d00h, 6700h, 7100h ;09 - F10 <43>
        dw      4400h, 5d00h, 6700h, 7100h ;09 - F10 <43>
        dw      4200h, 5b00h, 6500h, 6f00h ;0a - F8 <44>
        dw      4200h, 5b00h, 6500h, 6f00h ;0a - F8 <44>
        dw      4000h, 5900h, 6300h, 6d00h ;0b - F6 <45>
        dw      4000h, 5900h, 6300h, 6d00h ;0b - F6 <45>
        dw      3e00h, 5700h, 6100h, 6b00h ;0c - F4 <46>
        dw      3e00h, 5700h, 6100h, 6b00h ;0c - F4 <46>
        dw      0f09h, 0f00h, 9400h, 0000h ;0d - TAB <47>
        dw      0f09h, 0f00h, 9400h, 0000h ;0d - TAB <47>
        dw      2960h, 297eh, 0000h, 2900h ;0e - ` ~ <48>
        dw      2960h, 297eh, 0000h, 2900h ;0e - ` ~ <48>
        dw      0231h, 0221h, 0000h, 7800h ;16 - 1 ! <49>
        dw      0231h, 0221h, 0000h, 7800h ;16 - 1 ! <49>
        dw      0332h, 0340h, 0300h, 7900h ;1e - 2 @ <50>
        dw      0332h, 0340h, 0300h, 7900h ;1e - 2 @ <50>
        dw      0534h, 0524h, 0000h, 7b00h ;25 - 4 $ <51>
        dw      0534h, 0524h, 0000h, 7b00h ;25 - 4 $ <51>
        dw      0433h, 0423h, 0000h, 7a00h ;26 - 3 # <52>
        dw      0433h, 0423h, 0000h, 7a00h ;26 - 3 # <52>
        dw      3920h, 3920h, 3920h, 3920h ;29 - SPC <53>
        dw      3920h, 3920h, 3920h, 3920h ;29 - SPC <53>
        dw      0635h, 0625h, 0000h, 7c00h ;2e - 5 % <54>
        dw      0635h, 0625h, 0000h, 7c00h ;2e - 5 % <54>
        dw      0736h, 075eh, 071eh, 7d00h ;36 - 6 ^ <55>
        dw      0736h, 075eh, 071eh, 7d00h ;36 - 6 ^ <55>
        dw      0837h, 0826h, 0000h, 7e00h ;3d - 7 & <56>
        dw      0837h, 0826h, 0000h, 7e00h ;3d - 7 & <56>
        dw      0938h, 092ah, 0000h, 7f00h ;3e - 8 * <57>
        dw      0938h, 092ah, 0000h, 7f00h ;3e - 8 * <57>
        dw      332ch, 333ch, 0000h, 3300h ;41 - , < <58>
        dw      332ch, 333ch, 0000h, 3300h ;41 - , < <58>
        dw      0b30h, 0b29h, 0000h, 8100h ;45 - 0 ) <59>
        dw      0b30h, 0b29h, 0000h, 8100h ;45 - 0 ) <59>
        dw      0a39h, 0a28h, 0000h, 8000h ;46 - 9 ( <60>
        dw      0a39h, 0a28h, 0000h, 8000h ;46 - 9 ( <60>
        dw      342eh, 343eh, 0000h, 3400h ;49 - . > <61>
        dw      342eh, 343eh, 0000h, 3400h ;49 - . > <61>
        dw      352fh, 353fh, 0000h, 3500h ;4a - / ? <62>
        dw      352fh, 353fh, 0000h, 3500h ;4a - / ? <62>
        dw      0e02fh, 0e02fh, 9500h, 0a400h ;4a - (e0)KP/ <63>
        dw      0e02fh, 0e02fh, 9500h, 0a400h ;4a - (e0)KP/ <63>
        dw      273bh, 273ah, 0000h, 2700h ;4c - ; : <64>
        dw      273bh, 273ah, 0000h, 2700h ;4c - ; : <64>
        dw      0c2dh, 0c5fh, 0c1fh, 8200h ;4e - - _ <65>
        dw      0c2dh, 0c5fh, 0c1fh, 8200h ;4e - - _ <65>
        dw      2827h, 2822h, 0000h, 2800h ;52 - ’ “ <66>
        dw      2827h, 2822h, 0000h, 2800h ;52 - ’ “ <66>
        dw      1a5bh, 1a7bh, 1a1bh, 1a00h ;54 - [ { <67>
        dw      1a5bh, 1a7bh, 1a1bh, 1a00h ;54 - [ { <67>
        dw      0d3dh, 0d2bh, 0000h, 8300h ;55 - = + <68>
        dw      0d3dh, 0d2bh, 0000h, 8300h ;55 - = + <68>
        dw      1c0dh, 1c0dh, 1c0ah, 1c00h ;5a - Enter, (E0)KPEnter <69>
        dw      1c0dh, 1c0dh, 1c0ah, 1c00h ;5a - Enter, (E0)KPEnter <69>
        dw      1b5dh, 1b7dh, 1b1dh, 1b00h ;5b - ] } <70>
        dw      1b5dh, 1b7dh, 1b1dh, 1b00h ;5b - ] } <70>
        dw      2b5ch, 2b7ch, 2b1ch, 2b00h ;5d - \ | <71>
        dw      2b5ch, 2b7ch, 2b1ch, 2b00h ;5d - \ | <71>
        dw      0e08h, 0e08h, 0e7fh, 0e00h ;66 - BKSP <72>
        dw      0e08h, 0e08h, 0e7fh, 0e00h ;66 - BKSP <72>
        dw      4f00h, 4f00h, 7500h, 9f00h ;69 - (E0)END <73>
        dw      4f00h, 4f00h, 7500h, 9f00h ;69 - (E0)END <73>
        dw      4b00h, 4b00h, 7300h, 9b00h ;6b - (E0)LEFT <74>
        dw      4b00h, 4b00h, 7300h, 9b00h ;6b - (E0)LEFT <74>
        dw      4700h, 4700h, 7700h, 9700h ;6c - (E0)HOME <75>
        dw      4700h, 4700h, 7700h, 9700h ;6c - (E0)HOME <75>
        dw      5200h, 5200h, 9200h, 0a200h ;70 - (E0)INS <76>
        dw      5200h, 5200h, 9200h, 0a200h ;70 - (E0)INS <76>
        dw      5300h, 5300h, 9300h, 0a300h ;71 - (E0)DEL <77>
        dw      5300h, 5300h, 9300h, 0a300h ;71 - (E0)DEL <77>
        dw      5000h, 5000h, 9100h, 0a000h ;72 - (E0)DOWN <78>
        dw      5000h, 5000h, 9100h, 0a000h ;72 - (E0)DOWN <78>
        dw      4300h, 5c00h, 6600h, 7000h ;01 - F9 <79>
        dw      4300h, 5c00h, 6600h, 7000h ;01 - F9 <79>
        dw      4d00h, 4d00h, 7400h, 9d00h ;74 - (E0)RIGHT <80>
        dw      4d00h, 4d00h, 7400h, 9d00h ;74 - (E0)RIGHT <80>
        dw      4800h, 4800h, 8d00h, 9800h ;75 - (E0)UP <81>
        dw      4800h, 4800h, 8d00h, 9800h ;75 - (E0)UP <81>
        dw      011bh, 011bh, 011bh, 0100h ;76 - ESC <82>
        dw      011bh, 011bh, 011bh, 0100h ;76 - ESC <82>
        dw      8500h, 8700h, 8900h, 8b00h ;78 - F11 <83>
        dw      8500h, 8700h, 8900h, 8b00h ;78 - F11 <83>
        dw      4e2bh, 4e2bh, 9000h, 4e00h ;79 - KP+ <84>
        dw      4e2bh, 4e2bh, 9000h, 4e00h ;79 - KP+ <84>
        dw      5100h, 5100h, 7600h, 0a100h ;7a - (E0)PGDN <85>
        dw      5100h, 5100h, 7600h, 0a100h ;7a - (E0)PGDN <85>
        dw      4a2dh, 4a2dh, 8e00h, 4a00h ;7b - KP- <86>
        dw      4a2dh, 4a2dh, 8e00h, 4a00h ;7b - KP- <86>
        dw      372ah, 372ah, 9600h, 3700h ;7c - KP* --- on VMWare, it does not send 3710h with CTL <87>
        dw      372ah, 372ah, 9600h, 3700h ;7c - KP* --- on VMWare, it does not send 3710h with CTL <87>
        dw      4900h, 4900h, 8400h, 9900h ;7d - (E0)PGUP <88>
        dw      4900h, 4900h, 8400h, 9900h ;7d - (E0)PGUP <88>
        dw      4600h, 4600h, 4600h, 4600h ;7e - SCRL <89>
        dw      4600h, 4600h, 4600h, 4600h ;7e - SCRL <89>
        dw      4100h, 5a00h, 6400h, 6e00h ;83 - F7 <90>
        dw      4100h, 5a00h, 6400h, 6e00h ;83 - F7 <90>
; ------------------------- POWER ON RESET -----------------------
; ------------------------- POWER ON RESET -----------------------
        org     0fff0h
        org     0fff0h
        db      0eah
        db      0eah
        dw      coldboot, 0f000h
        dw      coldboot, 0f000h
        db      '02/05/13'
        db      '02/05/13'
        db      0ffh, 0ffh, 0
        db      0ffh, 0ffh, 0
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.