;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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    60,132
        TITLE   XVIOLINK.ASM -- Service routines for XVIO

;/*****************************************************************************
;*
;* SOURCE FILE NAME = XVIOLINK.ASM
;*
;* DESCRIPTIVE NAME = Service Routines for XVIO
;*
;*
;* VERSION      V2.0
;*
;* DATE
;*
;* DESCRIPTION
;*
;* FUNCTIONS    BVHUpdatePVB, BVHCursorPos, BVHCursorType
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES  NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVIY =
;*   DATE      FLAG       APAR    CHANGE DESCRIPTION
;*   --------  ---------- -----   --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx xxxxx   xxxxxxx
;    91/08/07  J-TS01V            T.Sobue PTR JS01614     fix. XVIO thinks blink option
;                                         is always off.
;    91/10/21  J-TS102191         T.Sobue XVIO internal video buffer format is changed
;                                         from ATLAS 3 bytes format to common format
;    92/01/11  J-TS011792         T.Sobue PTR JS02380
;****************************************************************************/

        .286c                           ; 286 protect mode instructions

        .xlist
        INCLUDE struc.inc               ; Structure macro
        INCLUDE vdhequ.inc              ; Buffer update equates
        INCLUDE vdhstruc.inc            ; Buffer update data structures
        include vdh.inc                 ; Definitions
        include vgaemu.inc              ; VGA text emulation video buffer
        .list

        extrn   DOSFSRAMSEMREQUEST : FAR                                ;J-TS011792
        extrn   DOSFSRAMSEMCLEAR   : FAR                                ;J-TS011792

_DATA   SEGMENT WORD PUBLIC 'DATA'
;************************************************************************
;*  Global data                                                         *
;************************************************************************
        extrn   VideoBuffSel  : word
        extrn   _SemAccessAPA : byte        ; APA exclusive access      ;J-TS011792

_DATA   ENDS

        extrn   SetupAPAWrite       : far   ; setup APA write mode
        extrn   SetAPAColor         : far   ; set APA write color
        extrn   SetGridColor        : far   ; set grid draw color
        extrn   SaveFont            : far   ; save font from APA
        extrn   RestoreFont         : far   ; restore font to APA
        extrn   ShowCursor          : near  ; show cursor
        extrn   HideCursor          : near  ; hide cursor
        extrn   XorCursor           : far   ; xor cursor
;J-TS102191        extrn   UpdateRegenOneLineA : near  ; common DBCS format one line draw
        extrn   UpdateRegenOneLineC : near  ; common DBCS format one line draw ;J-TS102191
        extrn   _CheckInstanceData  : near  ; check instance data initialization
        extrn   FontGetSBCS         : near  ; get SBCS font image
        extrn   FontGetDBCS         : near  ; get DBCS font image
        extrn   DrawGrid            : near  ; draw character grid

R2CSEG  SEGMENT WORD    PUBLIC 'CODE'
        ASSUME  CS:R2CSEG,DS:NOTHING,ES:NOTHING

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     BVHUpdatePVB                                    *
;*                                                                      *
;* DESCRIPTIVE NAME:    Update shadow buffer & APA based on the         *
;*                      request from XVIO (BXVSCALL.DLL)                *
;*                                                                      *
;* INPUT:                                                               *
;* CARRY  --->  On = real mode, off = protect mode                      *
;* DS:SI  --->  PSVB pointer                                            *
;* ES     --->  APA selector                                            *
;* AX     --->  Video mode                                              *
;* BX     --->  APA update method selection                             *
;*              0 = PSVB is compared shadow buffer (text mode)          *
;*              1 = All character is redraw with no condition           *
;*                                                 (graph mode)         *
;* CX     --->  Cell count                                              *
;* DX     --->  Screen Group ID                                         *
;*                                                                      *
;* INTERNAL REFERENCES: UpdateRegenOneLineC                             *
;*                      HideCursor, ShowCursor                          *
;*                                                                      *
;* EXTERNAL REFERENCES: None                                            *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************

CURR_SG     equ     08h

BVHUpdatePVB    proc    far
        public  BVHUpdatePVB

        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        push    -1                                                      ;J-TS011792
        push    -1                                                      ;J-TS011792
        call    DOSFSRAMSEMREQUEST                                      ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        push    ax
        push    cx                      ; check Instance data initialization
        push    si                      ; because some application calls XVIO
        push    ds                      ; without any VIO calls. In this
        push    es                      ; situation, instance data in BVH are
        call    _CheckInstanceData      ; not initialized yet.
        pop     es
        pop     ds
        pop     si
        pop     cx
        pop     ax

        sub     sp, WORK_END-PVB_Sel+2      ; Make local stack frame
        push    bp                          ; 
        mov     bp, sp                      ; 

        .if     <bx eq 0>                   ; text mode ?

            .if     <ax ne 0>
                jmp     BVHUpdatePVBExit
            .endif

            call    HideCursor              ; hide cursor

            call    SetupAPAWrite           ; setup APA write mode
            mov     [bp].APAPrevColor, -1   ; reset preset color

            mov     ax, not BLINK_STATE                                 ;J-TS01V
            mov     [bp].Sub_Option, ax     ; set blink state
            mov     [bp].PVB_Sel, es        ; save APA selector
            mov     [bp].Sub_cols, cx       ; save pvb width
            mov     [bp].Sub_colors, 4      ; color mode
            mov     al, 26*4
            mul     cl
            mov     [bp].Sub_PVBend, ax     ; set shadow buffer limitation
            mov     ax, _DATA               ; setup shadow buffer pointer
            mov     es, ax
            mov     es, es:VideoBuffSel
            mov     di, si

            call    UpdateRegenOneLineC     ; call update shadow buffer & APA   ;J-TS102191

            call    ShowCursor              ; show cursor

        .else                               ; graph mode

            call    XVIOToGraph

        .endif

BVHUpdatePVBExit:
        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        call    DOSFSRAMSEMCLEAR                                        ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        pop     bp                          ; restore local stack frame
        add     sp, WORK_END                ; 
        xor     ax, ax
        ret
BVHUpdatePVB    endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     BVHCursorPos                                    *
;*                                                                      *
;* DESCRIPTIVE NAME:    Set Cursor Position                             *
;*                                                                      *
;* INPUT:                                                               *
;* CARRY  --->  On = real mode, off = protect mode                      *
;* AX     --->  Video mode                                              *
;* BX     --->  0 = set, 1 = get                                        *
;* CX     --->  cursor position row                                     *
;* DX     --->  cursor position column                                  *
;* OUTPUT:                                                              *
;* CX     --->  cursor position row                                     *
;* DX     --->  cursor position column                                  *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: HideCursor, ShowCursor, XorCursor               *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************
BVHCursorPos    proc    far
        public  BVHCursorPos

        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        push    -1                                                      ;J-TS011792
        push    -1                                                      ;J-TS011792
        call    DOSFSRAMSEMREQUEST                                      ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        push    ds                          ; save ds

        push    _DATA                       ; set selector
        pop     ds
        mov     ds, ds:VideoBuffSel

        .if     <bx eq 0>                   ; set position ?
            .if     <ax eq 0>               ; test mode ?
                call    HideCursor          ; hide cursor
            .endif

            mov     ds:VGA_CsrRow, cx       ; set new cursor position
            mov     ds:VGA_CsrCol, dx

            .if     <ax eq 0>               ; text mode ?
                call    ShowCursor          ; show cursor
            .else                           ; graphics mode ?
                call    XorCursor           ; xor cursor
            .endif
        .else                               ; get position
            mov     cx, ds:VGA_CsrRow       ; get cursor position
            mov     dx, ds:VGA_CsrCol
        .endif

        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        call    DOSFSRAMSEMCLEAR                                        ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        pop     ds                          ; restore ds
        ret

BVHCursorPos    endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     BVHCursorType                                   *
;*                                                                      *
;* DESCRIPTIVE NAME:    Set Cursor Type                                 *
;*                                                                      *
;* INPUT:                                                               *
;* CARRY  --->  On = real mode, off = protect mode                      *
;* AX     --->  Video mode                                              *
;* BX     --->  0 = set, 1 = get                                        *
;* CX     --->  top scan line                                           *
;* DX     --->  bottom scan line                                        *
;* SI     --->  width                                                   *
;* DI     --->  attribute                                               *
;* OUTPUT:                                                              *
;* CX     --->  top scan line                                           *
;* DX     --->  bottom scan line                                        *
;* SI     --->  width                                                   *
;* DI     --->  attribute                                               *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: HideCursor, ShowCursor                          *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************
CURSOR_HIDDEN   equ     0001h

BVHCursorType   proc    far
        public  BVHCursorType

        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        push    -1                                                      ;J-TS011792
        push    -1                                                      ;J-TS011792
        call    DOSFSRAMSEMREQUEST                                      ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        push    ds                          ; save ds

        push    _DATA                       ; set selector
        pop     ds
        mov     ds, ds:VideoBuffSel

        .if     <bx eq 0>                   ; set type ?

            .if     <ax eq 0>               ; text mode ?
                call    HideCursor          ; hide cursor
            .endif

            push    ax                      ; save video mode

            push    dx                      ; save dx

            mov     ax, 450                 ; CsrStart = start*450/725
            mul     cx
            mov     cx, 725
            div     cx
            mov     ds:VGA_CsrStart, ax

            pop     dx                      ; restore dx

            mov     ax, 450                 ; CsrEnd = end*450/725
            mul     dx
            mov     cx, 725
            div     cx
            mov     ds:VGA_CsrEnd, ax

            mov     ds:VGA_CsrWidth, si     ; set cursor width

            mov     ax, di
            .if     <bit al and CURSOR_HIDDEN>
                mov     ds:VGA_CsrAttrib, -1 ; cursor is hidden
            .else
                mov     ds:VGA_CsrAttrib, 0 ; cursor is visible
            .endif

            shr     ax, 4                   ; set cursor color
            mov     ds:VGA_CsrColor, ax

            pop     ax                      ; restore video mode

            .if     <ax eq 0>               ; text mode ?
                call    ShowCursor          ; show cursor
            .else                           ; graphics mode
                .if     <ds:VGA_CsrAttrib eq -1>
                    mov     ds:VGA_CsrColor, 0
                .endif
                mov     ds:VGA_CsrAttrib, -1
            .endif
        .else                               ; get type
            mov     ax, ds:VGA_CsrStart     ; start=CsrStart*725/450
            mov     bx, 725
            mul     bx
            mov     bx, 450
            div     bx
            mov     cx, ax

            mov     ax, ds:VGA_CsrEnd       ; end=CsrEnd*725/450
            mov     bx, 725
            mul     bx
            mov     bx, 450
            div     bx
            mov     dx, ax

            mov     si, ds:VGA_CsrWidth     ; get cursor width

            mov     ax, ds:VGA_CsrColor     ; get cursor color
            shl     al, 4

            .if     <ds:VGA_CsrAttrib eq -1>
                or      al, CURSOR_HIDDEN   ; cursor is hidden
            .endif
            xor     ah, ah
            mov     di, ax

        .endif

        pusha                                                           ;J-TS011792
        push    ds                                                      ;J-TS011792
        push    es                                                      ;J-TS011792
        push    _DATA                                                   ;J-TS011792
        push    offset _SemAccessAPA                                    ;J-TS011792
        call    DOSFSRAMSEMCLEAR                                        ;J-TS011792
        pop     es                                                      ;J-TS011792
        pop     ds                                                      ;J-TS011792
        popa                                                            ;J-TS011792

        pop     ds                          ; restore ds
        ret

BVHCursorType   endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     XVIOToGraph                                     *
;*                                                                      *
;* DESCRIPTIVE NAME:    Update APA according to shadow buffer from XVIO *
;*                                                                      *
;* INPUT:                                                               *
;* DS:SI  --->  PSVB pointer                                            *
;* ES     --->  APA selector                                            *
;* AX     --->  Color(=1)/Mono(=2)                                      *
;* CX     --->  Cell count                                              *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: XVIOSetAPAColor, FontGetSBCS, FontGetDBCS,      *
;*                      XVIODrawGrid                                    *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************

XVIOToGraph proc    near
        public  XVIOToGraph

        mov     [bp].APA_ColorMono, ax      ; save display mode

        call    SetupAPAWrite               ; setup APA write mode

        mov     ax, si                      ; calc APA target offset from
        shr     ax, 2                       ; PSVB offset
        mov     dl, SCREEN_WIDTH            ; APA = (PSVB / 4) / 80 * 1440 +
        idiv    dl                          ;       (PSVB / 4) % 80
        mov     bl, ah
        xor     bh, bh
        xor     ah, ah
        mov     dx, SCREEN_WIDTH*FONT_HEIGHT
        mul     dx
        add     ax, bx
        mov     di, ax

        mov     bx, si                      ; move PSVB offset reg.
        mov     dx, cx                      ; move cell counter reg.
        mov     [bp].APAPrevColor, -1       ; preset color

GraphMainLoop:

        .if <<word ptr ds:[bx+0]> eq 0> and near ; skip character ?
        .if <<word ptr ds:[bx+2]> eq 0> near

            add     bx, 4                   ; increase shadow buf ptr
            inc     di                      ; increase APA pointer
            dec     dx                      ; dec loop counter

        .elseif <bit <byte ptr ds:[bx+3]> and dbcsA1> near ; DBCS ?

            mov     al, ds:[bx+1]           ; get APA write color (left  harf)
            xor     ah, ah

            call    XVIOSetAPAColor         ; set APA write color (left harf)

            push    ds                      ; push shadow buffer selector
            push    ds:[bx+4]               ; save right char/attr
            push    ds:[bx+2]               ; save left attr1/2

            mov     al, ds:[bx+4]           ; get DBCS font
            mov     ah, ds:[bx]
            call    FontGetDBCS
                                            ; move font image
            xor     al, al                  ; from font buf to APA (left half)
            stosb                           ; clear first line
            add     di, SCREEN_WIDTH-1

            mov     cx, FONT_HEIGHT-2
GraphLoop1:
            movsb
            inc     si
            add     di, SCREEN_WIDTH-1
            loop    GraphLoop1

            stosb                           ; clear last line

            sub     di, SCREEN_WIDTH*(FONT_HEIGHT-1) ; resotre & inc APA ptr
            sub     si, (FONT_HEIGHT-2)*2-1         ; restore font pointer

            pop     ax                      ; get attr1/2 word
                                            ; underline ?
            .if     <bit al and A_UNDERLINE_BIT>
                mov     byte ptr es:[di+SCREEN_WIDTH*(FONT_HEIGHT-1)-1], 0ffh
            .endif
                                            ; Horz/Vert grid ?
            .if     <bit al and A_HORZ_BIT+A_VERT_BIT>
                push    di
                dec     di
                call    XVIODrawGrid        ; draw horz & vert grid
                pop     di
            .endif

            pop     ax                      ; get right half color
            shr     ax, 8

            call    XVIOSetAPAColor         ; set APA write color (right harf)
                                            ; move font image
            xor     al, al                  ; from font buf to APA (right half)
            stosb                           ; clear first line
            add     di, SCREEN_WIDTH-1

            mov     cx, FONT_HEIGHT-2
GraphLoop2:
            movsb
            inc     si
            add     di, SCREEN_WIDTH-1
            loop    GraphLoop2

            stosb                           ; clear last line

            sub     di, SCREEN_WIDTH*(FONT_HEIGHT-1) ; resotre & inc APA ptr

            pop     ds                      ; pop shadow buffer selector

            mov     ax, ds:[bx+6]           ; get attr1/2 word
                                            ; underline ?
            .if     <bit al and A_UNDERLINE_BIT>
                mov     byte ptr es:[di+SCREEN_WIDTH*(FONT_HEIGHT-1)-1], 0ffh
            .endif
                                            ; Horz/Vert grid ?
            .if     <bit al and A_HORZ_BIT+A_VERT_BIT>
                push    di
                dec     di
                call    XVIODrawGrid        ; draw horz & vert grid
                pop     di
            .endif

            add     bx, 8                   ; increase shadow buf ptr
            sub     dx, 2                   ; dec loop counter

        .else near                          ; SBCS

            mov     al, ds:[bx+1]           ; set APA write color
            xor     ah, ah

            call    XVIOSetAPAColor

            push    ds                      ; push shadow buffer selector

            mov     al, ds:[bx]             ; get SBCS font
            mov     ah, ds:[bx+3]
            call    FontGetSBCS
                                            ; move font image
            mov     cx, FONT_HEIGHT         ; from font buf to APA
GraphLoop3:
            movsb
            add     di, SCREEN_WIDTH-1
            loop    GraphLoop3

            sub     di, SCREEN_WIDTH*FONT_HEIGHT-1 ; resotre & inc APA ptr

            pop     ds                      ; pop shadow buffer selector

            mov     al, ds:[bx+2]           ; get attr1
                                            ; underline ?
            .if     <bit al and A_UNDERLINE_BIT>
                mov     byte ptr es:[di+SCREEN_WIDTH*(FONT_HEIGHT-1)-1], 0ffh
            .endif
                                            ; Horz/Vert grid ?
            .if     <bit al and A_HORZ_BIT+A_VERT_BIT>
                push    di
                dec     di
                call    XVIODrawGrid        ; draw horz & vert grid
                pop     di
            .endif

            add     bx, 4                   ; increase shadow buf ptr
            dec     dx                      ; dec loop counter

        .endif

        jz      GraphExit                   ; check loop end
        jmp     GraphMainLoop

GraphExit:
        ret
XVIOToGraph endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     XVIOSetAPAColor                                 *
;*                                                                      *
;* DESCRIPTIVE NAME:    Set character draw color for XVIO.              *
;*                                                                      *
;* INPUT:                                                               *
;* AX          character color                                          *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: SetAPAColor                                     *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************
XVIOSetAPAColor proc    near
        public  XVIOSetAPAColor
        .if     <[bp].APA_ColorMono eq 2>   ; mono mode ?
            .if     <bit al and 0fh>        ; foreground is not black ?
                and     al, 0f0h
                .if     <al eq 50h>         ; background is magenda ?
                    mov     al, 10h         ; reverse color
                .else
                    mov     al, 01h         ; normal color
                .endif
            .elseif <bit al and 0f0h>       ; background is not black ?
                mov     al, 10h             ; reverse color
            .else                           ; fore/back is black
                mov     al, 00h             ; unvisible
            .endif
        .endif
        .if     <ax ne [bp].APAPrevColor>   ; color is changed ?
            mov     [bp].APAPrevColor, ax   ; set APA write color
            call    SetAPAColor
        .endif
        ret
XVIOSetAPAColor endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     XVIODrawGrid                                    *
;*                                                                      *
;* DESCRIPTIVE NAME:    Draw vertical & horizontal grid lines for XVIO. *
;*                                                                      *
;* INPUT:                                                               *
;* AL          Grid attribute                                           *
;* ES:DI --->  APA Address                                              *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: SetGridColor                                    *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************
XVIODrawGrid    proc    near
        public  XVIODrawGrid

        push    ax                          ; save grid flag

        push    ds                          ; get grid color
        mov     ax, _DATA
        mov     ds, ax
        mov     ds, ds:VideoBuffSel
        mov     al, ds:VGA_GridColor
        pop     ds

        .if     <[bp].APA_ColorMono eq 2>   ; mono mode ?
            mov     ax, [bp].APAPrevColor
            .if     <al eq 00h> or          ; invisible ?
            .if     <al eq 01h>             ; normal ?
                mov     al, 01h             ; set white grid
            .else                           ; reverse
                mov     al, 10h             ; set black grid
            .endif
        .endif
        call    SetGridColor                ; set grid color

        pop     ax                          ; restore grid flag

        .if     <bit al and A_HORZ_BIT>     ; horizontal grid ?
            mov     byte ptr es:[di], 0ffh
        .endif

        .if     <bit al and A_VERT_BIT> near ; vertical grid ?
            mov     al, 80h
            mov     cx, FONT_HEIGHT
DrawGridLoop:
            mov     ah, es:[di]
            stosb
            add     di, SCREEN_WIDTH-1
            loop    DrawGridLoop
        .endif

        mov     [bp].APAPrevColor, -1       ; reset draw color
        ret
XVIODrawGrid    endp

;********************** START OF SPECIFICATIONS *************************
;*                                                                      *
;* SUBROUTINE NAME:     BVHSaveRestorePVB                               *
;*                                                                      *
;* DESCRIPTIVE NAME:    Save/Restore graphics mode APA contents         *
;*                      based on the request from XVIO (BXVSCALL.DLL)   *
;*                                                                      *
;* INPUT:                                                               *
;* CARRY  --->  On = real mode, off = protect mode                      *
;* AX     --->  Video mode                                              *
;* BL     --->  0 = save / 1 = restore                                  *
;* BH     --->  Huge delta                                              *
;* CX     --->  Character length                                        *
;* DX     --->  Number of planes of APA                                 *
;* SI     --->  Row position of start character                         *
;* DI     --->  Column position of start character                      *
;* DS     --->  Save buffer selector (huge segment)                     *
;* ES     --->  APA selector                                            *
;*                                                                      *
;* INTERNAL REFERENCES: None                                            *
;*                                                                      *
;* EXTERNAL REFERENCES: None                                            *
;*                                                                      *
;********************** END OF SPECIFICATIONS ***************************
BVHSaveRestoreAPA   proc    far
        public  BVHSaveRestoreAPA

        push    dx                          ; calc APA/buf offset
        mov     ax, SCREEN_WIDTH*FONT_HEIGHT
        mul     si
        add     ax, di
        push    ax                          ; save APA offset

        mov     ax, SCREEN_WIDTH
        mul     si
        add     ax, di
        mov     dx, FONT_HEIGHT
        mul     dx

        pop     di                          ; set APA offset

        pop     dx                          ; restore number of planes
        push    dx
        .if      <dx eq 4>                  ; 16 color mode ?
            xor     dx, dx
            shl     ax, 1
            rcl     dx, 1
            shl     ax, 1
            rcl     dx, 1
            .if     <dx ae 1> or            ; buffer selector
            .if     <ax ae 0fd20h>
                .if     <dx ae 2> or
                .if     <dx eq 1> and
                .if     <ax ae 0fd20h>
                    sub     ax, 0fa40h
                    mov     dx, ds
                    add     dl, bh
                    adc     dh, 0
                    add     dl, bh
                    adc     dh, 0
                    mov     ds, dx
                .else
                    sub     ax, 0fd20h
                    mov     dx, ds
                    add     dl, bh
                    adc     dh, 0
                    mov     ds, dx
                .endif
            .endif
        .endif
        mov     si, ax                      ; buffer offset
        pop     dx

        mov     dh, cl                      ; move character length
        xchg    bx, dx                      ; change bx/dx

SaveRestoreLoop:
        mov     ax, SCREEN_WIDTH
        .if     <dl eq 0>                   ; save ?
            call    SaveFont
        .else                               ; restore
            call    RestoreFont
        .endif

        inc     di                          ; point to next character
        .if     <bl eq 4>
            add     si, FONT_HEIGHT*4
        .else
            add     si, FONT_HEIGHT
        .endif
        .if     <si ae 0fd20h>
            sub     si, 0fd20h
            mov     ax, ds
            add     al, dh
            adc     ah, 0
            mov     ds, ax
        .endif

        dec     bh                          ; dec loop counter
        jnz     SaveRestoreLoop

        ret
BVHSaveRestoreAPA   endp

R2CSEG  ENDS
        END
