;*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    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME = BOARDBLT.ASM
;*
;* DESCRIPTIVE NAME = Generate ROP tables for memory to board or board to board blt. 
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/26/88
;*
;* DESCRIPTION  
;*
;* FUNCTIONS    BoardBlt
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   03/26/88                     Author: Geoff Shapiro [geoffs]
;*****************************************************************************/

        .286p
        .xlist
        include cmacros.inc
ifdef PALMGR
INCL_GPIBITMAPS         equ     1
INCL_GPILOGCOLORTABLE   equ     1
endif
        include pmgre.inc
DINCL_BB_ROPS           equ     1
DINCL_PAT_CACHE_DEFS    equ     1
        include driver.inc
        include display.inc
        include 8514.inc
        include 8514mem.inc
        include oemblt.inc
        include assert.mac
        include njmp.mac
ifdef PALMGR
        include palette.inc
endif
        .list

BOARDBLT        Equ     1               ; include code for board blts

        ??_out  boardblt


sBegin  PtrData
        externB screen_busy             ; screen semaphore
sEnd    PtrData


sBegin  Data
        externD idBrushCache
        externW PatCacheX               ; ul of cached pattern
        externW PatCacheY               ; ul of cached pattern
        externW PatCacheXExt            ; width of cached pattern
        externW PatCacheYExt            ; height of cached pattern
        externW BltBufferX              ; blt tmp buffer origin x
        externW BltBufferY              ; blt tmp buffer origin y
        externW BltBufferXExt           ; width of the blt buffer
        externW BltBufferYExt           ; height of the blt buffer
        externW BoardMaxY               ; max real addressable y on board
        externW OffScreenValid          ; Offscreen font cache validity flag
        externW hwFlags                 ; hardware status flags
sEnd    Data

        externA DOSHUGEINCR             ; incr to get next selector
        externFP far_exclude            ; exclude area from screen
        externFP far_unexclude          ; restore excluded area to screen

sBegin  Code
        assumes cs,Code
        assumes ds,nothing
        assumes es,nothing

        include constant.blt
        include gendata.blt
        include devdata.blt

        externW CodeData                ; local data segment access
        externW MyPtrCodeData           ; for access to pointer data segment


cProc   BoardBlt,<PUBLIC,FAR,NODATA>,<DI,SI>
        include frame.blt

; These are used by all or most of the low level routines

        localW  BltHeight               ; height of each subblt
        localW  BltIncrement            ; +/- BltHeight depending on y--,y++
        localW  tempRows                ; working scan counter
        localW  ScanOff                 ; offset into each src scan
        localW  TwiceSrcScan            ; double(?) the width of a src scan
        localW  HalfSrcScan             ; half(?) the width of a src scan
        localW  BltDirections           ; direction due to overlap of blts
        localW  npBltOps                ; -> blt operation words
        localW  npCurBltOp              ; -> current blt operation
        localW  cyDst                   ; current destination y origin

;/*
;** These are used in the local source to board blt
;*/

        localB  PhaseShift              ; diff between src,dest nibble aligns
        localB  RorMask                 ; mask when phase shift is to right
        localW  CenterWords             ; # words in center of mono src blt
        localW  BltFlags                ; local src to board blt flags
        localW  ncxExt                  ; cxExt adjust to src word boundaries
        localW  nxDst                   ; dest x origin adj to src word bdry's

cBegin  BoardBlt

ifdef FIREWALLS
        fw_zero <ds,es>
        mov     ax,pddcDst.off
        ddc?    ax,<SURFACE>
endif


        Mov     BltFlags,0              ; src flags all zero'ed at start
        Cld                             ; will always work up in address

;/*
;** Based on the 3-op raster op index passed in, we fetch a pointer to the
;** blt operation words which uniquely describe the operations required to
;** achieve the particular blt requested.
;*/

        mov     bx,usMix                ; 3-op raster op index 0-255
        Shl     Bx,1                    ; word index
        Mov     Bx,npBoardRops[Bx]      ; fetch -> blt operations vector
        Mov     npBltOps,Bx             ; store for later referral

        Mov     Bl,Cs:Byte Ptr [Bx][1]  ; set fbF0 for src and pattern
        And     Bl,High (SU+PU)
        Ror     Bl,1
        .errnz  SU -     0010000000000000b
        .errnz  PU -     0100000000000000b
        .errnz  F0_SRC_PRESENT - 00010000b
        .errnz  F0_PAT_PRESENT - 00100000b


;/*
;** We have picked up the raster op information.  Get the source, pattern,
;** and destination parameters as needed.
;*/

        mov     ax,ss                   ;Leave ES set to frame segment
        mov     es,ax
        assumes es,nothing

        call    bb_pdevice_processing
        assumes ds,Data                 ;Will be data from here on out
        call    bb_pattern_preprocessing
page

;/*
;**        Cursor Exclusion
;** 
;**  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.
;*/

bb_cursor_exclusion:

        mov     si,cxExt
        mov     di,cyExt
        dec     si                      ;Make the extents inclusive of the
        dec     di                      ;  last point

        mov     cx,xDst                 ;Assume only a destination on the
        mov     dx,yDst                 ;  display

        test    fbF0,F0_SRC_IS_DEV;Is the source a memory bitmap?
        jz      bb_cursor_exclusion_no_union;  Yes, go set right and bottom

        mov     ax,cx                   ;  dest is always device
        mov     bx,dx

        mov     cx,xSrc                 ;Set source org
        mov     dx,ySrc

;/*
;**     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
;*/

        cmp     cx,ax                   ;Get smallest x
        jle     bb_cursor_exclusion_y   ;CX is smallest
        xchg    ax,cx                   ;AX is smallest

bb_cursor_exclusion_y:
        cmp     dx,bx                   ;Get smallest y
        jle     bb_cursor_exclusion_union       ;DX is smallest
        xchg    dx,bx                   ;BX is smallest

bb_cursor_exclusion_union:
        add     si,ax                   ;Set right
        add     di,bx                   ;Set bottom
        jmp     short bb_cursor_exclusion_do_it ;Go do exclusion

bb_cursor_exclusion_no_union:
        add     si,cx                   ;Set right
        add     di,dx                   ;Set bottom

bb_cursor_exclusion_do_it:
        call    far_exclude             ;Exclude the area from the screen

        GrabScreen  boardblt            ; don't allow cursor to kill us

        mov     ds,CodeData             ; need access to data segment
        assumes ds,Data

;/*
;**  Set up the default parameters for the upcoming blt. This includes:
;** 
;**        (a) The number of smaller blts that must be performed to achieve
;**            a blt of the region requested. The specified blt may have to be
;**            chunked due to overlap of source and destination, or because
;**            the blt must use the temporary buffer space which is of limited
;**            height.
;** 
;**        (b) The height of the blt chunks which must be executed. This is
;**            related to (a) above.
;** 
;**        (c) The direction in which blts must be performed. This is determined
;**            by overlap between the source and the destination when the
;**            source is the screen device also.
;*/

        Mov     BltDirections,(CMD_DX+CMD_DY); down,right is default

        Mov     Ax,cyExt                        ; entire height of requested blt
        Mov     Bx,npBltOps             ; -> blt operations
        Test    Cs:[Bx],BU              ; will blt buffer be needed ?
        Jz      @F                      ; no...
        Mov     Cx,BltBufferYExt        ; height of temp blt buffer
        usmin_ax        Cx              ; get the smaller of the two
        ??_out  <Change next line when font caching fixed up>
        Mov     OffScreenValid,0        ; invalid font cache
@@:     Mov     BltHeight,Ax            ; height of each blt
        Mov     BltIncrement,Ax         ; assume always working y++

;/*
;** Take into account the source device for determination of the blt directions
;** and height. It also might determine the usage of an alternate blt operation
;** vector.
;*/

        Mov     Al,fbF0

        Test    Al,F0_SRC_PRESENT       ; will a source be needed ?
        Jnz     @F                      ; yes...
        Jmp     source_accounted_for    ; no...
@@:

        Test    Al,F0_SRC_IS_DEV        ; screen to screen copy ?
        njz     source_is_local         ; no...

;/*
;** The source is on the device. We must compute an intersection between the
;** source and destination rectangles. If the intersection is null then overlap
;** does not have to be taken into account.
;*/

        Mov     Ax,xSrc         ; left edge of src rectangle
        Cmp     Ax,xDst         ; if src left is to right of dest left
        Jae     @F                      ; no need to go x--
        And     BltDirections,Not CMD_DX; else indicate going x--
@@:

        Mov     Ax,ySrc         ; top edge of src rectangle
        Mov     Cx,Ax
        Mov     Si,cyExt
        Add     Cx,Si
        Dec     Cx              ; bottom edge of src rectangle
        Mov     Di,Cx           ; will save this
        Mov     Bx,yDst         ; top edge of dest rectangle
        Mov     Dx,Bx
        Add     Dx,Si
        Dec     Dx                      ; bottom edge of dest rectangle
        Cmp     Ax,Bx                   ; top edge = max(src,dest tops)
        Jae     @F                      ; src top edge is >
        Mov     Ax,Bx                   ; dest top edge is >
@@:     Cmp     Cx,Dx                   ; bottom edge = min(src,dest bottom)
        Jbe     @F                      ; src bottom edge is <
        Mov     Cx,Dx                   ; dest bottom edge is <
@@:     Cmp     Cx,Ax                   ; if top > bottom we have null intersect
        Jc      source_is_dev_done      ; so no overlap problems...

;/*
;** We probably have a real overlap case but since we didn't do an actual
;** x intersection we may have a y overlap only. Treat for now as though
;** it were actually overlapping.
;**
;** Complex blts often require source or destination to be involved with
;** the blt more than once. These cases need an alternate spelling in which
;** the blt temporary buffer may be utilized. These spellings are usually
;** less efficient and that is why we only conditionally utilize them.
;*/

        Mov     Bx,npBltOps             ; -> blt operations
        Test    Cs:Word Ptr [Bx],OVL    ; alternate overlap spelling required ?
        Jz      no_ovl_spelling         ; no...

@@:     Add     Bx,2                    ; point to next spelling word
        Test    Cs:[Bx],LASTENTRY       ; at end of no overlap spelling ?
        Jz      @B                      ; spin until we are...

        Add     Bx,2                    ; now point to overlap spelling
        Mov     npBltOps,Bx             ; update -> blt operations

                                        ; blt buffer is always needed
        Mov     Ax,BltBufferYExt        ; height of temp blt buffer
        cmp     ax,cyExt
        jb      @F
        mov     ax,cyExt
@@:
        Mov     BltHeight,Ax            ; height of each blt
        Mov     BltIncrement,Ax         ; assume always working y++
        ??_out  <Change next line when font caching fixed up>
        Mov     OffScreenValid,0        ; invalid font cache

no_ovl_spelling:

        Cmp     Di,Dx                   ; if src bottom is below dest bottom
        Jae     source_is_dev_done      ; no need to go y--

        And     BltDirections,Not CMD_DY; indicate going y--
        Mov     Ax,BltHeight            ; height of each blt
        Dec     Ax
        Sub     Di,Ax                   ; ul y of last src blt band
        Mov     ySrc,Di
        Sub     Dx,Ax
        Mov     yDst,Dx                 ; ul y of last dest blt band
        Neg     Ax                      ; blt increment is up screen
        Mov     BltIncrement,Ax

source_is_dev_done:

        Jmp     source_accounted_for

;/*
;** The source is in the local memory.
;*/

source_is_local:

;/*
;** Setup for blts when source is local memory based
;*/

        Test    Al,F0_SRC_IS_COLOR      ; local src color ?
        Jz      source_is_mono          ; no...

;/*
;** We would like to have as fast a local color src to board dest blt as is
;** possible. This means that we would like to pull pixels out of the src
;** bitmap as words from word aligned boundaries (the best Intel architecture
;** case, this may change to dwords in the 80386 world), and push the pixels
;** to the 8514/A in byte mode (meaning 2 pixels / word output to the board).
;*/

        Mov     Cl,1                    ; assume 8 bpp, 2 bytes/word
        Mov     Dx,1                    ; 01b mask for rounding

ifdef   4BPP_USED
        Test    hwFlags,HW_8_BPP
        Jnz     @F

        Mov     Cl,2                    ; 4 bpp, 4 nibbles/word
        Mov     Dl,3                    ; 11b mask for rounding
@@:
endif;  4BPP_USED

        Mov     Di,cxExt                ; actual width of blt

        Mov     Ax,xSrc                 ; clipped src x origin
        Add     Di,Ax                   ; last pixel in scan + 1
        Add     Di,Dx                   ; round end up to next word boundary
        Not     Dx                      ; form round down to word bdry mask
        And     Di,Dx                   ; end x on scan rounded down
        Mov     Bx,Ax                   ; save original start x
        And     Ax,Dx                   ; start x on scan rounded down
        Sub     Bx,Ax                   ; # pixels moved left for start x
        Neg     Bx                      ; moving left edge left
        Add     Bx,xDst                 ; move dest x over by that amt
        And     Bx,XY_SIGNIFICANT       ; mask to just hw bits
        Mov     nxDst,Bx                ; save for src blt usage later
        Sub     Di,Ax                   ; # pixels in adjusted scan
        Shr     Di,Cl                   ; # whole words total
        Mov     CenterWords,Di

        Shl     Di,Cl                   ; new cxExt
        Dec     Di                      ; 0-based for hw
        Mov     ncxExt,Di               ; padded cxExt

        Jmp     source_accounted_for    ; converge below...

source_is_mono:

;/*
;**  Because the 8514/A aligns along nibble boundaries for mono
;**  sources the source must be shifted left or right to align it with the
;**  screen destination. Calculate the nibble phase difference between
;**  the destination and the source.
;*/

        Mov     Cl,Byte Ptr xDst        ; destination origin in x
        And     Cl,3                    ; bit # in destination nibble

        Mov     Al,Byte Ptr xSrc        ; source origin in x
        And     Al,3                    ; bit # in source word, zero hi byte

        Sub     Cl,Al                   ; phase difference between them
        And     Cl,3                    ; make left phasing look like right
        Mov     PhaseShift,Cl           ; save rotate count

;/*
;** Given the phase difference we can also precalculate the mask needed
;** for preserving bits to be pipelined to the next operation.
;*/

        Mov     Dl,0ffh                 ; precalculate masks also
        Shr     Dl,Cl                   ; 0s to high end,this is the ror mask
        Mov     RorMask,Dl              ; save for inner loop

;/*
;** The bottom-level operations conduct their operations as a left-edge
;** fetch/store, all center words fetch/store, right-edge fetch/store
;** series of operations. Depending on the situation, all, some, or just 1
;** of these operations may actually be executed.
;*/

        Mov     Dx,cxExt                ; width of blt in pixels
        Sub     Ch,Ch                   ; zext'ed phase difference

;/*
;**   Calculate # whole words to fetch for mono src. We adjust the starting
;**   destination origin left and destination extent upwards so that we may
;**   always fetch src pixels as words (ie: 16 pixels at a time) and write
;**   2 nibbles with one output to the board. Pixels written to the destination
;**   on the board which are to the left of the specified left of the destination
;**   rectangle are not actually written since the hw clip rectangle is set
;**   for the originally specified rectangle. The situation is similar for
;**   pixels written beyond the original right edge of the destination.
;**
;** Calculate the new destination left x origin. The amount of the adjustment
;** is determined by the number of pixels needed to bring the src left x origin
;** left to a word boundary. This amount must be calculated after the adjustment
;** for aligning to the destination nibble boundary is added in.
;*/

        Mov     Ax,xSrc                 ; src left edge x
        Mov     Bx,Ax                   ; need it later also
        And     Ax,15                   ; bit position in src word
        Add     Ax,Cx                   ; adjust for right phase shift
        Neg     Ax                      ; # pixels to adjust dest x by
        Add     Ax,xDst                 ; dest adj. for src word fetches
        And     Ax,XY_SIGNIFICANT       ; mask to just hw bits
        Mov     nxDst,Ax                ; save new left x for bottom level

;/*
;**  Calculate the # of whole src words which must be fetched for the extended
;**  scanline. This is determined by rounding the left side down to a word
;**  boundary and the right side up to the next word boundary. The # of pixels
;**  in between divided by 16 is the number of whole src words to be fetched.
;*/

        Mov     Ax,Bx                   ; src left edge x
        Add     Ax,Dx                   ; point to right edge x + 1
        And     Bx,Not 15               ; src left rounded down to word bdry
        Sub     Ax,Bx                   ; # pixels in extended scan
        Mov     Di,Ax                   ; need this later
        Add     Ax,15                   ; round up to word boundary
        Shr     Ax,4                    ; now # whole src words to fetch
        Mov     CenterWords,Ax          ; save for bottom level

;/*
;** Calculate the new extent of the scanline which is actually output to the
;** board. It will always be the number of pixels determined from the number
;** of whole src words to be fetched (this quantity times 16) plus the
;** pixels in any extra word which must be output because of overflow of
;** pipelined pixels into a next word.
;*/

        Mov     Ax,Di                   ; # pixels in extended scan
        Add     Ax,Cx                   ; adjust extent by phase shift
        Add     Ax,15                   ; round up to word boundary
        And     Ax,Not 15               ; now # pixels in adj extent
        Dec     Ax                      ; 0-based for hw
        Mov     ncxExt,Ax               ; save for bottom level

;/*
;**  Determine whether or not a final output of 4 nibbles must be done. This will
;**  occur if pipelined pixels overflow into a next word not accounted for by
;**  src word fetches. An extra src fetch must be avoided because of the
;**  possibility of GP faults if we access beyond the end of the src bitmap
;**  memory.
;*/

        Inc     Ax                      ; back to 1-based new x extent
        Shr     Ax,4                    ; # words in extent
        Cmp     Ax,CenterWords          ; equal to src word fetches ?
        Jbe     @F                      ; yes, no pipelined pixels...
        Or      BltFlags,PURGE_PIPELINE ; have to write pipelined pixels
@@:

source_accounted_for:

;/*
;** 0-base the width of the blts so that the bottom level doesn't have to
;** continually do this.
;*/

        Dec     cxExt                   ; 0-based width of blts

;/*
;**  Since our source and destination have already been pre-clipped we do not
;**  have to worry about GP faults locally or coordinate wrap on the board.
;**  Therefore, we set up the board clip rectangle here so that it need not
;**  be done anywhere in the loop.
;** 
;**  In addition, we can assume that we are always writing to/from all planes,
;**  since PM doesn't seem to utilize plane enable as a concept, and we do not
;**  use it in the blt. Therefore, go ahead and enable all planes for reading
;**  and / or writing.
;*/

        WaitQ   6                       ; set up scissor rectangle
        Mov     Ax,xDst                 ; min left x
        Or      Ah,High XMIN_2DECODE
        .errnz  Low XMIN_2DECODE
        outwQ   XMIN,Ax                 ; x clip bounds is clipped rect bounds
        And     Ah,Not (High DECODE_FIELD)
        .errnz  Low DECODE_FIELD
        Add     Ax,cxExt                ; max right x
        Or      Ah,High XMAX_2DECODE
        .errnz  Low XMAX_2DECODE
        outwQ   XMAX,Ax
        outwQ   YMIN,YMIN_2DECODE       ; min y is always 0
        Mov     Ax,BoardMaxY            ; max y is max addressable y
        Or      Ah,High YMAX_2DECODE
        .errnz  Low YMAX_2DECODE
        outwQ   YMAX,Ax
        Mov     Al,0ffh                 ; all planes enabled for r/w
        outbQ   READ_ENABLE,Al
        outbQ   WRITE_ENABLE,Al

;/*
;**  The OUTER loop -- we loop for the # of chunks that our blt has been
;**  split up into. We hope of course that the blt will be able to be done
;**  in one operation either because it is <= the height of our temporary
;**  blt buffer or because it doesn't require the use of the blt buffer.
;** 
;**  At this point the starting origin for both src and dest is contained in
;**  the locals, xSrc, ySrc, xDst, yDst. As we procede through
;**  the blt(s) we will update these origins to point to the next subblt
;**  origin in case there is a next blt.
;*/

bb_outer_lp:

        Mov     Bx,npBltOps             ; -> blt operations
        Mov     npCurBltOp,Bx           ; initialize -> operations

;/*
;**  The INNER loop -- we loop for the # of operations (ie: blts or solid
;**  fills) which must be performed for the current subblt. In the best
;**  case there will only be one operation (ie: s->d, ~d, etc...).
;*/

bb_inner_lp:

        Mov     Bx,npCurBltOp           ; get -> current operation to perform 
        Add     npCurBltOp,2            ; bump -> next operation code
        Mov     Bx,Cs:[Bx]              ; fetch current operation code

;/*
;** Set up some values here for the current atomic operation
;*/

        Mov     Dx,yDst                 ; assume going to actual destination

        Mov     Al,Bl                   ; isolate destination operand
        And     Al,TARGET_FIELD         ; target field only
        .errnz  High TARGET_FIELD
        Cmp     Al,DEST_TARGET          ; going to dest ?
        .errnz  High DEST_TARGET
        Je      @F                      ; yes...
        Mov     Dx,BltBufferY           ; use the temporary buffer
@@:
        Mov     cyDst,Dx                ; store current destination origin

;/*
;** Dispatch to the specialists based on source operand
;*/

        Mov     Si,Bx
        If      SRC_FIELD_SHIFT
        Shr     Si,SRC_FIELD_SHIFT
        Endif
        And     Si,SRC_FIELD            ; isolate src field bits
        Shl     Si,1                    ; offset into jump table
        Call    Cs:npSpecialists[Si]    ; specialist routine...

        Shl     Bx,1                    ; last operation ?
        Jnc     bb_inner_lp             ; no...

        Mov     Ax,BltHeight            ; the height of each blt band
        Mov     Cx,cyExt                ; get remaining cyExt
        Sub     Cx,Ax                   ; reduce remaining height by band height
        Jz      bb_bitblt_exit          ; no more blts remaining...

        Cmp     Cx,Ax                   ; full band to do yet ?
        Jae     @F                      ; yes...
        Mov     BltHeight,Cx            ; new blt height is remaining y extent
@@:     Mov     cyExt,Cx                ; store updated y extent of blts
        Mov     Dx,BltIncrement         ; +/- height depending on y++ or y--
        Add     ySrc,Dx                 ; update src y origin by increment
        Add     yDst,Dx                 ; update dest y origin by increment

        Jmp     Short bb_outer_lp       ; for all outstanding blt bands...

;/*
;** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;**     exit - leave BitBLT
;**
;**     Well, the BLT has been processed.  Restore the stack to its
;**     original status, restore the saved user registers, show no
;**     error, and return to the caller.
;**
;**     Entry:  None
;**
;**     Exit:   AX = 1
;**
;**     Uses:   All
;** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;*/

bb_bitblt_exit:

        mov     ax,1                    ;Clear out error register (good exit)
        errn$   bb_bitblt_exit_fail

;/*
;** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;**     bb_bitblt_exit_fail - exit because of failure
;**
;**     The BLT is exited.
;**
;**     Entry:  AX = error code (0 if error)
;** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
;*/

bb_bitblt_exit_fail:

        ReleaseScreen  boardblt         ; let the cursor do its thing
        Call    far_unexclude           ; remove any exclusion area

        mov     ax,BBRC_NORMAL          ;Want pass 2 if image data blt
        fw_zero <cx,ds,es>

cEnd    BoardBlt


;/*
;** Service routines
;*/

        include surface.blt             ;Surface preprocessing
        include pattern.blt             ;Pattern preprocessing
        include bbspec.blt              ; hw specialist routines

sEnd    Code

        public  bb_cursor_exclusion
        public  bb_cursor_exclusion_y
        public  bb_cursor_exclusion_union
        public  bb_cursor_exclusion_no_union
        public  bb_cursor_exclusion_do_it
        public  no_ovl_spelling
        public  source_is_dev_done
        public  source_is_local
        public  source_is_mono
        public  source_accounted_for
        public  bb_outer_lp
        public  bb_inner_lp
        public  bb_bitblt_exit
        public  bb_bitblt_exit_fail

        End
