;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        PAGE    ,132
        NAME    VVGALE
        TITLE   Virtual Video Device Driver Int 10h Support for Gale VDM

;/*****************************************************************************
;*
;* SOURCE FILE NAME = VVGALE.ASM
;*
;* DESCRIPTIVE NAME = Virtual Video Device Driver Int 10h Support for Gale VDM
;*
;*
;* VERSION      V2.0
;*
;* DATE         07/23/91
;*
;* DESCRIPTION  This module defines the VVD entry point and provides
;*              routing to various other C entry points.
;*
;* FUNCTIONS
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*   07/23/91                     Created.
;*   06/02/93  J-TS0602           PTR JS05340 fix
;*   08/25/93  J-TS0825   JS05651 Starting message of Fullscreen WinJOS2
;*                                becomes strane color bars.
;*   08/27/93  J-TS0827   JS05893 DOS/V VDM screen switch to fullscreen
;*                                sometimes fails.
;*
;*****************************************************************************/

        .xlist
        include mvdm.inc
        include vddseg.inc
        include mi.inc
        include beep.inc
        include struc30.inc
        .list
        include vvd.inc
        include vvdp.inc

IFDEF   GALE

        DefData     EXPORT,SWAP,C
        USHORT      GaleScroll              ; hardware scroll option
        USHORT      APAWidthText            ; APAwidth in text mode
        UCHAR       FlagXGA                 ; video adapter is XGA ?

        public      _DBCSVector
        public      _UserFontVector
_DBCSVector         label byte
DBCSVector          db    4 dup(0)          ; DBCS vector
_UserFontVector     label byte
UserFontVector      db    2 dup(0)          ; user defined DBCS vector
        EndData

        DefData     IMPORT,SWAP,C
        ULONG       TKSSBase                ; required for SSToDS macro
        PBYTE       pPhysVRAM               ; global address of APA
        ULONG       vfvfunc                 ; vfntv service entry
        EndData

XGA_OP_MODE_REG_1   equ     2110h
VGA_ENABLED_MODE    equ     01h

SeqAddressPort      equ     03C4h
GraphAddressPort    equ     03CEh
MiscOutputRegRead   equ     03CCh
CRTCtlAddressReg    equ     03B4h
InputStatusReg1     equ     03BAh
ColorAdjustment     equ     20h
MonoAdjustment      equ     0

LG_SET_RESET        equ     00h
LG_ENABLE_SET_RESET equ     01h
LG_COMP             equ     02h
LG_FUNCTION         equ     03h
LG_MODE             equ     05h
LG_READ_MAP         equ     04h
LG_BIT_MASK         equ     08h
LG_COMMAND          equ     0Bh

LS_CLOCK_MODE       equ     01h
LS_MAP_MASK         equ     02h

LC_OVERFLOW         equ     07h
LC_MAX_SCAN_LINE    equ     09h
LC_START_HIGH       equ     0Ch
LC_START_LOW        equ     0Dh
LC_DISP_ENABLE      equ     12h
LC_LINE_WIDTH       equ     13h
LC_LINE_COMP        equ     18h

        DefData     PRIVATE,SWAP,C

Int10FuncGale   dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=00h
                dd  FLAToffset vvInt10SetCurTypeGale        ; Int 10h AH=01h
                dd  FLAToffset vvInt10SetCurPosGale         ; Int 10h AH=02h
                dd  FLAToffset vvInt10ReadCurPosGale        ; Int 10h AH=03h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=04h
                dd  FLAToffset vvInt10SelectPageGale        ; Int 10h AH=05h
                dd  FLAToffset vvInt10ScrollUpGale          ; Int 10h AH=06h
                dd  FLAToffset vvInt10ScrollDownGale        ; Int 10h AH=07h
                dd  FLAToffset vvInt10ReadAttrCharGale      ; Int 10h AH=08h
                dd  FLAToffset vvInt10WriteAttrCharGale     ; Int 10h AH=09h
                dd  FLAToffset vvInt10WriteCharGale         ; Int 10h AH=0Ah
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=0Bh
                dd  FLAToffset vvInt10WriteDotGale          ; Int 10h AH=0Ch
                dd  FLAToffset vvInt10ReadDotGale           ; Int 10h AH=0Dh
                dd  FLAToffset vvInt10WriteTTYGale          ; Int 10h AH=0Eh
                dd  FLAToffset vvInt10ReadVideoStateGale    ; Int 10h AH=0Fh
                dd  FLAToffset vvInt10SetPalleteGale        ; Int 10h AH=10h
                dd  FLAToffset vvInt10CharGenGale           ; Int 10h AH=11h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=12h
                dd  FLAToffset vvInt10ReadWriteStrGale      ; Int 10h AH=13h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=14h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=15h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=16h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=17h
                dd  FLAToffset vvInt10RequestFontGale       ; Int 10h AH=18h
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=19h
                dd  FLAToffset vvInt10ReadDispTypeGale      ; Int 10h AH=1Ah
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=1Bh
                dd  FLAToffset vvInt10NotSupportGale        ; Int 10h AH=1Ch
                dd  FLAToffset vvInt10ShiftStatGale         ; Int 10h AH=1Dh
DBCS1st         db  256 dup(0)
        EndData

        DefData     PRIVATE,SWAPINST,C
        ULONG       APABottomBound          ; APA boundary
        ULONG       APATopBound             ; AND mask is required ?
        ULONG       SkipLineAPA             ; APA one char row skip count
        USHORT      Gale_DBCS_First_Char    ; First byte data (char/attr)
        USHORT      PrevColor               ; previousely set color
        USHORT      PrevLineComp            ; previousely set line compare reg.
        USHORT      MaxLineComp             ; max set line compare reg.
        USHORT      Gale_Start_Addr         ; VGA graphics start addr
        USHORT      APAWidth                ; APAwidth
        ULONG       SkipLasterAPA           ; laster skip value
        ULONG       GaleInitFlag, FALSE     ; initialized after creation ?
        UCHAR       Gale_Max_Row            ; max row count (25 or 30)
        UCHAR       FontHeight              ; font height (16 or 19)
        UCHAR       Gale_DBCS_Attr_Cnt      ; First byte attr count
        UCHAR       Gale_DBCS_First_Flag    ; First byte draw flag
        UCHAR       Gale_Supported_Mode     ; current mode is suppoted by gale ?
        UCHAR       Gale_Text_Mode          ; current mode is text ?

ExtWriteRegSave dw  SeqAddressPort,   LS_MAP_MASK   ; save/restore registers
                dw  GraphAddressPort, LG_FUNCTION   ; definitions for
                dw  GraphAddressPort, LG_BIT_MASK   ; XVIO string write
                dw  GraphAddressPort, LG_MODE       ; in graphics mode
                dw  GraphAddressPort, LG_SET_RESET
                dw  GraphAddressPort, LG_ENABLE_SET_RESET
                dw  GraphAddressPort, LG_READ_MAP
                dw  0
ExtWriteAddrSave dw SeqAddressPort,   ?
                 dw GraphAddressPort, ?
                 dw 0
ExtWriteLatch   db  4 dup(0)
ExtWriteAPASave db  4 dup(0)

        EndData

        DefCode IMPORT,SWAP,PASCAL
        DefFn   VDHPopInt
        DefFn   VDHNotIdle
        DefFn   VDHDevBeep
        DefFn   VDHArmReturnHook

        DefFn   vvUpdateCursorData
        DefFn   vvFlushEvent
        DefFn   vvAddEvent
IFDEF   XVIO
        DefFn   vxUpdateCursorData
        DefFn   vxAddEvent
        DefFn   vxFlushEvent
ENDIF   ;XVIO
        EndCode

VfntGetDBCSVector   equ     vfvfunc[ 0]     ; get DBCS vector & user font vector
VfntGetSBCS16Buf    equ     vfvfunc[ 4]     ; get SBCS 16 font buffer
VfntGetDBCS16Font   equ     vfvfunc[ 8]     ; get DBCS 16 font
VfntGetSBCS24Font   equ     vfvfunc[12]     ; get SBCS 24 font
VfntGetDBCS24Font   equ     vfvfunc[16]     ; get DBCS 24 font
VfntPutDBCS16Font   equ     vfvfunc[20]     ; put DBCS 16 font
VfntPutDBCS24Font   equ     vfvfunc[24]     ; put DBCS 24 font

SIZE_SBCS16         equ     19
SIZE_DBCS16         equ     32
SIZE_DBCS24         equ     72
SIZE_SBCS16_BUF     equ     SIZE_SBCS16*256

SBCS_FONT_VECTOR_OFF    equ     word ptr ds:[43h*4+0]
SBCS_FONT_VECTOR_SEL    equ     word ptr ds:[43h*4+2]

APA_BASE            equ     0A0000h
APA_WIDTH           equ     640/8
APA_HEIGHT          equ     480
FONT_HEIGHT         equ     19
FONT_HEIGHT_LOW     equ     16
FONT_WIDTH          equ     1

SCREEN_WIDTH        equ     80
SCREEN_HEIGHT       equ     30

INT10_REQUESTFONT   equ     018h            ; Gale mode only function
INT10_SHIFTSTATUS   equ     01Dh            ; 
INT10_GETVIDEOBUF   equ     0FEh            ; 
INT10_UPDATEVIDEO   equ     0FFh            ; 

BIOSVMODE_CO640X480X16_GALE     equ     072h
BIOSVMODE_CO80_GALE             equ     073h

DEFAULT_ATTR0       equ     07h
DEFAULT_CHAR_ATTR0  equ     0720h
DEFAULT_ATTR1_ATTR2 equ     0000h

APA_START_ADDR      equ     0a0000h
APA_ADDR_MASK       equ     0fffeffffh

SET_TEXT_COLOR      equ     0
SET_SCROLL_COLOR    equ     1

RETURN_SBCS_FONT_INFORMATION    equ     30h

MIN_ROW_HARD_SCROLL equ     21

DEFAULT_CUR_TYPE    equ     0607h
DEFAULT_CUR_POS     equ     0000h

HORZ_GRID           equ     04h
VERT_GRID           equ     08h
UNDERLINE           equ     80h
GRID_COLOR          equ     07h
GRID_COLOR_MONO     equ     01h

GALE_HS_OFF         equ     00h
GALE_HS_ON          equ     01h
GALE_HS_LC          equ     02h

        DefCode     EXPORT,SWAP,PASCAL

        DefFn   VVInt10Gale
        DefFn   VVLoadDefaultSBCS
        DefFn   VVInitScreen
        DefFn   VVRedrawScreen
        DefFn   VVCheckXGAAdapter
        DefFn   VVInitDBCSTable
        DefFn   mapc
        DefFn   IsKanjiGale
        DefFn   QueryCharTypeGale
        DefFn   RedrawScreenGale
        DefFn   RedrawPtrGale
        DefFn   RestoreScreenPtrGale
        DefFn   vvConvAPAToPrtGale
        DefFn   VVInt15Hook
IFDEF   XVIO
        DefFn   vvExtWriteStrGale
        DefFn   vvSetCurPosGale
        DefFn   vvSetCurTypeGale
ENDIF   ;XVIO

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVInt10Gale                                       */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Int 10H hook entry for Gale mode except AH=0     */
;/*                    Mode Set.                                        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear                                                 */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine)                  */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVInt10Gale
        .if     <Gale_Supported_Mode ne 0>
            push    ebx                         ; save regs
            push    esi
            push    edi

            .if     <ah be INT10_SHIFTSTATUS>
                movzx   esi, ah
                call    Int10FuncGale[esi*4]
            .elseif <ah eq INT10_GETVIDEOBUF>
                call    vvInt10GetVideoBufGale
            .elseif <ah eq INT10_UPDATEVIDEO>
                call    vvInt10UpdateVideoGale
            .else
                stc
            .endif

            pop     edi                         ; restore regs
            pop     esi
            pop     ebx
        .else
            stc
        .endif
        ExitProc
EndProc     VVInt10Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10NotSupportGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Not supported function.                          */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Never)                                         */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Always)         */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10NotSupportGale
        stc
        ExitProc
EndProc     vvInt10NotSupportGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10SetCurTypeGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set cursor type.                                 */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10SetCurTypeGale
        call    HideCursorGale                  ; hide cursor
        mov     ax, [ebx].crf_ecx.off
        mov     VDMBase.rb_wVCursorMode, ax
        call    SetCursorGale                   ; net new cursor
        call    DrawCursorGale                  ; draw cursor

IFDEF   XVIO
        CallFn  vxUpdateCursorData, <CURRENT_VDM>
ENDIF   ;XVIO
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
            CallFn  vvUpdateCursorData, <CURRENT_VDM>
        .endif
        clc
        ExitProc
EndProc     vvInt10SetCurTypeGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10SetCurPosGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set cursor position.                             */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10SetCurPosGale
;       .if     <[ebx].crf_ebx.hi eq 0>         ; Comment out is because of compatibility with GALE
            call    HideCursorGale              ; hide cursor
            mov     ax, [ebx].crf_edx.off
;           .if     <ah b Gale_Max_Row> and     ; check position
;           .if     <al b SCREEN_WIDTH>         ; Comment out is because of compatibility with GALE
                mov     VDMBase.rb_awVCursorPos, ax
;           .endif
            call    SetCursorGale               ; net new cursor
            call    DrawCursorGale              ; draw cursor
;       .endif                                  ;

IFDEF   XVIO
        CallFn  vxUpdateCursorData, <CURRENT_VDM>
ENDIF   ;XVIO
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
            CallFn  vvUpdateCursorData, <CURRENT_VDM>
        .endif
        clc
        ExitProc
EndProc     vvInt10SetCurPosGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadCurPosGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read cursor type & position.                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadCurPosGale
;       .if     <[ebx].crf_ebx.hi eq 0>         ; Comment out is because of compatibility with GALE
            mov     ax, VDMBase.rb_wVCursorMode
            mov     [ebx].crf_ecx.off, ax
            mov     ax, VDMBase.rb_awVCursorPos
            mov     [ebx].crf_edx.off, ax
;       .else
;           mov     [ebx].crf_ecx.off, 0607h    ; default shape
;           mov     [ebx].crf_edx.off, 0000h    ; default position
;       .endif
        clc
        ExitProc
EndProc     vvInt10ReadCurPosGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10SelectPageGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Select active page.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10SelectPageGale
        clc
        ExitProc
EndProc     vvInt10SelectPageGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ScrollUpGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up the specified region.                  */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ScrollUpGale
        call    HideCursorGale                  ; hide cursor
        mov     cx, [ebx].crf_ecx.off
        mov     dx, [ebx].crf_edx.off
        mov     bh, [ebx].crf_ebx.hi
        call    vvScrollUpGale
        call    DrawCursorGale                  ; draw cursor
        clc
        ExitProc
EndProc     vvInt10ScrollUpGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ScrollDownGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down the specified region.                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ScrollDownGale
        call    HideCursorGale                  ; hide cursor
        mov     cx, [ebx].crf_ecx.off
        mov     dx, [ebx].crf_edx.off
        mov     bh, [ebx].crf_ebx.hi
        call    vvScrollDownGale
        call    DrawCursorGale                  ; draw cursor
        clc
        ExitProc

EndProc     vvInt10ScrollDownGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadAttrCharGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read current cursor position character/attribute.*/
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadAttrCharGale
        .if     <[ebx].crf_ebx.hi eq 0>
            mov     dx, VDMBase.rb_awVCursorPos
            mov     ecx, ebx
            call    MakePointer
            .if     nc
                mov     ax, [ebx]
                mov     [ecx].crf_eax.off, ax
            .endif
        .endif
        clc
        ExitProc
EndProc     vvInt10ReadAttrCharGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteAttrCharGale                          */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write character with the specified attribute.    */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteAttrCharGale
        .if     <[ebx].crf_ebx.hi eq 0>
            mov     ah, [ebx].crf_ebx.lo
            mov     cx, [ebx].crf_ecx.off
            mov     dx, VDMBase.rb_awVCursorPos
            call    HideCursorGale              ; hide cursor
            call    SetupAPAWriteGale
            call    vvDrawCharGale1
            call    DrawCursorGale              ; draw cursor
        .endif
        .if     <Gale_Text_Mode eq 0>           ; graphics mode ?
            call    vvSetDefaultRegsGale
        .endif
        clc
        ExitProc
EndProc     vvInt10WriteAttrCharGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteCharGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write character with the current attribute.      */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteCharGale
        .if     <[ebx].crf_ebx.hi eq 0>
            mov     cx, [ebx].crf_ecx.off
            mov     dx, VDMBase.rb_awVCursorPos
            call    HideCursorGale              ; hide cursor
            call    SetupAPAWriteGale
            call    vvDrawCharGale0
            call    DrawCursorGale              ; draw cursor
        .endif
        .if     <Gale_Text_Mode eq 0>           ; graphics mode ?
            call    vvSetDefaultRegsGale
        .endif
        clc
        ExitProc
EndProc     vvInt10WriteCharGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteDotGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write graphics dot.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteDotGale
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> near and
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE> near and
        .if     <[ebx].crf_ebx.hi eq 0> near and
        .if     <[ebx].crf_ecx.off b 640> and
        .if     <[ebx].crf_edx.off b 480>

            call    SetupAPAWriteGale           ; setup APA write mode & color

            mov     dx, GraphAddressPort        ; set VGA port address

            mov     al, LG_MODE                 ; set write mode 3
            mov     ah, 03h
            out     dx, ax

            mov     al, LG_SET_RESET            ; set dot color
            mov     ah, [ebx].crf_eax.lo
            and     ah, 0fh
            out     dx, ax

            .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
                mov     VDMData.aregGDCData[LG_MODE     ], 03h
                mov     VDMData.aregGDCData[LG_SET_RESET], ah
            .endif

            .if     <bit [ebx].crf_eax.lo and 80h>  ; XOR ?
                mov     al, LG_FUNCTION         ; set XOR function
                mov     ah, 18h
                out     dx, ax
                .if     <bit VDMData.flVDMVideo nand VDM_FGND>
                    mov     VDMData.aregGDCData[LG_FUNCTION], 18h
                .endif
            .endif

            movzx   esi, [ebx].crf_edx.off
            lea     esi, [esi*4+esi]
            shl     esi, 4                      ; row offset (byte)
            movzx   eax, [ebx].crf_ecx.off
            mov     ecx, eax
            shr     eax, 3
            add     esi, eax                    ; column offset (byte)
            and     cl, 07h
            mov     al, 80h
            shr     al, cl                      ; column offset (bit)

            xchg    APA_START_ADDR[esi], al     ; write dot

        .endif

        .if     <Gale_Text_Mode eq 0>           ; graphics mode ?
            call    vvSetDefaultRegsGale
        .endif

        clc
        ExitProc
EndProc     vvInt10WriteDotGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadDotGale                                */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read graphics dot.                               */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadDotGale
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> near and
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE> near and
        .if     <[ebx].crf_ebx.hi eq 0> near and
        .if     <[ebx].crf_ecx.off b 640> near and
        .if     <[ebx].crf_edx.off b 480> near

            movzx   esi, [ebx].crf_edx.off
            lea     esi, [esi*4+esi]
            shl     esi, 4                      ; row offset (byte)
            movzx   eax, [ebx].crf_ecx.off
            mov     ecx, eax
            shr     eax, 3
            add     esi, eax                    ; column offset (byte)
            and     cl, 07h
            mov     ch, 80h
            shr     ch, cl                      ; column offset (bit)
                                                ; setup VGA regs
            mov     dx, SeqAddressPort          ; set VGA port address
            mov     al, LS_MAP_MASK             ; set map mask ffh
            mov     ah, 0ffh
            out     dx, ax

            mov     dx, GraphAddressPort        ; set VGA port address

            mov     al, LG_MODE                 ; set read mode 0
            mov     ah, 03h
            out     dx, ax

            .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
                mov     VDMData.aregSEQData[LS_MAP_MASK], 0ffh
                mov     VDMData.aregGDCData[LG_MODE    ], 03h
            .endif

            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2>
                mov     ah, 0
            .else
                mov     ah, 3
            .endif
            xor     cl, cl

ReadDotLoop:
            mov     al, LG_READ_MAP             ; set read map select
            out     dx, ax

            .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
                mov     VDMData.aregGDCData[LG_READ_MAP], ah
            .endif

            mov     al, APA_START_ADDR[esi]     ; read APA
            and     al, ch

            .if     nz                          ; bit is ON ?
                or      cl, 01h
            .endif

            .if     <ah ne 0>
                shl     cl, 1
                dec     ah
                jmp     ReadDotLoop
            .endif

            mov     [ebx].crf_eax.lo, cl        ; set return value (color)

        .endif

        .if     <Gale_Text_Mode eq 0>           ; graphics mode ?
            call    vvSetDefaultRegsGale
        .endif

        clc
        ExitProc
EndProc     vvInt10ReadDotGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteTTYGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write character with the current attribute       */
;/*                    like teletype.                                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteTTYGale

        call    HideCursorGale                  ; hide cursor

        call    SetupAPAWriteGale               ; prepare to write

        mov     ah, [ebx].crf_ebx.lo            ; set color in graphics mode

        call    vvWriteTTYGale                  ; draw char

        call    SetCursorGale                   ; net new cursor

IFDEF   XVIO
        CallFn  vxUpdateCursorData, <CURRENT_VDM>
ENDIF   ;XVIO

        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
            CallFn  vvUpdateCursorData, <CURRENT_VDM>
        .endif

        call    DrawCursorGale                  ; draw cursor

        .if     <Gale_Text_Mode eq 0>           ; graphics mode ?
            call    vvSetDefaultRegsGale
        .endif

        clc

        ExitProc
EndProc     vvInt10WriteTTYGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvWriteTTYGale                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write character with the current attribute       */
;/*                    like teletype.                                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     AL  =  character code to be written                             */
;/*     AH  =  character color in graphics mode                         */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvWriteTTYGale

        .if     <Gale_DBCS_First_Flag eq 0> and ; check right-most DBCS write
        movzx   esi, al
        .if     <DBCS1st[esi] eq 1> and
        .if     <<byte ptr VDMBase.rb_awVCursorPos> eq SCREEN_WIDTH-1>
            push    ax
            mov     al, ' '
            call    vvWriteTTYGaleSub           ; draw space to skip line end
            pop     ax
        .endif

        call    vvWriteTTYGaleSub               ; draw char

        ExitProc

EndProc     vvWriteTTYGale

Procedure   vvWriteTTYGaleSub

        .if     <al be 0dh> near                ; control char posibility ?
            .if     <al eq 0dh>                 ; Carrige Return ?
                mov     dx, VDMBase.rb_awVCursorPos
                xor     dl, dl
                mov     VDMBase.rb_awVCursorPos, dx

            .elseif <al eq 0ah>                 ; Line Feed ?
                mov     dx, VDMBase.rb_awVCursorPos
                inc     dh
                .if     <dh a VDMBase.rb_nVRows>
                    dec     dh
                    .if     <dh eq VDMBase.rb_nVRows>
                        call    vvScrollUpOneGale
                    .endif
                .endif
                mov     VDMBase.rb_awVCursorPos, dx

            .elseif <al eq 08h>                 ; Back Space ?
                mov     dx, VDMBase.rb_awVCursorPos
                .if     <dl ne 0>
                    dec     dl
                .endif
                mov     VDMBase.rb_awVCursorPos, dx

            .elseif <al eq 07h>                 ; Bell ?
                push    cx
                push    dx
                CallFn  VDHDevBeep,<BELL_FREQ, BELL_DURATION>
                pop     dx
                pop     cx

            .else
                jmp     WriteTTYPrintableChar
            .endif

        .else                                   ; printable character
WriteTTYPrintableChar:
            mov     cx, 1
            mov     dx, VDMBase.rb_awVCursorPos
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                call    vvDrawCharGale0
            .else
                call    vvDrawCharGale1
            .endif
            mov     dx, VDMBase.rb_awVCursorPos
            inc     dl
            .if     <dl ae SCREEN_WIDTH>
                xor     dl, dl
                inc     dh
                .if     <dh a VDMBase.rb_nVRows>
                    dec     dh
                    .if     <dh eq VDMBase.rb_nVRows>
                        call    vvScrollUpOneGale
                    .endif
                .endif
            .endif
            mov     VDMBase.rb_awVCursorPos, dx
        .endif
        clc

        ExitProc
EndProc     vvWriteTTYGaleSub

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadVideoStateGale                         */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read current video state.                        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadVideoStateGale
        mov     al, VDMBase.rb_bVMode
        mov     [ebx].crf_eax.lo, al
        mov     [ebx].crf_eax.hi, SCREEN_WIDTH
        mov     al, VDMBase.rb_bVPage
        mov     [ebx].crf_ebx.hi, al
        clc
        ExitProc
EndProc     vvInt10ReadVideoStateGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10SetPalleteGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set palette registers.                           */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10SetPalleteGale
        .if     <ax eq 1003h>
            clc                                 ; eat the request (compatibe
        .else                                   ; with DOS/V 5.0)
            stc                                 ; reroute to original ROM BIOS
        .endif
        ExitProc
EndProc     vvInt10SetPalleteGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10CharGenGale                                */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set user defined SBCS font set.                  */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10CharGenGale

        .if     <al ae RETURN_SBCS_FONT_INFORMATION>
            stc                                 ; call ROM BIOS
            ret
        .endif

        .if     <[ebx].crf_eax.lo ne 0> or      ; parameter check
        .if     <[ebx].crf_ebx.lo ne 0>
            clc
            ret
        .endif

        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> and   ; graphics mode ?
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
            clc                                 ; not supported
            ret
        .endif

        movzx   esi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     esi, 4
        add     esi, eax                        ; ESI = user font buffer

        movzx   eax, [ebx].crf_edx.off
        lea     edi, [eax*8+eax]
        lea     edi, [edi*2+eax]
        add     edi, VDMData.GaleData.GaleSBCS  ; EDI = system font buffer

        mov     ah, [ebx].crf_ecx.lo            ; AH = number of char

        movzx   ecx, [ebx].crf_ebx.hi
        .if     <ecx a FONT_HEIGHT>
            mov     ecx, FONT_HEIGHT
        .endif
        mov     edx, FONT_HEIGHT
        sub     edx, ecx
        cld

CharGenLoop:
        push    ecx
        .if     <ecx eq FONT_HEIGHT_LOW>        ; if char height = 16
            movsb                               ; make 1 laster top margin
            dec     esi                         ; from top of user font
            rep     movsb
            dec     esi                         ; make 2 laster bottom margin
            movsb                               ; from bottom of user font
            dec     esi
            movsb
        .else
            rep     movsb
            add     edi, edx
        .endif
        pop     ecx
        dec     ah
        jnz     CharGenLoop
        mov     dx, 0000h
        mov     al, SCREEN_WIDTH
        mul     Gale_Max_Row
        mov     cx, ax
        call    RedrawScreenGale
        clc
        ExitProc
EndProc     vvInt10CharGenGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadWriteStrGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read/Write string.                               */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadWriteStrGale

        .if     <al be 03h> or
        .if     <al eq 20h> or
        .if     <al eq 21h> or
        .if     <al eq 0ffh>                    ; CON driver private interface
            .if     <[ebx].crf_ebx.hi eq 0> or
            .if     <al eq 0ffh>
                call    HideCursorGale          ; hide cursor
                call    vvInt10WriteStrGale
                call    DrawCursorGale          ; draw cursor
                .if     <Gale_Text_Mode eq 0>   ; graphics mode ?
                    call    vvSetDefaultRegsGale
                .endif
            .endif
        .elseif <al eq 10h> or
        .if     <al eq 11h>
            call    vvInt10ReadStrGale
        .endif
        clc
        ExitProc
EndProc     vvInt10ReadWriteStrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10RequestFontGale                            */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get/Put SBCS/DBCS font image.                    */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Never)                                         */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Always)         */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10RequestFontGale
        .if     <[ebx].crf_ebx.off ne 0>        ; check reserved reg
            mov     [ebx].crf_eax.lo, -1        ; & font selection
            clc
            ret
        .endif

        movzx   edi, [ebx].crf_es               ; get pointer to font image buf
        movzx   ecx, [ebx].crf_esi.off
        shl     edi, 4
        add     edi, ecx                        ; edi -> font buf
        mov     cx, [ebx].crf_ecx.off           ; char code
        mov     dx, [ebx].crf_edx.off           ; char size

        .if     <al eq 00h> near                ; get font ?
            .if     <dx eq 0810h>               ;  8 x 16 dots
                .if     <ch eq 0> near          ; char code check
                    mov     al, cl
                    call    vvGetSBCSDefaultFont
                    inc     esi
                    mov     ecx, FONT_HEIGHT_LOW
                    cld
                    rep     movsb
                    mov     [ebx].crf_eax.lo, 0
                .else near
                    mov     [ebx].crf_eax.lo, -1
                .endif

            .elseif <dx eq 0813h>               ;  8 x 19 dots
                .if     <ch eq 0> near          ; char code check
                    mov     al, cl
                    call    vvGetSBCSDefaultFont
                    mov     ecx, FONT_HEIGHT
                    cld
                    rep     movsb
                    mov     [ebx].crf_eax.lo, 0
                .else near
                    mov     [ebx].crf_eax.lo, -1
                .endif

            .elseif <dx eq 1010h>               ; 16 x 16 dots
                mov     ax, cx
                call    vvGetDBCSFont
                .if     <nc>
                    mov     [ebx].crf_eax.lo, 0
                .else near
                    mov     [ebx].crf_eax.lo, -1
                .endif
                mov     ecx, FONT_HEIGHT_LOW
                cld
                rep     movsw

            .elseif <dx eq 0c18h> near          ; 12 x 24 dots
                mov     ax, cx
                call    VfntGetSBCS24Font
                .if     <nc>
                    mov     ecx, 24*2
                    cld
                    rep     movsb
                    mov     [ebx].crf_eax.lo, 0
                .else near
                    mov     [ebx].crf_eax.lo, -1
                .endif

            .elseif <dx eq 1818h> near          ; 24 x 24 dots
                mov     ax, cx
                call    VfntGetDBCS24Font
                .if     <nc>
                    mov     [ebx].crf_eax.lo, 0
                .else near
                    mov     [ebx].crf_eax.lo, -1
                .endif
                mov     ecx, 24*3
                cld
                rep     movsb

            .else near
                mov     [ebx].crf_eax.lo, -1
            .endif

        .elseif <al eq 01h> near                ; put font ?
            .if     <dx eq 0810h>               ;  8 x 16 dots
                mov     [ebx].crf_eax.lo, -1    ; not supported

            .elseif <dx eq 0813h>               ;  8 x 19 dots
                mov     [ebx].crf_eax.lo, -1    ; not supported

            .elseif <dx eq 1010h>               ; 16 x 16 dots
                .if     <ch ae UserFontVector[0]> and   ; char code check
                .if     <ch be UserFontVector[1]>
                    mov     esi, edi
                    mov     ax, cx
                    call    VfntPutDBCS16Font
                    .if     <nc>
                        mov     [ebx].crf_eax.lo, 0
                    .else
                        mov     [ebx].crf_eax.lo, -1
                    .endif
                .endif

            .elseif <dx eq 0813h>               ; 12 x 24 dots
                mov     [ebx].crf_eax.lo, -1    ; not supported

            .elseif <dx eq 1818h>               ; 24 x 24 dots
                .if     <ch ae UserFontVector[0]> and   ; char code check
                .if     <ch be UserFontVector[1]>
                    mov     esi, edi
                    mov     ax, cx
                    call    VfntPutDBCS24Font
                    .if     <nc>
                        mov     [ebx].crf_eax.lo, 0
                    .else
                        mov     [ebx].crf_eax.lo, -1
                    .endif
                .endif

            .else
                mov     [ebx].crf_eax.lo, -1
            .endif
        .endif

        clc
        ExitProc
EndProc     vvInt10RequestFontGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadDispTypeGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read display combination.                        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Never)                                         */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Always)         */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadDispTypeGale
        stc
        ExitProc
EndProc     vvInt10ReadDispTypeGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ShiftStatGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get/Release shift status line.                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ShiftStatGale
        .if     <al eq 00h>                     ; get shift status line
            mov     ax, [ebx].crf_ebx.off
            movzx   cx, Gale_Max_Row
            .if     <ax b cx>
                sub     cx, ax
                dec     cx
                mov     VDMBase.rb_nVRows, cl
            .endif
        .elseif <al eq 01h>                     ; release shift status line
            mov     al, Gale_Max_Row
            dec     al
            mov     VDMBase.rb_nVRows, al
        .elseif <al eq 02h>                     ; query shift status line
            mov     al, Gale_Max_Row
            sub     al, VDMBase.rb_nVRows
            dec     al
            movzx   ax, al
            mov     [ebx].crf_ebx.off, ax
        .endif
        clc
        ExitProc
EndProc     vvInt10ShiftStatGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10GetVideoBufGale                            */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get video buffer.                                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10GetVideoBufGale
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            mov     eax, VDMData.GaleData.GaleLVB
            shr     eax, 4
            mov     [ebx].crf_es, ax
            mov     [ebx].crf_edi.off, 0
        .endif
        clc
        ExitProc
EndProc     vvInt10GetVideoBufGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10UpdateVideoGale                            */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get video buffer.                                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10UpdateVideoGale
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            movzx   esi, [ebx].crf_es
            movzx   eax, [ebx].crf_edi.off
            shl     esi, 4
            add     eax, esi
            sub     eax, VDMData.GaleData.GaleLVB
            .if     <eax b 80*25*2>             ; check pointer points into LVB
                shr     eax, 1
                mov     dl, SCREEN_WIDTH
                div     dl
                mov     dh, al
                mov     dl, ah                  ; (row,col) position
                mov     cx, [ebx].crf_ecx.off   ; char count
                call    RedrawScreenGale
            .endif
        .endif
        clc
        ExitProc
EndProc     vvInt10UpdateVideoGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStrGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string.                                    */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStrGale

        LocalVar    vva,    VVSTRING
IFDEF   XVIO
        LocalVar    vxa,    VXSTRING
ENDIF   ;XVIO

        EnterProc

        .if     <[ebx].crf_eax.lo eq 0ffh>
            call    vvInt10WriteStrGalePrivate
            jmp     WriteStrExit
        .endif

        push    ebx
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED> and   ; windowed ?
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            .if     <al b 20h>
                call    vvInt10WriteStrWindowedGale
                jmp     WriteStrExit
            .endif
        .endif

        .if <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            call    vvInt10WriteStr4Gale
        .else
            call    vvInt10WriteStr2Gale
        .endif
        pop     ebx

IFDEF   XVIO
        mov     dx, [ebx].crf_edx.off           ; start cursor pos
        movzx   eax, dh
        mov     vxa.vxa_row, eax                ; row of string
        mov     al, dl
        mov     vxa.vxa_col, eax                ; column of string
        movzx   eax, [ebx].crf_ecx.off
        mov     vxa.vxa_nChars, eax             ; length
        SSToDS  eax, vxa
        push    ebx
        CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, eax, 0>
        pop     ebx

        .if     <[ebx].crf_eax.lo eq 01h> or
        .if     <[ebx].crf_eax.lo eq 03h>
            CallFn  vxUpdateCursorData, <CURRENT_VDM>
        .endif
ENDIF   ;XVIO
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED> and   ; windowed ?
        .if     <[ebx].crf_ecx.off ne 0> and
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dx, [ebx].crf_edx.off       ; start cursor pos
            movzx   eax, dh
            mov     vva.vva_row, eax            ; row of string
            mov     al, dl
            mov     vva.vva_col, eax            ; column of string
            movzx   eax, [ebx].crf_ecx.off
            mov     vva.vva_nChars, eax         ; length
            SSToDS  eax, vva
            push    ebx
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>
            pop     ebx
            .if     <[ebx].crf_eax.lo eq 01h> or
            .if     <[ebx].crf_eax.lo eq 03h>
                CallFn  vvUpdateCursorData, <CURRENT_VDM>
            .endif
        .endif

WriteStrExit:
        ExitProc
EndProc     vvInt10WriteStrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStrGalePrivate                        */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (private interface)                 */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStrGalePrivate

        movzx   esi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     esi, 4
        add     esi, eax                        ; ESI = source str pointer
        movzx   ecx, [ebx].crf_ecx.off          ; character count

        .if     <ecx ne 0>
            call    HideCursorGale              ; hide cursor

            call    SetupAPAWriteGale           ; prepare to write

            .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> and
            .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
                mov     ah, DEFAULT_ATTR0 ; default attr in graphics mode
            .endif

WriteStrPrivateLoop:
            mov     al, [esi]
            push    ax
            push    ecx
            push    esi
            call    vvWriteTTYGale
            pop     esi
            pop     ecx
            pop     ax
            inc     esi
            loop    WriteStrPrivateLoop

            call    SetCursorGale               ; net new cursor

IFDEF   XVIO
            CallFn  vxUpdateCursorData, <CURRENT_VDM>
ENDIF   ;XVIO

            .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
                CallFn  vvUpdateCursorData, <CURRENT_VDM>
            .endif

            call    DrawCursorGale              ; draw cursor
        .endif

        ExitProc
EndProc     vvInt10WriteStrGalePrivate

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStrWindowedGale                       */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (mode 03h and 73h)                  */
;/*                                 (command 01h, 02h, 03h, 04h)        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStrWindowedGale
        LocalVar cmd,            BYTE
        LocalVar CharAttr0,      WORD
        LocalVar Attr1Attr2,     WORD
        LocalVar CharAttr0_2nd,  WORD
        LocalVar Attr1Attr2_2nd, WORD
        LocalVar StartPos,       WORD
        LocalVar count,          WORD
        LocalVar    vva,         VVSTRING

        EnterProc
        mov     cmd, al                         ; save command
        mov     al, [ebx].crf_ebx.lo
        mov     byte ptr CharAttr0+1, al        ; save attribute
        mov     byte ptr CharAttr0_2nd+1, al
        mov     Attr1Attr2, DEFAULT_ATTR1_ATTR2 ; set default attribute
        mov     Attr1Attr2_2nd, DEFAULT_ATTR1_ATTR2

        movzx   esi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     esi, 4
        add     esi, eax                        ; ESI = source str pointer

        mov     cx, [ebx].crf_ecx.off           ; character count

        mov     dx, [ebx].crf_edx.off           ; start cursor pos

        mov     count, 0                        ; windowed event counter
        mov     StartPos, dx                    ; save start cursor position

        call    MakePointer                     ; EBX = pointer into LVB
        .if     c or                            ; overflow check
        .if     <cx eq 0>                       ; zero length check
            jmp     WriteStrWindowedExit
        .endif

WriteStrWindowedLoop:
        movzx   eax, byte ptr [esi]             ; get one char
        .if     <cmd be 03h> near
            .if     <count ne 0> and
            .if     <al eq 0dh> or              ; Carrige Return ?
            .if     <al eq 0ah> or              ; Line Feed ?
            .if     <al eq 08h> or              ; Back Space ?
            .if     <al eq 07h>                 ; Bell ?
                movzx   edi, byte ptr StartPos+1
                mov     vva.vva_row, edi        ; row of string
                movzx   edi, byte ptr StartPos
                mov     vva.vva_col, edi        ; column of string
                movzx   edi, count
                mov     vva.vva_nChars, edi     ; length
                SSToDS  edi, vva
                pushad
                CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, edi, 0>
                popad
IFDEF   XVIO
                pushad
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, edi, 0>
                popad
ENDIF   ;XVIO
            .endif

            .if     <al eq 0dh>                 ; Carrige Return ?
                xor     dl, dl
                call    MakePointer             ; calc new pointer

            .elseif <al eq 0ah>                 ; Line Feed ?
                inc     dh
                .if     <dh a VDMBase.rb_nVRows>
                    dec     dh
                    .if     <dh eq VDMBase.rb_nVRows>
                        call    vvScrollUpOneGale
                    .endif
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 08h>                 ; Back Space ?
                .if     <dl ne 0>
                    dec     dl
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 07h>                 ; Bell ?
                push    cx
                push    dx
                CallFn  VDHDevBeep,<BELL_FREQ, BELL_DURATION>
                pop     dx
                pop     cx
            .else                               ; printable ?
                jmp     WriteStrWindowedChar
            .endif
            mov     StartPos, dx
            mov     count, 0
            inc     esi
            dec     cx
            jnz     WriteStrWindowedLoop
            jmp     WriteStrWindowedSetCur
        .endif

WriteStrWindowedChar:
        mov     byte ptr CharAttr0, al
        cmp     DBCS1st[eax], 0
        jne     WriteStrWindowedDBCS

WriteStrWindowedSBCS:
        .if <cmd ae 02h>                        ; char/attr draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
        .endif

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            mov     ax, CharAttr0               ; update LVB
            mov     [ebx], ax
        .else
            mov     ax, Attr1Attr2              ; update LVB
            mov     [ebx+2], ax
            mov     ax, CharAttr0
            mov     [ebx], ax
        .endif

        mov     al, 1                           ; increment count
        jmp     WriteStrWindowedIncPtr

WriteStrWindowedDBCS:
        .if     <cx eq 1>                       ; check length
            mov     al, 1                       ; increment count
            jmp     WriteStrWindowedIncPtr
        .endif

        .if <cmd ae 02h>                        ; char/attr draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
            mov     ax, [esi+2]
            mov     CharAttr0_2nd, ax
        .else                                   ; char only draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0_2nd, al
        .endif

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            mov     ax, CharAttr0                   ; update LVB
            mov     [ebx], ax
            mov     ax, CharAttr0_2nd
            mov     [ebx+2], ax
        .else
            mov     ax, CharAttr0                   ; update LVB
            mov     [ebx], ax
            mov     ax, Attr1Attr2
            mov     [ebx+2], ax
            mov     ax, CharAttr0_2nd
            mov     [ebx+4], ax
            mov     ax, Attr1Attr2_2nd
            mov     [ebx+6], ax
        .endif

        mov     al, 2                           ; increment count

WriteStrWindowedIncPtr:
        .if     <cmd be 01h>                    ; inc source str pointer
            inc     esi
        .else
            add     esi, 2
        .endif
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            add     ebx, 2                      ; inc LVB ptr
        .else
            add     ebx, 4                      ; inc LVB ptr
        .endif
        inc     dl                              ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            xor     dl, dl
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows> and
                .if     <count ne 0>
                    movzx   edi, byte ptr StartPos+1
                    mov     vva.vva_row, edi        ; row of string
                    movzx   edi, byte ptr StartPos
                    mov     vva.vva_col, edi        ; column of string
                    movzx   edi, count
                    mov     vva.vva_nChars, edi     ; length
                    SSToDS  edi, vva
                    pushad
                    CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, edi, 0>
                    popad
IFDEF   XVIO
                    pushad
                    CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, edi, 0>
                    popad
ENDIF   ;XVIO
                    mov     StartPos, dx
                    mov     count, 0
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer             ; calc new pointer
            .endif
        .endif

        inc     count
        dec     cx
        jz      WriteStrWindowedSetCur
        dec     al
        jnz     WriteStrWindowedIncPtr
        jmp     WriteStrWindowedLoop

WriteStrWindowedSetCur:
        .if     <count ne 0>
            movzx   edi, byte ptr StartPos+1
            mov     vva.vva_row, edi            ; row of string
            movzx   edi, byte ptr StartPos
            mov     vva.vva_col, edi            ; column of string
            movzx   edi, count
            mov     vva.vva_nChars, edi         ; length
            SSToDS  edi, vva
            pushad
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, edi, 0>
            popad
IFDEF   XVIO
            pushad
            CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, edi, 0>
            popad
ENDIF   ;XVIO
        .endif

        .if     <cmd eq 01h> or
        .if     <cmd eq 03h>
            mov     VDMBase.rb_awVCursorPos, dx
            call    SetCursorGale               ; net new cursor
IFDEF   XVIO
            CallFn  vxUpdateCursorData, <CURRENT_VDM>
ENDIF   ;XVIO
            CallFn  vvUpdateCursorData, <CURRENT_VDM>
        .endif

WriteStrWindowedExit:
        ExitProc
EndProc     vvInt10WriteStrWindowedGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStr2Gale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (char/attr0 format).                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStr2Gale

        LocalVar    cmd,  BYTE
        LocalVar    attr, BYTE

        EnterProc

        mov     cmd, al                         ; save command

        mov     al, [ebx].crf_ebx.lo
        mov     attr, al                        ; save attribute

        movzx   esi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     esi, 4
        add     esi, eax                        ; ESI = source str pointer
        mov     cx, [ebx].crf_ecx.off           ; character count
        .if     <cmd ne 0ffh>
            mov     dx, [ebx].crf_edx.off       ; start cursor pos
        .else
            mov     dx, VDMBase.rb_awVCursorPos ; private interface
        .endif

        call    SetupAPAWriteGale               ; setup write mode
        call    MakePointer                     ; EDI = pointer into APA
                                                ; EBX = pointer into LVB
        .if     c or                            ; overflow check
        .if     <cx eq 0>                       ; zero length check
            jmp     WriteStr2Exit
        .endif

        .if     <cmd be 01h>
            mov     al, attr
            call    vvInt10WriteStr2_0001Gale

        .elseif <cmd be 03h>
            call    vvInt10WriteStr2_0203Gale

        .elseif <cmd eq 20h>
            call    vvInt10WriteStr2_20Gale

        .endif

        .if     <cmd eq 01h> or
        .if     <cmd eq 03h>
            mov     VDMBase.rb_awVCursorPos, dx
            call    SetCursorGale               ; net new cursor
        .endif

WriteStr2Exit:
        ExitProc

EndProc     vvInt10WriteStr2Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStr2_0001Gale                         */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (char/attr0 format).                */
;/*                    AL = attribute                                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStr2_0001Gale

        LocalVar attr, BYTE

        EnterProc
        mov     attr, al                        ; save attribute

WriteStr2_0001Loop:
        movzx   eax, byte ptr [esi]             ; get one char
        .if     <al be 0dh>                     ; may be control char ?
            .if     <al eq 0dh>                 ; Carrige Return ?
                xor     dl, dl
                call    MakePointer             ; calc new pointer

            .elseif <al eq 0ah>                 ; Line Feed ?
                inc     dh
                .if     <dh a VDMBase.rb_nVRows>
                    dec     dh
                    .if     <dh eq VDMBase.rb_nVRows>
                        call    vvScrollUpOneGale
                    .endif
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 08h>                 ; Back Space ?
                .if     <dl ne 0>
                    dec     dl
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 07h>                 ; Bell ?
                push    cx
                push    dx
                CallFn  VDHDevBeep,<BELL_FREQ, BELL_DURATION>
                pop     dx
                pop     cx
            .else                               ; printable ?
                jmp     WriteStr2_0001Char
            .endif
            inc     esi
            jmp     WriteStr2_0001Next
        .endif

WriteStr2_0001Char:
        cmp     DBCS1st[eax], 0
        jne     WriteStr2_0001DBCS

WriteStr2_0001SBCS:
        mov     ah, attr                        ; update LVB
        mov     [ebx], ax
        push    esi
        call    vvGetSBCSFont                   ; get font image
        call    vvUpdateAPAwithSBCS             ; draw APA
        pop     esi

WriteStr2_0001IncPtr:
        inc     esi                             ; inc source str pointer
        add     ebx, 2                          ; inc LVB ptr
        inc     dl                              ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            xor     dl, dl
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .endif
        .else
            inc     edi
        .endif
        and     edi, APA_ADDR_MASK
        jmp     WriteStr2_0001Next

WriteStr2_0001DBCS:
        .if     <cx eq 1>                       ; check length
            jmp     WriteStr2_0001IncPtr
        .endif

        mov     ah, attr                        ; update LVB
        mov     [ebx], ax
        mov     al, [esi+1]
        mov     [ebx+2], ax
        mov     ah, [esi]
        mov     al, [esi+1]
        push    esi
        call    vvGetDBCSFont                   ; get font image
        call    vvUpdateAPAwithDBCS             ; draw APA
        pop     esi

        add     esi, 2                          ; inc source str pointer
        add     ebx, 4                          ; inc LVB ptr
        add     dl, 2                           ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            sub     dl, SCREEN_WIDTH
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .endif
        .else
            add     edi, 2
        .endif
        and     edi, APA_ADDR_MASK

        dec     cx

WriteStr2_0001Next:
        dec     cx
        jz      WriteStr2_0001Exit
        jmp     WriteStr2_0001Loop

WriteStr2_0001Exit:
        ExitProc
EndProc     vvInt10WriteStr2_0001Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStr2_0203Gale                         */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (char/attr0 format).                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStr2_0203Gale

WriteStr2_0203Loop:
        movzx   eax, byte ptr [esi]             ; get one char
        .if     <al be 0dh>                     ; may be control char ?
            .if     <al eq 0dh>                 ; Carrige Return ?
                xor     dl, dl
                call    MakePointer             ; calc new pointer

            .elseif <al eq 0ah>                 ; Line Feed ?
                inc     dh
                .if     <dh a VDMBase.rb_nVRows>
                    dec     dh
                    .if     <dh eq VDMBase.rb_nVRows>
                        call    vvScrollUpOneGale
                    .endif
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 08h>                 ; Back Space ?
                .if     <dl ne 0>
                    dec     dl
                .endif
                call    MakePointer             ; calc new pointer

            .elseif <al eq 07h>                 ; Bell ?
                push    cx
                push    dx
                CallFn  VDHDevBeep,<BELL_FREQ, BELL_DURATION>
                pop     dx
                pop     cx
            .else                               ; printable ?
                jmp     WriteStr2_0203Char
            .endif
            inc     esi
            jmp     WriteStr2_0203Next
        .endif

WriteStr2_0203Char:
        cmp     DBCS1st[eax], 0
        jne     WriteStr2_0203DBCS

WriteStr2_0203SBCS:
        mov     ah, [esi+1]                     ; update LVB
        mov     [ebx], ax
        push    esi
        call    vvGetSBCSFont                   ; get font image
        call    vvUpdateAPAwithSBCS             ; draw APA
        pop     esi

WriteStr2_0203IncPtr:
        add     esi, 2                          ; inc source str pointer
        add     ebx, 2                          ; inc LVB ptr
        inc     dl                              ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            xor     dl, dl
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .endif
        .else
            inc     edi
        .endif
        and     edi, APA_ADDR_MASK
        jmp     WriteStr2_0203Next

WriteStr2_0203DBCS:
        .if     <cx eq 1>                       ; check length
            jmp     WriteStr2_0203IncPtr
        .endif

        mov     ah, [esi+1]                     ; update LVB
        mov     [ebx], ax
        mov     ax, [esi+2]
        mov     [ebx+2], ax
        mov     ah, [esi]
        mov     al, [esi+2]
        push    esi
        call    vvGetDBCSFont                   ; get font image
        call    vvUpdateAPAwithDBCS             ; draw APA
        pop     esi

        add     esi, 4                          ; inc source str pointer
        add     ebx, 4                          ; inc LVB ptr
        add     dl, 2                           ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            sub     dl, SCREEN_WIDTH
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .endif
        .else
            add     edi, 2
        .endif
        and     edi, APA_ADDR_MASK

        dec     cx

WriteStr2_0203Next:
        dec     cx
        jz      WriteStr2_0203Exit
        jmp     WriteStr2_0203Loop

WriteStr2_0203Exit:
        ExitProc
EndProc     vvInt10WriteStr2_0203Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStr2_20Gale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (char/attr0 format).                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStr2_20Gale

WriteStr2_20Loop:
        movzx   eax, byte ptr [esi]             ; get one char
        cmp     DBCS1st[eax], 0
        jne     WriteStr2_20DBCS

WriteStr2_20SBCS:
        mov     ah, [esi+1]                     ; update LVB
        mov     [ebx], ax
        push    esi
        call    vvGetSBCSFont                   ; get font image
        call    vvUpdateAPAwithSBCS             ; draw APA
        pop     esi

WriteStr2_20IncPtr:
        add     esi, 2                          ; inc source str pointer
        add     ebx, 2                          ; inc LVB ptr
        inc     dl                              ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            xor     dl, dl
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                jmp     WriteStr2_20Exit
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .endif
        .else
            inc     edi
        .endif
        and     edi, APA_ADDR_MASK
        jmp     WriteStr2_20Next

WriteStr2_20DBCS:
        .if     <cx eq 1>                       ; check length
            jmp     WriteStr2_20IncPtr
        .endif

        mov     ah, [esi+1]                     ; update LVB
        mov     [ebx], ax
        mov     ax, [esi+2]
        mov     [ebx+2], ax
        mov     ah, [esi]
        mov     al, [esi+2]
        push    esi
        call    vvGetDBCSFont                   ; get font image
        call    vvUpdateAPAwithDBCS             ; draw APA
        pop     esi

        add     esi, 4                          ; inc source str pointer
        add     ebx, 4                          ; inc LVB ptr
        add     dl, 2                           ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            sub     dl, SCREEN_WIDTH
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                jmp     WriteStr2_20Exit
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .endif
        .else
            add     edi, 2
        .endif
        and     edi, APA_ADDR_MASK

        dec     cx

WriteStr2_20Next:
        dec     cx
        jz      WriteStr2_20Exit
        jmp     WriteStr2_20Loop

WriteStr2_20Exit:
        ExitProc
EndProc     vvInt10WriteStr2_20Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10WriteStr4Gale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string (char/attr0/attr1/attr2 format).    */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10WriteStr4Gale
        LocalVar cmd,            BYTE
        LocalVar CharAttr0,      WORD
        LocalVar Attr1Attr2,     WORD
        LocalVar CharAttr0_2nd,  WORD
        LocalVar Attr1Attr2_2nd, WORD

        EnterProc
        mov     cmd, al                         ; save command
        mov     al, [ebx].crf_ebx.lo
        mov     byte ptr CharAttr0+1, al        ; save attribute
        mov     byte ptr CharAttr0_2nd+1, al
        mov     Attr1Attr2, DEFAULT_ATTR1_ATTR2 ; set default attribute
        mov     Attr1Attr2_2nd, DEFAULT_ATTR1_ATTR2

        movzx   esi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     esi, 4
        add     esi, eax                        ; ESI = source str pointer
        mov     cx, [ebx].crf_ecx.off           ; character count
        mov     dx, [ebx].crf_edx.off           ; start cursor pos

        call    SetupAPAWriteGale               ; setup write mode
        call    MakePointer                     ; EDI = pointer into APA
                                                ; EBX = pointer into LVB
        .if     c or                            ; overflow check
        .if     <cx eq 0>                       ; zero length check
            jmp     WriteStr4Exit
        .endif

WriteStr4Loop:
        movzx   eax, byte ptr [esi]             ; get one char
        .if     <cmd be 03h>
            .if     <al be 0dh>
                .if     <al eq 0dh>             ; Carrige Return ?
                    xor     dl, dl
                    call    MakePointer         ; calc new pointer

                .elseif <al eq 0ah>             ; Line Feed ?
                    inc     dh
                    .if     <dh a VDMBase.rb_nVRows>
                        dec     dh
                        .if     <dh eq VDMBase.rb_nVRows>
                            call    vvScrollUpOneGale
                        .endif
                    .endif
                    call    MakePointer         ; calc new pointer

                .elseif <al eq 08h>             ; Back Space ?
                    .if     <dl ne 0>
                        dec     dl
                    .endif
                    call    MakePointer         ; calc new pointer

                .elseif <al eq 07h>             ; Bell ?
                    push    cx
                    push    dx
                    CallFn  VDHDevBeep,<BELL_FREQ, BELL_DURATION>
                    pop     dx
                    pop     cx
                .else                           ; printable ?
                    jmp     WriteStr4Char
                .endif
                inc     esi
                jmp     WriteStr4Next
            .endif
        .endif

WriteStr4Char:
        cmp     DBCS1st[eax], 0
        jne     WriteStr4DBCS

WriteStr4SBCS:
        mov     byte ptr CharAttr0, al
        .if     <cmd eq 02h> or                 ; char/attr draw
        .if     <cmd eq 03h> or
        .if     <cmd eq 20h>
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
        .elseif <cmd eq 21h>                    ; char/attr012 draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
            mov     ax, [esi+2]
            mov     Attr1Attr2, ax
        .endif

        mov     ax, Attr1Attr2                  ; update LVB
        mov     [ebx+2], ax
        mov     ax, CharAttr0
        mov     [ebx], ax
        push    esi
        call    vvGetSBCSFont                   ; get font image
        call    vvUpdateAPAwithSBCS             ; draw APA
        pop     esi

WriteStr4IncPtr:
        .if     <cmd eq 00h> or                 ; inc source str pointer
        .if     <cmd eq 01h>
            inc     esi
        .elseif <cmd eq 21h>
            add     esi, 4
        .else
            add     esi, 2
        .endif
        add     ebx, 4                          ; inc LVB ptr
        inc     dl                              ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            xor     dl, dl
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                .if     <cmd eq 20h> or
                .if     <cmd eq 21h>
                    jmp     WriteStr4Exit
                .endif
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .endif
        .else
            inc     edi
        .endif
        and     edi, APA_ADDR_MASK
        jmp     WriteStr4Next

WriteStr4DBCS:
        .if     <cx eq 1>                       ; check length
            jmp     WriteStr4IncPtr
        .endif

        mov     byte ptr CharAttr0, al
        .if     <cmd eq 02h> or                 ; char/attr draw
        .if     <cmd eq 03h> or
        .if     <cmd eq 20h>
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
            mov     ax, [esi+2]
            mov     CharAttr0_2nd, ax
        .elseif <cmd eq 21h>                    ; char/attr012 draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0+1, al
            mov     ax, [esi+2]
            mov     Attr1Attr2, ax
            mov     ax, [esi+4]
            mov     CharAttr0_2nd, ax
            mov     ax, [esi+6]
            mov     Attr1Attr2_2nd, ax
        .else                                   ; char only draw
            mov     al, [esi+1]
            mov     byte ptr CharAttr0_2nd, al
        .endif

        mov     ax, CharAttr0                   ; update LVB
        mov     [ebx], ax
        mov     ax, Attr1Attr2
        mov     [ebx+2], ax
        mov     ax, CharAttr0_2nd
        mov     [ebx+4], ax
        mov     ax, Attr1Attr2_2nd
        mov     [ebx+6], ax
        mov     ah, byte ptr CharAttr0
        mov     al, byte ptr CharAttr0_2nd
        push    esi
        call    vvGetDBCSFont                   ; get font image
        call    vvUpdateAPAwithDBCS             ; draw APA
        pop     esi

        .if     <cmd eq 00h> or                 ; inc source str pointer
        .if     <cmd eq 01h>
            add     esi, 2
        .elseif <cmd eq 21h>
            add     esi, 8
        .else
            add     esi, 4
        .endif
        add     ebx, 8                          ; inc LVB ptr
        add     dl, 2                           ; inc (row,col) & APA ptr
        .if     <dl ae SCREEN_WIDTH>
            sub     dl, SCREEN_WIDTH
            inc     dh
            .if     <dh a VDMBase.rb_nVRows>
                .if     <cmd eq 20h> or
                .if     <cmd eq 21h>
                    jmp     WriteStr4Exit
                .endif
                dec     dh
                .if     <dh eq VDMBase.rb_nVRows>
                    call    vvScrollUpOneGale
                .endif
                call    MakePointer                 ; calc new pointer
            .else
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .endif
        .else
            add     edi, 2
        .endif
        and     edi, APA_ADDR_MASK

        dec     cx

WriteStr4Next:
        dec     cx
        jz      WriteStr4SetCur
        jmp     WriteStr4Loop

WriteStr4SetCur:
        .if     <cmd eq 01h> or
        .if     <cmd eq 03h>
            mov     VDMBase.rb_awVCursorPos, dx
            call    SetCursorGale               ; net new cursor
        .endif

WriteStr4Exit:
        ExitProc
EndProc     vvInt10WriteStr4Gale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvInt10ReadStrGale                                */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Read string.                                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  AH:AL value from V86 mode                                */
;/*     EBX -> VDM register frame                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (pass control to PC-DOS routine) (Never)          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvInt10ReadStrGale

        mov     dx, [ebx].crf_edx.off           ; start cursor pos
        .if     <dh ge Gale_Max_Row> or         ; position check
        .if     <dl ge SCREEN_WIDTH>
            jmp     ReadStrExit
        .endif
        .if     <al eq 11h> and                 ; check mode
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
            jmp     ReadStrExit
        .endif
        .if     <[ebx].crf_ecx.off eq 0>        ; char count check
            jmp     ReadStrExit
        .endif

        mov     al, SCREEN_WIDTH
        mul     Gale_Max_Row
        movzx   ecx, ax                         ; max character number

        mov     al, SCREEN_WIDTH
        mul     dh
        movzx   esi, ax
        movzx   eax, dl
        add     esi, eax
        sub     ecx, esi
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     esi, 2
        .else
            shl     esi, 1
        .endif
        add     esi, VDMData.GaleData.GaleLVB   ; ESI = pointer into LVB

        movzx   edi, [ebx].crf_es
        movzx   eax, [ebx].crf_ebp.off
        shl     edi, 4
        add     edi, eax                        ; EDI = target str pointer

        .if     <[ebx].crf_ecx.off lt cx>
            mov     cx, [ebx].crf_ecx.off       ; CX = requested char count
        .endif

        cld

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            .if     <[ebx].crf_eax.lo eq 10h>
ReadStrLoop:
                movsw
                add     esi, 2
                loop    ReadStrLoop
            .else
                rep     movsd
            .endif
        .else
            rep     movsw
        .endif

ReadStrExit:
        ExitProc
EndProc     vvInt10ReadStrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: RedrawScreenGale                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Redraw specified region of LVB in text mode.     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*       DX = Start (Row,Column) position                              */
;/*       CX = Character count                                          */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   RedrawScreenGale

        LocalVar    vva,       VVSTRING
IFDEF   XVIO
        LocalVar    vxa,       VXSTRING
ENDIF   ;XVIO

        EnterProc

        .if     <cx eq 0> or
        .if     <dh ae Gale_Max_Row> or
        .if     <dl ae SCREEN_WIDTH>
            jmp     RedrawExit2
        .endif

        call    MakePointer                     ; EBX = LVB pointer
        .if     c                               ; EDI = APA pointer
            jmp     RedrawExit2
        .endif

        mov     al, Gale_Max_Row
        sub     al, dh
        mov     ah, SCREEN_WIDTH
        mul     ah
        add     ax, SCREEN_WIDTH
        sub     al, dl
        sbb     ah, 0
        .if     <cx a ax>                       ; check char count
            mov     cx, ax
        .endif
        movzx   ecx, cx

        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
            mov     vva.vva_nChars, ecx         ; length
            movzx   eax, dh
            mov     vva.vva_row, eax            ; row of string
            mov     al, dl
            mov     vva.vva_col, eax            ; column of string
            SSToDS  eax, vva
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>
            jmp     RedrawExit2
        .endif

        call    HideCursorGale                  ; hide cursor

        call    SetupAPAWriteGale

        push    ebp

        mov     ebp, SkipLineAPA
        sub     ebp, SCREEN_WIDTH-1

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> near

RedrawLoop1:
            movzx   eax, byte ptr [ebx]
            cmp     DBCS1st[eax], 0
            jne     RedrawDBCS1

RedrawSBCS1:
            call    vvGetSBCSTextFont           ; get font image
            call    vvUpdateAPAwithSBCS2        ; draw APA with SBCS

            add     ebx, 2                      ; increase pointers
            inc     dl
            .if     <dl ge SCREEN_WIDTH>
                xor     dl, dl
                inc     dh
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .else
                inc     edi
            .endif
            and     edi, APA_ADDR_MASK
            loop    RedrawLoop1
            jmp     RedrawExit

RedrawDBCS1:
            .if     <ecx b 2>                   ; check length
                jmp     RedrawExit
            .endif

            mov     ah, al
            mov     al, [ebx+2]
            call    vvGetDBCSFont               ; get font image
            call    vvUpdateAPAwithDBCS2        ; draw APA with DBCS

            add     ebx, 4                      ; increase pointers
            add     dl, 2
            .if     <dl ge SCREEN_WIDTH>
                sub     dl, SCREEN_WIDTH
                inc     dh
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .else
                add     edi, 2
            .endif
            and     edi, APA_ADDR_MASK
            sub     ecx, 2
            jnz     RedrawLoop1

        .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE> near

RedrawLoop2:
            mov     al, [ebx]
            movzx   eax, byte ptr [ebx]
            cmp     DBCS1st[eax], 0
            jne     RedrawDBCS2

RedrawSBCS2:
            call    vvGetSBCSTextFont           ; get font image
            call    vvUpdateAPAwithSBCS4        ; draw APA with SBCS

            add     ebx, 4                      ; increase pointers
            inc     dl
            .if     <dl ge SCREEN_WIDTH>
                xor     dl, dl
                inc     dh
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-1
            .else
                inc     edi
            .endif
            and     edi, APA_ADDR_MASK
            loop    RedrawLoop2
            jmp     RedrawExit

RedrawDBCS2:
            .if     <ecx b 2>                   ; check length
                jmp     RedrawExit
            .endif

            mov     ah, al
            mov     al, [ebx+4]
            call    vvGetDBCSFont               ; get font image
            call    vvUpdateAPAwithDBCS4        ; draw APA with DBCS

            add     ebx, 8                      ; increase pointers
            add     dl, 2
            .if     <dl ge SCREEN_WIDTH>
                sub     dl, SCREEN_WIDTH
                inc     dh
                add     edi, SkipLineAPA
                sub     edi, SCREEN_WIDTH-2
            .else
                add     edi, 2
            .endif
            and     edi, APA_ADDR_MASK
            sub     ecx, 2
            jnz     RedrawLoop2

        .endif

RedrawExit:
        pop     ebp
        call    DrawCursorGale                  ; draw cursor

RedrawExit2:
IFDEF   XVIO
        mov     vxa.vxa_nChars, ecx             ; length
        movzx   eax, dh
        mov     vxa.vxa_row, eax                ; row of string
        mov     al, dl
        mov     vxa.vxa_col, eax                ; column of string
        SSToDS  eax, vxa
        CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, eax, 0>
ENDIF   ;XVIO
        ExitProc
EndProc     RedrawScreenGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpOneGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up one line.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpOneGale
        push    eax                             ; save all regs
        push    ebx
        push    ecx
        push    edx
        push    esi
        push    edi
                                                ; blank attribute
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode ?
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dh, VDMBase.rb_nVRows
            mov     dl, 0                       ; (lowest, leftmost) char pos
            call    MakePointer
            mov     bh, [ebx+1]
        .else                                   ; graphics mode
            mov     bh, 00h                     ; black
        .endif

        mov     al, 1                           ; number of scroll line
        mov     ch, 0                           ; upper left position
        mov     cl, 0
        mov     dh, VDMBase.rb_nVRows           ; lower right position
        mov     dl, SCREEN_WIDTH-1
        call    vvScrollUpGale                  ; scroll
        pop     edi                             ; restore all regs
        pop     esi
        pop     edx
        pop     ecx
        pop     ebx
        pop     eax
        ExitProc
EndProc     vvScrollUpOneGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpGale                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up screen.                                */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpGale

        LocalVar vvs,         VVSCROLL
        LocalVar CursorFlag,  FLAGS

        EnterProc

        .if     <dh ae Gale_Max_Row>            ; check max row
            mov     dh, Gale_Max_Row
            dec     dh
        .endif

        .if     <dl ae SCREEN_WIDTH>            ; check max column
            mov     dl, SCREEN_WIDTH-1
        .endif

        .if     <ch a dh> or                    ; check scroll window
        .if     <cl a dl>
            ExitProc premature
        .endif

        mov     bl, dh                          ; check scroll count
        sub     bl, ch
        inc     bl

        .if     <al a bl> or
        .if     <al eq 0>
            mov     al, bl
        .endif

IFNDEF  XVIO
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
ENDIF   ;XVIO
            mov     bl, ' '
            movzx   ebx, bx
            mov     [vvs].vvs_fill, ebx

            mov     [vvs].vvs_nCols, 0
            movzx   eax, al
            mov     [vvs].vvs_nRows, eax

            movzx   esi, ch
            mov     [vvs].vvs_rcl.yTop, esi
            movzx   esi, cl
            mov     [vvs].vvs_rcl.xLeft, esi
            movzx   esi, dh
            mov     [vvs].vvs_rcl.yBottom, esi
            movzx   esi, dl
            mov     [vvs].vvs_rcl.xRight, esi

IFDEF   XVIO
            .if     <Gale_Text_Mode ne 0>                           ; text mode
                pushad
                SSToDS  eax,[vvs]
                CallFn  vxAddEvent,<CURRENT_VDM, VXEVENT_HIDE, eax, 0>
                CallFn  vxFlushEvent,<CURRENT_VDM, VXEVENT_HIDE, 0>
                popad
            .endif
ENDIF   ;XVIO
            .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
                pushad
                CallFn  vvFlushEvent,<CURRENT_VDM, VVDEVENT_STRING, 0>
                popad
            .endif
IFNDEF  XVIO
        .endif
ENDIF   ;XVIO

        push    ax                              ; scroll up LVB
        push    bx
        push    cx
        push    dx
        .if     <cl eq 0> and
        .if     <dl eq SCREEN_WIDTH-1>
            call    vvScrollUpLVBFastGale
        .else
            call    vvScrollUpLVBGale
        .endif
        pop     dx
        pop     cx
        pop     bx
        pop     ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; windowed ?
        .if     <Gale_Text_Mode ne 0>           ; text mode
            jmp     ScrollUpExit
        .endif
                                                ; confirm cursor hiding
        mov     esi, VDMData.GaleData.GaleCursor.GaleCurDisp
        mov     CursorFlag, esi
        .if     <esi eq TRUE>
            call    HideCursorGale
        .endif
                                                ; scroll up APA
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>

            .if     <GaleScroll eq GALE_HS_ON> or           ; hardware scroll
            .if     <GaleScroll eq GALE_HS_LC>              ; switch on

                .if     <cl eq 0> and                       ; full screen width
                .if     <dl eq SCREEN_WIDTH-1> and
                .if     <al lt Gale_Max_Row> and            ; not screen clear
                mov     ah, dh
                sub     ah, ch
                inc     ah
                .if     <ah ge MIN_ROW_HARD_SCROLL>         ; large area scroll
                    call    vvScrollUpAPAHardGale
                    jmp     ScrollUpRestoreCursor
                .endif
            .endif
        .endif

        .if     <cl eq 0> and
        .if     <dl eq SCREEN_WIDTH-1>
            call    vvScrollUpAPASoftFastGale
        .else
            call    vvScrollUpAPASoftGale
        .endif

ScrollUpRestoreCursor:
        .if     <CursorFlag eq TRUE>            ; restore cursor state
            call    DrawCursorGale
        .endif

ScrollUpExit:
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>       ; windowed ?
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                SSToDS  eax,[vvs]
                CallFn  vvAddEvent,<CURRENT_VDM, VVDEVENT_SCROLL, eax, EVENT_FLUSH>
            .endif
        .endif
IFDEF   XVIO
        .if     <Gale_Text_Mode ne 0>                           ; text mode
            movzx   eax, Gale_Max_Row
            dec     eax
            .if     <[vvs].vvs_rcl.yBottom eq eax>
                SSToDS  eax, [vvs]
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_REDRAW, eax, <XEVENT_FLUSH or XEVENT_FORCE>>
            .else
                SSToDS  eax, [vvs]
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_REDRAW, eax, XEVENT_FLUSH>
            .endif
        .endif
ENDIF   ;XVIO

        ExitProc

EndProc     vvScrollUpGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpLVBGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up LVB.                                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpLVBGale

        LocalVar SourceLVB,   DWORD
        LocalVar TargetLVB,   DWORD
        LocalVar ColCntLVB,   WORD
        LocalVar RowCntLVB,   WORD
        LocalVar SkipLVB,     DWORD
        LocalVar BlankRowLVB, WORD

        LocalVar BlankAttr,   BYTE

        EnterProc
                                                ; save blank attr
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     BlankAttr, bh
        .else                                   ; graphics mode
            mov     BlankAttr, DEFAULT_ATTR0
        .endif

        xor     ah, ah                          ; calc LVB values
        mov     BlankRowLVB, ax                 ; line count to be blanked

        sub     dh, ch
        inc     dh
        sub     dh, byte ptr BlankRowLVB
        movzx   ax, dh
        mov     RowCntLVB, ax                   ; line count to be moved up

        sub     dl, cl
        inc     dl
        movzx   dx, dl
        mov     ColCntLVB, dx                   ; col count per one line

        xor     eax, eax
        mov     ax, SCREEN_WIDTH
        sub     ax, ColCntLVB
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     ax, 2
        .else
            shl     ax, 1
        .endif
        mov     SkipLVB, eax                    ; skip byte per one line

        mov     al, SCREEN_WIDTH
        mul     ch
        movzx   eax, ax
        movzx   ebx, cl
        add     eax, ebx
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     eax, 2
        .else
            shl     eax, 1
        .endif
        add     eax, VDMData.GaleData.GaleLVB
        mov     TargetLVB, eax                  ; target LVB pointer

        mov     al, SCREEN_WIDTH
        mul     byte ptr BlankRowLVB
        movzx   eax, ax
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     eax, 2
        .else
            shl     eax, 1
        .endif
        add     eax, TargetLVB
        mov     SourceLVB, eax                  ; source LVB pointer
                                                ; scroll up LVB
        cld
        mov     esi, SourceLVB
        mov     edi, TargetLVB

        mov     dx, RowCntLVB
        or      dx, dx
        jz      ScrollUpLVBBlank

ScrollUpLoop1:
        movzx   ecx, ColCntLVB

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            rep     movsd
        .else
            rep     movsw
        .endif

        add     esi, SkipLVB
        add     edi, SkipLVB
        dec     dx
        jnz     ScrollUpLoop1
                                                ; blank LVB
ScrollUpLVBBlank:
        mov     eax, DEFAULT_ATTR1_ATTR2*10000h
        mov     ah, BlankAttr
        mov     al, ' '
        mov     dx, BlankRowLVB

ScrollUpLoop2:
        movzx   ecx, ColCntLVB

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            rep     stosd
        .else
            rep     stosw
        .endif

        add     edi, SkipLVB
        dec     dx
        jnz     ScrollUpLoop2

        ExitProc
EndProc     vvScrollUpLVBGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpLVBFastGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up LVB. (screen max width scroll)         */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpLVBFastGale
                                                ; save blank attr in dl
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dl, bh
        .else                                   ; graphics mode
            mov     dl, DEFAULT_ATTR0
        .endif

        sub     dh, ch                          ; calc LVB values
        inc     dh
        sub     dh, al

        mov     ah, SCREEN_WIDTH
        mul     ah
        movzx   ebx, ax                         ; ebx = cell count to be blanked

        mov     al, SCREEN_WIDTH
        mul     ch
        movzx   edi, ax                         ; edi = target cell offset

        mov     al, SCREEN_WIDTH
        mul     dh
        movzx   ecx, ax                         ; ecx = cell count to be moved up

        mov     esi, edi
        add     esi, ebx                        ; esi = source cell offset

        cld

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     esi, 2
            shl     edi, 2
            mov     eax, VDMData.GaleData.GaleLVB
            add     esi, eax                    ; esi = source pointer
            add     edi, eax                    ; edi = target pointer
                                                ; scroll up LVB
            .if     <ecx ne 0>
                rep     movsd
            .endif
                                                ; blank LVB
            mov     ecx, ebx
            mov     eax, DEFAULT_ATTR1_ATTR2*10000h+' '
            mov     ah, dl
            rep     stosd
        .else
            shl     esi, 1
            shl     edi, 1
            mov     eax, VDMData.GaleData.GaleLVB
            add     esi, eax                    ; esi = source pointer
            add     edi, eax                    ; edi = target pointer
                                                ; scroll up LVB
            .if     <ecx ne 0>
                rep     movsw
            .endif
                                                ; blank LVB
            mov     ecx, ebx
            mov     al, ' '
            mov     ah, dl
            rep     stosw
        .endif

        ExitProc
EndProc     vvScrollUpLVBFastGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpAPASoftGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up LVB.                                   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpAPASoftGale

        LocalVar SourceAPA,   DWORD
        LocalVar TargetAPA,   DWORD
        LocalVar ColCntAPA,   WORD
        LocalVar RowCntAPA,   WORD
        LocalVar SkipAPA,     DWORD
        LocalVar BlankRowAPA, WORD

        LocalVar BlankAttr,   BYTE

        EnterProc

        mov     BlankAttr, bh                   ; save blank attr
                                                ; calc APA values
        mul     FontHeight
        mov     BlankRowAPA, ax                 ; laster count to be blanked

        sub     dh, ch
        inc     dh
        mov     al, FontHeight
        mul     dh
        sub     ax, BlankRowAPA
        mov     RowCntAPA, ax                   ; laster count to be scrolled up

        sub     dl, cl
        inc     dl
        movzx   dx, dl
        mov     ColCntAPA, dx                   ; byte count in one laster

        mov     ax, APAWidth
        sub     ax, ColCntAPA
        movzx   eax, ax
        mov     SkipAPA, eax                    ; skip byte in one laster

        mov     ax, word ptr SkipLineAPA
        movzx   bx, ch
        mul     bx
        movzx   eax, ax
        movzx   ebx, cl
        add     eax, ebx
        add     eax, APA_START_ADDR
        movzx   ebx, Gale_Start_Addr
        add     eax, ebx
        and     eax, APA_ADDR_MASK
        mov     TargetAPA, eax                  ; target pointer in APA

        mov     ax, APAWidth
        mul     BlankRowAPA
        movzx   eax, ax
        add     eax, TargetAPA
        and     eax, APA_ADDR_MASK
        mov     SourceAPA, eax                  ; source pointer in APA

        mov     esi, SourceAPA                  ; scroll up APA
        mov     edi, TargetAPA
        call    SetupAPAMoveGale

        cld
        mov     dx, RowCntAPA
        or      dx, dx
        jz      ScrollUpAPASoftBlank

ScrollUpAPASoftLoop1:
        movzx   ecx, ColCntAPA

        call    vvScrollUpAPAEdge

        add     esi, SkipAPA
        add     edi, SkipAPA
        and     esi, APA_ADDR_MASK
        and     edi, APA_ADDR_MASK
        dec     dx
        jnz     ScrollUpAPASoftLoop1
                                                ; blank APA
ScrollUpAPASoftBlank:
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        xor     al, al
        mov     dx, BlankRowAPA

ScrollUpAPASoftLoop2:
        movzx   ecx, ColCntLVB

        call    vvBlankUpAPAEdge

        add     edi, SkipAPA
        dec     dx
        jnz     ScrollUpAPASoftLoop2

        ExitProc

EndProc     vvScrollUpAPASoftGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpAPASoftFastGale                         */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up screen (screen wull width).            */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpAPASoftFastGale

        LocalVar    BlankAttr, BYTE

        EnterProc

        mov     BlankAttr, bh                   ; save blank attr

        sub     dh, ch                          ; calc APA values
        inc     dh
        sub     dh, al
        push    dx

        movzx   ax, al
        mul     word ptr SkipLineAPA
        movzx   ebx, ax                         ; ebx = APA count to be blanked

        movzx   ax, ch
        mul     word ptr SkipLineAPA
        movzx   edi, ax                         ; edi = target APA offset

        pop     dx
        movzx   ax, dh
        mul     word ptr SkipLineAPA
        movzx   ecx, ax                         ; ecx = APA count to be moved up

        mov     esi, edi
        add     esi, ebx                        ; esi = source cell offset

        movzx   eax, Gale_Start_Addr
        add     esi, APA_START_ADDR
        add     esi, eax
        and     esi, APA_ADDR_MASK              ; esi = source pointer
        add     edi, APA_START_ADDR
        add     edi, eax
        and     edi, APA_ADDR_MASK              ; edi = target pointer

        cld
                                                ; scroll up APA
        call    SetupAPAMoveGale
        call    vvScrollUpAPAEdge
                                                ; blank APA
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        mov     ecx, ebx
        call    vvBlankUpAPAEdge

        ExitProc

EndProc     vvScrollUpAPASoftFastGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpAPAHardGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up screen using hardware.                 */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpAPAHardGale

        LocalVar ScrollAPA1,    DWORD
        LocalVar ScrollAPA2,    DWORD
        LocalVar ScrollCntAPA1, WORD
        LocalVar ScrollCntAPA2, WORD
        LocalVar BlankCntAPA,   WORD
        LocalVar NewTopAPA,     WORD

        LocalVar BlankAttr,   BYTE

        EnterProc
                                                ; calc LVB & APA values
        mov     BlankAttr, bh

        push    dx
        movzx   ax, al
        mul     SkipLineAPA
        pop     dx
        mov     BlankCntAPA, ax                 ; byte count to be blanked

        mov     al, Gale_Max_Row
        dec     al
        sub     al, dh
        movzx   ax, al
        push    dx
        mul     SkipLineAPA
        pop     dx                              ; byte count to be moved
        mov     ScrollCntAPA2, ax               ; (lower part)

        movzx   ax, ch
        push    dx
        mul     SkipLineAPA
        pop     dx                              ; byte count to be moved
        mov     ScrollCntAPA1, ax               ; (upper part)

        movzx   eax, Gale_Start_Addr
        movzx   ebx, ScrollCntAPA1
        add     eax, ebx
        dec     eax
        add     eax, APA_START_ADDR
        and     eax, APA_ADDR_MASK
        mov     ScrollAPA1, eax                 ; upper scrolled area top ptr

        movzx   ax, Gale_Max_Row
        push    dx
        mul     SkipLineAPA
        pop     dx
        add     ax, Gale_Start_Addr
        dec     ax
        movzx   eax, ax
        add     eax, APA_START_ADDR
        and     eax, APA_ADDR_MASK
        mov     ScrollAPA2, eax                 ; lower scrolled area top ptr

        mov     ax, Gale_Start_Addr
        add     ax, BlankCntAPA
        mov     NewTopAPA, ax                   ; new VGA start address

                                                ; VGA & XGA bug
                                                ; LineComp cannot be 0
        .if     <GaleScroll eq GALE_HS_LC> and
        .if     <NewTopAPA eq 0ff80h>
            mov     NewTopAPA, 0
            add     ScrollAPA1, 80h
            and     ScrollAPA1, APA_ADDR_MASK
            add     ScrollAPA2, 80h
            and     ScrollAPA2, APA_ADDR_MASK
            movzx   esi, Gale_Start_Addr
            add     esi, APA_START_ADDR+19*25*80h-1
            and     esi, APA_ADDR_MASK
            lea     edi, [esi+80h]
            and     edi, APA_ADDR_MASK
            mov     ecx, 19*25*80h
            std
            call    SetupAPAMoveGale
            call    vvScrollDownAPAEdge
        .endif

        mov     ax, NewTopAPA                   ; scroll APA (hard)
        mov     Gale_Start_Addr, ax
        call    SetAPAStartGale                 ; hardware scroll up
                                                ; adjust upper unscroll area
        call    SetupAPAMoveGale
        std
        .if     <ScrollCntAPA1 ne 0>
            mov     esi, ScrollAPA1
            movzx   edi, BlankCntAPA
            add     edi, esi
            and     edi, APA_ADDR_MASK
            movzx   ecx, ScrollCntAPA1
            call    vvScrollDownAPAEdge
        .endif
                                                ; adjust lower unscroll area
        mov     esi, ScrollAPA2
        movzx   edi, BlankCntAPA
        add     edi, esi
        and     edi, APA_ADDR_MASK
        .if     <ScrollCntAPA2 ne 0>
            movzx   ecx, ScrollCntAPA2
            call    vvScrollDownAPAEdge
        .endif
                                                ; blank APA
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        movzx   ecx, BlankCntAPA
        call    vvBlankDownAPAEdge

        cld

        ExitProc

EndProc     vvScrollUpAPAHardGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollUpAPAEdge                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll up APA with consideration of APA edge.    */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     ESI =  source APA pointer                                       */
;/*     EDI =  target APA pointer                                       */
;/*     ECX =  APA byte count to move                                   */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollUpAPAEdge

        push    eax
        push    ebx

        mov     eax, APA_START_ADDR+10000h      ; check source area boundary
        sub     eax, esi
        .if     <eax ae ecx>
            mov     ebx, ecx
        .else
            mov     ebx, eax
        .endif

        mov     eax, APA_START_ADDR+10000h      ; check target area boundary
        sub     eax, edi
        .if     <eax ae ecx>
            mov     eax, ecx
        .endif

        .if     <ebx ne ecx>                    ; source area must be separated ?
            .if     <eax ne ecx>                ; target area must be separated ?
                sub     ecx, eax
                sub     eax, ebx
                xchg    ebx, ecx
                rep     movsb
                and     esi, APA_ADDR_MASK
                mov     ecx, eax
                rep     movsb
                and     edi, APA_ADDR_MASK
                mov     ecx, ebx
                rep     movsb
            .else                               ; target is one area.
                xchg    ebx, ecx
                sub     ebx, ecx
                rep     movsb
                and     esi, APA_ADDR_MASK
                mov     ecx, ebx
                rep     movsb
            .endif
        .else                                   ; source is one area.
            .if     <eax ne ecx>                ; target area must be separated ?
                xchg    eax, ecx
                sub     eax, ecx
                rep     movsb
                and     edi, APA_ADDR_MASK
                mov     ecx, eax
                rep     movsb
            .else                               ; target is one area.
                rep     movsb
            .endif
        .endif

        and     edi, APA_ADDR_MASK              ; adjust wrapped pointer
        or      edi, APA_START_ADDR

        pop     ebx
        pop     eax
        ExitProc

EndProc     vvScrollUpAPAEdge

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvBlankUpAPAEdge                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Blank APA with consideration of APA edge.        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  blank color                                              */
;/*     EDI =  target APA pointer                                       */
;/*     ECX =  APA byte count to move                                   */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvBlankUpAPAEdge

        push    ebx

        xor     al, al

        mov     ebx, APA_START_ADDR+10000h      ; check 64K lap
        sub     ebx, edi
        .if     <ebx ae ecx>
            rep     stosb
        .else
            xchg    ebx, ecx
            sub     ebx, ecx
            rep     stosb
            and     edi, APA_ADDR_MASK
            mov     ecx, ebx
            rep     stosb
        .endif

        pop     ebx
        ExitProc

EndProc     vvBlankUpAPAEdge

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownGale                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down screen.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownGale

        LocalVar vvs,         VVSCROLL
        LocalVar CursorFlag,  FLAGS

        EnterProc

        .if     <dh ae Gale_Max_Row>            ; check max row
            mov     dh, Gale_Max_Row
            dec     dh
        .endif

        .if     <dl ae SCREEN_WIDTH>            ; check max column
            mov     dl, SCREEN_WIDTH-1
        .endif

        .if     <ch a dh> or                    ; check scroll window
        .if     <cl a dl>
            ExitProc premature
        .endif

        mov     bl, dh                          ; check scroll count
        sub     bl, ch
        inc     bl

        .if     <al a bl> or
        .if     <al eq 0>
            mov     al, bl
        .endif

IFNDEF  XVIO
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED> near  ; windowed ?
ENDIF   ;XVIO
            mov     bl, ' '
            movzx   ebx, bx
            mov     [vvs].vvs_fill, ebx

            mov     [vvs].vvs_nCols, 0
            movzx   eax, al
            neg     eax
            mov     [vvs].vvs_nRows, eax
            neg     eax

            movzx   esi, ch
            mov     [vvs].vvs_rcl.yTop, esi
            movzx   esi, cl
            mov     [vvs].vvs_rcl.xLeft, esi
            movzx   esi, dh
            mov     [vvs].vvs_rcl.yBottom, esi
            movzx   esi, dl
            mov     [vvs].vvs_rcl.xRight, esi

IFDEF   XVIO
            .if     <Gale_Text_Mode ne 0>                           ; text mode
                pushad
                SSToDS  eax, [vvs]
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_HIDE, eax, 0>
                CallFn  vxFlushEvent, <CURRENT_VDM, VXEVENT_HIDE, 0>
                popad
            .endif
ENDIF   ;XVIO
            .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>   ; windowed ?
                pushad
                CallFn  vvFlushEvent, <CURRENT_VDM, VVDEVENT_STRING, 0>
                popad
            .endif
IFNDEF  XVIO
        .endif
ENDIF   ;XVIO

        push    ax                              ; scroll down LVB
        push    bx
        push    cx
        push    dx
        .if     <cl eq 0> and
        .if     <dl eq SCREEN_WIDTH-1>
            call    vvScrollDownLVBFastGale
        .else
            call    vvScrollDownLVBGale
        .endif
        pop     dx
        pop     cx
        pop     bx
        pop     ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; windowed ?
        .if     <Gale_Text_Mode ne 0>           ; text mode
            jmp     ScrollDownExit
        .endif
                                                ; confirm cursor hiding
        mov     esi, VDMData.GaleData.GaleCursor.GaleCurDisp
        mov     CursorFlag, esi
        .if     <esi eq TRUE>
            call    HideCursorGale
        .endif
                                                ; scroll down APA
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>

            .if     <GaleScroll eq GALE_HS_ON> or           ; hardware scroll
            .if     <GaleScroll eq GALE_HS_LC>              ; switch on

                .if     <cl eq 0> and                       ; full screen width
                .if     <dl eq SCREEN_WIDTH-1> and
                .if     <al lt Gale_Max_Row> and            ; not screen clear
                mov     ah, dh
                sub     ah, ch
                inc     ah
                .if     <ah ge MIN_ROW_HARD_SCROLL>         ; large area scroll
                    call    vvScrollDownAPAHardGale
                    jmp     ScrollDownRestoreCursor
                .endif
            .endif
        .endif

        .if     <cl eq 0> and
        .if     <dl eq SCREEN_WIDTH-1>
            call    vvScrollDownAPASoftFastGale
        .else
            call    vvScrollDownAPASoftGale
        .endif

ScrollDownRestoreCursor:
        .if     <CursorFlag eq TRUE>            ; restore cursor state
            call    DrawCursorGale
        .endif

ScrollDownExit:
        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED>       ; windowed ?
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                SSToDS  eax, [vvs]
                CallFn  vvAddEvent,<CURRENT_VDM, VVDEVENT_SCROLL, eax, EVENT_FLUSH>
            .endif
        .endif
IFDEF   XVIO
        .if     <Gale_Text_Mode ne 0>                           ; text mode
            movzx   eax, Gale_Max_Row
            dec     eax
            .if     <[vvs].vvs_rcl.yBottom eq eax>
                SSToDS  eax, [vvs]
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_REDRAW, eax, <XEVENT_FLUSH or XEVENT_FORCE>>
            .else
                SSToDS  eax, [vvs]
                CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_REDRAW, eax, XEVENT_FLUSH>
            .endif
        .endif
ENDIF   ;XVIO

        ExitProc

EndProc     vvScrollDownGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownLVBGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down LVB.                                 */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownLVBGale

        LocalVar SourceLVB,   DWORD
        LocalVar TargetLVB,   DWORD
        LocalVar ColCntLVB,   WORD
        LocalVar RowCntLVB,   WORD
        LocalVar SkipLVB,     DWORD
        LocalVar BlankRowLVB, WORD

        LocalVar BlankAttr,   BYTE

        EnterProc
                                                ; save blank attr
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     BlankAttr, bh
        .else                                   ; graphics mode
            mov     BlankAttr, DEFAULT_ATTR0
        .endif

        xor     ah, ah                          ; calc LVB values
        mov     BlankRowLVB, ax                 ; line count to be blanked

        mov     al, dh
        sub     al, ch
        inc     al
        sub     al, byte ptr BlankRowLVB
        movzx   ax, al
        mov     RowCntLVB, ax                   ; line count to be moved down

        mov     al, dl
        sub     al, cl
        inc     al
        movzx   ax, al
        mov     ColCntLVB, ax                   ; col count per one line

        xor     eax, eax
        mov     ax, SCREEN_WIDTH
        sub     ax, ColCntLVB
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     ax, 2
        .else
            shl     ax, 1
        .endif
        mov     SkipLVB, eax                    ; skip byte per one line

        mov     ax, RowCntLVB
        add     al, ch
        dec     ax
        mov     ah, SCREEN_WIDTH
        mul     ah
        movzx   eax, ax
        movzx   ebx, dl
        add     eax, ebx
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     eax, 2
        .else
            shl     eax, 1
        .endif
        add     eax, VDMData.GaleData.GaleLVB
        mov     SourceLVB, eax                  ; source LVB pointer

        mov     al, SCREEN_WIDTH
        mul     dh
        xor     dh, dh
        add     ax, dx
        movzx   eax, ax
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     eax, 2
        .else
            shl     eax, 1
        .endif
        add     eax, VDMData.GaleData.GaleLVB
        mov     TargetLVB, eax                  ; target LVB pointer
                                                ; scroll down LVB
        std
        mov     esi, SourceLVB
        mov     edi, TargetLVB

        mov     dx, RowCntLVB
        or      dx, dx
        jz      ScrollDownLVBBlank

ScrollDownLoop1:
        movzx   ecx, ColCntLVB

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            rep     movsd
        .else
            rep     movsw
        .endif

        sub     esi, SkipLVB
        sub     edi, SkipLVB
        dec     dx
        jnz     ScrollDownLoop1
                                                ; blank LVB
ScrollDownLVBBlank:
        mov     eax, DEFAULT_ATTR1_ATTR2*10000h
        mov     ah, BlankAttr
        mov     al, ' '
        mov     dx, BlankRowLVB

ScrollDownLoop2:
        movzx   ecx, ColCntLVB

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            rep     stosd
        .else
            rep     stosw
        .endif

        sub     edi, SkipLVB
        dec     dx
        jnz     ScrollDownLoop2

        cld

        ExitProc
EndProc     vvScrollDownLVBGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownLVBFastGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down LVB. (screen max width scroll)       */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownLVBFastGale
                                                ; save blank attr in dl
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; text mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dl, bh
        .else                                   ; graphics mode
            mov     dl, DEFAULT_ATTR0
        .endif
                                                ; calc LVB values
        mov     cl, dh
        sub     cl, ch
        inc     cl
        sub     cl, al

        mov     ah, SCREEN_WIDTH
        mul     ah
        movzx   ebx, ax                         ; ebx = cell count to be blanked

        mov     al, SCREEN_WIDTH
        mul     dh
        add     ax, SCREEN_WIDTH-1
        movzx   edi, ax                         ; edi = target cell offset

        mov     esi, edi
        sub     esi, ebx                        ; esi = source cell offset

        mov     al, SCREEN_WIDTH
        mul     cl
        movzx   ecx, ax                         ; ecx = cell count to be moved up

        std

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     esi, 2
            shl     edi, 2
            mov     eax, VDMData.GaleData.GaleLVB
            add     esi, eax                    ; esi = source pointer
            add     edi, eax                    ; edi = target pointer
                                                ; scroll up LVB
            .if     <ecx ne 0>
                rep     movsd
            .endif
                                                ; blank LVB
            mov     ecx, ebx
            mov     eax, DEFAULT_ATTR1_ATTR2*10000h+' '
            mov     ah, dl
            rep     stosd
        .else
            shl     esi, 1
            shl     edi, 1
            mov     eax, VDMData.GaleData.GaleLVB
            add     esi, eax                    ; esi = source pointer
            add     edi, eax                    ; edi = target pointer
                                                ; scroll up LVB
            .if     <ecx ne 0>
                rep     movsw
            .endif
                                                ; blank LVB
            mov     ecx, ebx
            mov     al, ' '
            mov     ah, dl
            rep     stosw
        .endif

        cld

        ExitProc
EndProc     vvScrollDownLVBFastGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownAPASoftGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down LVB.                                 */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownAPASoftGale

        LocalVar SourceAPA,   DWORD
        LocalVar TargetAPA,   DWORD
        LocalVar ColCntAPA,   WORD
        LocalVar RowCntAPA,   WORD
        LocalVar SkipAPA,     DWORD
        LocalVar BlankRowAPA, WORD

        LocalVar BlankAttr,   BYTE

        EnterProc

        mov     BlankAttr, bh                   ; save blank attr
                                                ; calc APA values
        mul     FontHeight
        mov     BlankRowAPA, ax                 ; laster count to be blanked

        mov     al, dh
        sub     al, ch
        inc     al
        mul     FontHeight
        sub     ax, BlankRowAPA
        mov     RowCntAPA, ax                   ; laster count to be scrolled down

        mov     al, dl
        sub     al, cl
        inc     al
        movzx   ax, al
        mov     ColCntAPA, ax                   ; byte count in one laster

        mov     ax, APAWidth
        sub     ax, ColCntAPA
        movzx   eax, ax
        mov     SkipAPA, eax                    ; skip byte in one laster

        mov     al, ch
        mul     FontHeight
        add     ax, RowCntAPA
        dec     ax
        movzx   ebx, dl
        mul     APAWidth
        movzx   eax, ax
        add     eax, ebx
        add     eax, APA_START_ADDR
        movzx   ebx, Gale_Start_Addr
        add     eax, ebx
        and     eax, APA_ADDR_MASK
        mov     SourceAPA, eax                  ; source pointer in APA

        mov     ax, APAWidth
        mul     BlankRowAPA
        movzx   eax, ax
        add     eax, SourceAPA
        and     eax, APA_ADDR_MASK
        mov     TargetAPA, eax                  ; target pointer in APA

        mov     esi, SourceAPA                  ; scroll down APA
        mov     edi, TargetAPA
        call    SetupAPAMoveGale

        std
        mov     dx, RowCntAPA
        or      dx, dx
        jz      ScrollDownAPASoftBlank

ScrollDownAPASoftLoop1:
        movzx   ecx, ColCntAPA

        call    vvScrollDownAPAEdge

        sub     esi, SkipAPA
        add     esi, 10000h
        sub     edi, SkipAPA
        add     edi, 10000h
        and     esi, APA_ADDR_MASK
        and     edi, APA_ADDR_MASK
        dec     dx
        jnz     ScrollDownAPASoftLoop1
                                                ; blank APA
ScrollDownAPASoftBlank:
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        xor     al, al
        mov     dx, BlankRowAPA

ScrollDownAPASoftLoop2:
        movzx   ecx, ColCntLVB

        call    vvBlankDownAPAEdge

        sub     edi, SkipAPA
        add     edi, 10000h
        and     edi, APA_ADDR_MASK
        dec     dx
        jnz     ScrollDownAPASoftLoop2

        cld

        ExitProc

EndProc     vvScrollDownAPASoftGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownAPASoftFastGale                       */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down screen (screen wull width).          */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownAPASoftFastGale

        LocalVar    BlankAttr, BYTE

        EnterProc

        mov     BlankAttr, bh                   ; save blank attr
                                                ; calc APA values
        mov     cl, dh
        sub     cl, ch                          ; calc APA values
        inc     cl
        sub     cl, al

        push    dx
        movzx   ax, al
        mul     word ptr SkipLineAPA
        movzx   ebx, ax                         ; ebx = APA count to be blanked
        pop     dx

        movzx   ax, dh
        inc     ax
        mul     word ptr SkipLineAPA
        dec     ax
        movzx   edi, ax                         ; edi = target APA offset

        movzx   ax, cl
        mul     word ptr SkipLineAPA
        movzx   ecx, ax                         ; ecx = APA count to be moved up

        mov     esi, edi
        sub     si, bx                          ; esi = source cell offset

        movzx   eax, Gale_Start_Addr
        add     esi, APA_START_ADDR
        add     esi, eax
        and     esi, APA_ADDR_MASK              ; esi = source pointer
        add     edi, APA_START_ADDR
        add     edi, eax
        and     edi, APA_ADDR_MASK              ; edi = target pointer

        std
                                                ; scroll up APA
        call    SetupAPAMoveGale
        call    vvScrollDownAPAEdge
                                                ; blank APA
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        mov     ecx, ebx
        call    vvBlankDownAPAEdge

        cld

        ExitProc

EndProc     vvScrollDownAPASoftFastGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownAPAHardGale                           */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down screen using hardware.               */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Number of lines to be scrolled                           */
;/*      BH =  attribute of blank line                                  */
;/*      CX =  upper left position                                      */
;/*      DX =  lower right position                                     */
;/*      None                                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownAPAHardGale

        LocalVar ScrollAPA1,    DWORD
        LocalVar ScrollAPA2,    DWORD
        LocalVar ScrollCntAPA1, WORD
        LocalVar ScrollCntAPA2, WORD
        LocalVar BlankCntAPA,   WORD
        LocalVar NewTopAPA,     WORD

        LocalVar BlankAttr,   BYTE

        EnterProc
                                                ; calc LVB & APA values
        mov     BlankAttr, bh

        push    dx
        movzx   ax, al
        mul     SkipLineAPA
        pop     dx
        mov     BlankCntAPA, ax                 ; byte count to be blanked

        mov     al, Gale_Max_Row
        dec     al
        sub     al, dh
        movzx   ax, al
        push    dx
        mul     SkipLineAPA
        pop     dx                              ; byte count to be moved
        mov     ScrollCntAPA2, ax               ; (lower part)

        movzx   ax, ch
        push    dx
        mul     SkipLineAPA
        pop     dx                              ; byte count to be moved
        mov     ScrollCntAPA1, ax               ; (upper part)

        movzx   eax, Gale_Start_Addr
        add     eax, APA_START_ADDR
        and     eax, APA_ADDR_MASK
        mov     ScrollAPA1, eax                 ; upper scrolled area top ptr

        movzx   ax, dh
        inc     ax                                                      ;J-TS4954
        mul     SkipLineAPA
;J-TS4954        add     ax, BlankCntAPA
        movzx   eax, ax
        add     eax, ScrollAPA1
        and     eax, APA_ADDR_MASK
        mov     ScrollAPA2, eax                 ; lower scrolled area top ptr

        mov     ax, Gale_Start_Addr
        sub     ax, BlankCntAPA
        mov     NewTopAPA, ax                   ; new VGA start address

                                                ; VGA & XGA bug
                                                ; LineComp cannot be 0
        .if     <GaleScroll eq GALE_HS_LC> and
        .if     <NewTopAPA eq 0ff80h>
            mov     NewTopAPA, 0
            add     ScrollAPA1, 80h
            and     ScrollAPA1, APA_ADDR_MASK
            add     ScrollAPA2, 80h
            and     ScrollAPA2, APA_ADDR_MASK
            movzx   esi, Gale_Start_Addr
            add     esi, APA_START_ADDR+19*25*80h-1
            and     esi, APA_ADDR_MASK
            lea     edi, [esi+80h]
            and     edi, APA_ADDR_MASK
            mov     ecx, 19*25*80h
            std
            call    SetupAPAMoveGale
            call    vvScrollDownAPAEdge
        .endif

        mov     ax, NewTopAPA                   ; scroll APA (hard)
        mov     Gale_Start_Addr, ax
        call    SetAPAStartGale                 ; hardware scroll up
                                                ; adjust lower unscroll area
        call    SetupAPAMoveGale
        cld
        .if     <ScrollCntAPA2 ne 0>
            mov     esi, ScrollAPA2
            mov     edi, esi
            sub     di, BlankCntAPA
            movzx   ecx, ScrollCntAPA2
            call    vvScrollUpAPAEdge
        .endif
                                                ; adjust upper unscroll area
        mov     esi, ScrollAPA1
        mov     edi, esi
        sub     di, BlankCntAPA
        .if     <ScrollCntAPA1 ne 0>
            movzx   ecx, ScrollCntAPA1
            call    vvScrollUpAPAEdge
        .endif
                                                ; blank APA
        call    SetupAPAWriteGale
        mov     al, BlankAttr
        call    SetAPAColorScrollGale
        movzx   ecx, BlankCntAPA

        call    vvBlankUpAPAEdge

        ExitProc

EndProc     vvScrollDownAPAHardGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvScrollDownAPAEdge                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Scroll down APA with consideration of APA edge.  */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     ESI =  source APA pointer                                       */
;/*     EDI =  target APA pointer                                       */
;/*     ECX =  APA byte count to move                                   */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvScrollDownAPAEdge

        push    eax
        push    ebx

        mov     eax, esi                        ; check source area boundary
        sub     eax, APA_START_ADDR
        inc     eax
        .if     <eax ae ecx>
            mov     ebx, ecx
        .else
            mov     ebx, eax
        .endif

        mov     eax, edi                        ; check target area boundary
        sub     eax, APA_START_ADDR
        inc     eax
        .if     <eax ae ecx>
            mov     eax, ecx
        .endif

        .if     <ebx ne ecx>                    ; source area must be separated ?
            .if     <eax ne ecx>                ; target area must be separated ?
                sub     ecx, eax
                sub     eax, ebx
                xchg    ebx, ecx
                rep     movsb
                add     esi, 10000h
                and     esi, APA_ADDR_MASK
                mov     ecx, eax
                rep     movsb
                add     edi, 10000h
                and     edi, APA_ADDR_MASK
                mov     ecx, ebx
                rep     movsb
            .else                               ; target is one area.
                xchg    ebx, ecx
                sub     ebx, ecx
                rep     movsb
                add     esi, 10000h
                and     esi, APA_ADDR_MASK
                mov     ecx, ebx
                rep     movsb
            .endif
        .else                                   ; source is one area.
            .if     <eax ne ecx>                ; target area must be separated ?
                xchg    eax, ecx
                sub     eax, ecx
                rep     movsb
                add     edi, 10000h
                and     edi, APA_ADDR_MASK
                mov     ecx, eax
                rep     movsb
            .else                               ; target is one area.
                rep     movsb
            .endif
        .endif

        and     edi, APA_ADDR_MASK              ; adjust wrapped pointer
        or      edi, APA_START_ADDR

        pop     ebx
        pop     eax
        ExitProc

EndProc     vvScrollDownAPAEdge

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvBlankDownAPAEdge                                */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Blank APA with consideration of APA edge.        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  blank color                                              */
;/*     EDI =  target APA pointer                                       */
;/*     ECX =  APA byte count to move                                   */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      None                                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvBlankDownAPAEdge

        push    ebx

        xor     al, al

        mov     ebx, edi                        ; check 64K lap
        sub     ebx, APA_START_ADDR
        inc     ebx
        .if     <ebx ae ecx>
            rep     stosb
        .else
            xchg    ebx, ecx
            sub     ebx, ecx
            rep     stosb
            add     edi, 10000h
            and     edi, APA_ADDR_MASK
            mov     ecx, ebx
            rep     stosb
        .endif

        pop     ebx
        ExitProc

EndProc     vvBlankDownAPAEdge

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvDrawCharGale0                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw specified char into LVB & PVB with no attr. */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  character code                                           */
;/*      CX =  character count                                          */
;/*      DX =  DH = row position, DL = column position                  */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (Never)                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvDrawCharGale0

        LocalVar    Character, BYTE
        LocalVar    count,     WORD
        LocalVar    pos,       WORD
        LocalVar    vva,       VVSTRING
IFDEF   XVIO
        LocalVar    vxa,       VXSTRING
ENDIF   ;XVIO

        EnterProc

        mov     Character, al                   ; save char
        mov     count, cx                       ; save count
        mov     pos,   dx                       ; save position

        .if     <cx eq 0>                       ; check length = 0
            jmp     DrawCharGale0Exit
        .endif

        .if     <Gale_DBCS_First_Flag eq 0> near
            movzx   esi, al                     ; check DBCS 1st
            cmp     DBCS1st[esi], 0
            .if     e near                      ; SBCS draw
                call    vvGetSBCSFont           ; get font
                call    MakePointer             ; EBX = LVB pointer
                                                ; EDI = APA pointer
                .if     c                       ; position check
                    jmp     DrawCharGale0Exit
                .endif

DrawCharGale0Loop1:
                .if     <dh ae Gale_Max_Row>    ; check screen out
                    sub     count, cx
                    jmp     DrawCharGale0Windowed
                .endif

                mov     [ebx], al               ; draw char

                .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
                    call    vvUpdateAPAwithSBCS2
                .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                    call    vvUpdateAPAwithSBCS4
                .else
                    call    vvUpdateAPAwithSBCS2G
                .endif

                dec     cx                      ; count check
                jnz     DrawCharGale0IncPtr1
                jmp     DrawCharGale0Windowed

DrawCharGale0IncPtr1:                           ; increment pointers
                .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                    add     ebx, 4              ; inc LVB pointer
                .else
                    add     ebx, 2              ; inc LVB pointer
                .endif
                inc     dl                      ; inc (row,col)
                .if     <dl ae SCREEN_WIDTH>
                    xor     dl, dl
                    inc     dh
                    add     edi, SkipLineAPA    ; inc APA pointer
                    sub     edi, SCREEN_WIDTH-1
                .else
                    inc     edi
                .endif
                and     edi, APA_ADDR_MASK
                mov     al, Character           ; restore char code
                jmp     DrawCharGale0Loop1

            .else near                          ; DBCS 1st
                mov     Gale_DBCS_First_Char, ax    ; save DBCS first byte
                mov     Gale_DBCS_Attr_Cnt, 0       ; save attr count
                mov     Gale_DBCS_First_Flag, -1    ; set flag
            .endif

        .else near                              ; DBCS draw
            mov     Gale_DBCS_First_Flag, 0     ; clear DBCS 1st flag

            .if     <dx eq 0>                   ; check DBCS 2nd on (0,0).
                jmp     DrawCharGale0Exit
            .endif

            mov     ah, byte ptr Gale_DBCS_First_Char   ; get font
            call    vvGetDBCSFont
            call    MakePointer                 ; EBX = LVB pointer
                                                ; EDI = APA pointer
            .if     c                           ; position check
                jmp     DrawCharGale0Exit
            .endif

            dec     byte ptr pos                ; prepare for windowed
            add     count, cx                   ; 

DrawCharGale0Loop2:
            .if     <dh ae Gale_Max_Row>        ; check screen out
                sub     count, cx
                sub     count, cx
                jmp     DrawCharGale0Windowed
            .endif

            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
                mov     [ebx], al
                mov     [ebx-2], ah
                sub     ebx, 2                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS2
            .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                mov     [ebx], al
                mov     [ebx-4], ah
                sub     ebx, 4                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS4
            .else
                mov     [ebx], al
                mov     [ebx-2], ah
                sub     ebx, 2                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS2G
            .endif

            dec     cx                          ; count check
            jnz     DrawCharGale0IncPtr2
            jmp     DrawCharGale0Windowed

DrawCharGale0IncPtr2:                           ; restore ptr to 2nd byte &
            inc     edi                         ; increment pointers
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                add     ebx, 12
            .else
                add     ebx, 6
            .endif
            add     dl, 2                       ; inc (row,col)
            .if     <dl ae SCREEN_WIDTH>
                sub     dl, SCREEN_WIDTH
                inc     dh
                add     edi, SkipLineAPA        ; inc APA pointer
                sub     edi, SCREEN_WIDTH-2
            .else
                add     edi, 2
            .endif
            and     edi, APA_ADDR_MASK
            mov     al, Character               ; restore char code
            mov     ah, byte ptr Gale_DBCS_First_Char
            jmp     DrawCharGale0Loop2
        .endif

DrawCharGale0Windowed:
IFDEF   XVIO
        .if     <count ne 0> and
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dx, pos
            .if     <dl eq 0ffh>
                mov     dl, 0
                dec     dh
            .endif
            movzx   eax, dh
            mov     vxa.vxa_row, eax            ; row of string
            mov     al, dl
            mov     vxa.vxa_col, eax            ; column of string
            movzx   eax, count
            mov     vxa.vxa_nChars, eax         ; length
            SSToDS  eax, vxa
            CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, eax, 0>
        .endif
ENDIF   ;XVIO

        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED> and   ; windowed ?
        .if     <count ne 0> and
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dx, pos
            .if     <dl eq 0ffh>
                mov     dl, 0
                dec     dh
            .endif
            movzx   eax, dh
            mov     vva.vva_row, eax            ; row of string
            mov     al, dl
            mov     vva.vva_col, eax            ; column of string
            movzx   eax, count
            mov     vva.vva_nChars, eax         ; length
            SSToDS  eax, vva
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>
        .endif

DrawCharGale0Exit:
        ExitProc
EndProc     vvDrawCharGale0

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvDrawCharGale1                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw specified char into LVB & PVB with attr0.   */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  character code                                           */
;/*      AH =  attribute 0                                              */
;/*      CX =  character count                                          */
;/*      DX =  DH = row position, DL = column position                  */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EMULATED                                                        */
;/*         Carry clear (Always)                                        */
;/*     NOT EMULATED                                                    */
;/*         Carry set (Never)                                           */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvDrawCharGale1

        LocalVar    CharAttr0, WORD
        LocalVar    count,     WORD
        LocalVar    pos,       WORD
        LocalVar    vva,       VVSTRING
IFDEF   XVIO
        LocalVar    vxa,       VXSTRING
ENDIF   ;XVIO

        EnterProc

        mov     CharAttr0, ax                   ; save char/attr0
        mov     count, cx                       ; save count
        mov     pos,   dx                       ; save position

        .if     <cx eq 0>                       ; check length = 0
            jmp     DrawCharGale1Exit
        .endif

        .if     <Gale_DBCS_First_Flag eq 0> near
            movzx   esi, al                     ; check DBCS 1st
            cmp     DBCS1st[esi], 0
            .if     e near                      ; SBCS draw
                call    vvGetSBCSFont           ; get font
                call    MakePointer             ; EBX = LVB pointer
                                                ; EDI = APA pointer
                .if     c                       ; position check
                    jmp     DrawCharGale1Exit
                .endif

DrawCharGale1Loop1:
                .if     <dh ae Gale_Max_Row>    ; check screen out
                    sub     count, cx
                    jmp     DrawCharGale1Windowed
                .endif

                mov     [ebx], ax

                .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
                    call    vvUpdateAPAwithSBCS2
                .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                    mov     word ptr [ebx+2], DEFAULT_ATTR1_ATTR2
                    call    vvUpdateAPAwithSBCS4
                .else
                    call    vvUpdateAPAwithSBCS2G
                .endif

                dec     cx                      ; count check
                jnz     DrawCharGale1IncPtr1
                jmp     DrawCharGale1Windowed

DrawCharGale1IncPtr1:                           ; increment pointers
                .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                    add     ebx, 4              ; inc LVB pointer
                .else
                    add     ebx, 2              ; inc LVB pointer
                .endif
                inc     dl                      ; inc (row,col)
                .if     <dl ae SCREEN_WIDTH>
                    xor     dl, dl
                    inc     dh
                    add     edi, SkipLineAPA    ; inc APA pointer
                    sub     edi, SCREEN_WIDTH-1
                .else
                    inc     edi
                .endif
                and     edi, APA_ADDR_MASK
                mov     ax, CharAttr0           ; restore char/attr0
                jmp     DrawCharGale1Loop1

            .else near                          ; DBCS 1st
                mov     Gale_DBCS_First_Char, ax    ; save DBCS first byte
                mov     Gale_DBCS_Attr_Cnt, 1       ; save attr count
                mov     Gale_DBCS_First_Flag, -1    ; set flag
            .endif

        .else near                              ; DBCS draw
            .if     <dx eq 0>                   ; check DBCS 2nd on (0,0).
                jmp     DrawCharGale1Exit
            .endif

            .if     <Gale_DBCS_Attr_Cnt eq 0>   ; attribute count check
                call    vvDrawCharGale0
                jmp     DrawCharGale1Exit
            .endif

            mov     Gale_DBCS_First_Flag, 0     ; clear DBCS 1st flag

            mov     ah, byte ptr Gale_DBCS_First_Char   ; get font
            call    vvGetDBCSFont
            call    MakePointer                 ; EBX = LVB pointer
                                                ; EDI = APA pointer
            .if     c                           ; position check
                jmp     DrawCharGale1Exit
            .endif

            dec     byte ptr pos                ; prepare for windowed
            add     count, cx                   ; 

DrawCharGale1Loop2:
            .if     <dh ae Gale_Max_Row>        ; check screen out
                sub     count, cx
                sub     count, cx
                jmp     DrawCharGale1Windowed
            .endif

            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
                mov     ax, CharAttr0           ; set LVB
                mov     [ebx], ax
                mov     ax, Gale_DBCS_First_Char
                mov     [ebx-2], ax
                sub     ebx, 2                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS2
            .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                mov     ax, CharAttr0           ; set LVB
                mov     [ebx], ax
                mov     word ptr [ebx+2], DEFAULT_ATTR1_ATTR2
                mov     ax, Gale_DBCS_First_Char
                mov     [ebx-4], ax
                mov     word ptr [ebx-2], DEFAULT_ATTR1_ATTR2
                sub     ebx, 4                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS4
            .else
                mov     ax, CharAttr0           ; set LVB
                mov     [ebx], ax
                mov     ax, Gale_DBCS_First_Char
                mov     [ebx-2], ax
                sub     ebx, 2                  ; move ptr to 1st byte
                dec     edi
                call    vvUpdateAPAwithDBCS2G
            .endif

            dec     cx                          ; count check
            jnz     DrawCharGale1IncPtr2
            jmp     DrawCharGale1Windowed

DrawCharGale1IncPtr2:                           ; restore ptr to 2nd byte &
            inc     edi                         ; increment pointers
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
                add     ebx, 12
            .else
                add     ebx, 6
            .endif
            add     dl, 2                       ; inc (row,col)
            .if     <dl ae SCREEN_WIDTH>
                sub     dl, SCREEN_WIDTH
                inc     dh
                add     edi, SkipLineAPA        ; inc APA pointer
                sub     edi, SCREEN_WIDTH-2
            .else
                add     edi, 2
            .endif
            and     edi, APA_ADDR_MASK
            mov     al, Character               ; restore char code
            mov     ah, byte ptr Gale_DBCS_First_Char
            jmp     DrawCharGale1Loop2
        .endif

DrawCharGale1Windowed:
IFDEF   XVIO
        .if     <count ne 0> and
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dx, pos
            .if     <dl eq 0ffh>
                mov     dl, 0
                dec     dh
            .endif
            movzx   eax, dh
            mov     vxa.vxa_row, eax            ; row of string
            mov     al, dl
            mov     vxa.vxa_col, eax            ; column of string
            movzx   eax, count
            mov     vxa.vxa_nChars, eax         ; length
            SSToDS  eax, vxa
            CallFn  vxAddEvent, <CURRENT_VDM, VXEVENT_STRING, eax, 0>
        .endif
ENDIF   ;XVIO

        .if     <bit VDMData.flVDMVideo and VDM_WINDOWED> and   ; windowed ?
        .if     <count ne 0> and
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     dx, pos
            .if     <dl eq 0ffh>
                mov     dl, 0
                dec     dh
            .endif
            movzx   eax, dh
            mov     vva.vva_row, eax            ; row of string
            mov     al, dl
            mov     vva.vva_col, eax            ; column of string
            movzx   eax, count
            mov     vva.vva_nChars, eax         ; length
            SSToDS  eax, vva
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>
        .endif

DrawCharGale1Exit:
        ExitProc
EndProc     vvDrawCharGale1

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithSBCS                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw SBCS character into APA                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> SBCS 19 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithSBCS
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            jmp     vvUpdateAPAwithSBCS2
        .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            jmp     vvUpdateAPAwithSBCS4
        .endif
            jmp     vvUpdateAPAwithSBCS2G
        ExitProc
EndProc     vvUpdateAPAwithSBCS

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithDBCS                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw DBCS character into APA                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> DBCS 16 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithDBCS
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80>
            jmp     vvUpdateAPAwithDBCS2
        .elseif <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            jmp     vvUpdateAPAwithDBCS4
        .endif
            jmp     vvUpdateAPAwithDBCS2G
        ExitProc
EndProc     vvUpdateAPAwithDBCS

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithSBCS2                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw SBCS character into APA                     */
;/*                    with Char/Attr0 format (text mode).              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> SBCS 19 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithSBCS2

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>      ; windowed ?
            ret
        .endif

        push    esi
        push    edi

        movzx   ax, [ebx+1]                     ; set color
        call    SetAPAColorTextGale

        mov     eax, SkipLasterAPA              ; get skip count
        cld

        .if     <edi be APABottomBound>         ; no check ?
            movsb                               ; laster  0
            add     edi, eax
            movsb                               ; laster  1
            add     edi, eax
            movsb                               ; laster  2
            add     edi, eax
            movsb                               ; laster  3
            add     edi, eax
            movsb                               ; laster  4
            add     edi, eax
            movsb                               ; laster  5
            add     edi, eax
            movsb                               ; laster  6
            add     edi, eax
            movsb                               ; laster  7
            add     edi, eax
            movsb                               ; laster  8
            add     edi, eax
            movsb                               ; laster  9
            add     edi, eax
            movsb                               ; laster 10
            add     edi, eax
            movsb                               ; laster 11
            add     edi, eax
            movsb                               ; laster 12
            add     edi, eax
            movsb                               ; laster 13
            add     edi, eax
            movsb                               ; laster 14
            add     edi, eax
            movsb                               ; laster 15
            add     edi, eax
            movsb                               ; laster 16
            add     edi, eax
            movsb                               ; laster 17
            add     edi, eax
            movsb                               ; laster 18

        .else near
            movsb                               ; laster  0
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  1
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 17
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 18
        .endif

        pop     edi
        pop     esi
        ExitProc
EndProc     vvUpdateAPAwithSBCS2

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithSBCS4                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw SBCS character into APA                     */
;/*                    with Char/Attr0/Attr1/Attr2 format.              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> SBCS 19 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithSBCS4

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>      ; windowed ?
            ret
        .endif

        push    esi
        push    edi

        movzx   ax, [ebx+1]                     ; set color
        call    SetAPAColorTextGale

        mov     eax, SkipLasterAPA              ; get skip count
        cld

        push    edi                             ; save for grid draw

        .if     <edi be APABottomBound>         ; no check ?
            movsb                               ; laster  0
            add     edi, eax
            movsb                               ; laster  1
            add     edi, eax
            movsb                               ; laster  2
            add     edi, eax
            movsb                               ; laster  3
            add     edi, eax
            movsb                               ; laster  4
            add     edi, eax
            movsb                               ; laster  5
            add     edi, eax
            movsb                               ; laster  6
            add     edi, eax
            movsb                               ; laster  7
            add     edi, eax
            movsb                               ; laster  8
            add     edi, eax
            movsb                               ; laster  9
            add     edi, eax
            movsb                               ; laster 10
            add     edi, eax
            movsb                               ; laster 11
            add     edi, eax
            movsb                               ; laster 12
            add     edi, eax
            movsb                               ; laster 13
            add     edi, eax
            movsb                               ; laster 14
            add     edi, eax
            movsb                               ; laster 15
            add     edi, eax
            movsb                               ; laster 16
            add     edi, eax
            movsb                               ; laster 17
            add     edi, eax

        .else near
            movsb                               ; laster  0
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  1
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            add     edi, eax
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 17
            add     edi, eax
            and     edi, APA_ADDR_MASK
        .endif

        mov     ah, [ebx+2]                     ; get attribute 1
        .if     <bit ah and UNDERLINE>
            mov     byte ptr [edi], 0ffh
        .else
            movsb
        .endif
        pop     edi                             ; restore edi
        .if     <bit ah and VERT_GRID+HORZ_GRID>
            call    DrawGridGale
        .endif

        pop     edi
        pop     esi
        ExitProc
EndProc     vvUpdateAPAwithSBCS4

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithSBCS2G                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw SBCS character into APA                     */
;/*                    with Char/Attr0 format (graphics mode).          */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> SBCS 19 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithSBCS2G
        push    ecx
        push    esi
        push    edi

        movzx   ax, [ebx+1]                     ; set color
        call    SetAPAColorGraphGale

        movzx   ecx, FontHeight
        mov     eax, SkipLasterAPA              ; get skip count
        cld

        .if     <bit <byte ptr [ebx+1]> nand 80h>   ; overwrite draw ?
UpdateSBCS2GLoop1:
            movsb
            add     edi, eax
            loop    UpdateSBCS2GLoop1

        .else                                   ; xor draw
UpdateSBCS2GLoop2:
            cmp     [edi], al                   ; read APA
            movsb
            add     edi, eax
            loop    UpdateSBCS2GLoop2
        .endif

        pop     edi
        pop     esi
        pop     ecx
        ExitProc
EndProc     vvUpdateAPAwithSBCS2G

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithDBCS2                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw DBCS character into APA                     */
;/*                    with Char/Attr0 format (text mode).              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> DBCS 16 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithDBCS2

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>      ; windowed ?
            ret
        .endif

        push    ecx
        push    esi
        push    edi

        cld

        movzx   ax, [ebx+1]                     ; set 1st byte color
        call    SetAPAColorTextGale

        push    esi                             ; save for 2nd byte draw
        push    edi

        mov     ecx, SkipLasterAPA              ; set loop counter

        .if     <edi be APABottomBound> near    ; no check ?
                                                ; draw 1st byte font
            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx

            xor     al, al                      ; clear bottom 2 lasters
            stosb
            add     edi, ecx
            stosb

            pop     edi                         ; restore esi, edi
            pop     esi
            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+3]                 ; set 2nd byte color
            call    SetAPAColorTextGale

            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
                                                ; draw 2nd byte font
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx

        .else near
                                                ; draw 1st byte font
            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK

            xor     al, al                      ; clear bottom 2 lasters
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            stosb

            pop     edi                         ; restore esi, edi
            pop     esi
            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+3]                 ; set 2nd byte color
            call    SetAPAColorTextGale

            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
                                                ; draw 2nd byte font
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
        .endif

        xor     al, al                          ; clear bottom 2 lasters
        stosb
        add     edi, ecx
        and     edi, APA_ADDR_MASK
        stosb

        pop     edi
        pop     esi
        pop     ecx
        ExitProc
EndProc     vvUpdateAPAwithDBCS2

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithDBCS4                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw DBCS character into APA.                    */
;/*                    with Char/Attr0/Attr1/Attr2 format.              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> DBCS 16 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithDBCS4

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>      ; windowed ?
            ret
        .endif

        push    ecx
        push    esi
        push    edi

        cld

        movzx   ax, [ebx+1]                     ; set 1st byte color
        call    SetAPAColorTextGale

        mov     ecx, SkipLasterAPA              ; preload skip count

        push    esi                             ; save for 2nd byte draw
        push    edi

        .if     <edi be APABottomBound> near    ; no check ?
                                                ; draw 1st byte font
            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx

            xor     al, al                      ; clear bottom 2 lasters
            stosb
            add     edi, ecx
            mov     ah, [ebx+2]
            .if     <bit ah and UNDERLINE>
                mov     al, 0ffh                ; underline is on
            .endif
            stosb

            pop     edi                         ; restore esi, edi
            pop     esi

            .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                push    esi
                push    edi
                call    DrawGridGale
                pop     edi
                pop     esi
            .endif

            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+5]                 ; set 2nd byte color
            call    SetAPAColorTextGale

            push    esi                         ; save for grid draw
            push    edi

            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
                                                ; draw 2nd byte font
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx

        .else near
                                                ; draw 1st byte font
            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK

            xor     al, al                      ; clear bottom 2 lasters
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            mov     ah, [ebx+2]
            .if     <bit ah and UNDERLINE>
                mov     al, 0ffh                ; underline is on
            .endif
            stosb

            pop     edi                         ; restore esi, edi
            pop     esi

            .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                push    esi
                push    edi
                call    DrawGridGale
                pop     edi
                pop     esi
            .endif

            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+5]                 ; set 2nd byte color
            call    SetAPAColorTextGale

            push    esi                         ; save for grid draw
            push    edi

            xor     al, al                      ; clear top laster
            stosb
            add     edi, ecx
            and     edi, APA_ADDR_MASK
                                                ; draw 2nd byte font
            movsb                               ; laster  1
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  2
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  3
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  4
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  5
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  6
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  7
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  8
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster  9
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 10
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 11
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 12
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 13
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 14
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 15
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK
            movsb                               ; laster 16
            inc     esi
            add     edi, ecx
            and     edi, APA_ADDR_MASK

        .endif

        xor     al, al                          ; clear bottom 2 lasters
        stosb
        add     edi, ecx
        and     edi, APA_ADDR_MASK
        mov     ah, [ebx+6]
        .if     <bit ah and UNDERLINE>
            mov     al, 0ffh                    ; underline is on
        .endif
        stosb

        pop     edi                             ; restore esi, edi
        pop     esi

        .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
            call    DrawGridGale
        .endif

        pop     edi
        pop     esi
        pop     ecx
        ExitProc
EndProc     vvUpdateAPAwithDBCS4

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithDBCS2G                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw DBCS character into APA                     */
;/*                    with Char/Attr0 format (graphics mode).          */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ESI -> DBCS 16 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithDBCS2G
        push    ecx
        push    edx
        push    esi
        push    edi

        cld

        mov     edx, SkipLasterAPA

        .if     <bit <byte ptr [ebx+1]> nand 80h> near  ; xor draw ?
                                                ; no, overwrite draw
            movzx   ax, [ebx+1]                 ; set 1st byte color
            call    SetAPAColorGraphGale

            push    esi                         ; save for 2nd byte draw
            push    edi

            .if     <Gale_Max_Row eq 25>        ; clear top laster
                xor     al, al
                stosb
                add     edi, edx
                and     edi, APA_ADDR_MASK
            .endif

            mov     ecx, FONT_HEIGHT_LOW        ; set loop counter
                                                ; draw 1st byte font
UpdateDBCS2GLoop1:
            movsb
            inc     esi
            add     edi, edx
            loop    UpdateDBCS2GLoop1

            .if     <Gale_Max_Row eq 25>        ; clear bottom 2 lasters
                xor     al, al
                stosb
                add     edi, edx
                and     edi, APA_ADDR_MASK
                stosb
            .endif

            pop     edi                         ; restore esi, edi
            pop     esi
            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+3]                 ; set 2nd byte color
            call    SetAPAColorGraphGale

            .if     <Gale_Max_Row eq 25>        ; clear top laster
                xor     al, al
                stosb
                add     edi, edx
                and     edi, APA_ADDR_MASK
            .endif

            mov     ecx, FONT_HEIGHT_LOW        ; set loop counter
                                                ; draw 2nd byte font
UpdateDBCS2GLoop2:
            movsb
            inc     esi
            add     edi, edx
            loop    UpdateDBCS2GLoop2

            .if     <Gale_Max_Row eq 25> near   ; clear bottom 2 lasters
                xor     al, al
                stosb
                add     edi, edx
                and     edi, APA_ADDR_MASK
                stosb
            .endif

        .else near                              ; xor draw
            movzx   ax, [ebx+1]                 ; set 1st byte color
            call    SetAPAColorGraphGale

            push    esi                         ; save for 2nd byte draw
            push    edi

            .if     <Gale_Max_Row eq 25>        ; skip top laster
                add     edi, edx
                inc     edi
                and     edi, APA_ADDR_MASK
            .endif

            mov     ecx, FONT_HEIGHT_LOW        ; set loop counter
                                                ; draw 1st byte font
UpdateDBCS2GLoop3:
            mov     al, [edi]
            movsb
            inc     esi
            add     edi, edx
            loop    UpdateDBCS2GLoop3

            pop     edi                         ; restore esi, edi
            pop     esi
            inc     esi                         ; skip to next column
            inc     edi

            movzx   ax, [ebx+3]                 ; set 2nd byte color
            call    SetAPAColorGraphGale

            .if     <Gale_Max_Row eq 25>        ; skip top laster
                add     edi, edx
                inc     edi
                and     edi, APA_ADDR_MASK
            .endif

            mov     ecx, FONT_HEIGHT_LOW        ; set loop counter
                                                ; draw 2nd byte font
UpdateDBCS2GLoop4:
            mov     al, [edi]
            movsb
            inc     esi
            add     edi, edx
            loop    UpdateDBCS2GLoop4
        .endif

        pop     edi
        pop     esi
        pop     edx
        pop     ecx
        ExitProc
EndProc     vvUpdateAPAwithDBCS2G

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: DrawGridGale                                      */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw vertical & horizontal grid line             */
;/*                    in Extended CGA mode.                            */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AH = attribte 1                                                */
;/*     EBX = LVB pointer                                               */
;/*     EDI = APA pointer                                               */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   DrawGridGale
        push    ecx
        push    edx

        mov     al, GRID_COLOR
        call    SetGridColorGale

        mov     edx, SkipLasterAPA

        .if     <bit ah and HORZ_GRID>
            mov     byte ptr [edi], 0ffh
        .endif

        .if     <bit ah and VERT_GRID>
            mov     ecx, FONT_HEIGHT
            mov     al, 80h

            .if     <edi be APABottomBound> near    ; no check ?
DrawGridLoop1:
                mov     ah, [edi]
                stosb
                add     edi, edx
                loop    DrawGridLoop1
            .else
DrawGridLoop2:
                mov     ah, [edi]
                stosb
                add     edi, edx
                and     edi, APA_ADDR_MASK
                loop    DrawGridLoop2
            .endif
        .endif

        pop     edx
        pop     ecx
        ExitProc

EndProc     DrawGridGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetSBCSDefaultFont                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get SBCS 16 font image addr.                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  SBCS character code                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     ESI -> SBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetSBCSDefaultFont
        push    eax
        push    edi
        push    eax
        call    VfntGetSBCS16Buf
        pop     eax
        movzx   eax, al
        lea     edi, [eax*8+eax]
        lea     edi, [edi*2+eax]
        add     esi, edi
        pop     edi
        pop     eax
        ExitProc
EndProc     vvGetSBCSDefaultFont

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetSBCSFont                                     */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get SBCS 16 font image addr.                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  SBCS character code                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     ESI -> SBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetSBCSFont
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            jmp     vvGetSBCSTextFont
        .else
            jmp     vvGetSBCSGraphicsFont
        .endif
        ExitProc
EndProc     vvGetSBCSFont

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetSBCSTextFont                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get SBCS 16 font image addr (text mode).         */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  SBCS character code                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     ESI -> SBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetSBCSTextFont
        push    eax
        movzx   eax, al
        lea     esi, [eax*8+eax]
        lea     esi, [esi*2+eax]
        add     esi, VDMData.GaleData.GaleSBCS
        pop     eax
        ExitProc
EndProc     vvGetSBCSTextFont

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetSBCSGraphicsFont                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get SBCS 16 font image addr (graphics mode).     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  SBCS character code                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     ESI -> SBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetSBCSGraphicsFont
        push    eax
        push    edx
        mul     FontHeight
        movzx   esi, ax
        movzx   eax, SBCS_FONT_VECTOR_SEL
        shl     eax, 4
        add     esi, eax
        movzx   eax, SBCS_FONT_VECTOR_OFF
        add     esi, eax
        pop     edx
        pop     eax
        ExitProc
EndProc     vvGetSBCSGraphicsFont

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetDBCSFont                                     */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get DBCS 16 font image addr.                     */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AX =  DBCS character code                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     Carry = set : error, clear : no error                           */
;/*     ESI -> DBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetDBCSFont
        push    eax
        push    ebx
        xor     ebx, ebx
        call    VfntGetDBCS16Font
        pop     ebx
        pop     eax
        ExitProc
EndProc     vvGetDBCSFont

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVLoadDefaultSBCS                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Load default SBCS font from VFNTV.               */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVLoadDefaultSBCS
        pushad
        call    VfntGetSBCS16Buf
        .if     nc
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or    ; 19 dots ?
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE> or
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16_GALE>
                mov     edi, VDMData.GaleData.GaleSBCS
                cld
                mov     ecx, SIZE_SBCS16_BUF/4
                rep     movsd
            .else                               ; 16 dots font
                mov     edi, VDMData.GaleData.GaleSBCS
                cld
                mov     bx, 256
DefaultSBCSLoop:
                inc     esi
                mov     ecx, FONT_HEIGHT_LOW
                rep     movsb
                inc     esi
                inc     esi
                dec     bx
                jnz     DefaultSBCSLoop
            .endif
            .if     <Gale_Supported_Mode ne 0> and
            .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> and   ; graphics ?
            .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
                mov     eax, VDMData.GaleData.GaleSBCS  ; set font vector
                shr     eax, 4
                mov     SBCS_FONT_VECTOR_SEL, ax
                mov     SBCS_FONT_VECTOR_OFF, 0
            .endif
        .endif
        popad
        ExitProc
EndProc     VVLoadDefaultSBCS

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVInitScreen                                      */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Clear LVB & set internal flag                    */
;/*                    & adjust screen size                             */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVInitScreen
        pushad
        cld
        mov     edi, VDMData.GaleData.GaleLVB       ; clear LVB in DOS mem
        mov     ecx, SCREEN_WIDTH*SCREEN_HEIGHT
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
            mov     ax, DEFAULT_CHAR_ATTR0
            rep     stosw
        .else
            mov     eax, DEFAULT_ATTR1_ATTR2*10000h+DEFAULT_CHAR_ATTR0
            rep     stosd
        .endif

IFDEF   XVIO
        mov     edi, VDMData.XVIOData.GaleXVIOLVB   ; clear XVIO LVB
        mov     ecx, SCREEN_WIDTH*SCREEN_HEIGHT
        xor     eax, eax
        rep     stosd
                                                ; foreground
        .if     <bit VDMData.flVDMVideo and VDM_FGND> and
                                                ; and graphics mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16_GALE>
                                                ; clear saved screen for XVIO
            .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2>
                mov     ebx, 0
            .else
                mov     ebx, 3
            .endif
            xor     eax, eax

ClearXVIOLoop:
            mov     ecx, [BANK0][ebx*4].VDMData.anpgPlane
            .if     <ecx ne 0>
                shl     ecx, 10
                mov     edi, [BANK0][ebx*4].VDMData.apPlane
                rep stosd
            .endif
            dec     ebx
            .if     <bl ne 0ffh>
                jmp     ClearXVIOLoop
            .endif
        .endif
ENDIF   ;XVIO
                                                ; check supported mode
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16_GALE> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     Gale_Supported_Mode, 1
        .else
            mov     Gale_Supported_Mode, 0
        .endif
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            mov     Gale_Text_Mode, 1
        .else
            mov     Gale_Text_Mode, 0
        .endif
                                                ; set APA width
        .if     <Gale_Text_Mode ne 0>
            mov     ax, APAWidthText
            mov     APAWidth, ax
        .else
            mov     APAWidth, APA_WIDTH
        .endif
                                                ; set skip count
        movzx   eax, APAWidth
        dec     eax
        mov     SkipLasterAPA, eax
                                                ; set max row
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X16>
            mov     Gale_Max_Row, 30
            mov     ax, 16
        .else
            mov     Gale_Max_Row, 25
            mov     ax, 19
        .endif
        mov     FontHeight, al                  ; set font height & skip count
        mul     APAWidth
        movzx   eax, ax
        mov     SkipLineAPA, eax
                                                ; calc APA boundary
        mov     eax, APA_START_ADDR
        add     eax, SkipLineAPA
        mov     APATopBound, eax
        mov     eax, APA_START_ADDR+10000h
        sub     eax, SkipLineAPA
        movzx   ecx, APAWidth
        add     eax, ecx
        dec     eax
        dec     eax                             ; DBCS consideration
        mov     APABottomBound, eax
                                                ; clear start address
        mov     Gale_Start_Addr, 0
        mov     al, FontHeight
        mul     Gale_Max_Row
        dec     ax
        mov     PrevLineComp, ax
        mov     MaxLineComp, ax
                                                ; adjust screen vertical size
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            .if     <bit VDMData.flVDMVideo and VDM_FGND>   ; foreground ?
                mov     dx, MiscOutputRegRead   ; Read Misc Output Register
                in      al, dx
                mov     dx, CRTCtlAddressReg
                .if     <bit al and 01h>        ; bit 0 = 1 - color, 0 - mono
                    add     dx, ColorAdjustment
                .else
                    add     dx, MonoAdjustment
                .endif
                mov     ax, 0DA00h+LC_DISP_ENABLE
                out     dx, ax
            .else
                mov     VDMData.aregCRTData[LC_DISP_ENABLE], 0DAh
            .endif
                                                ; adjust APA width
            mov     ax, APAWidth
            shl     ax, 7
            .if     <bit VDMData.flVDMVideo and VDM_FGND>   ; foreground ?
                mov     al, LC_LINE_WIDTH
                out     dx, ax
            .else
                mov     VDMData.aregCRTData[LC_LINE_WIDTH], ah
            .endif
        .endif
                                                ; set default cursor
        mov     VDMBase.rb_wVCursorMode, DEFAULT_CUR_TYPE
        mov     VDMBase.rb_awVCursorPos, DEFAULT_CUR_POS
        mov     VDMData.GaleData.GaleCursor.GaleCurDisp, FALSE
        call    SetCursorGale                   ; net new cursor

        call    DrawCursorGale                  ; draw cursor

        mov     GaleInitFlag, TRUE              ; initialized after creation

        popad
        ExitProc
EndProc     VVInitScreen

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVRedrawScreen                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Redraw all screen because of screen switch.      */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     hvdm  =  hvdm                                                   */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVRedrawScreen
        ArgVar      hvdm,   HVDM

        EnterProc
        pushad


        mov     edx, hvdm                       ; get VDM handle

        .if     <[edx].GaleInitFlag ne TRUE>    ; initialized after creation ?
            ExitProc premature
        .endif

        call    HideCursorGeneral               ; hide cursor

        mov     eax, [edx].VDMData.GaleData.GaleLVB ; get top addr of LVB
        add     eax, edx
        mov     bx, 0000h                       ; set top (row,col)

VVRedrawScreenLoop:
        movzx   esi, byte ptr [eax]
        .if     <DBCS1st[esi] eq 1>             ; DBCS ?
            mov     ecx, -2
        .else                                   ; SBCS ?
            mov     ecx, -1
        .endif
        call    DrawCharGeneral                 ; request DBCS draw

        neg     ecx
        add     bl, cl                          ; inc column
        .if     <bl ge SCREEN_WIDTH>
            sub     bl, SCREEN_WIDTH            ; inc row
            inc     bh
        .endif

        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
            shl     ecx, 1
        .else                                   ; mode = BIOSVMODE_CO80_GALE
            shl     ecx, 2
        .endif
        add     eax, ecx                        ; inc LVB pointer

        .if     <bh l [edx].Gale_Max_Row>       ; more chars ?
            jmp     VVRedrawScreenLoop
        .endif

        call    DrawCursorGeneral               ; show cursor

        popad
        ExitProc
EndProc     VVRedrawScreen

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVCheckXGAAdapter                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Check current display adapter is XGA or not.     */
;/*                    Make DBCS 1st byte table.                        */
;/*  ENTRY:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVCheckXGAAdapter

        pushad

        mov     FlagXGA, 0                      ; reset XGA flag

        mov     ecx, 6                          ; 2110, 2110, 2120, ..., 2160
        mov     dx, XGA_OP_MODE_REG_1

CheckXGALoop:
        in      al, dx
        add     dx, 10h                         ; go to next register
        and     al, 07h
        .if     <al eq VGA_ENABLED_MODE>
            mov     FlagXGA, 1                  ; set XGA flag
            jmp     CheckXGAExit
        .endif
        loop    CheckXGALoop

CheckXGAExit:
        .if     <ecx ne 0>
                            ; We may have found the VGA function in a XGA.
                            ; But we should further check whether it is
                            ; truely the one we are searching for, because
                            ; it might be a VGA-Speed.
            sub     dx, 10h                     ; back to the port just examined
            in      al, dx
            mov     ah, al                      ; save it to restore later
            xor     al, 02h                     ; check if the bit 1 is
                                                ; implemented or not.
            out     dx, al
            in      al, dx
            xchg    ah, al                      ; restore the original data
            out     dx, al
            xor     al, ah
            .if     z
                mov     FlagXGA, 0              ; set XGA flag
            .endif
        .endif

        popad
        ExitProc

EndProc     VVCheckXGAAdapter

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: VVInitDBCSTable                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Create DBCS 1st byte check table.                */
;/*  ENTRY:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   VVInitDBCSTable

        pushad
                                                ; get DBCS vector
        mov     esi, FLAToffset DBCSVector      ; & user font vector
        mov     edi, FLAToffset UserFontVector
        call    VfntGetDBCSVector
                                                ; make DBCS 1st byte table
        movzx   edi, DBCSVector[0]
        movzx   ecx, DBCSVector[1]
        sub     ecx, edi
        inc     ecx
        add     edi, FLAToffset DBCS1st
        mov     al, 1
        rep     stosb
        movzx   edi, DBCSVector[2]
        movzx   ecx, DBCSVector[3]
        sub     ecx, edi
        inc     ecx
        add     edi, FLAToffset DBCS1st
        mov     al, 1
        rep     stosb

        popad
        ExitProc

EndProc     VVInitDBCSTable

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvSetDefaultRegsGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set default values to VGA registers.             */
;/*                                                                     */
;/*  INPUT: None                                                        */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvSetDefaultRegsGale

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_FUNCTION                 ; set rotate 0
        mov     ah, 0
        out     dx, ax
        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax
        mov     al, LG_MODE                     ; set write mode 0
        mov     ah, 0
        out     dx, ax
        mov     al, LG_ENABLE_SET_RESET         ; disable set/reser regs
        mov     ah, 0
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregSEQData[LS_MAP_MASK        ], 0ffh
            mov     VDMData.aregGDCData[LG_FUNCTION        ], 0
            mov     VDMData.aregGDCData[LG_BIT_MASK        ], 0ffh
            mov     VDMData.aregGDCData[LG_MODE            ], 0
            mov     VDMData.aregGDCData[LG_ENABLE_SET_RESET], 0
        .endif

        ExitProc
EndProc     vvSetDefaultRegsGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetupAPAWriteGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Setup VGA registers to update APA.               */
;/*                                                                     */
;/*  INPUT: None                                                        */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetupAPAWriteGale

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; not foreground ?
        .if     <Gale_Text_Mode ne 0>
            ret
        .endif

        mov     PrevColor, -1                   ; reset color

        push    ax                              ; save ax, dx
        push    dx

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_FUNCTION                 ; set rotate 0
        mov     ah, 0
        out     dx, ax
        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_FUNCTION], 0
            mov     VDMData.aregGDCData[LG_BIT_MASK], 0ffh
            mov     VDMData.aregSEQData[LS_MAP_MASK], 0ffh
        .endif

        pop     dx                              ; restore ax, dx
        pop     ax
        ExitProc

EndProc     SetupAPAWriteGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetupAPAMoveGale                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Setup VGA registers to move APA.                 */
;/*                                                                     */
;/*  INPUT: None                                                        */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetupAPAMoveGale

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; not foreground ?
        .if     <Gale_Text_Mode ne 0>
            ret
        .endif

        mov     PrevColor, -1                   ; reset color

        push    ax                              ; save ax, dx
        push    dx

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_MODE                     ; set write mode 1
        mov     ah, 01h
        out     dx, ax

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_MODE    ], 01h
            mov     VDMData.aregSEQData[LS_MAP_MASK], 0ffh
        .endif

        pop     dx                              ; restore ax, dx
        pop     ax
        ExitProc

EndProc     SetupAPAMoveGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetAPAColorScrollGale                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA write colors.                            */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AL      = Foreground (0-3 bit) and Background (4-7) Colors      */
;/*               or XOR bit (7)                                        */
;/*     EDI   --> Target APA address (in text mode)                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetAPAColorScrollGale

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            jmp     SetAPAColorTextGale
        .else
            shl     al, 4
            jmp     SetAPAColorTextGale
        .endif
        ExitProc

EndProc     SetAPAColorScrollGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetAPAColorTextGale                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA write colors in text mode.               */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AL      = Foreground (0-3 bit) and Background (4-7) Colors      */
;/*     EDI   --> Target APA address (in text mode)                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetAPAColorTextGale

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; not foreground ?
        .if     <Gale_Text_Mode ne 0>
            ret
        .endif

        .if     <PrevColor eq ax>               ; color is changed ?
            ret
        .endif
        mov     PrevColor, ax                   ; save the color

        push    bx                              ; save bx, dx
        push    dx                              ; 

        mov     dx, GraphAddressPort            ; set VGA port address

        mov     bl, al                          ; save color

        mov     al, LG_MODE                     ; set write mode 3
        mov     ah, 03h
        out     dx, ax

        mov     al, LG_SET_RESET                ; set background color
        mov     ah, bl                          ; 
        shr     ah, 4                           ; get background color
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_MODE     ], 03h
            mov     VDMData.aregGDCData[LG_SET_RESET], ah
        .endif

        mov     byte ptr ds:[edi], 0ffh         ; clear APA with background color
        mov     al, ds:[edi]                    ; set complement register

        mov     al, LG_SET_RESET                ; set foreground color
        mov     ah, bl                          ; 
        and     ah, 0fh                         ; get foreground color
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_SET_RESET], ah
        .endif

        pop     dx                              ; restore bx, dx
        pop     bx                              ; 
        ExitProc

EndProc     SetAPAColorTextGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetAPAColorGraphGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA write colors in graphics mode            */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AL      = Foreground color (0-3 bit) and XOR bit (7)            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetAPAColorGraphGale

        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO640X480X2>    ; if mono mode ?
            and     al, 80h
            or      al, 01h
        .else
            and     al, 8fh
        .endif

        .if     <bit al nand 80h>
            jmp     SetAPAColorTextGale
        .endif

        .if     <PrevColor eq ax>               ; color is changed ?
            ret
        .endif
        mov     PrevColor, ax                   ; save the color

        push    bx                              ; save bx, dx
        push    dx                              ; 

        mov     dx, GraphAddressPort            ; set VGA port address

        push    ax

        mov     ah, al                          ; set set/reset with write color
        mov     al, LG_SET_RESET
        out     dx, ax

        not     ah                              ; enable set/reset reg
        mov     al, LG_ENABLE_SET_RESET         ; with inverted write color
        out     dx, ax

        mov     al, LG_FUNCTION                 ; set rotate 0 & func XOR
        mov     ah, 18h
        out     dx, ax

        mov     al, LG_MODE                     ; set write mode 0
        mov     ah, 00h
        out     dx, ax

        pop     ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_SET_RESET       ], al
            not     al
            mov     VDMData.aregGDCData[LG_ENABLE_SET_RESET], al
            mov     VDMData.aregGDCData[LG_FUNCTION        ], 18h
            mov     VDMData.aregGDCData[LG_MODE            ], 00h
        .endif

        pop     dx                              ; restore bx, dx
        pop     bx                              ; 
        ExitProc

EndProc     SetAPAColorGraphGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetGridColorGale                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA grid write colors.                       */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AL      = Grid Color                                            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetGridColorGale

        .if     <bit VDMData.flVDMVideo nand VDM_FGND> and  ; not foreground ?
        .if     <Gale_Text_Mode ne 0>
            ret
        .endif

        .if     <PrevColor eq ax>               ; color is changed ?
            ret
        .endif
        mov     PrevColor, ax                   ; save the color

        push    ax                              ; save ax, dx
        push    dx

        push    ax                              ; save grid color

        mov     dx, GraphAddressPort            ; set VGA port address

        mov     al, LG_MODE                     ; set write mode 3
        mov     ah, 03h
        out     dx, ax

        pop     ax                              ; restore grid color
        mov     ah, al

        mov     al, LG_SET_RESET                ; set grid color
        and     ah, 0fh                         ; get foreground color
        out     dx, ax

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>  ; not foreground ?
            mov     VDMData.aregGDCData[LG_SET_RESET], ah
            mov     VDMData.aregGDCData[LG_MODE     ], 03h
        .endif

        pop     dx                              ; restore ax,dx
        pop     ax

        ExitProc

EndProc     SetGridColorGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetAPAStartGale                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA start address register on VGA to support */
;/*                    hardware scroll.                                 */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AX      = APA Start Address                                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetAPAStartGale

        push    ax
        push    bx
        push    cx
        push    dx

        push    ax
                                            ; calc line compare reg
        not     ax                          ; ax = 10000h - ax
        inc     ax
        xor     dx, dx
        mov     bx, APAWidth
        div     bx
        .if     <ax gt FONT_HEIGHT*25>
            mov     ax, FONT_HEIGHT*25
        .endif
        dec     ax
        mov     cx, ax                      ; line compare reg value in cx

        mov     dx, MiscOutputRegRead       ; Read Miscellaneous Output Register
        in      al, dx
        mov     bx, InputStatusReg1
        mov     dx, CRTCtlAddressReg
        .if     <bit ax and 01h>            ; bit 0 = 1 - color, 0 - monochrome
            add     bx, ColorAdjustment
            add     dx, ColorAdjustment
        .else
            add     bx, MonoAdjustment
            add     dx, MonoAdjustment
        .endif

        pop     ax

        .if     <GaleScroll eq GALE_HS_LC> or
        .if     <FlagXGA ne 0> and
        .if     <GaleScroll ne GALE_HS_OFF> ; line compare scroll
            push    si
            mov     si, PrevLineComp
            .if     <si b MaxLineComp> and  ; LineComp already enabled
            .if     <cx b si>               ; scroll up
                push    ax
                call    SetLineCompGale
                pop     ax
                call    SetCRTStartGale
            .else                           ; scroll down
                call    SetCRTStartGale
                call    SetLineCompGale
            .endif
            pop     si
        .else                               ; only start address scroll
            call    SetCRTStartGale
        .endif

        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ExitProc

EndProc     SetAPAStartGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetCRTStartGale                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set CRT start address register on VGA to support */
;/*                    hardware scroll.                                 */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AX      = APA Start Address                                     */
;/*     BX      = InputStatusReg1                                       */
;/*     CX      = New Line Compare                                      */
;/*     DX      = CRTCtlAddressReg                                      */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetCRTStartGale

        push    ax
        mov     al, LC_START_HIGH           ; set new start address
        out     dx, ax
        pop     ax

        mov     ah, al
        mov     al, LC_START_LOW
        out     dx, ax

        ret
EndProc     SetCRTStartGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetLineCompGale                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set Line compare register on VGA to support      */
;/*                    hardware scroll.                                 */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AX      = APA Start Address                                     */
;/*     BX      = InputStatusReg1                                       */
;/*     CX      = New Line Compare                                      */
;/*     DX      = CRTCtlAddressReg                                      */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetLineCompGale

        xchg    bx, dx

CRTStartLoop:                               ; wait until entering in vertical retrace
        sti
        nop
        cli
        in      al, dx
        test    al, 08h
        jz      CRTStartLoop

        xchg    bx, dx

        mov     al, LC_LINE_COMP            ; set lower 8 bit value
        mov     ah, cl
        out     dx, ax

        mov     al, LC_OVERFLOW             ; set bit 8 value
        out     dx, al
        inc     dx
        in      al, dx
        dec     dx
        and     al, 0efh
        mov     ah, ch
        and     ah, 01h
        shl     ah, 4
        or      ah, al
        mov     al, LC_OVERFLOW
        out     dx, ax

        mov     al, LC_MAX_SCAN_LINE        ; set bit 9 value
        out     dx, al
        inc     dx
        in      al, dx
        dec     dx
        and     al, 0bfh
        mov     ah, ch
        and     ah, 02h
        shl     ah, 5
        or      ah, al
        mov     al, LC_MAX_SCAN_LINE
        out     dx, ax

        mov     PrevLineComp, cx

        ret
EndProc     SetLineCompGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: DrawCursorGale                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw cursor.                                     */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   DrawCursorGale
        .if     <VDMData.GaleData.GaleCursor.GaleCurDisp eq FALSE>  ; cursor is off ?
            call    XorCursorToAPA
            mov     VDMData.GaleData.GaleCursor.GaleCurDisp, TRUE
        .endif
        ExitProc
EndProc     DrawCursorGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: HideCursorGale                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Hide cursor.                                     */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   HideCursorGale
        .if     <VDMData.GaleData.GaleCursor.GaleCurDisp eq TRUE>   ; cursor is on ?
            call    XorCursorToAPA
            mov     VDMData.GaleData.GaleCursor.GaleCurDisp, FALSE
        .endif
        ExitProc
EndProc     HideCursorGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetCursorGale                                     */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set cursor type & position from BIOS data area   */
;/*                    to display data.                                 */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetCursorGale
        .if     <VDMData.GaleData.GaleCursor.GaleCurDisp eq TRUE>   ; cursor is on ?
            call    XorCursorToAPA
        .endif
        push    ax
        mov     ax, VDMBase.rb_awVCursorPos     ; copy cursor position
        mov     VDMData.GaleData.GaleCursor.GaleCurPos, ax
        mov     ax, VDMBase.rb_wVCursorMode     ; copy cursor mode
        mov     VDMData.GaleData.GaleCursor.GaleCurMode, ax
        pop     ax
        .if     <VDMData.GaleData.GaleCursor.GaleCurDisp eq TRUE>   ; cursor is on ?
            call    XorCursorToAPA
        .endif
        ExitProc
EndProc     SetCursorGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: XorCursorToAPA                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw character cursor on APA with XOR attribute. */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     None                                                            */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   XorCursorToAPA

        .if     <bit VDMData.flVDMVideo nand VDM_FGND>      ; windowed ?
            ret
        .endif

        push    ax
        push    ebx
        push    cx
        push    dx
        push    edi

        mov     cx, VDMData.GaleData.GaleCursor.GaleCurMode ; cursor type
        mov     bx, VDMData.GaleData.GaleCursor.GaleCurPos  ; cursor position

        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80> and
        .if     <VDMBase.rb_bVMode ne BIOSVMODE_CO80_GALE>
            jmp     XorCursorExit               ; not text mode
        .endif

        movzx   ax, bh
        mul     SkipLineAPA
        add     ax, Gale_Start_Addr
        movzx   edi, ax
        movzx   eax, bl
        add     edi, eax
        add     edi, APA_START_ADDR
        and     edi, APA_ADDR_MASK              ; pointer into APA

        mov     al, 19                          ; convert cursor type scale
        call    mapc

        .if     <ch ae 19> or                   ; hidden cursor
        .if     <ch a cl>                       ; or invalid type
            jmp     XorCursorExit
        .endif

        .if     <cl ae 19>                      ; check too large cursor
            mov     cl, 18
        .endif

        mov     al, byte ptr APAWidth
        mul     ch
        movzx   eax, ax
        add     edi, eax
        and     edi, APA_ADDR_MASK              ; edi = cursor start pos in APA

        sub     cl, ch
        inc     cl
        movzx   ecx, cl                         ; cx = cursor height

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_FUNCTION                 ; set rotate 0 & xor op
        mov     ah, 18h
        out     dx, ax

        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     al, LG_MODE                     ; set write mode 2
        mov     ah, 02h
        out     dx, ax

        mov     al, 0ffh
        cld

        mov     edx, SkipLasterAPA              ; preload skip count

        .if     <edi be APABottomBound> near    ; no check ?
XorCursorLoop1:
            mov     ah, [edi]
            stosb
            add     edi, edx
            loop    XorCursorLoop1
        .else
XorCursorLoop2:
            mov     ah, [edi]
            stosb
            add     edi, edx
            and     edi, APA_ADDR_MASK
            loop    XorCursorLoop2
        .endif

XorCursorExit:
        pop     edi
        pop     dx
        pop     cx
        pop     ebx
        pop     ax

        ExitProc

EndProc     XorCursorToAPA

;       cursor size translation routine from ROM BIOS
;
;       Entry:  al = character height
;               cx = cursor mode
;       Exit:   cx = mapped cursor mode(start/end)
;               ax = destroyed
;
Procedure   mapc
        push    dx
;  TEST FOR NO CURSOR (CURSOR OFF)
        TEST    CX,0E0E0H               ; (IE 2020H)
        JNZ     MAPX
;  USE CURRENT POINTS [AL]
        MOV     DL,AL
        DEC     DL                      ; 08 14 16
        MOV     DH,DL                   ; 07 13 15
        DEC     DH                      ; 06 12 14
;  DO THEY KNOW WHAT THEY'RE DOING?
        CMP     CL,CH                   ; END ? START
        JB      MAP1                    ; B: SPLIT, ELSE
        MOV     AH,CH
        OR      AH,CL                   ; START OR END
        CMP     AH,AL                   ; MAX ? POINTS
        JAE     MAP2
        CMP     CL,DL                   ; END ? POINTS-1
        JE      MAPX
        CMP     CH,DH                   ; START ? POINTS-2
        JE      MAPX
        JMP     SHORT MAP2              ; CHECK OTHER TYPES
;  SPLIT CURSOR [END < START]
MAP1:   CMP     CL,0                    ; END ? 0
        JZ      MAPX                    ; Z: LEAVE IT BE
        MOV     CH,DL                   ; START = POINTS -1
        XCHG    CL,CH                   ; NO SPLIT CURSORS!
        JMP     SHORT MAPX
;  CHECK FOR OVERBAR CURSOR (END > START)
MAP2:   CMP     CL,3                    ; END ? 3
        JBE     MAPX                    ; BE: OK
;  CHECK FOR UNDERLINE CURSOR
MAP3:   MOV     AH,CH                   ; START
        ADD     AH,2                    ; START+2
        CMP     AH,CL                   ; START+2 ? END
        JB      MAP4                    ; B: MUST BE BLOCK
        SUB     CH,CL                   ; START-END
        ADD     CH,DL                   ; POINTS-1 + (START-END)
        MOV     CL,DL                   ; POINTS-1
        CMP     AL,14D                  ; CHECK TALL FONTS
        JL      MAPX                    ; L: ENOUGH, ELSE
        SUB     CX,0101H                ; POINTS -2/-3
        JMP     SHORT MAPX
;  CHECK FOR FULL BLOCK CURSOR
MAP4:   CMP     CH,2                    ; START ? 2
        JA      MAP5                    ; A: HALF, ELSE
        MOV     CL,DL                   ; POINTS-1
        JMP     SHORT MAPX
;  MUST BE HALF BLOCK CURSOR
MAP5:   MOV     CH,AL                   ; POINTS
        SHR     CH,1                    ; POINTS/2
        MOV     CL,DL                   ; POINTS-1
MAPX:
        pop     dx
        ret
EndProc     mapc

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: MakePointer                                       */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Make LVB & APA pointer from (row,col) position.  */
;/*                    Mode Set.                                        */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      DX =  (Row,Col) position                                       */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     EBX =  pointer to LVB                                           */
;/*     EDI =  pointer to APA                                           */
;/*     CRY =  Off: Success, On: position overflow                      */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   MakePointer

        .if     <dh ge Gale_Max_Row> or         ; overflow check
        .if     <dl ge SCREEN_WIDTH>
            stc
            ret
        .endif

        push    ax
        push    dx

        mov     bx, dx                          ; save (row,col) in bx
        movzx   ax, bh
        mul     SkipLineAPA
        add     ax, Gale_Start_Addr
        movzx   edi, ax
        movzx   eax, bl
        add     edi, eax
        add     edi, APA_START_ADDR
        and     edi, APA_ADDR_MASK              ; pointer into APA

        mov     al, SCREEN_WIDTH
        mul     bh
        movzx   bx, bl
        add     ax, bx
        movzx   ebx, ax
        .if     <VDMBase.rb_bVMode eq BIOSVMODE_CO80_GALE>
            shl     ebx, 2
        .else
            shl     ebx, 1
        .endif
        add     ebx, VDMData.GaleData.GaleLVB   ; pointer into LVB
        clc

        pop     dx
        pop     ax

        ExitProc

EndProc     MakePointer

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: IsKanjiGale                                       */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Check DBCS first byte.                           */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  Character code                                           */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     Carry = ON  : DBCS 1st                                          */
;/*           = OFF : SBCS                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   IsKanjiGale
        push    eax
        movzx   eax, al
        sub     ah, DBCS1st[eax]
        pop     eax
        ExitProc
EndProc     IsKanjiGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: QueryCharTypeGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Check character type SBCS/DBCS 1st/DBCS 2nd      */
;/*                    (Text mode only)                                 */
;/*  ENTRY:                                                             */
;/*     EBX =  hvdm->VDMData                                            */
;/*      DX =  (Row,Col) character position                             */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*      AL =  0 : SBCS                                                 */
;/*            1 : DBCS 1st                                             */
;/*            2 : DBCS 2nd                                             */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   QueryCharTypeGale

        LocalVar    CharType, BYTE

        EnterProc
        push    ebx
        push    esi

        mov     al, SCREEN_WIDTH
        mul     dh
        movzx   eax, ax
        .if     <[ebx].ulBIOSMode eq BIOSVMODE_CO80>
            shl     eax, 1
            mov     esi, 2
        .else
            shl     eax, 2
            mov     esi, 4
        .endif
        add     eax, [ebx].GaleData.GaleLVB
        sub     ebx, FLAToffset VDMData
        add     ebx, eax
        mov     CharType, 0
        movzx   ecx, dl
        inc     ecx

CharTypeLoop:
        .if     <CharType eq 1>
            mov     CharType, 2
        .else
            movzx   eax, [ebx]
            .if     <DBCS1st[eax] ne 0>
                mov     CharType, 1
            .else
                mov     CharType, 0
            .endif
        .endif
        add     ebx, esi
        loop    CharTypeLoop

        mov     al, CharType

        pop     esi
        pop     ebx
        ExitProc

EndProc     QueryCharTypeGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: RedrawPtrGale                                     */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Redraw oe SBCS/DBCS char for mouse pointer.      */
;/*                    (Text mode only)                                 */
;/*  ENTRY:                                                             */
;/*     EAX =  LVB pointer                                              */
;/*     EBX =  hvdm->VDMData                                            */
;/*      CX =  1 : SBCS, 2 : DBCS                                       */
;/*      DX =  (Row,Col) character position                             */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   RedrawPtrGale

        LocalVar    vva, VVSTRING

        EnterProc
        pushad

        push    ebx
        push    edx

        xchg    ebx, edx
        sub     edx, FLAToffset VDMData         ; hvdm

        .if     <bit [edx].VDMData.flVDMVideo and VDM_WINDOWED> ; windowed ?
            movzx   eax, bh
            mov     vva.vva_row, eax            ; row of string
            mov     al, bl
            mov     vva.vva_col, eax            ; column of string
            movzx   eax, cx
            mov     vva.vva_nChars, eax         ; length
            SSToDS  eax, vva
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>

        .else                                                   ; full screen
            call    HideCursorGeneral               ; hide cursor

            pop     edx
            pop     ebx

            call    SaveScreenPtrGale               ; save APA text image

            xchg    ebx, edx
            sub     edx, FLAToffset VDMData         ; hvdm

            neg     cx
            .if     <cx eq -2> and
            movzx   esi, [eax]
            .if     <DBCS1st[esi] eq 0>
                mov     cx, -1
                call    DrawCharGeneral             ; draw one char
                inc     bl
                .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
                    add     eax, 2
                .else
                    add     eax, 4
                .endif
                call    DrawCharGeneral             ; draw one char
            .else
                call    DrawCharGeneral             ; draw one char
            .endif

            call    DrawCursorGeneral               ; show cursor
        .endif

        popad
        ExitProc

EndProc     RedrawPtrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SaveScreenPtrGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Save APA for pointer drwaing.                    */
;/*                    (Text mode only)                                 */
;/*  ENTRY:                                                             */
;/*     EBX =  hvdm->VDMData                                            */
;/*      CX =  1 : SBCS, 2 : DBCS                                       */
;/*      DX =  (Row,Col) character position                             */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SaveScreenPtrGale

        LocalVar    CharType, BYTE

        EnterProc
        pushad

        mov     CharType, cl                    ; save char type

        sub     ebx, FLAToffset VDMData         ; hvdm

        movzx   eax, dh
        movzx   esi, dl
        mul     [ebx].SkipLineAPA
        add     esi, eax
        movzx   eax, [ebx].Gale_Start_Addr
        add     esi, eax
        and     esi, APA_ADDR_MASK
        add     esi, pPhysVRAM                  ; APA top address
        lea     edi, [ebx].VDMData.PtrData.abPtrSaveGale ; screen save buffer

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_MODE                     ; set read mode 0
        mov     ah, 00h
        out     dx, ax

        mov     ch, 4                           ; set plane counter

SaveScrnLoop1:
        mov     al, LG_READ_MAP                 ; set read map
        mov     ah, ch
        dec     ah
        out     dx, ax

        mov     cl, [ebx].FontHeight            ; set font height loop counter
        push    esi

        .if     <CharType eq 1>                 ; SBCS ?
SaveScrnLoop2:
            movsb                               ; save one laster
            sub     esi, pPhysVRAM
            add     esi, [ebx].SkipLasterAPA    ; skip to next laster
            and     esi, APA_ADDR_MASK
            add     esi, pPhysVRAM
            dec     cl
            jnz     SaveScrnLoop2
        .else                                   ; DBCS
SaveScrnLoop3:
            movsw                               ; save one laster
            sub     esi, pPhysVRAM
            add     esi, [ebx].SkipLasterAPA    ; skip to next laster
            dec     esi
            and     esi, APA_ADDR_MASK
            add     esi, pPhysVRAM
            dec     cl
            jnz     SaveScrnLoop3
        .endif

        pop     esi                             ; restore APA pointer

        dec     ch
        jnz     SaveScrnLoop1                   ; next plane

        popad
        ExitProc

EndProc     SaveScreenPtrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: RestoreScreenPtrGale                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Restore APA for pointer drwaing.                 */
;/*                    (Text mode only)                                 */
;/*  ENTRY:                                                             */
;/*     EBX =  hvdm->VDMData                                            */
;/*      CX =  1 : SBCS, 2 : DBCS                                       */
;/*      DX =  (Row,Col) character position                             */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   RestoreScreenPtrGale

        LocalVar    CharType, BYTE
        LocalVar    vva,      VVSTRING

        EnterProc
        pushad

        sub     ebx, FLAToffset VDMData     ; hvdm

        .if     <bit [ebx].VDMData.flVDMVideo and VDM_WINDOWED> ; windowed ?
            movzx   eax, dh
            mov     vva.vva_row, eax            ; row of string
            mov     al, dl
            mov     vva.vva_col, eax            ; column of string
            movzx   eax, cx
            mov     vva.vva_nChars, eax         ; length
            SSToDS  eax, vva
            CallFn  vvAddEvent, <CURRENT_VDM, VVDEVENT_STRING, eax, 0>

        .else near                                              ; full screen
            mov     CharType, cl                ; save char type

            push    edx
            mov     edx, ebx
            call    HideCursorGeneral           ; hide cursor
            pop     edx

            movzx   eax, dh
            movzx   edi, dl
            mul     [ebx].SkipLineAPA
            add     edi, eax
            movzx   eax, [ebx].Gale_Start_Addr
            add     edi, eax
            and     edi, APA_ADDR_MASK
            add     edi, pPhysVRAM              ; APA top address
            lea     esi, [ebx].VDMData.PtrData.abPtrSaveGale ; screen save buffer

            mov     dx, GraphAddressPort        ; set VGA port address
            mov     al, LG_MODE                 ; set write mode 0
            mov     ah, 00h
            out     dx, ax
            mov     al, LG_FUNCTION             ; set rotate 0
            mov     ah, 0
            out     dx, ax
            mov     al, LG_BIT_MASK             ; set bit mask ffh
            mov     ah, 0ffh
            out     dx, ax
            mov     al, LG_ENABLE_SET_RESET     ; set set/reset enable
            mov     ah, 0
            out     dx, ax

            mov     ch, 4                       ; set plane counter

    RestoreScrnLoop1:
            mov     dx, SeqAddressPort          ; set VGA port address
            mov     al, LS_MAP_MASK
            mov     cl, ch
            dec     cl
            mov     ah, 01h
            shl     ah, cl
            out     dx, ax                      ; select restore map

            mov     cl, [ebx].FontHeight        ; loop counter
            push    edi                         ; save APA pointer

            .if     <CharType eq 1>             ; SBCS ?
    RestoreScrnLoop2:
                movsb                           ; save one laster
                sub     edi, pPhysVRAM
                add     edi, [ebx].SkipLasterAPA ; skip to next laster
                and     edi, APA_ADDR_MASK
                add     edi, pPhysVRAM
                dec     cl
                jnz     RestoreScrnLoop2
            .else                               ; DBCS
    RestoreScrnLoop3:
                movsw                           ; save one laster
                sub     edi, pPhysVRAM
                add     edi, [ebx].SkipLasterAPA ; skip to next laster
                dec     edi
                and     edi, APA_ADDR_MASK
                add     edi, pPhysVRAM
                dec     cl
                jnz     RestoreScrnLoop3
            .endif

            pop     edi                         ; restore APA pointer

            dec     ch
            jnz     RestoreScrnLoop1            ; next plane

            mov     dx, SeqAddressPort          ; restore map mask
            mov     al, LS_MAP_MASK
            mov     ah, 0ffh
            out     dx, ax                      ; set map mask ffh

            mov     edx, ebx
            call    DrawCursorGeneral           ; show cursor
        .endif

        popad
        ExitProc

EndProc     RestoreScreenPtrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: DrawCharGeneral                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw one SBCS/DBCS char for pointer & XVIO.      */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EAX =  LVB pointer                                              */
;/*      BX =  (Row,Col) character position                             */
;/*      CX =  1 : SBCS, 2 : DBCS   (-1, -2 means requesrt from         */
;/*                                  RedrawScreen during screen switch) */
;/*     EDX =  hvdm                                                     */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   DrawCharGeneral

        LocalVar    CharRow, BYTE
        LocalVar    CharCol, BYTE
        LocalVar    hvdm,    DWORD
        LocalVar    LVBChar, DWORD
        LocalVar    APATop,  DWORD

        EnterProc

        pushad

        mov     CharRow, bh                     ; save char position
        mov     CharCol, bl

        .if      <cx l 0>                       ; cx < 0 ?
            neg     ecx                         ; request from RedrawScreen &
            mov     esi, pPhysVRAM              ; mouse pointer
            mov     APATop, esi                 ; (only full screen)
        .else
            mov     APATop, edx                 ; request from XVIO, etc.
        .endif                                  ; (can be in windowed)

        mov     hvdm, edx                       ; save hvdm
        mov     LVBChar, eax                    ; save LVB pointer
                                                ; setup VGA registers
        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_FUNCTION                 ; set rotate 0
        mov     ah, 0
        out     dx, ax
        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     edi, hvdm                       ; get hvdm in esi
        movzx   ax, CharRow
        mul     [edi].SkipLineAPA
        movzx   bx, CharCol
        add     ax, bx
        add     ax, [edi].Gale_Start_Addr
        movzx   edi, ax
        and     edi, APA_ADDR_MASK              ; offset in APA
        add     edi, APA_START_ADDR

        mov     ebx, LVBChar                    ; pointer to LVB
        mov     edx, hvdm                       ; hvdm
        .if     <edx ne APATop>
            sub     edi, APA_START_ADDR
        .endif

        .if     <cx eq 1>
            mov     al, [ebx]
            call    vvGetSBCSFontGeneral
            mov     ecx, APATop
            call    vvUpdateAPAwithSBCSGeneral
        .else
            mov     ah, [ebx]
            .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
                mov     al, [ebx+2]
            .else
                mov     al, [ebx+4]
            .endif
            push    ebx
            mov     ebx, edx
            call    VfntGetDBCS16Font
            pop     ebx
            mov     ecx, APATop
            call    vvUpdateAPAwithDBCSGeneral
        .endif

        popad
        ExitProc

EndProc     DrawCharGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: DrawCursorGeneral                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw cursor for pointer & XVIO.                  */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     EDX =  hvdm                                                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   DrawCursorGeneral
        .if     <[edx].VDMData.GaleData.GaleCursor.GaleCurDisp eq FALSE> ; cursor is off ?
            call    XorCursorToAPAGeneral
            mov     [edx].VDMData.GaleData.GaleCursor.GaleCurDisp, TRUE
        .endif
        ExitProc
EndProc     DrawCursorGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: HideCursorGeneral                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Hide cursor for pointer & XVIO.                  */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     EDX =  hvdm                                                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   HideCursorGeneral
        .if     <[edx].VDMData.GaleData.GaleCursor.GaleCurDisp eq TRUE> ; cursor is on ?
            call    XorCursorToAPAGeneral
            mov     [edx].VDMData.GaleData.GaleCursor.GaleCurDisp, FALSE
        .endif
        ExitProc
EndProc     HideCursorGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: XorCursorToAPAGeneral                             */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw character cursor on APA with XOR attribute  */
;/*                    for pointer & XVIO.                              */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     EDX =  hvdm                                                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   XorCursorToAPAGeneral

        .if     <bit [edx].VDMData.flVDMVideo nand VDM_FGND> ; not foreground ?
            ret
        .endif

        pushad

        mov     cx, VDMData.GaleData.GaleCursor.GaleCurMode[edx] ; cursor type
        mov     bx, VDMData.GaleData.GaleCursor.GaleCurPos[edx]  ; cursor position

        movzx   ax, bh
        push    edx
        mul     [edx].SkipLineAPA
        pop     edx
        add     ax, [edx].Gale_Start_Addr
        movzx   edi, ax
        movzx   eax, bl
        add     edi, eax
        and     edi, APA_ADDR_MASK              ; pointer offset in APA

        mov     al, 19                          ; convert cursor type scale
        call    mapc

        .if     <ch ae 19> or                   ; hidden cursor
        .if     <ch a cl>                       ; or invalid type
            jmp     XorCursorGenExit
        .endif

        .if     <cl ae 19>                      ; check too large cursor
            mov     cl, 18
        .endif

        mov     al, byte ptr [edx].APAWidth
        mul     ch
        movzx   eax, ax
        add     edi, eax
        and     edi, APA_ADDR_MASK              ; edi = cursor start pos in APA (offset)

        sub     cl, ch
        inc     cl
        movzx   ecx, cl                         ; cx = cursor height

        push    edx                             ; save hvdm

        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK                 ; set map mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_FUNCTION                 ; set rotate 0 & xor op
        mov     ah, 18h
        out     dx, ax

        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax

        mov     al, LG_MODE                     ; set write mode 2
        mov     ah, 02h
        out     dx, ax

        mov     al, 0ffh
        cld

        pop     edx                             ; restore hvdm

        mov     edx, [edx].SkipLasterAPA        ; preload skip count

XorCursorGenLoop:
        add     edi, pPhysVRAM
        mov     ah, [edi]
        stosb
        sub     edi, pPhysVRAM
        add     edi, edx
        and     edi, APA_ADDR_MASK
        loop    XorCursorGenLoop

XorCursorGenExit:
        popad

        ExitProc

EndProc     XorCursorToAPAGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithSBCSGeneral                        */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw SBCS character into APA                     */
;/*                    for pointer & XVIO.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ECX =  vertural APA top address                                 */
;/*     EDX =  hvdm                                                     */
;/*     ESI -> SBCS 19 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithSBCSGeneral

        LocalVar    TargetPtr, DWORD

        EnterProc

        movzx   ax, [ebx+1]                     ; set color
        add     edi, ecx
        call    SetAPAColorGaleGeneral
        sub     edi, ecx

        mov     eax, [edx].SkipLasterAPA        ; get skip count
        cld

        mov     TargetPtr, edi

        push    ebx
        xchg    ebx, ecx

        movzx   ecx, [edx].FontHeight
        dec     ecx

UpdateSBCSGenLoop:
        add     edi, ebx
        movsb
        sub     edi, ebx
        add     edi, eax
        and     edi, APA_ADDR_MASK
        loop    UpdateSBCSGenLoop

        xchg    ebx, ecx
        pop     ebx

        add     edi, ecx
        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
            movsb
        .else
            mov     ah, [ebx+2]                     ; get attribute 1
            .if     <bit ah and UNDERLINE>
                mov     byte ptr [edi], 0ffh
            .else
                movsb
            .endif
            mov     edi, TargetPtr                  ; restore edi
            .if     <bit ah and VERT_GRID+HORZ_GRID>
                call    DrawGridGaleGeneral
            .endif
        .endif

        ExitProc
EndProc     vvUpdateAPAwithSBCSGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvUpdateAPAwithDBCSGeneral                        */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw DBCS character into APA                     */
;/*                    for pointer & XVIO.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*     EBX -> LVB                                                      */
;/*     ECX =  vertural APA top address                                 */
;/*     EDX =  hvdm                                                     */
;/*     ESI -> DBCS 16 font                                             */
;/*     EDI -> APA                                                      */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvUpdateAPAwithDBCSGeneral

        LocalVar    SourcePtr, DWORD
        LocalVar    TargetPtr, DWORD

        EnterProc

        cld

        movzx   ax, [ebx+1]                     ; set 1st byte color
        add     edi, ecx
        call    SetAPAColorGaleGeneral
        sub     edi, ecx

        mov     SourcePtr, esi                  ; save for 2nd byte draw
        mov     TargetPtr, edi

        .if     <[edx].FontHeight eq FONT_HEIGHT>
            xor     al, al                      ; clear top laster
            add     edi, ecx
            stosb
            sub     edi, ecx
            add     edi, [edx].SkipLasterAPA
            and     edi, APA_ADDR_MASK
        .endif

        push    ebx
        xchg    ebx, ecx

        mov     ecx, FONT_HEIGHT_LOW            ; set loop counter

UpdateDBCSGenLoop1:
        add     edi, ebx
        movsb
        sub     edi, ebx
        inc     esi
        add     edi, [edx].SkipLasterAPA
        and     edi, APA_ADDR_MASK
        loop    UpdateDBCSGenLoop1

        xchg    ebx, ecx
        pop     ebx

        .if     <[edx].FontHeight eq FONT_HEIGHT>
            xor     al, al                      ; clear bottom 2 lasters
            add     edi, ecx
            stosb
            sub     edi, ecx
            add     edi, [edx].SkipLasterAPA
            and     edi, APA_ADDR_MASK
            add     edi, ecx
            .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
                stosb
            .else
                mov     ah, [ebx+2]
                .if     <bit ah and UNDERLINE>
                    mov     al, 0ffh            ; underline is on
                .endif
                stosb
                .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                    mov     esi, SourcePtr      ; restore esi, edi
                    mov     edi, TargetPtr
                    call    DrawGridGaleGeneral
                .endif
            .endif
        .else
            mov     ah, [ebx+2]
            .if     <bit ah and UNDERLINE>
                sub     edi, [edx].SkipLasterAPA
                dec     edi
                add     edi, ecx
                mov     byte ptr [edi], 0ffh    ; underline is on
            .endif
            .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                mov     esi, SourcePtr          ; restore esi, edi
                mov     edi, TargetPtr
                call    DrawGridGaleGeneral
            .endif
        .endif

        mov     esi, SourcePtr                  ; restore esi, edi
        mov     edi, TargetPtr
        inc     esi                             ; skip to next column
        inc     edi

        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
            movzx   ax, [ebx+3]
        .else
            movzx   ax, [ebx+5]
        .endif
        add     edi, ecx
        call    SetAPAColorGaleGeneral      ; set 2nd byte color
        sub     edi, ecx

        .if     <[edx].FontHeight eq FONT_HEIGHT>
            xor     al, al                  ; clear top laster
            add     edi, ecx
            stosb
            sub     edi, ecx
            add     edi, [edx].SkipLasterAPA
            and     edi, APA_ADDR_MASK
        .endif

        push    ebx
        xchg    ebx, ecx

        mov     ecx, FONT_HEIGHT_LOW            ; set loop counter

UpdateDBCSGenLoop2:
        add     edi, ebx
        movsb
        sub     edi, ebx
        inc     esi
        add     edi, [edx].SkipLasterAPA
        and     edi, APA_ADDR_MASK
        loop    UpdateDBCSGenLoop2

        xchg    ebx, ecx
        pop     ebx

        .if     <[edx].FontHeight eq FONT_HEIGHT>
            xor     al, al                          ; clear bottom 2 lasters
            add     edi, ecx
            stosb
            sub     edi, ecx
            add     edi, [edx].SkipLasterAPA
            and     edi, APA_ADDR_MASK
            add     edi, ecx
            .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80>
                stosb
            .else
                mov     ah, [ebx+6]
                .if     <bit ah and UNDERLINE>
                    mov     al, 0ffh                ; underline is on
                .endif
                stosb
                .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                    mov     esi, SourcePtr          ; restore esi, edi
                    mov     edi, TargetPtr
                    inc     esi
                    inc     edi
                    call    DrawGridGaleGeneral
                .endif
            .endif
        .else
            mov     ah, [ebx+6]
            .if     <bit ah and UNDERLINE>
                sub     edi, [edx].SkipLasterAPA
                dec     edi
                add     edi, ecx
                mov     byte ptr [edi], 0ffh    ; underline is on
            .endif
            .if     <bit ah and VERT_GRID+HORZ_GRID>    ; grid is on ?
                mov     esi, SourcePtr          ; restore esi, edi
                mov     edi, TargetPtr
                inc     esi
                inc     edi
                call    DrawGridGaleGeneral
            .endif
        .endif

        ExitProc
EndProc     vvUpdateAPAwithDBCSGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: DrawGridGaleGeneral                               */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Draw vertical & horizontal grid line             */
;/*                    in Extended CGA mode for pointer & XVIO.         */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AH = attribte 1                                                */
;/*     EBX = LVB pointer                                               */
;/*     ECX =  vertural APA top address                                 */
;/*     EDX = hvdm                                                      */
;/*     EDI = APA pointer                                               */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     None                                                            */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   DrawGridGaleGeneral
        pushad

        mov     esi, ecx                        ; save APA top addr
        mov     ebx, edx                        ; save hvdm
        push    ax                              ; save attribute 1

        mov     dx, GraphAddressPort            ; set VGA port address

        mov     al, LG_SET_RESET                ; set grid color
        .if     <VDMBase.rb_bVMode[ebx] eq BIOSVMODE_CO640X480X2>   ; if mono mode ?
            mov     ah, GRID_COLOR_MONO
        .else
            mov     ah, GRID_COLOR
        .endif
        out     dx, ax

        mov     al, LG_MODE                     ; set write mode 3
        mov     ah, 03h
        out     dx, ax

        pop     ax                              ; restore attribute 1

        mov     edx, [ebx].SkipLasterAPA

        .if     <bit ah and HORZ_GRID>
            add     edi, esi
            mov     byte ptr [edi], 0ffh
            sub     edi, esi
        .endif

        .if     <bit ah and VERT_GRID>
            movzx   ecx, [ebx].FontHeight
            mov     al, 80h

DrawGridGenLoop:
            add     edi, esi
            mov     ah, [edi]
            stosb
            sub     edi, esi
            add     edi, edx
            and     edi, APA_ADDR_MASK
            loop    DrawGridGenLoop
        .endif

        popad
        ExitProc

EndProc     DrawGridGaleGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvGetSBCSFontGeneral                              */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Get SBCS 16 font image addr                      */
;/*                    for pointer & XVIO.                              */
;/*                                                                     */
;/*  ENTRY:                                                             */
;/*      AL =  SBCS character code                                      */
;/*     EDX =  hvdm                                                     */
;/*                                                                     */
;/*  EXIT:                                                              */
;/*     ESI -> SBCS font image                                          */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvGetSBCSFontGeneral
        push    eax

        .if     <VDMBase.rb_bVMode[edx] eq BIOSVMODE_CO80> or
        .if     <VDMBase.rb_bVMode[edx] eq BIOSVMODE_CO80_GALE>
            movzx   eax, al
            lea     esi, [eax*8+eax]
            lea     esi, [esi*2+eax]
            add     esi, [edx].VDMData.GaleData.GaleSBCS
            add     esi, edx
        .else
            mul     [edx].FontHeight
            movzx   esi, ax
            movzx   eax, SBCS_FONT_VECTOR_SEL[edx]
            shl     eax, 4
            add     esi, eax
            movzx   eax, SBCS_FONT_VECTOR_OFF[edx]
            add     esi, eax
            add     esi, edx
        .endif

        pop     eax
        ExitProc
EndProc     vvGetSBCSFontGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: SetAPAColorGaleGeneral                            */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set APA write colors in text mode.               */
;/*                    (mouse pointer special)                          */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     AL      = Foreground (0-3 bit) and Background (4-7) Colors      */
;/*     EDX     = hvdm                                                  */
;/*     EDI   --> Target APA address (in text mode)                     */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   SetAPAColorGaleGeneral

        .if     <VDMBase.rb_bVMode[edx] eq BIOSVMODE_CO640X480X2>   ; if mono mode ?
            .if     <bit al and 0f0h>           ; make bgnd color mono
                and     al, 0fh
                or      al, 10h
            .endif
            .if     <bit al and 0fh>            ; make fgnd color mono
                and     al, 0f0h
                or      al, 01h
            .endif
        .endif

        push    bx                              ; save bx, dx
        push    dx                              ; 

        mov     dx, GraphAddressPort            ; set VGA port address

        mov     bl, al                          ; save color

        mov     al, LG_MODE                     ; set write mode 3
        mov     ah, 03h
        out     dx, ax

        mov     al, LG_SET_RESET                ; set background color
        mov     ah, bl                          ; 
        shr     ah, 4                           ; get background color
        out     dx, ax

        mov     byte ptr ds:[edi], 0ffh         ; clear APA with background color
        mov     al, ds:[edi]                    ; set complement register

        mov     al, LG_SET_RESET                ; set foreground color
        mov     ah, bl                          ; 
        and     ah, 0fh                         ; get foreground color
        out     dx, ax

        pop     dx                              ; restore bx, dx
        pop     bx                              ; 
        ExitProc

EndProc     SetAPAColorGaleGeneral

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvConvAPAToPrtGale                                */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Convert APA bitmap to patterned printer bitmap.  */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     planes = array of pointers to APA planes                        */
;/*     buff  =  output buffer for printer                              */
;/*     conv  =  box pattern array                                      */
;/*     color =  display mode (TRUE = color, FALSE = mono)              */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvConvAPAToPrtGale
        ArgVar      planes,  ULONG
        ArgVar      buff,    ULONG
        ArgVar      conv,    ULONG
        ArgVar      color,   ULONG
        LocalVar    row,     ULONG
        LocalVar    col,     ULONG
        LocalVar    planes2, 16
        EnterProc
        pushad

        .if     <color ne 0> near               ; color mode ?

            mov     esi, planes                 ; copy pointers
            mov     eax, [esi+ 0]
            mov     dword ptr planes2[ 0], eax
            mov     eax, [esi+ 4]
            mov     dword ptr planes2[ 4], eax
            mov     eax, [esi+ 8]
            mov     dword ptr planes2[ 8], eax
            mov     eax, [esi+12]
            mov     dword ptr planes2[12], eax

            mov     edi, buff                   ; get output buff ptr

            mov     row, 480                    ; reset row loop counter

APAToPrtLoopC1:
            mov     edx, conv                   ; get convert table
            .if     <bit row and 1>             ; adjust conv table
                add     edx, 4
            .endif

            mov     col, 640/8                  ; reset col loop counter

APAToPrtLoopC2:
            xor     esi, esi                    ; set plane loop counter
            xor     eax, eax                    ; clear color container
            push    edi

APAToPrtLoopC3:
            mov     edi, dword ptr planes2[esi*4] ; get plane pointer
            mov     ch, [edi]                   ; get 8 dots in one plane
            xor     ebx, ebx                    ; expand 8 dots in byte to
            shl     ch, 1                       ; 8 dots in dword
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            shr     ebx, 3
            shl     ch, 1
            rcr     ebx, 1
            or      eax, ebx                    ; merge to color container
            ror     eax, 1
            inc     esi
            cmp     esi, 4                      ; next plane ?
            jl      APAToPrtLoopC3

            pop     edi
            mov     ebx, eax
            rol     ebx, 1                      ; 8 dots color data in EBX

            xor     ax, ax                      ; clear printer data

            mov     esi, ebx                    ; dot 7
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+0+0]
            or      ah, [edx+esi*8+0+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 6
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+2+0]
            or      ah, [edx+esi*8+2+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 5
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+0+0]
            or      ah, [edx+esi*8+0+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 4
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+2+0]
            or      ah, [edx+esi*8+2+1]
            shr     ebx, 4

            mov     [edi], al                   ; save first 4 dots pattern
            mov     [edi+640*2/8], ah
            inc     edi

            xor     ax, ax                      ; clear printer data

            mov     esi, ebx                    ; dot 3
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+0+0]
            or      ah, [edx+esi*8+0+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 2
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+2+0]
            or      ah, [edx+esi*8+2+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 1
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+0+0]
            or      ah, [edx+esi*8+0+1]
            shl     ax, 2
            shr     ebx, 4
            mov     esi, ebx                    ; dot 0
            and     esi, 0fh                    ; get one dot color
            or      al, [edx+esi*8+2+0]
            or      ah, [edx+esi*8+2+1]

            mov     [edi], al                   ; save 2nd 4 dots pattern
            mov     [edi+640*2/8], ah
            inc     edi

            inc     dword ptr planes2[ 0]
            inc     dword ptr planes2[ 4]
            inc     dword ptr planes2[ 8]
            inc     dword ptr planes2[12]
            dec     col
            jz      APAToPrtLoopExitC2
            jmp     APAToPrtLoopC2

APAToPrtLoopExitC2:
            add     edi, 640*2/8
            dec     row
            jz      APAToPrtLoopExitC1
            jmp     APAToPrtLoopC1

APAToPrtLoopExitC1:
        .else near                              ; mono mode
            mov     esi, planes
            mov     esi, [esi]                  ; get APA ptr
            mov     edi, buff                   ; get output buff ptr

            mov     row, 480                    ; reset row loop counter

APAToPrtLoopM1:
            mov     edx, conv                   ; get convert table
            .if     <bit row and 1>             ; adjust conv table
                add     edx, 4
            .endif

            mov     col, 640/8                  ; reset col loop counter

APAToPrtLoopM2:
            mov     bl, [esi]                   ; get 8 dots

            xor     ax, ax                      ; clear output data

            shl     bl, 1                       ; bit 7
            .if     nc                          ; bit off ?
                or      al, [edx+0+0+0]
                or      ah, [edx+0+0+1]
            .else                               ; bit on
                or      al, [edx+8+0+0]
                or      ah, [edx+8+0+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 6
            .if     nc                          ; bit off ?
                or      al, [edx+0+2+0]
                or      ah, [edx+0+2+1]
            .else                               ; bit on
                or      al, [edx+8+2+0]
                or      ah, [edx+8+2+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 5
            .if     nc                          ; bit off ?
                or      al, [edx+0+0+0]
                or      ah, [edx+0+0+1]
            .else                               ; bit on
                or      al, [edx+8+0+0]
                or      ah, [edx+8+0+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 4
            .if     nc                          ; bit off ?
                or      al, [edx+0+2+0]
                or      ah, [edx+0+2+1]
            .else                               ; bit on
                or      al, [edx+8+2+0]
                or      ah, [edx+8+2+1]
            .endif
            mov     [edi], al                   ; save first 4 dots pattern
            mov     [edi+640*2/8], ah
            inc     edi

            xor     ax, ax                      ; clear output data

            shl     bl, 1                       ; bit 3
            .if     nc                          ; bit off ?
                or      al, [edx+0+0+0]
                or      ah, [edx+0+0+1]
            .else                               ; bit on
                or      al, [edx+8+0+0]
                or      ah, [edx+8+0+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 2
            .if     nc                          ; bit off ?
                or      al, [edx+0+2+0]
                or      ah, [edx+0+2+1]
            .else                               ; bit on
                or      al, [edx+8+2+0]
                or      ah, [edx+8+2+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 1
            .if     nc                          ; bit off ?
                or      al, [edx+0+0+0]
                or      ah, [edx+0+0+1]
            .else                               ; bit on
                or      al, [edx+8+0+0]
                or      ah, [edx+8+0+1]
            .endif
            shl     ax, 2
            shl     bl, 1                       ; bit 0
            .if     nc                          ; bit off ?
                or      al, [edx+0+2+0]
                or      ah, [edx+0+2+1]
            .else                               ; bit on
                or      al, [edx+8+2+0]
                or      ah, [edx+8+2+1]
            .endif
            mov     [edi], al                   ; save 2nd 4 dots pattern
            mov     [edi+640*2/8], ah
            inc     edi

            inc     esi
            dec     col
            jz      APAToPrtLoopExitM2
            jmp     APAToPrtLoopM2

APAToPrtLoopExitM2:
            add     edi, 640*2/8
            dec     row
            jz      APAToPrtLoopExitM1
            jmp     APAToPrtLoopM1

APAToPrtLoopExitM1:
        .endif

        popad
        ExitProc
EndProc     vvConvAPAToPrtGale

;***EP  VVInt15Hook() - Process VDM Int 15h calls
;
;   ENTRY
;       EBX -> VDM register frame
;   EXIT
;       EMULATED
;           Carry clear
;       NOT EMULATED
;           Carry set (pass control to next VDD)
;   USES
;       32-bit small-model PASCAL calling/register conventions
;
;   CONTEXT
;       VDM Task-time
;
;   PSEUDO-CODE                                     REFERENCES
;

INT15_GET_BIOS_TYPE     equ     4900h

Procedure VVInt15Hook

        mov     ax, [ebx].crf_eax.off
        .if     <ax eq INT15_GET_BIOS_TYPE>
            CallFn  VDHPopInt
            mov     [ebx].crf_ebx.lo, 0
            mov     [ebx].crf_eax.hi, 0
            and     [ebx].crf_eflag, not F_CARRY
            clc
IFDEF   VTEXT
            or  VDMData.GaleData.flVtext, VDMV_PROCESSED_BY_MYSELF
ENDIF   ;VTEXT
        .else
            stc
        .endif

        ExitProc
EndProc   VVInt15Hook

IFDEF   XVIO
;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvExtWriteStrGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Write string into APA (XVIO support).            */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     hvdm  =  hvdm                                                   */
;/*     prcl  =  rectangle                                              */
;/*     pBuff =  screen image buffer    (common format)                 */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvExtWriteStrGale
        ArgVar      hvdm,    HVDM
        ArgVar      pvxWStr, PVXWSTR
        ArgVar      pBuff,   PVOID

        LocalVar    BIOSMode, DWORD
        LocalVar    LoopCnt,  DWORD
        LocalVar    flDirty,  DWORD

        EnterProc
        pushad

        mov     edx, hvdm
        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80> or
        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO80_GALE> near  ; text mode?
            mov     eax, [edx].VDMData.ulBIOSMode
            mov     BIOSMode, eax               ; save BIOS mode
            mov     [edx].VDMData.ulBIOSMode, BIOSVMODE_CO80_GALE   ; force BIOS mode to common format

            .if     <bit [edx].VDMData.flVDMVideo and VDM_FGND>     ;J-TS0825
                mov     esi, pvxWStr                                ;J-TS0825
                mov     bh, byte ptr [esi].vxws_row ; start row     ;J-TS0825
                mov     bl, 0                       ; start column  ;J-TS0825
                xor     cx, cx                      ; text mode     ;J-TS0827
                call    vvSaveRegsGale                              ;J-TS0825
            .endif                                                  ;J-TS0825

            call    HideCursorGeneral           ; hide cursor

            mov     esi, pvxWStr
            mov     eax, [esi].vxws_row
            mov     ah, SCREEN_WIDTH
            mul     ah
            movzx   eax, ax
            shl     eax, 2                      ; LVB offset

            .if     <bit [edx].VDMData.flVDMVideo and VDM_FGND> ; foreground ?
                add     eax, pBuff              ; LVB pointer
                mov     bh, byte ptr [esi].vxws_row ; start row
                mov     esi, [esi].vxws_depth   ; row count
                mov     LoopCnt, esi

ExtWriteStrLoop1:
                mov     bl, 0                   ; start column
                mov     esi, SCREEN_WIDTH
                push    eax

ExtWriteStrLoop2:
                movzx   edi, byte ptr [eax]
                .if     <DBCS1st[edi] eq 0> or  ; SBCS ?
                .if     <esi eq 1>
                    mov     ecx, -1
                    call    DrawCharGeneral
                    inc     bl
                    add     eax, 4
                    dec     esi
                .else                           ; DBCS
                    mov     ecx, -2
                    call    DrawCharGeneral
                    add     bl, 2
                    add     eax, 8
                    sub     esi, 2
                .endif
                jnz     ExtWriteStrLoop2

                pop     eax
                add     eax, SCREEN_WIDTH*4
                inc     bh
                dec     LoopCnt
                jnz     ExtWriteStrLoop1

                mov     eax, BIOSMode           ; restore BIOS mode
                mov     [edx].VDMData.ulBIOSMode, eax

            .else                               ; background
                mov     ebx, [esi].vxws_depth   ; row count
                mov     esi, eax
                mov     edi, eax
                add     esi, pBuff              ; LVB pointer
                add     edi, [edx].VDMData.XVIOData.GaleXVIOLVB ; XVIO save LVB
                mov     edx, pvxWStr            ; start row
                mov     cl, byte ptr [edx].vxws_row
                mov     edx, [edx].vxws_psinfo
                shr     edx, cl
                cld

ExtWriteStrLoop3:
                mov     ecx, SCREEN_WIDTH
                .if     <bit edx and 00000001h> ; PS exits ?
                    rep     movsd
                .else                           ; not exist
                    xor     eax, eax
                    rep     stosd
                    add     esi, SCREEN_WIDTH*4
                .endif
                shr     edx, 1
                dec     ebx
                jnz     ExtWriteStrLoop3
            .endif
            mov     edx, hvdm                   ; hdm handle

            call    DrawCursorGeneral           ; draw cursor

            mov     eax, BIOSMode               ; restore BIOS mode
            mov     [edx].VDMData.ulBIOSMode, eax

            .if     <bit [edx].VDMData.flVDMVideo and VDM_FGND>     ;J-TS0825
                xor     cx, cx                      ; text mode     ;J-TS0827
                call    vvRestoreRegsGale                           ;J-TS0825
            .endif                                                  ;J-TS0825

            .if     <bit [edx].VDMData.flVDMVideo and VDM_WINDOWED> near
                    mov     flDirty, TRUE
                    SSToDS  eax, flDirty
                    CallFn  vvAddEvent, <hvdm, VVDEVENT_LVB, eax, 0>
            .endif

        .else near                              ; graphics mode

            .if     <bit [edx].VDMData.flVDMVideo and VDM_FGND>
                mov     edx, hvdm
                mov     esi, pvxWStr
                mov     bh, byte ptr [esi].vxws_row ; start row
                mov     bl, 0                       ; start column
                mov     cx, -1                      ; graphics mode ;J-TS0827
                call    vvSaveRegsGale
            .endif

            mov     esi, pvxWStr
            mov     eax, [esi].vxws_row
            mov     ah, SCREEN_WIDTH
            mul     ah
            movzx   eax, ax
            shl     eax, 2                      ; LVB offset

            add     eax, pBuff                  ; LVB pointer
            mov     bh, byte ptr [esi].vxws_row ; start row
            mov     esi, [esi].vxws_depth       ; row count
            mov     LoopCnt, esi

ExtWriteStrLoop4:
            mov     bl, 0                       ; start column
            mov     esi, SCREEN_WIDTH
            push    eax

ExtWriteStrLoop5:
            .if     <<dword ptr [eax]> eq 0>    ; No character ?
                pushad
                mov     edx, hvdm               ; hvdm
                call    vvRestoreCell
                popad
                inc     bl
                add     eax, 4
                dec     esi
                nop
            .else
                movzx   edi, byte ptr [eax]
                .if <DBCS1st[edi] eq 0> or      ; SBCS ?
                .if     <esi eq 1>
                    mov     ecx, 1
                    call    DrawCharGeneral
                    inc     bl
                    add     eax, 4
                    dec     esi
                .else                           ; DBCS
                    mov     ecx, 2
                    call    DrawCharGeneral
                    add     bl, 2
                    add     eax, 8
                    sub     esi, 2
                .endif
                mov     edi, hvdm
                mov     [edi].VDMData.mstateCopy, MEMORY_NONE
            .endif
            jnz     ExtWriteStrLoop5

            pop     eax
            add     eax, SCREEN_WIDTH*4
            inc     bh
            dec     LoopCnt
            jnz     ExtWriteStrLoop4

            mov     edx, hvdm
            .if     <bit [edx].VDMData.flVDMVideo and VDM_FGND>
                mov     cx, -1                      ; graphics mode ;J-TS0827
                call    vvRestoreRegsGale
            .endif
        .endif

        popad
        ExitProc

EndProc     vvExtWriteStrGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvRestoreCell                                     */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Restore one char space graphics images.          */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     bx    =  (row,col)                                              */
;/*     edx   =  hvdm                                                   */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvRestoreCell

        LocalVar    hvdm,      HVDM
        LocalVar    PtrOffset, PBYTE
        LocalVar    CellHeight, ULONG                               ;J-TS0602

        EnterProc

        mov     hvdm, edx                       ; save hvdm
        movzx   eax, bh
        mul     [edx].SkipLineAPA
        movzx   ebx, bl
        add     ebx, eax
        mov     PtrOffset, ebx                  ; offset

        mov     edi, hvdm
        add     edi, APA_START_ADDR             ; APA top address
                                                ; setup APA access
        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_MODE                     ; set write mode 0
        mov     ah, 00h
        out     dx, ax
        mov     al, LG_FUNCTION                 ; set rotate 0
        mov     ah, 0
        out     dx, ax
        mov     al, LG_BIT_MASK                 ; set bit mask ffh
        mov     ah, 0ffh
        out     dx, ax
        mov     al, LG_ENABLE_SET_RESET         ; set set/reset enable
        mov     ah, 0
        out     dx, ax

        mov     edx, hvdm
        .if     <[edx].VDMData.ulBIOSMode eq BIOSVMODE_CO640X480X2>
            mov     bl, 0                       ; single plane
        .else
            mov     bl, 3                       ; 4 planes
        .endif

RestoreCellLoop1:
        mov     dx, SeqAddressPort              ; set VGA port address
        mov     al, LS_MAP_MASK
        mov     cl, bl
        mov     ah, 01h
        shl     ah, cl
        out     dx, ax                          ; select restore map

        mov     edx, hvdm

        mov     al, SCREEN_WIDTH                                    ;J-TS0602
        mul     [edx].FontHeight                                    ;J-TS0602
        movzx   eax, ax                                             ;J-TS0602
        mov     CellHeight, eax                                     ;J-TS0602

        movzx   eax, bl

                                                ; get APA save buffer addr
        .if     <bit [edx].VDMData.flVDMVideo nand VDM_WINDOWED> ; foreground ?
            mov     esi, [BANK0][edx+eax*4].VDMData.apPlane
            mov     eax, [BANK0][edx+eax*4].VDMData.anpgPlane       ;J-TS0602
        .else
            mov     esi, [edx+eax*4].VDMData.XVIOData.apPlaneXVIO
            mov     eax, [edx+eax*4].VDMData.XVIOData.anpgPlaneXVIO ;J-TS0602
        .endif

        shl     eax, 12                         ; get buffer size   ;J-TS0602

        movzx   ecx, [edx].FontHeight           ; loop counter

        mov     edx, PtrOffset                  ; offset

        .if     <eax ne 0> and                                      ;J-TS0602
        sub     eax, CellHeight                                     ;J-TS0602
        .if     <edx be eax>                                        ;J-TS0602
RestoreCellLoop2:
            mov     al, [esi+edx]               ; move one laster
            mov     [edi+edx], al
            add     edx, SCREEN_WIDTH           ; skip to next laster
            loop    RestoreCellLoop2
        .else
            xor     al, al

RestoreCellLoop3:
            mov     [edi+edx], al
            add     edx, SCREEN_WIDTH           ; skip to next laster
            loop    RestoreCellLoop3
        .endif

        dec     bl
        .if     <bl ne 0ffh>
            jmp     RestoreCellLoop1            ; next plane
        .endif

        mov     dx, SeqAddressPort              ; restore map mask
        mov     al, LS_MAP_MASK
        mov     ah, 0ffh
        out     dx, ax                          ; set map mask ffh

        ExitProc

EndProc     vvRestoreCell

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvSaveRegsGale                                    */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Save registers used by XVIO char write.          */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     bx    =  (row,col)                                              */
;/*     cx    =  0: text mode, -1:graphics mode                         */ ;J-TS0827
;/*     edx   =  hvdm                                                   */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvSaveRegsGale

        LocalVar    hvdm,    HVDM

        EnterProc
        pushad

        mov     hvdm, edx                       ; save hvdm
        movzx   eax, bh
        mul     [edx].SkipLineAPA
        movzx   ebx, bl
        add     ebx, eax
        .if     <cx eq 0>                       ; text mode         ;J-TS0827
            mov     edx, hvdm                                       ;J-TS0827
            add     bx, [edx].Gale_Start_Addr                       ;J-TS0827
            add     ebx, pPhysVRAM                                  ;J-TS0827
                                                                    ;J-TS0827
        .else                                   ; graphics mode     ;J-TS0827
            add     ebx, hvdm
            add     ebx, APA_START_ADDR         ; APA address to write char
                                                ; save address registers
        .endif                                                      ;J-TS0827
        mov     esi, FLAToffset ExtWriteAddrSave
        add     esi, hvdm

SaveRegsGaleLoop1:
        mov     dx, [esi]                       ; get I/O address
        .if     <dx ne 0>
            in      al, dx
            mov     [esi+2], al
            add     esi, 4
            jmp     SaveRegsGaleLoop1
        .endif
                                                ; save data redisters
        mov     esi, FLAToffset ExtWriteRegSave
        add     esi, hvdm

SaveRegsGaleLoop2:
        mov     dx, [esi]                       ; get I/O address
        .if     <dx ne 0>
            mov     al, [esi+2]                 ; get index
            out     dx, al
            inc     dx
            in      al, dx                      ; in red data
            mov     [esi+3], al                 ; save it
            add     esi, 4                      ; next reg
            jmp     SaveRegsGaleLoop2
        .endif
                                                ; save latches
        mov     dx, SeqAddressPort
        mov     al, LS_MAP_MASK
        mov     ah, 0ffh
        out     dx, ax                          ; set map ask

        mov     dx, GraphAddressPort
        mov     al, LG_MODE
        mov     ah, 01h
        out     dx, ax                          ; set write mode 1, read mode 0

        mov     byte ptr [ebx], 0               ; dummy write to put latch data
                                                ; into APA
        mov     ecx, 4
        mov     edi, hvdm

SaveRegsGaleLoop3:
        mov     al, LG_READ_MAP
        mov     ah, cl
        dec     ah
        out     dx, ax                          ; select map
        mov     al, [ebx]
        mov     ExtWriteLatch[edi+ecx-1], al
        loop    SaveRegsGaleLoop3

        popad
        ExitProc
EndProc     vvSaveRegsGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvRestoreRegsGale                                 */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Restore registers used by XVIO char write.       */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     cx    =  0: text mode, -1:graphics mode                         */ ;J-TS0827
;/*     edx   =  hvdm                                                   */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvRestoreRegsGale

        LocalVar    hvdm,    HVDM

        EnterProc
        pushad

        mov     hvdm, edx                       ; save hvdm

        .if     <cx eq 0>                       ; text mode         ;J-TS0827
            movzx   esi, [edx].Gale_Start_Addr                      ;J-TS0827
            dec     si                                              ;J-TS0827
            add     esi, pPhysVRAM                                  ;J-TS0827
                                                                    ;J-TS0827
        .else                                   ; graphics mode     ;J-TS0827
            mov     esi, edx
            add     esi, APA_START_ADDR+0ffffh  ; last APA address
                                                ; save APA contents
        .endif                                                      ;J-TS0827
        mov     dx, SeqAddressPort
        mov     al, LS_MAP_MASK
        mov     ah, 0ffh
        out     dx, ax                          ; set map ask

        mov     dx, GraphAddressPort
        mov     al, LG_MODE
        mov     ah, 00h
        out     dx, ax                          ; read mode 0

        mov     ecx, 4
        mov     edi, hvdm

RestoreRegsGaleLoop1:
        mov     al, LG_READ_MAP
        mov     ah, cl
        dec     ah
        out     dx, ax                          ; select map
        mov     al, [esi]
        mov     ExtWriteAPASave[edi+ecx-1], al
        loop    RestoreRegsGaleLoop1
                                                ; Restore Latches data
        mov     dx, GraphAddressPort            ; set VGA port address
        mov     al, LG_MODE
        mov     ah, 00h
        out     dx, ax                          ; set read mode 0, write mode 0
        mov     al, LG_FUNCTION
        mov     ah, 0
        out     dx, ax                          ; set rotate 0
        mov     al, LG_BIT_MASK
        mov     ah, 0ffh
        out     dx, ax                          ; set bit mask ffh
        mov     al, LG_ENABLE_SET_RESET
        mov     ah, 0
        out     dx, ax                          ; set set/reset enable

        mov     ecx, 4
        mov     edi, hvdm
        mov     dx, SeqAddressPort              ; set VGA port address

RestoreRegsGaleLoop2:
        mov     al, LS_MAP_MASK
        mov     ah, 80h
        rol     ah, cl
        out     dx, ax                          ; select restore map

        mov     al, ExtWriteLatch[edi+ecx-1]
        mov     [esi], al                       ; restore latch data into APA
        loop    RestoreRegsGaleLoop2

        mov     al, [esi]                       ; dummy read to put data into
                                                ; latch from APA
                                                ; restore saved APA data
        mov     ecx, 4
        mov     edi, hvdm
        mov     dx, SeqAddressPort              ; set VGA port address

RestoreRegsGaleLoop3:
        mov     al, LS_MAP_MASK
        mov     ah, 80h
        rol     ah, cl
        out     dx, ax                          ; select restore map

        mov     al, ExtWriteAPASave[edi+ecx-1]
        mov     [esi], al                       ; restore saved data into APA
        loop    RestoreRegsGaleLoop3

        mov     esi, FLAToffset ExtWriteRegSave
        add     esi, hvdm

RestoreRegsGaleLoop4:
        mov     dx, [esi]                       ; get I/O address
        .if     <dx ne 0>
            mov     ax, [esi+2]                 ; get index & data
            out     dx, ax
            add     esi, 4                      ; next reg
            jmp     RestoreRegsGaleLoop4
        .endif
                                                ; save address registers
        mov     esi, FLAToffset ExtWriteAddrSave
        add     esi, hvdm

RestoreRegsGaleLoop5:
        mov     dx, [esi]                       ; get I/O address
        .if     <dx ne 0>
            mov     al, [esi+2]
            out     dx, al
            add     esi, 4
            jmp     RestoreRegsGaleLoop5
        .endif

        popad
        ExitProc
EndProc     vvRestoreRegsGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvSetCurPosGale                                   */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set cursor position for XVIO.                    */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     hvdm  =  hvdm                                                   */
;/*     row   =  cursor row                                             */
;/*     col   =  cursor column                                          */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvSetCurPosGale
        ArgVar      hvdm,   HVDM
        ArgVar      CurRow, ULONG
        ArgVar      CurCol, ULONG
        EnterProc
        pushad

        mov     edx, hvdm
        call    HideCursorGeneral               ; hide cursor
        mov     ah, byte ptr CurRow
        mov     al, byte ptr CurCol
        .if     <ah b [edx].Gale_Max_Row> and   ; check position
        .if     <al b SCREEN_WIDTH>
            mov     VDMData.GaleData.GaleCursor.GaleCurPos[edx], ax
        .endif
        call    DrawCursorGeneral               ; draw cursor

        .if     <bit [edx].VDMData.flVDMVideo and VDM_WINDOWED> ; windowed ?
            CallFn  vvUpdateCursorData, <edx>
        .endif

        popad
        ExitProc
EndProc     vvSetCurPosGale

;/**********************  START OF SPECIFICATIONS  **********************/
;/*                                                                     */
;/*  SUBROUTINE NAME: vvSetCurTypeGale                                  */
;/*                                                                     */
;/*  DESCRIPTIVE NAME: Set cursor type for XVIO.                        */
;/*                                                                     */
;/*  INPUT:                                                             */
;/*     hvdm  =  hvdm                                                   */
;/*     start =  cursor start position                                  */
;/*     end   =  cursor end position                                    */
;/*     attr  =  visibility attribute                                   */
;/*                                                                     */
;/*  INTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/*  EXTERNAL REFERENCES:                                               */
;/*    ROUTINES: None                                                   */
;/*                                                                     */
;/***********************  END OF SPECIFICATIONS  ***********************/

Procedure   vvSetCurTypeGale
        ArgVar      hvdm,     HVDM
        ArgVar      CurStart, ULONG
        ArgVar      CurEnd,   ULONG
        ArgVar      attr,     ULONG
        EnterProc
        pushad

        mov     edx, hvdm
        call    HideCursorGeneral               ; hide cursor
        .if     <bit attr nand 0001h>           ; cursor is visible ?
            mov     ah, byte ptr CurStart
            mov     al, byte ptr CurEnd
        .else                                   ; invisible
            mov     ax, 2000h
        .endif
        mov     VDMData.GaleData.GaleCursor.GaleCurMode[edx], ax

        call    DrawCursorGeneral               ; draw cursor

        .if     <bit [edx].VDMData.flVDMVideo and VDM_WINDOWED> ; windowed ?
            CallFn  vvUpdateCursorData, <edx>
        .endif

        popad
        ExitProc
EndProc     vvSetCurTypeGale
ENDIF   ;XVIO

        EndCode     EXPORT,SWAP,PASCAL

ENDIF   ;GALE

        END
