;*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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = ENUMBANK.ASM
;*
;* DESCRIPTIVE NAME = Enumeration functions
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/09/92
;*
;* DESCRIPTION  Enumeration functions  
;*
;* FUNCTIONS    enum_dispatch 
;*              enum_dispatch
;*              _do_bitblt
;*              only_src_dev 
;*              screen_to_screen_blit
;*              try_oembit 
;*              sts_case0 
;*              sts_case1 
;*              sts_case2 
;*              sts_case3 
;*              sts_case4 
;*              sts_case5 
;*              sts_case6 
;*              sts_case7 
;*              sts_case8 
;*              sts_case81
;*              sts_case82
;*              sts_case83
;*              FastMove
;*              save_PointerSaveArea 
;*              restore_PointerSaveArea
;*              do_bitblit1
;*              only_dest_dev 
;*              cursor_unexclude 
;*              cursor_exclude 
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/09/92                     Written by Scott Lawson
;*
;*****************************************************************************/

.386
.MODEL FLAT
ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT
        .xlist
        include pmgre.inc
DINCL_ENABLE            equ                      1
DINCL_BITMAP            equ     1
        include driver.inc
        include extern.inc
        include protos.inc

if SCAN_CNT NE 768
        .list
.DATA
.CODE

;/***************************************************************************
;*
;* FUNCTION NAME = enum_dispatch
;*
;* DESCRIPTION   = Dispatch routine for enumerate_clip_rects
;*
;* INPUT         = pfn
;*                 flagsIn
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

enum_dispatch PROC SYSCALL,
        pfn:DWORD,
        flagsIn:DWORD

        push    ebx

        call    pfn

        pop     ebx
        ret
enum_dispatch ENDP
else ;!768

        include oem_macs.inc
        include oemblt.inc
        include ega.inc
        include constant.blt
        include assert.mac
        .list

 
SRC_IN_BANK0            equ 00000001b
SRC_IN_BANK1            equ 00000010b
SRC_CROSSES_BANKS       equ 00000011b
DST_IN_BANK0            equ 00000100b
DST_IN_BANK1            equ 00001000b
DST_CROSSES_BANKS       equ 00001100b

EXTRA_BYTE              EQU 1
EXTRA_WORD              EQU 2
NRECTS                  EQU NUM_CLIP_RECTS+1


.DATA
ALIGN 4
bfPointerSaveAreaDirty  db  FALSE
fastmove_buffer         db                       (2048) dup (0)
PUBLIC EnumBankFlag
EnumBankFlag            db      0

ALIGN 4
sts_jmp dd  OFFSET try_oembit,OFFSET try_oembit,OFFSET try_oembit
        dd  OFFSET try_oembit,OFFSET try_oembit,OFFSET sts_case0
        dd  OFFSET sts_case3, OFFSET sts_case6, OFFSET try_oembit
        dd  OFFSET sts_case2, OFFSET sts_case1, OFFSET sts_case7
        dd  OFFSET try_oembit,OFFSET sts_case4, OFFSET sts_case5
        dd  OFFSET sts_case8

.CODE

;/*
;** macro used to copy the clip rectangle
;*/

;/*
;** Clean Up the pointer save area macro
;** This macro is uses at the end of each blit sub function.
;** If the pointer save area has not been cleaned up by the end of
;** the blit sub-function then this routine will do the clean up.
;*/

CleanUpPSA macro
        cmp     bfPointerSaveAreaDirty,FALSE
        je      @f
        call    restore_PointerSaveArea
@@:
endm

copyw   macro dst,src,len
        cld                                       ; make sure
        mov     ecx,len/2                         ; cx = length
        lea     edi,dst                           ; di = source addr
        lea     esi,src                           ; si = dest addr
        rep     movsd                             ; do the move
endm

Adjust MACRO which
ASSUME EBX:NOTHING
ifidni <which>,<BOTH>
        SUB     [EBX].OBB_ARGS.obba_ySrc,SCREEN_LPB
        SUB     [EBX].OBB_ARGS.obba_yDst,SCREEN_LPB
endif
ifidni <which>,<SOURCE>
        SUB     [EBX].OBB_ARGS.obba_ySrc,SCREEN_LPB
endif
ENDM

;/***************************************************************************
;*
;* FUNCTION NAME = enum_dispatch
;*
;* DESCRIPTION   = Dispatch routine for enumerate_clip_rects                  
;*
;* INPUT         = ESI,EDI to pass on to pfn  
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
enum_dispatch PROC SYSCALL USES EBX,
        pfn:DWORD,
        flagsIn:DWORD

        include enumbank.inc

        mov     SavedSI,esi
        mov     SavedDI,edi

        cmp     pfn,offset do_bitblt
        jne     @F

;/*
;** If this is the bitblit,then pass the entire rectangle through.
;** BUT FIRST CHANGE do_bitblt to OUR _do_bitblt !!!
;*/

        mov     pfn,OFFSET _do_bitblt
        jmp     not_device
ALIGN 4
@@:     

;/*
;** If this is the screen,then iterate through the segment boundaries.
;*/

        test    flagsIn[0],SD_DEVICE
        jz      not_device
;/*
;** It's the device.
;*/

;/*
;** F0_GAG_CHOKE used here to indicate that the [EBX].RECTL
;** is to be used for cursor exclusion.
;*/

        mov     al,F0_GAG_CHOKE+F0_DEST_IS_DEV
        call    cursor_exclude

;/*
;** Calculate the banks for the top and bottom line
;*/

        ASSUME  EBX:PRECTL

        mov     eax,[ebx].rcl_yTop  ; eax = PM yTop
        sub     eax,SCREEN_CY
        neg     eax                              ; ax = Screen yTop
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line

        mul     edx                              ; dx:ax = byte addr of line
        shr     eax,16
        mov     bank_top,al                      ; eax = bank of top line

        mov     eax,[ebx].rcl_yBottom  ;ax = PM yBottom
        sub     eax,SCREEN_CY
        neg     eax                              ; ax = Screen yBottom
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx:ax = byte addr of line
        shr     eax,16
        mov     bank_bottom,al                   ; eax = bank of bottom line

        mov     dl,bank_top                      ; dx = Bank of Top line
        SetBankRW                                ; set the Bank,both read and write

        cld
        mov     esi,ebx
        lea     edi,local_rect
        mov     ecx,4
        rep     movsd

        cmp     bank_top,1
        je      ed_only_last_bank

        mov     dl,bank_bottom
        cmp     dl,bank_top
        je      bank_loop               ;doesn't span a bank, so
                                        ;don't recalculate yBottom

;/*
;** Calculate the bottom line of the clip rect in screen coordinates.
;** Then,convert to PM coordinates.
;*/

        mov     eax,0
        mov     al,bank_top                           ; ax = line of top bank
        mov     edx,SCREEN_LPB                        ; dx = lines per bank
        mul     edx                                   ; ax = first line in top bank
        add     eax,SCREEN_LPB                        ; ax = last line in top bank
        sub     eax,SCREEN_CY                         ; convert to PM coordinates
        neg     eax                                   ; ax = PM coord last line top bank
        mov     local_rect.rcl_yBottom,eax
bank_loop:
        push    ebx

        copyw   temp_rect,local_rect,8

        lea     ebx,temp_rect                         ; bx = addr of clip rect
        mov     esi,SavedSI
        mov     edi,SavedDI
        call    pfn
        pop     ebx

        cmp     bank_bottom,1
        jne     enum_exit              ; none in bank_bottom

;/*
;** Calculate the next rectangle.
;** The new clip rectangle Top line will be the previous clip rectangle's
;** bottom line - 1
;*/


        mov     eax,local_rect.rcl_yBottom
        mov     local_rect.rcl_yTop,eax

;/*
;** Subtract the lines per bank from Top line in this bank
;** (remember we are still in PM coordinates at this point).
;** If there are less lines to process than are in a screen bank,then
;** goto the last bank code.
;*/

        sub     eax,SCREEN_LPB             ; ax = screen lines per bank
        cmp     eax,[ebx].rcl_yBottom      ; are there any full banks to process
        jle     last_bank

ifdef   LOTSA_BANKS

;/*
;** There is a full bank to process.
;** (This code should never be reached in the 1024 X 768 X 4 driver.)
;** Set the clip rectangle bottom line.
;*/

        mov     local_rect.rcl_yBottom,eax

;/*
;** set the new bank
;*/

        mov     eax,local_rect.rcl_yTop          ; ax = PM yTop
        sub     eax,SCREEN_CY                    ; convert to screen coordinates
        neg     eax                              ; ax = SCREEN yTop
        mov     edx,SCREEN_CBSCAN                ; dx = Screen scan lines per bank
        mul     edx                              ; dx = bank
        shld    edx,eax,16

        SetBankRW                                ; set the read/write bank

        jmp     bank_loop
ALIGN 4
else
        jmp     enum_exit
ALIGN 4
endif   ;LOTSA_BANKS

last_bank:

;/*
;** set the new bank
;*/

        mov     eax,local_rect.rcl_yTop          ; ax = PM yTop
        sub     eax,SCREEN_CY                    ; convert to screen coordinates
        neg     eax                              ; ax = SCREEN yTop
        mov     edx,SCREEN_CBSCAN                ; dx = Screen scan lines per bank
        mul     edx                              ; dx = bank
        shld    edx,eax,16

        SetBankRW                                ; set the read/write bank


        mov     eax,[ebx].rcl_yBottom            ; ax = original clip y Bottom
        mov     local_rect.rcl_yBottom,eax

ed_only_last_bank:

        copyw   temp_rect,local_rect,8
        mov     edi,SavedDI
        mov     al,0
        cmp     pfn,offset do_exttextout
        jne     ed_copy_obb

;/*
;** Copy eto_args
;*/

        mov     al,1
        mov     esi,edi                           ; esi -> eto_args
        lea     edi,obb1        ;big enough
        .ERRE  (sizeof OBB_ARGS) GE (sizeof eto_args)
        mov     ecx,(size eto_args) / 4
        rep     movsd
;/*
;** end copy
;*/

        lea     edi,obb1
        SUB     [edi].eto_args.eto_y,SCREEN_LPB
        jmp     ed_end_copy
ALIGN 4


ed_copy_obb:
        cmp     pfn,do_stretchblt
        je      @F
        cmp     pfn,do_drawbits
        jne     ed_end_copy
@@:
        mov     al,1
;/*
;** Copy obb_args
;*/

        mov     esi,edi                           ; esi -> OBB_ARGS
        lea     edi,obb1
        mov     ecx,(size OBB_ARGS) / 4
        rep     movsd
;/*
;** end copy
;*/

        ADD     obb1.obba_yDst,SCREEN_LPB
        lea     edi,obb1


ed_end_copy:
        lea     ebx,temp_rect
        mov     esi,SavedSI
        cmp     al,0
        je      no_add
        add     temp_rect.rcl_yBottom,SCREEN_LPB
        add     temp_rect.rcl_yTop,SCREEN_LPB
no_add:
        cmp     pfn,offset do_stretchblt
        jne     not_device
        mov     eax,[edi].OSB_ARGS.osba_lpParm
        mov     eax,[eax].STBLT.stb_lpRectl
        add     [eax].RECTL.rcl_yTop,SCREEN_LPB
        add     [eax].RECTL.rcl_yBottom,SCREEN_LPB
not_device:
        call    pfn
enum_exit:
        call    cursor_unexclude
        ret
enum_dispatch ENDP

OPTION PROLOGUE :NONE
OPTION EPILOGUE:NONE



;/***************************************************************************
;*
;* FUNCTION NAME = _do_bitblt 
;*
;* DESCRIPTION   = Handle a bitblt
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
_do_bitblt PROC SYSCALL
        include enumbank.inc

;/*
;** Determine if the source,dest,or both are the device.
;*/

        mov     edx,esi                           ; save the frame pointer

;/*
;** get the destination surface definition flags
;*/


        ASSUME  EDI:PTR OBB_ARGS

        mov     esi,[edi].obba_pddcDst
        mov     esi,[esi].DDC.ddc_npsd



        mov     al,[esi].SURFACE.sd_fb           ; al = destination surface definition

;/*
;** Get the source surface definition flags.
;** If there is no source then we get a GP. First test for a source.
;*/

        mov     ah,0                             ; assume no source
        test    [edi].obba_fsBlt,BBF_HAVE_SOURCE
        jz      @f

        mov     esi,[edi].obba_psdSrc
        mov     ah,[esi].SURFACE.sd_fb           ; ah = source surface definition
@@:
        mov     esi,edx                          ; restore the frame pointer

;/*
;** Now determine if one or both of the surfaces are the device.
;*/

        and     al,SD_DEVICE                     ; mask for dest surface type
        and     ah,SD_DEVICE                     ; mask for source surface type
        mov     edx,eax                          ; dx = temp
        or      al,ah                            ; 0 if neither is the device
        jnz     @f
        jmp     db_not_device
ALIGN 4
@@:

;/*
;** Either the source,dest,or both are the device.
;*/
        xor     ah,dl                             ; 0 if both are device
        jnz     @f
        jmp     db_screen_to_screen_blt
ALIGN 4
@@:

;/*
;** Determine if the source is the device and the destination is not
;** the device.
;*/

        test    dl,SD_DEVICE
        jnz     @f
        test    dh,SD_DEVICE
        jz      @f

;/*
;** to get here the source is the device and the dest is not
;*/

        jmp     db_only_src_dev
ALIGN 4

@@:

;/*
;** The destination is the device.
;** Is the rectangle contained within one segment?
;** Must exclude only the dest rect
;*/

        mov     al,F0_DEST_IS_DEV
        call    cursor_exclude

;/*
;** Calculate the banks for the top and bottom line.
;*/

        mov     eax,[ebx].rcl_yTop               ; ax = PM yTop
        sub     eax,SCREEN_CY
        neg     eax                              ; ax = Screen yTop
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx:ax = byte addr of line
        shr     eax,16
        mov     bank_top,al                      ; dx = bank of top line

        mov     eax,[ebx].rcl_yBottom  ;ax = PM yBottom
        sub     eax,SCREEN_CY
        neg     eax                              ; ax = Screen yBottom
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx:ax = byte addr of line
        shr     eax,16
        mov     bank_bottom,al                   ; dx = bank of bottom line

        mov     dl,bank_top                      ; dx = Bank of Top line
        SetBankRW                                ; set the Bank,both read and write
                                                 ;CASE 1
        call    only_dest_dev                    ;Src is bitmap,dest is device
        jmp     db_exit
ALIGN 4


public  db_screen_to_screen_blt
                                                 ;CASE 2
db_screen_to_screen_blt::                        ;Src is device,dest is device

;/*
;** Must exclude the union of the 2 rects
;*/

        mov     al,F0_SRC_IS_DEV+F0_DEST_IS_DEV
        call    cursor_exclude

        call    screen_to_screen_blit
        jmp     db_exit
ALIGN 4


public  db_only_src_dev
                                                 ;CASE 3
db_only_src_dev::                                ;Src is device,dest is bitmap

;/*
;** Must exclude only the source rect
;*/
        mov     al,F0_SRC_IS_DEV
        call    cursor_exclude

        call    only_src_dev
        jmp     db_exit
ALIGN 4

db_not_device:
        push    ebx                              ;CASE 4
        call    do_bitblt                        ;Src is bitmap,dest is bitmap
        pop     ebx

db_exit:
        mov     eax,1                            ; make sure we go through clip rects
        ret
_do_bitblt ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = only_src_dev
;*
;* DESCRIPTION   = The source is the device,but the destination isn't.  The 
;*                 clipping rectangle is used for the destination,so it's of
;*                 no use in determining the banks in this case.            
;*                                                                          
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
only_src_dev PROC SYSCALL
        include enumbank.inc


;/*
;** first make a copy of the obb arguments in the enumclip_rect frame
;*/

        cld
        mov     esi,edi                           ; ss:si -> OBB_ARGS
        lea     edi,obb1
        mov     ecx,(size OBB_ARGS) / 4

        rep     movsd

;/*
;** Flip the coordinate system over for the old Window's way
;** where 0,0 is the upper left corner
;*/

        mov     esi,obb1.obba_pddcDst            ;ES:SI --> DDC
        mov     esi,[esi].DDC.ddc_npsd           ;Need surface definition part
        mov     eax,[esi].SURFACE.sd_cy
        sub     eax,obb1.obba_yDst
        sub     eax,obb1.obba_cyExt
        mov     obb1.obba_yDst,eax

        test    obb1.obba_fsBlt,BBF_HAVE_SOURCE
        jz      @F
        mov     esi,obb1.obba_psdSrc
        mov     eax,[esi].SURFACE.sd_cy
        sub     eax,obb1.obba_ySrc
        sub     eax,obb1.obba_cyExt
        mov     obb1.obba_ySrc,eax
@@:

;/*
;** Determine what bank(s) the source and destination are in.
;** At this point obb1 contains device coordinates.
;*/

        xor     cl,cl
        mov     eax,obb1.obba_ySrc               ; ax = Top line of source
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx = bank of top line of source
        shld    edx,eax,16

        cmp     dl,0                             ; Top Line in bank 0?
        jne     @f
        or      cl,SRC_IN_BANK0                  ; Indicate that at least part of
        jmp     jn5                              ; the source is in bank0
ALIGN 4
@@:
        or      cl,SRC_IN_BANK1                  ; Indicate that at least part of
jn5:                                             ; the source is in bank1

        mov     eax,obb1.obba_ySrc               ; ax = Top line of source
        add     eax,obb1.obba_cyExt              ; ax = Bottom line of source
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx = bank of bottom line of source
        shld    edx,eax,16

        cmp     dl,0                             ; Bottom Line in bank 0?
        jne     @f
        or      cl,SRC_IN_BANK0                  ; Indicate that at least part of
        jmp     jn6                              ; the source is in bank0
ALIGN 4
@@:
        or      cl,SRC_IN_BANK1
jn6:                                             ; the source is in bank1

;/*
;** Determine which bank or banks the source is in and
;** execute the appropriate blits.
;*/

;/*
;** Is the source only in bank 0?
;*/
        cmp     cl,SRC_IN_BANK0
        jne     @f

        mov     dl,0
        SetBankR
        lea     ebx,obb1
        call    do_bitblit1
        jmp     osd_exit
ALIGN 4
@@:

;/*
;** Is the source only in bank 1?
;*/
        cmp     cl,SRC_IN_BANK1

        jne     src_in_b1

        mov     dl,1
        SetBankR
        lea     ebx,obb1

        Adjust  SOURCE

        call    do_bitblit1
        jmp     osd_exit
ALIGN 4
src_in_b1:

;/*
;** Source must cross banks
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** determine the cyExt of the source in bank 0.
;*/

        mov     eax,SCREEN_LPB
        sub     eax,obb1.obba_ySrc               ; ax = cyExt in Bank 0

;/*
;** set the cyExt for bank 0 and 1
;*/

        mov     obb1.obba_cyExt,eax              ; set cyExt in bank 0
        sub     obb2.obba_cyExt,eax              ; set cyExt in Bank 1

;/*
;** Set the source and dest Y for the blit that goes between bank 0
;** and bank 1.
;*/

        mov     eax,obb1.obba_ySrc               ; ax = Original Y source
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_ySrc,eax               ; set new ySrc

        mov     eax,obb1.obba_yDst               ; ax = Original Y dest
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_yDst,eax               ; set new yDst

;/*
;** Do the blit from the source portion in bank 0 the destination
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

;/*
;** now blit the portion from bank 1 to the destination
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  SOURCE

        call    do_bitblit1


osd_exit:
        ret
only_src_dev ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = screen_to_screen_blit 
;*
;* DESCRIPTION   = Prepare for a screen to screen blt, and the call the
;*                 proper sts function to actually perform the blt.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
ALIGN 4
screen_to_screen_blit PROC SYSCALL
        include enumbank.inc

;/*
;** first make a copy of the obb arguments in the enumclip_rect frame
;*/

        cld
        mov     esi,edi                           ; ss:si -> OBB_ARGS
        lea     edi,obb1
        mov     ecx,(size OBB_ARGS) / 4

        rep     movsd

;/*
;** now clip to the clip rectangle Compute the new rectangle
;*/

        mov     eax,[ebx].RECTL.rcl_xLeft
        mov     edx,[ebx].RECTL.rcl_xRight
        sub     edx,eax                          ;New X extent
        mov     obb1.obba_cxExt,edx
        mov     ecx,eax                          ;Save a copy of new lhs
        xchg    eax,obb1.obba_xDst               ;Set new dest lhs
        sub     ecx,eax                          ;How much we moved right
        add     obb1.obba_xSrc,ecx               ;New source lhs

        mov     eax,[ebx].RECTL.rcl_yBottom
        mov     edx,[ebx].RECTL.rcl_yTop
        sub     edx,eax                          ;New Y extent
        mov     obb1.obba_cyExt,edx
        mov     ecx,eax                          ;Save a copy of new bottom
        xchg    eax,obb1.obba_yDst               ;Set new dest bottom
        sub     ecx,eax                          ;How much we moved up
        add     obb1.obba_ySrc,ecx               ;New source bottom

;/*
;** Flip the coordinate system over for the old Window's way
;** where 0,0 is the upper left corner
;*/

        mov     esi,obb1.obba_pddcDst            ;SI --> DDC
        mov     esi,[esi].DDC.ddc_npsd           ;Need surface definition part
        mov     eax,[esi].SURFACE.sd_cy
        sub     eax,obb1.obba_yDst
        sub     eax,edx                           ;DX = obba_cy
        mov     obb1.obba_yDst,eax

        test    obb1.obba_fsBlt,BBF_HAVE_SOURCE
        jz      @F
        mov     esi,obb1.obba_psdSrc
        mov     eax,[esi].SURFACE.sd_cy
        sub     eax,obb1.obba_ySrc
        sub     eax,edx                           ;DX = obba_cy
        mov     obb1.obba_ySrc,eax
@@:

;/*
;** Determine what bank(s) the source and destination are in.
;** At this point obb1 contains device coordinates.
;*/

        xor     cl,cl
        mov     eax,obb1.obba_ySrc               ; ax = Top line of source
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx = bank of top line of source
        shld    edx,eax,16
        cmp     dl,0                             ; Top Line in bank 0?
        jne     @f
        or      cl,SRC_IN_BANK0
        jmp     jn1                              ; the source is in bank0
ALIGN 4
@@:
        or      cl,SRC_IN_BANK1
jn1:                                             ; the source is in bank1

        mov     eax,obb1.obba_ySrc               ; ax = Top line of source
        add     eax,obb1.obba_cyExt              ; ax = Bottom line of source
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx = bank of bottom line of source
        shld    edx,eax,16

        cmp     dl,0                             ; Bottom Line in bank 0?
        jne     @f
        or      cl,SRC_IN_BANK0
        jmp     jn2                              ; the source is in bank0
ALIGN 4
@@:
        or      cl,SRC_IN_BANK1
jn2:                                             ; the source is in bank1
        mov     eax,obb1.obba_yDst               ; ax = Top line of source
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                              ; dx = bank of top line of source
        shld    edx,eax,16
        cmp     dl,0                             ; Top Line in bank 0?
        jne     @f
        or      cl,DST_IN_BANK0
        jmp     jn3                              ; the source is in bank0
ALIGN 4
@@:
        or      cl,DST_IN_BANK1
jn3:                                             ; the source is in bank1

        mov     eax,obb1.obba_yDst               ; ax = Top line of dest
        add     eax,obb1.obba_cyExt              ; ax = Bottom line of dest
        mov     edx,SCREEN_CBSCAN                ; dx = bytes per scan line
        mul     edx                               ; dx = bank of bottom line of dest
        shld    edx,eax,16

        cmp     dl,0                             ; Bottom Line in bank 0?
        jne     @f
        or      cl,DST_IN_BANK0
        jmp     jn4                              ; the dest is in bank0
ALIGN 4
@@:
        or      cl,DST_IN_BANK1
jn4:                                             ; the dest is in bank1
        mov     bank_map,cl


;/*
;** From the bank map,determine which bitblit routine to call.
;*/

        mov     ebx,0
        mov     bl,bank_map
        shl     ebx,2
        call    dword ptr sts_jmp[ebx]
screen_to_screen_exit:

        ret
screen_to_screen_blit ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = try_oembit 
;*
;* DESCRIPTION   = Sets up EBX and calls do_bitblit1
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
ALIGN 4
try_oembit PROC SYSCALL
        include enumbank.inc


        lea     ebx,obb1
        call    do_bitblit1
        ret
try_oembit ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case0
;*
;* DESCRIPTION   =  screen to screen blit case 0                   
;*                  Both source and dest are completely in Bank 0
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case0 PROC SYSCALL
        include enumbank.inc


        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

        ret
sts_case0 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case1
;*
;* DESCRIPTION   =  screen to screen blit case 1
;*                  Both source and dest are completely in Bank 1
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case1 PROC SYSCALL
        include enumbank.inc

        mov     dl,1
        SetBankRW

        lea     ebx,obb1

        Adjust  BOTH

        call    do_bitblit1

        ret
sts_case1 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case2
;*
;* DESCRIPTION   =  screen to screen blit case 2
;*                  Source is completely in bank 0,Dest is completely in Bank 1 
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case2 PROC SYSCALL
        include enumbank.inc

;/*
;** Move the source rectangle to bank 1.
;*/

        mov     eax,obb1.obba_xSrc
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb1.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb1.obba_ySrc
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** A rectangle that includes the bits we want has been
;** moved into bank 1
;** Adjust obb1 for the new Y
;*/

        mov     obb1.obba_ySrc,SCREEN_CY
        mov     dl,1
        SetBankRW

        lea     ebx,obb1
        Adjust  BOTH
        call    do_bitblit1

        CleanUpPSA
        ret
        
sts_case2 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case3
;*
;* DESCRIPTION   =  screen to screen blit case 3
;*                  Source is completely in Bank 1,Dest is completely in Bank 0  
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case3 PROC SYSCALL
        include enumbank.inc

;/*
;** First copy the dest rectangle to the bank 1 scratch area.
;*/

        mov     eax,obb1.obba_xDst
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb1.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb1.obba_yDst
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

        mov     eax,obb1.obba_yDst               ; save original yDst
        mov     obb2.obba_yDst,eax

;/*
;** Set the new dest rectangle to the temp rectangle in
;** the scratch area.
;*/

        mov     obb1.obba_yDst,SCREEN_CY

        mov     dl,1                                 ; Set the VGA to Bank 1 R/W
        SetBankRW

        lea     ebx,obb1
        Adjust  BOTH
        call    do_bitblit1                          ; Do the blit,entirely in Bank 1

;/*
;** Move the dest rectangle from bank 1 to bank 0
;*/

        mov     eax,obb2.obba_yDst
        mov     FastMove_yDst,eax

        mov     FastMove_ySrc,SCREEN_CY

        call    FastMove

        CleanUpPSA

        ret
sts_case3 ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = sts_case4
;*
;* DESCRIPTION   =  screen to screen blit case 4
;*                  Source is completely Bank 0,Dest crosss Bank 0 and Bank 1  
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case4 PROC SYSCALL
        include enumbank.inc

;/*
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** Determine the cyExt of the destination in bank 0.
;*/

        mov     eax,SCREEN_LPB
        sub     eax,obb1.obba_yDst               ; ax = cyExt in Bank 0

;/*
;** set the cyExt for bank 0 and 1
;*/

        mov     obb1.obba_cyExt,eax              ; set cyExt in bank 0
        sub     obb2.obba_cyExt,eax              ; set cyExt in Bank 1

;/*
;** Set the source and dest Y for the blit that goes between bank 0
;** and bank 1.
;*/


        mov     eax,obb1.obba_ySrc               ; ax = Original Y source
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_ySrc,eax               ; set new ySrc

        mov     eax,obb1.obba_yDst               ; ax = Original Y dest
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_yDst,eax               ; set new yDst

;/*
;** The blit must be done from bottom to top.
;**---
;** Take care of the portion of the blit that goes from
;** bank 0 to bank 1.
;**---
;** Move the portion of the source rectangle to bank 1
;*/

        mov     eax,obb1.obba_xSrc
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb2.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb2.obba_ySrc
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Do the Blit
;*/

        mov     obb2.obba_ySrc,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Do the blit from the source in bank 0 to the portion of the destination
;** in bank 0
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

        CleanUpPSA

        ret
sts_case4 ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = sts_case5
;*
;* DESCRIPTION   =  screen to screen blit case 5
;*                  Source is completely Bank 1,Dest crosss Bank 0 and Bank 1  
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case5 PROC SYSCALL
        include enumbank.inc

;/*
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** determine the cyExt of the destination in bank 0.
;*/

        mov     eax,SCREEN_LPB
        sub     eax,obb1.obba_yDst               ; ax = cyExt in Bank 0

;/*
;** set the cyExt for bank 0 and 1
;*/

        mov     obb1.obba_cyExt,eax              ; set cyExt in bank 0
        sub     obb2.obba_cyExt,eax              ; set cyExt in Bank 1

;/*
;** Set the source and dest Y for the blit that goes between bank 0
;** and bank 1.
;*/


        mov     eax,obb1.obba_ySrc               ; ax = Original Y source
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_ySrc,eax               ; set new ySrc

        mov     eax,obb1.obba_yDst               ; ax = Original Y dest
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_yDst,eax               ; set new yDst

;/*
;** Copy the portion of the destination in bank 0 to the scratch area
;** in bank 1.
;*/

        mov     eax,obb1.obba_xDst
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb1.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb1.obba_yDst
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Do the blit from the source in bank 1 to the portion of the destination
;** in the bank 1 scratch area.
;*/

        mov     eax,obb1.obba_yDst               ; save the dest Y
        mov     obb3.obba_yDst,eax

        mov     obb1.obba_yDst,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb1
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Now move the destination rectangle from the scratch area (bank 1)
;** into bank 0.
;*/

        mov     eax,obb3.obba_yDst
        mov     FastMove_yDst,eax

        mov     FastMove_ySrc,SCREEN_CY

        call    FastMove

;/*
;** Now take care of the portion of the blit that goes from
;** bank 1 to bank 1.
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  BOTH
        call    do_bitblit1

;/*
;** If the Pointer Save Area is dirty then clean it up
;*/

        CleanUpPSA

        ret
sts_case5 ENDP


;/***************************************************************************
;*
;* FUNCTION NAME = sts_case6
;*
;* DESCRIPTION   =  screen to screen blit case 6
;*                  Source crosss Bank 0 and Bank 1,Dest is completely in Bank 0 Source is completely Bank 1,Dest crosss Bank 0 and Bank 1  
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case6 PROC SYSCALL
        include enumbank.inc

;/*
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** determine the cyExt of the source in bank 0.
;*/

        mov     eax,SCREEN_LPB
        sub     eax,obb1.obba_ySrc               ; ax = cyExt in Bank 0

;/*
;** set the cyExt for bank 0 and 1
;*/

        mov     obb1.obba_cyExt,eax              ; set cyExt in bank 0
        sub     obb2.obba_cyExt,eax              ; set cyExt in Bank 1

;/*
;** Set the source and dest Y for the blit that goes between bank 0
;** and bank 1.
;*/

        mov     eax,obb1.obba_ySrc               ; eax = Original Y source
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_ySrc,eax               ; set new ySrc

        mov     eax,obb1.obba_yDst               ; eax = Original Y dest
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_yDst,eax               ; set new yDst

;/*
;** Do the blit from the source portion in bank 0 to the destination
;** in bank 0
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

;/*
;** Now take care of the portion of the blit that goes from
;** bank 1 to bank 0.
;** ---
;** Move portion of the destination rectangle from bank 0 to bank 1
;*/

        mov     eax,obb1.obba_xDst
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb2.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb2.obba_yDst
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Do the Blit of the bank portion of the source in the destination
;** in the scratch area.
;*/

        mov     eax,obb2.obba_yDst               ; save the yDst for the next move
        mov     obb3.obba_yDst,eax

        mov     obb2.obba_yDst,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb2

        Adjust  BOTH

        call    do_bitblit1

;/*
;** Now blit the destination in the scratch area back into bank 0
;*/

        mov     eax,obb3.obba_yDst
        mov     FastMove_yDst,eax

        mov     FastMove_ySrc,SCREEN_CY

        call    FastMove

        CleanUpPSA

        ret
sts_case6 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case7
;*
;* DESCRIPTION   =  screen to screen blit case 7
;*                  Source crosss Bank 0 and Bank 1,Dest is completely in Bank 1 Source is completely Bank 1,Dest crosss Bank 0 and Bank 1  
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case7 PROC SYSCALL
        include enumbank.inc

;/*
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** determine the cyExt of the source in bank 0.
;*/

        mov     eax,SCREEN_LPB
        sub     eax,obb1.obba_ySrc               ; eax = cyExt in Bank 0

;/*
;** set the cyExt for bank 0 and 1
;*/

        mov     obb1.obba_cyExt,eax              ; set cyExt in bank 0
        sub     obb2.obba_cyExt,eax              ; set cyExt in Bank 1

;/*
;** Set the source and dest Y for the blit that goes between bank 0
;** and bank 1.
;*/

        mov     eax,obb1.obba_ySrc               ; eax = Original Y source
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_ySrc,eax               ; set new ySrc

        mov     eax,obb1.obba_yDst               ; eax = Original Y dest
        add     eax,obb1.obba_cyExt              ; add in cyExt moved in bank 0
        mov     obb2.obba_yDst,eax               ; set new yDst

;/*
;** Blit the portion of the source rectangle that is in bank 1 first.
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Fast Move the portion of the source rectangle that is in bank 0
;** into the scratch area of bank 1.
;*/

        mov     eax,obb1.obba_xSrc
        mov     FastMove_xSrcDst,eax

        mov     eax,obb1.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb1.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb1.obba_ySrc
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Now do the blit from the source in the bank 1 scratch area
;** the destination in bank 1.
;*/

        mov     obb1.obba_ySrc,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb1
        Adjust  BOTH
        call    do_bitblit1

        CleanUpPSA

        ret
sts_case7 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case8
;*
;* DESCRIPTION   =  screen to screen blit case 8
;*                  Both source and destination cross bank 0 and bank 1 
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case8 PROC SYSCALL
        include enumbank.inc

;/*
;** There are sub cases here.
;**   1 - source bank 0 cyExt > dest bank 0 cyExt
;**   2 - source bank 0 cyExt == dest bank 0 cyExt
;**   3 - source bank 0 cyExt < dest bank 0 cyExt
;**---
;** Determine the cases and call the appropriate routine.
;*/


        mov     eax,SCREEN_LPB                    ; set the source bank 0 cyEXt
        sub     eax,obb1.obba_ySrc
        mov     src_bank0_cyExt,eax

        mov     edx,SCREEN_LPB                    ; set the dest bank 0 cyExt
        sub     edx,obb1.obba_yDst
        mov     dst_bank0_cyExt,edx

        cmp     eax,edx                           ; Case 1?
        jle     @f
        call    sts_case81
        jmp     sts_case8_exit
ALIGN 4
@@:
        cmp     eax,edx                           ; Case 2
        jl      @f
        call    sts_case82
        jmp     sts_case8_exit
ALIGN 4
@@:
        call    sts_case83                        ; Case 3


sts_case8_exit:

        CleanUpPSA

        ret

sts_case8 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case81
;*
;* DESCRIPTION   =  screen to screen blit case 81
;*                  Both source and destination cross bank 0 and bank 1 
;*                  source bank 0 cyExt > dest bank 0 cyExt             
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case81 PROC SYSCALL
        include enumbank.inc

;/*
;** Copy the params for the second and third rectangles.
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** copy obb1 to obb3
;*/

        lea     esi,obb1
        lea     edi,obb3
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** Set the cyExt for each of the rectangles.
;*/

        mov     eax,dst_bank0_cyExt              ; First the bank 0 only rectangle
        mov     obb1.obba_cyExt,eax

        mov     eax,src_bank0_cyExt              ; Then the sliver rectangle.
        sub     eax,dst_bank0_cyExt
        mov     obb2.obba_cyExt,eax

        mov     eax,src_bank0_cyExt              ; Then the bank 1 rectangle.
        sub     obb3.obba_cyExt,eax

;/*
;** Adjust the ySrc and yDst for rectangle 2 and 3.
;*/

        mov     eax,dst_bank0_cyExt
        add     obb2.obba_ySrc,eax               ; set rect 2 ySrc
        add     obb2.obba_yDst,eax               ; set rect 2 yDst

        mov     eax,src_bank0_cyExt
        add     obb3.obba_ySrc,eax               ; set rect 3 ySrc
        add     obb3.obba_yDst,eax               ; set rect 3 yDst

;/*
;** Now blit rectangle 3.
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb3
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Fast Move the source sliver to the scratch area
;*/

        mov     eax,obb2.obba_xSrc
        mov     FastMove_xSrcDst,eax

        mov     eax,obb2.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb2.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb2.obba_ySrc
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Blit the sliver from the scratch area to the dest.
;*/

        mov     obb2.obba_ySrc,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Blit the portion of the source to the portion of the dest
;** that is entirely in bank 0.
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1
        ret
sts_case81 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case82
;*
;* DESCRIPTION   =  screen to screen blit case 82
;*                  Both source and destination cross bank 0 and bank 1 
;*                  source bank 0 cyExt == dest bank 0 cyExt            
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case82 PROC SYSCALL
        include enumbank.inc

;/*
;** Adjust the cyExt for bank 0 and bank 1
;*/

        mov     eax,obb1.obba_cyExt              ; save original cyExt for bank 1
        mov     obb2.obba_cyExt,eax

        mov     eax,src_bank0_cyExt
        mov     obb1.obba_cyExt,eax              ; set bank 0 cyExt
        sub     obb2.obba_cyExt,eax              ; set bank 1 cyExt

;/*
;** Do the blit for bank 0
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

;/*
;** Adjust source and dest Y for bank 1
;*/

        mov     eax,src_bank0_cyExt
        add     obb1.obba_ySrc,eax               ; set the source for bank 1
        add     obb1.obba_yDst,eax               ; set the dest for bank 1

        mov     eax,obb2.obba_cyExt              ; set the extent for bank 1
        mov     obb1.obba_cyExt,eax

;/*
;** Do the bank 1 blit
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb1
        Adjust  BOTH
        call    do_bitblit1
        ret

sts_case82 ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = sts_case83
;*
;* DESCRIPTION   =  screen to screen blit case 83
;*                  Both source and destination cross bank 0 and bank 1 
;*                  source bank 0 cyExt < dest bank 0 cyExt             
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/
ALIGN 4
sts_case83 PROC SYSCALL
        include enumbank.inc


;/*
;** Copy the params for the second and third rectangles.
;** copy obb1 to obb2
;*/

        lea     esi,obb1
        lea     edi,obb2
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** copy obb1 to obb3
;*/

        lea     esi,obb1
        lea     edi,obb3
        mov     ecx,size OBB_ARGS / 4
        rep     movsd

;/*
;** Set the cyExt for each of the rectangles.
;*/

        mov     eax,src_bank0_cyExt              ; First the bank 0 only rectangle
        mov     obb1.obba_cyExt,eax

        mov     eax,dst_bank0_cyExt              ; Then the sliver rectangle.
        sub     eax,src_bank0_cyExt
        mov     obb2.obba_cyExt,eax

        mov     eax,dst_bank0_cyExt              ; Then the bank 1 rectangle.
        sub     obb3.obba_cyExt,eax

;/*
;** Adjust the ySrc and yDst for rectangle 2 and 3.
;*/

        mov     eax,src_bank0_cyExt
        add     obb2.obba_ySrc,eax               ; set rect 2 ySrc
        add     obb2.obba_yDst,eax               ; set rect 2 yDst

        mov     eax,dst_bank0_cyExt
        add     obb3.obba_ySrc,eax               ; set rect 3 ySrc
        add     obb3.obba_yDst,eax               ; set rect 3 yDst

;/*
;** Blit the portion of the source to the portion of the dest
;** that is entirely in bank 0.
;*/

        mov     dl,0
        SetBankRW

        lea     ebx,obb1
        call    do_bitblit1

;/*
;** Fast Move the dest sliver to the scratch area
;*/

        mov     eax,obb2.obba_xDst
        mov     FastMove_xSrcDst,eax

        mov     eax,obb2.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb2.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb2.obba_yDst
        mov     FastMove_ySrc,eax

        mov     FastMove_yDst,SCREEN_CY

        call    FastMove

;/*
;** Blit the sliver from the scratch area to the dest.
;*/

        mov     eax,obb2.obba_yDst               ; save the dest Y
        mov     obb1.obba_yDst,eax

        mov     obb2.obba_yDst,SCREEN_CY

        mov     dl,1
        SetBankRW

        lea     ebx,obb2
        Adjust  BOTH
        call    do_bitblit1

;/*
;** Now fast move it back
;*/

        mov     eax,obb1.obba_yDst               ; restore the yDst
        mov     obb2.obba_yDst,eax

;/*
;** Move the dest rectangle from bank 1 to bank 0
;*/

        mov     eax,obb2.obba_xDst
        mov     FastMove_xSrcDst,eax

        mov     eax,obb2.obba_cxExt
        mov     FastMove_cxExt,eax

        mov     eax,obb2.obba_cyExt
        mov     FastMove_cyExt,eax

        mov     eax,obb2.obba_yDst
        mov     FastMove_yDst,eax

        mov     FastMove_ySrc,SCREEN_CY

        call    FastMove

;/*
;** Now blit rectangle 3.
;*/

        mov     dl,1
        SetBankRW

        lea     ebx,obb3
        Adjust  BOTH
        call    do_bitblit1

        ret

sts_case83 ENDP




;/***************************************************************************
;*
;* FUNCTION NAME = Fast Move     
;*
;* DESCRIPTION   =  This is an optimized block move.                         
;*
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/

ALIGN 4
FastMove PROC SYSCALL
        include enumbank.inc

;/*
;** Check for a 0 cyExt,if cyExt == 0 then exit
;*/

        cmp     FastMove_cyExt,0
        je      fastmove_exit
@@:

;/*
;** Is the pointer save area about to get trashed?
;*/

        mov     eax,FastMove_yDst
        add     eax,FastMove_cyExt
        cmp     eax,1020
        jl      @f
        call    save_PointerSaveArea

@@:

;/*
;** Set the source bank
;*/

        mov     eax,FastMove_ySrc
        mov     edx,SCREEN_CBSCAN
        mul     edx                               ; dx = source bank,eax = offset
        mov     esi,eax                           ; set source line offset
        and     esi,0ffffh
        shld    edx,eax,16


        SetBankR                                  ; set source bank

;/*
;** Set the destination Bank
;*/

        mov     eax,FastMove_yDst
        mov     edx,SCREEN_CBSCAN
        mul     edx                               ; dx = dest bank,eax = dest offset
        mov     edi,eax                           ; set dest line offset
        and     edi,0ffffh
        
        shld    edx,eax,16

        SetBankW                                  ; set dest bank

;/*
;** calculate source byte
;*/

        mov     eax,FastMove_xSrcDst
        shr     eax,3                             ; convert bits to bytes

;/*
;** add X byte offset into source and dest line offsets
;*/

        add     esi,eax
        add     edi,eax

;/*
;** calculate cxExt in bytes
;** if xSrcDst mod 8 != 0 then add an extra byte to the width
;** if cxExt mod 8 != 0 then add an extra byte to the byte width
;*/

        mov     eax,FastMove_cxExt               ; eax = X extent in pixels
        mov     edx,7
        and     edx,eax                          ; dx = xExt mod 8
        shr     eax,3                            ; eax = x extent in bytes

        cmp     edx,0                            ; Should we add an extra byte for
        je      @f                               ; the extent
        inc     eax
@@:
        mov     edx,7                            ; should we add an extra byte for
        and     edx,FastMove_xSrcDst             ; the start positon
        cmp     edx,0
        je      @f
        inc     eax
@@:

;/*
;** calculate the distance to the beginning of the next line in the
;** blit rectangle.
;** next line = screen width - blit width
;*/

        mov     edx,SCREEN_CBSCAN
        sub     edx,eax                         ; dx = next line offset

        mov     FastMove_NextLine,edx           ; set next line offset
        mov     FastMove_cx,eax                 ; set width in bytes

;/*
;** Set up for the block move.
;*/

        mov     ebx,obb1.obba_pddcDst           ; bx = np to ddcDst
        ASSUME  EBX:NOTHING
        mov     ebx,[ebx].DDC.ddc_npsd          ; bx = sdDst
        add     edi,[ebx].SURFACE.sd_pBits      ; edi = screen selector
        add     esi,[ebx].SURFACE.sd_pBits      ; esi = screen selector

;/*
;** Set the VGA into write mode 1.
;** You need to save the current write mode first.
;*/

        mov     edx,EGA_BASE + GRAF_ADDR
        mov     al,GRAF_MODE
        out     dx,al                             ; Set the GDC mode addr
        inc     edx
        in      al,dx
        mov     saved_gdc_mode,al

        mov     al,M_LATCH_WRITE
        out     dx,al                             ; set latch read/write

        mov     ExtraFlag,0
        mov     eax,FastMove_cyExt
        mov     ebx,FastMove_cx
        mov     edx,FastMove_NextLine

;/*
;** do the block move
;*/

move_loop:
        mov     ecx,ebx                           ; set line byte counter
        rep     movsb
        add     esi,edx                           ; si = next source line addr
        add     edi,edx                           ; di = next dest line addr
        dec     eax                               ; update line counter
        jnz     move_loop

;/*
;** reset the VGA GDC mode
;*/

        mov     edx,EGA_BASE + GRAF_ADDR
        mov     al,GRAF_MODE
        out     dx,al                             ; Set the GDC mode addr
        inc     edx
        mov     al,saved_gdc_mode
        out     dx,al

;/*
;** Does the pointer save area need to be restored?
;*/

        mov     eax,FastMove_ySrc
        add     eax,FastMove_cyExt
        cmp     eax,1020
        jl      @f
        call    restore_PointerSaveArea

@@:

fastmove_exit:

        ret

FastMove ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = save pointer save area
;*
;* DESCRIPTION   = Occasionallu the pointer save area may get trashed if   
;*                 the screen to screen blit needs the last 4 lines of the 
;*                 temp area.  This condition is detected in Fastmove,and  
;*                 this routine is called to save the pointer save area    
;*                 before the data is trashed.                             
;*                                                                         
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
save_PointerSaveArea PROC SYSCALL
        include enumbank.inc

;/*
;** Set bank 1
;*/

        mov     dl,1
        SetBankRW

;/*
;** Setup the selectors for the move
;*/

        mov     ebx,obb1.obba_pddcDst            ; bx = pddcDst
        mov     ebx,[ebx].DDC.ddc_npsd           ; bx = sdDst

        ASSUME EBX:PSURFACE

        lea     edi,fastmove_buffer         ; di = offset of buffer

        mov     edx,EGA_BASE + GRAF_ADDR    ; dx = GDC addr reg
        mov     al,GRAF_READ_MAP                     ; al = GDC read select reg

        mov     ah,RM_C0
        out     dx,ax                                 ; select plane 0

;/*
;** bytes per plane = SCREEN_CBSCAN
;** 4 lines to move = SCREEN_CBSCAN * 4
;** mov dwords      = SCREEN_CBSCAN
;*/

        mov     ecx,SCREEN_CBSCAN

;/*
;** source offset of move = (SCREEN_LPB - 4) * SCREEN_CBSCAN
;**                                       = (512 - 4) * 128
;**                                        = 65024d,(FE00h)
;*/

ifdef FIREWALLS
        push    eax
        mov     esi,SCREEN_LPB
        mov     eax,512
        assert  esi,E,eax
        mov     eax,128
        mov     esi,SCREEN_CBSCAN
        assert  esi,E,eax
        pop     eax
endif
        mov     esi,65024
        add     esi,[ebx].sd_pBits      ; screen pointer
        push    esi

        rep     movsd                             ; do the move for plane 0

        mov     ah,RM_C1
        out     dx,ax                             ; set plane 1
        mov     esi,DWORD PTR [esp]
        mov     ecx,SCREEN_CBSCAN

        rep     movsd                             ; move plane 1

        mov     ah,RM_C2
        out     dx,eax                            ; set plane 2
        mov     esi,DWORD PTR [esp]
        mov     ecx,SCREEN_CBSCAN
        rep     movsd                             ; move plane 2

        mov     ah,RM_C3
        out     dx,eax                            ; set plane 3
        pop     esi
        mov     ecx,SCREEN_CBSCAN
        rep     movsd                             ; move plane 3

;/*
;** Indicate that the pointer save area is dirty.
;*/

        mov     bfPointerSaveAreaDirty,TRUE
        ret
save_PointerSaveArea ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = restore pointer save area 
;*
;* DESCRIPTION   = Occasionally,the pointer save area may get trashed if the
;*                 screen to screen blit needs the last 4 lines of the temp 
;*                 area.  Fastmove detects this condition and calls this    
;*                 routine to restore the pointer save area.                
;*                                                                          
;* INPUT         =  NONE
;* OUTPUT        =  NONE
;*
;* RETURN-NORMAL =  NONE
;* RETURN-ERROR  =  NONE
;*
;**************************************************************************/

ALIGN 4
restore_PointerSaveArea PROC SYSCALL
        include enumbank.inc

;/*
;** Set bank 1
;*/
        mov     dl,1
        SetBankRW

;/*
;** Setup the selectors for the move
;*/

        mov     ebx,obb1.obba_pddcDst                ; bx = np to ddcDst
ASSUME EBX:NOTHING
        mov     ebx,[ebx].DDC.ddc_npsd               ; bx = sdDst
ASSUME EBX:PSURFACE
        mov     esi,offset fastmove_buffer  ; si = offset of buffer

;/*
;** Set the GDC mode for processor writes to memory
;*/

        mov     edx,EGA_BASE + GRAF_ADDR    ; dx = GDC addr reg
        mov     al,GRAF_MODE                          ; al = GDC mode reg
        mov     ah,M_PROC_WRITE
        out     dx,ax                                 ; set for processor writes

;/*
;** Set the rotation count and function
;*/

        mov     al,GRAF_DATA_ROT
        mov     ah,DR_SET                             ; write data un-modifed,no rotation
        out     dx,ax

;/*
;** Set TS write plane mask for each plane
;*/

        mov     dl,SEQ_ADDR
        mov     al,SEQ_MAP_MASK

;/*
;** write plane 0
;*/

        mov     ah,MM_C0
        out     dx,ax                             ; select plane 0

;/*
;** bytes per plane = SCREEN_CBSCAN
;** 4 lines to move = SCREEN_CBSCAN * 4
;** mov dwords      = SCREEN_CBSCAN
;*/

        mov     ecx,SCREEN_CBSCAN

;/*
;** source offset of move = (SCREEN_LPB - 4) * SCREEN_CBSCAN
;**                                        = (512 - 4) * 128
;**                                        = 65024d,(FE00h)
;**                                        = 65024d,(FE00h)
;*/

ifdef FIREWALLS
        push    eax
        mov     edi,SCREEN_LPB
        mov     eax,512
        assert  edi,E,eax
        mov     eax,128
        mov     edi,SCREEN_CBSCAN
        assert  edi,E,eax
        pop     eax
endif

        mov     edi,65024                        ; di = offset of restore
        add     edi,[ebx].sd_pBits               ; eax = screen pointer
        push    edi

        rep     movsd                            ; restore plane 0

        ; Write plane 1

        mov     ah,MM_C1
        out     dx,ax                            ; select plane 1
        mov     ecx,SCREEN_CBSCAN
        mov     edi,DWORD PTR [esp]

        rep     movsd                            ; do the restore

        mov     ah,MM_C2
        out     dx,ax                            ; select plane 2
        mov     ecx,SCREEN_CBSCAN
        mov     edi,DWORD PTR [esp]

        rep     movsd                            ; do the restore

        mov     ah,MM_C3
        out     dx,ax                            ; select plane 2
        mov     ecx,SCREEN_CBSCAN
        pop     edi

        rep     movsd                            ; do the restore

;/*
;** reset for all plane write
;*/

        mov     ah,MM_ALL
        out     dx,ax

;/*
;** Indicate that the pointer save area is no longer dirty.
;*/

        mov     bfPointerSaveAreaDirty,FALSE
        ret
restore_PointerSaveArea ENDP



;/***************************************************************************
;*
;* FUNCTION NAME = do_bitblit1
;*
;* DESCRIPTION   = Sets up arguments on the stack and cal OEMBitBlt
;*
;* INPUT         = bx = offset,on the stack,of obba_structure 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
do_bitblit1 PROC SYSCALL

;/*
;** Test for a 0 cyExt,if there is nothing to blit then exit.
;*/

ASSUME  EBX:PTR OBB_ARGS

        cmp     [ebx].obba_cyExt,0
        je      do_end

;/*
;** Leave room for the arguments we'll copy to the stack
;*/

        mov     esi,ebx
        sub     esp,size OBB_ARGS
        mov     edi,esp

;/*
;** Get arguments onto our stack.
;** They are in our old stack segment.
;*/

        .errnz  (size OBB_ARGS) and 3
        mov     ecx,(size OBB_ARGS) / 4
        cld
        rep     movsd

;/*
;** Make the Bitblt call and then restore the stack frame
;*/

        call    OEMBitblt
        add     esp,sizeof OBB_ARGS
do_end:
        ret
do_bitblit1 endp

;/***************************************************************************
;*
;* FUNCTION NAME = only_dest_dev
;*
;* DESCRIPTION   = Performs a blt when only the destination is the device
;*
;* INPUT         = Pass in ECX = 1, spans banks 0 and 1 
;*                         ECX = 0, all in bank 1       
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
only_dest_dev PROC SYSCALL
        include enumbank.inc

;/*
;** Set up a local rectangle.
;*/

ASSUME EBX:PRECTL

;/*
;**COPY [EBX].RECTL to local_rect
;*/

        cld
        mov     esi,ebx
        lea     edi,local_rect
        mov     ecx,4
        rep     movsd

        cmp     bank_top,1
        je      dbctb_only_last_bank

        mov     dl,bank_bottom
        cmp     dl,bank_top
        je      dbctb_bank_loop         ;doesn't span a bank, so
                                        ;don't recalculate yBottom

;/*
;** Now calculate the bottom line of the clip rect in screen coordinates.
;** Then,convert to PM coordinates.
;*/

        mov     eax,0
        mov     al,bank_top                           ; eax = line of top bank
        mov     edx,SCREEN_LPB                        ; dx = lines per bank
        mul     edx                                   ; eax = first line in top bank
        add     eax,SCREEN_LPB                        ; eax = last line in top bank
        sub     eax,SCREEN_CY                         ; convert to PM coordinates
        neg     eax                                   ; eax = PM coord last line top bank
        mov     local_rect.rcl_yBottom,eax

dbctb_bank_loop:
        push    ebx

        copyw   temp_rect,local_rect,8

        lea     ebx,temp_rect                         ; bx = addr of clip rect
        mov     esi,SavedSI
        mov     edi,SavedDI

        call    do_bitblt

        pop     ebx

        cmp     bank_bottom,1
        jne     dbctb_exit              ; none in bank_bottom

;/*
;** Calculate the next rectangle
;** The new clip rectangle Top line will be the previous clip rectangle's
;** bottom line - 1
;*/

        mov     eax,local_rect.rcl_yBottom
        mov     local_rect.rcl_yTop,eax
        
ifdef   LOTSA_BANKS

;/*
;** Subtract the lines per bank from Top line in this bank,
;** (remember we are still in PM coordinates at this point).
;** If there are less lines to process than are in a screen bank then
;** goto the last bank code.
;*/

        sub     eax,SCREEN_LPB                        ; eax = screen lines per bank
        cmp     eax,[ebx].rcl_yBottom  ; are there any full banks to process
        jle     dbctb_last_bank

;/*
;** There is a full bank to process.
;** (This code should never be reached in the 1024 X 768 X 4 driver.)
;** Set the clip rectangle bottom line.
;*/

        mov     local_rect.rcl_yBottom,eax

;/*
;** set the new bank
;*/

        mov     eax,local_rect.rcl_yTop  ; eax = PM yTop
        sub     eax,SCREEN_CY                         ; convert to screen coordinates
        neg     eax                                   ; eax = SCREEN yTop
        mov     edx,SCREEN_CBSCAN                    ; dx = Screen scan lines per bank
        mul     edx                                   ; dx = bank
        shld    edx,eax,16
        SetBankRW                                     ; set the read/write bank

        jmp     dbctb_bank_loop
ALIGN 4
endif
dbctb_last_bank:

;/*
;** set the new bank
;*/

        mov     dl,bank_bottom
        SetBankRW                                     ; set the read/write bank


        mov     eax,[ebx].rcl_yBottom  ; eax = original clip y Bottom
        mov     local_rect.rcl_yBottom,eax

dbctb_only_last_bank:

        push    ebx

        copyw   temp_rect,local_rect,8

;/*
;** Copy obb_args
;*/
        cld
        mov     esi,SavedDI                        ; esi -> OBB_ARGS
        lea     edi,obb1
        mov     ecx,(size OBB_ARGS) / 4
        rep     movsd

;/*
;** end copy
;*/
        ADD     obb1.obba_yDst,SCREEN_LPB

        lea     ebx,temp_rect

        mov     esi,SavedSI
        lea     edi,obb1

        mov     eax,temp_rect.rcl_yTop
        sub     eax,temp_rect.rcl_yBottom
        jz      @f
        add     temp_rect.rcl_yBottom,SCREEN_LPB
        add     temp_rect.rcl_yTop,SCREEN_LPB

        call    do_bitblt

@@:
        pop     ebx

dbctb_exit:
        ret
only_dest_dev ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = cursor_unexclude 
;*
;* DESCRIPTION   = Calls far_unexclude
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
ALIGN 4
cursor_unexclude  PROC SYSCALL
        MOV     EnumBankFlag,0
        call    far_unexclude
        ret
cursor_unexclude  ENDP

;/***************************************************************************
;*
;* FUNCTION NAME = cursor_exclude  
;*
;* DESCRIPTION   = 
;*
;*     If either device or both devices are for the display, then the cursor
;*     must be excluded.  If both devices are the display, then a union of
;*     both rectangles must be performed to determine the exclusion area.
;*     Entry:
;*           al =    Flags (F0_SRC_IS_DEV, F0_DEST_IS_DEV)
;*           edi ->  OBB_ARGS
;*    OBB_ARGS       struct
;*    obba_pddcDst   DWORD   ?
;*    obba_xDst      DWORD   ?
;*    obba_yDst      DWORD   ?
;*    obba_psdSrc    DWORD   ?
;*    obba_xSrc      DWORD   ?
;*    obba_ySrc      DWORD   ?
;*    obba_cxExt     DWORD   ?
;*    obba_cyExt     DWORD   ?
;*    obba_usMix     DWORD   ?
;*    obba_ipcBkgnd  DWORD   ?
;*    obba_fsBlt     DWORD   ?
;*    OBB_ARGS       ends
;*    -----------------------------------------------------------------------;
;*     F0_GAG_CHOKE used here to indicate that the [EBX].RECTL
;*     is to be used for cursor exclusion.
;*    
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
cursor_exclude  PROC SYSCALL

        push    ebp
        push    esi
        push    edi
        push    ebx
        push    eax

        test    al,F0_GAG_CHOKE
        jz      @F
        ASSUME  EBX:PRECTL

        mov     edi,[ebx].rcl_yTop               
        mov     edx,[ebx].rcl_yBottom

        mov     ecx,[ebx].rcl_xLeft              
        mov     esi,[ebx].rcl_xRight

        dec     esi                               ;Make extents inclusive of last point
        dec     edi

        jmp     cur_exclusion_do_it
ALIGN 4
@@:
        mov     ebp,edi

        ASSUME  EBP:PTR OBB_ARGS
        ASSUME  EBX:NOTHING

        mov     esi,[ebp].obba_cxExt
        mov     edi,[ebp].obba_cyExt
        dec     esi                              ;Make extents inclusive of last point
        dec     edi
        mov     ecx,[ebp].obba_xDst              ;Assume only a destination on the
        mov     edx,[ebp].obba_yDst              ;  display

        test    al,F0_SRC_IS_DEV                 ;Is the source a memory bitmap?
        jz      cur_exclusion_no_union           ;  Yes, go set right and bottom
        test    al,F0_DEST_IS_DEV                ;  (set 'Z' if dest is memory)
        mov     eax,ecx                          ;  No, prepare for the union
        mov     ebx,edx
        mov     ecx,[ebp].obba_xSrc              ;Set source org
        mov     edx,[ebp].obba_ySrc
        jz      cur_exclusion_no_union           ;Dest is memory. Set right and bottom

;/*
;** If the source starting Y is greater than surface allows, then we're
;** supporting a restore_screen_bitmap call.  In this case, we only want
;** to exclude the dest rectangle.
;*/

        cmp     edx,0
        jg      cur_exclusion_not_sbb            ; then only use dest rectangle.
        
        mov     ecx,eax
        mov     edx,ebx
        jmp     cur_exclusion_no_union
ALIGN 4

;/*
;** The union of the two rectangles must be performed.  The top left corner
;** will be the smallest x and smallest y.  The bottom right corner will be
;** the largest x and the largest y added into the extents
;*/

cur_exclusion_not_sbb::
        cmp     ecx,eax                          ;Get smallest x
        jle     cur_exclusion_y                  ;CX is smallest
        xchg    eax,ecx                          ;AX is smallest

cur_exclusion_y::
        cmp     edx,ebx                          ;Get smallest y into EDX
        jle     cur_exclusion_union              ;DX is smallest
        xchg    edx,ebx                          ;BX is smallest

cur_exclusion_union::
        add     esi,eax                          ;Set right
        add     edi,ebx                          ;Set bottom
        jmp     cur_exclusion_do_it              ;Go do exclusion
ALIGN 4

cur_exclusion_no_union::
        add     esi,ecx                          ;Set right
        add     edi,edx                          ;Set bottom

cur_exclusion_do_it::
        pop     eax     ;flags
        test    al,F0_DEST_IS_DEV                ;  (set 'Z' if dest is memory)
        jz      must_be_src
        mov     ebx,SCREEN_CY
        jmp     got_deltay
ALIGN 4
must_be_src:
        mov     ebx,[ebp].obba_psdSrc
        mov     ebx,[ebx].SURFACE.sd_cy
got_deltay:

;/*
;** Flip the coordinate system over for the old Window's way
;*/

        mov     eax,ebx                 ;surface height in scans

        sub     eax,edx                 ;y value
        mov     edx,eax

        sub     ebx,edi                 ;y value
        mov     edi,ebx

        xchg    edi,edx

;/*
;**       ECX = X coordinate of left edge                    
;**       EDX = Y coordinate of top edge                     
;**       ESI = X coordinate of right edge (inclusive)       
;**       EDI = Y coordinate of bottom edge (inclusive)      
;*/                                                          

        INVOKE  far_exclude                      ;Exclude the area from the screen

        MOV     EnumBankFlag,1                   ;keep it excluded

cur_exclusion_end::
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp
        ASSUME  EBP:NOTHING
        ret
cursor_exclude ENDP

endif ;!768
END
