;*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.;
;*****************************************************************************/
; NB. The comments in this file have not been fully updated to reflect
; 32bit register usage.
; In particular no use is made of fs: or gs: registers in flat model.

;-------------------------------------------------------------------------
;
;   Module          = FFBLTPX
;
;   Description     = 386 code for the software pattern expand blt
;                     operations in MESS. These correspond to calls
;                     made from the text code.
;
;   Functions       = eddf_MESSPatExp16
;                     eddf_MESSPatExp81
;                     eddf_MESSPatExp41
;                     eddf_MESSPatExp11
;                     eddf_MESSPatExpFg16
;                     eddf_MESSPatExpFg81
;                     eddf_MESSPatExpFg41
;                     eddf_MESSPatExpFg11
;
;
;-------------------------------------------------------------------------

INCL_GPIBITMAPS EQU     1
include os2.inc
include eddinclt.inc

; Include the XGA assembler include files and the MESS include files

include eddhcone.inc
include eddhtype.inc
include eddhmacr.inc

include eddfcone.inc
include eddfmacr.inc
include eddftype.inc

?DF     equ     1       ; we dont want _TEXT segment defined
include cmacros.inc

include rmacros.inc

include ffmacros.inc



;-------------------------------------------------------------------------




_DATA           segment use32 dword public 'DATA'                       ;**
                assume  cs:FLAT, ds:FLAT, es:FLAT

; Declare the external data elements we use
ifndef  _8514
externDP        ShadowXGARegs
else
include         8514.inc
externDP        Shadow8514Regs
endif
externDP        dstPixmap
externDP        patPixmap
externDP        messSpad


; Declare mix tables defined in eddffast.asm
; use extrn not externDP because these do NOT have an _ at the start
; of their names
extrn        mixTrashSourceAllDD  : FAR
extrn        mixTrashSourceAllBY  : FAR
extrn        mixTrashSourceAllDW  : FAR

_DATA           ends


;-------------------------------------------------------------------------





_TEXT           segment use32 dword public 'CODE'                       ;**
                assume  cs:FLAT, ds:FLAT, es:FLAT


; These functions are defined in eddffast.asm
externP eddf_MESSSetUpPatDest11



; Define the macros used by this module.

IF1



;;;****************************************************************
;;;
;;; 8514 Macros
;;;
;;; These are the counterparts to the XGA macros defined in the
;;; next section.  We have to duplicate this because MASM cannot
;;; handle IFDEFs inside a macro IF.
;;;
;;;****************************************************************

IFDEF _8514

; This macro does pattern expand operations for 4, 8, and 16 bits
; per pel, producing special case code for blts with fg overpaint and
; bg leavealone mixes.

; This macro is very similar to the patDest macro in ffbltpd.asm, but
; handles operations in the other direction and the special cases are
; different. (ffbltpd.asm is optimised for bitblt and scanlines, ffbltpx.asm
; is optimised for text.)

; See individual function headers for more details.

patExp macro mode, bpp
        local perLineLoop, perPelLoop, mixBgPel, mixCodeBase
        local getPatByte, morePattern, lineEnd, vertWrapPattern
        local copyPel, copyFgPel, leaveAloneBgPel, exit

; First check that the mode and bpp parameters are valid.
    ifdif <mode>, <mix>
     ifdif <mode>, <fg>
      .err
      %out patExp macro mode parameter must be "mix" or "fg".
     endif
    endif
    if (bpp ne 4) and (bpp ne 8) and (bpp ne 16) and (bpp ne 24)
     .err
     %out patExp macro bits per pel parameter must be 4, 8, 16, or 24 bpp.
    endif
; Now do the real code.

if bpp eq 4
        ; Work out the mask for the first pel.
rName ebx StartsOnOddPel
        mov     cl, byte ptr Shadow8514Regs.dest_map_x
        and     cl, 01h
        movzx   ebxStartsOnOddPel, cl
        shl     cl, 2
        mov     dl, 0F0h
        shr     dl, cl
        mov     _messSpad.startMask, dl
endif

        ; Work out the length of each blt line in bytes (ie how many times
        ; we will increment edi whilst doing each line).
rName edx BltLengthInBytes
        movzx   edxBltLengthInBytes, Shadow8514Regs.dim1
        inc     edxBltLengthInBytes
if bpp eq 24
        mov     eax,edxBltLengthInBytes
        shl     edxBltLengthInBytes, 1
        add     edxBltLengthInBytes,eax
endif
if bpp eq 16
        shl     edxBltLengthInBytes, 1
endif
if bpp eq 4
rFree ebx StartsOnOddPel
        add     edxBltLengthInBytes, ebx
        shr     edxBltLengthInBytes, 1
endif

        ; Set up the destination line increment.
rFree edx BltLengthInBytes
        movzx   eax, dstPixmap.xLen
        inc     eax
if bpp eq 24
        mov     ebx,eax
        shl     eax, 1
        add     eax,ebx
endif
if bpp eq 16
        shl     eax, 1
endif
if bpp eq 4
        shr     eax, 1
endif
        add     edx, eax
        neg     edx
        mov     _messSpad.dstLineInc, edx


        ; Work out the start address of the destination.
        movzx   edx, Shadow8514Regs.dest_map_y
        mul     edx
        movzx   edx, Shadow8514Regs.dest_map_x
if bpp eq 24
        mov     esi,edx
        shl     edx, 1
        add     edx,esi
endif
if bpp eq 16
        shl     edx, 1
endif
if bpp eq 4
        shr     edx, 1
endif
        add     eax, edx
        mov     edi, dstPixmap.startAddr
        add     edi, eax
rName edi DestIndex

        ; Now set up all the local variable values we can before we go
        ; into the main line loop.


        ; First work out the pattern pixmap width in bytes.
rName eax PatWidthInBytes
        movzx   eaxPatWidthInBytes, patPixmap.xLen
        shr     eaxPatWidthInBytes, 3
        inc     eaxPatWidthInBytes
        mov     patWidthInBytes, eaxPatWidthInBytes

        ; Get the pattern x start postion and work out how many bytes
        ; offset this corresponds to from the left edge of the pixmap.
rName ecx PatXInBytes
rName edx PatXInPels
        movzx   edxPatXInPels, Shadow8514Regs.patt_map_x
        mov     ecxPatXInBytes, edxPatXInPels
        shr     ecxPatXInBytes, 3

        ; Work out the offset of the first pel within the first byte
        ; of the pattern to be blted.
rFree edx PatXInPels
        and     dl, 07h
        mov     patBitOffsetOfFirstPel, dl


        ; Work out the the address of the first byte of the pattern
        ; to be blted.
rFree eax PatWidthInBytes
        movzx   edx, Shadow8514Regs.patt_map_y
        mul     edx
        add     eax, ecxPatXInBytes
        mov     esi, patPixmap.startAddr
        add     esi, eax
rName esi PattIndex
rFree ecx PatXInBytes

ifidn <mode>, <mix>
        ; Work out the address of the mix code to jump to for both
        ; foreground and background pels. (Note that if this operation
        ; is from BitBlt then the mixes will be the same, if it is from
        ; a scanLines operation then they may be different.)
        movzx   ebx, byte ptr Shadow8514Regs.Function_1
        and     ebx, FUNC_ALU
 if bpp eq 24
        mov     eax, dword ptr mixTrashSourceAllDD[ebx*4]
 else
 if bpp eq 16
        mov     eax, dword ptr mixTrashSourceAllDW[ebx*4]
 else
        mov     eax, dword ptr mixTrashSourceAllBY[ebx*4]
 endif
 endif
        add     eax, offset FLAT:mixCodeBase
        mov     fgMixJumpAddress, eax

        movzx   ebx, byte ptr Shadow8514Regs.Function_0
        and     ebx, FUNC_ALU

 if bpp eq 24
        mov     eax, dword ptr mixTrashSourceAllDD[ebx*4]
 else
 if bpp eq 16
        mov     eax, dword ptr mixTrashSourceAllDW[ebx*4]
 else
        mov     eax, dword ptr mixTrashSourceAllBY[ebx*4]
 endif
 endif
        add     eax, offset FLAT:mixCodeBase
        mov     bgMixJumpAddress, eax
endif ; ifidn <mode>, <mix>

if bpp eq 24
 ifidn <mode>, <fg>
        ; Get the fg colour into a register.
rName ebx FgCol
        mov     ebxFgCol, Shadow8514Regs.Color_1
 endif
endif

if bpp eq 16
 ifidn <mode>, <fg>
        ; Get the fg colour into a register.
rName bx FgCol
        mov     bxFgCol, Shadow8514Regs.Color_1
 endif
endif

if bpp eq 8
        ; Get the fg and bg colours into registers.
rName bl FgCol
        mov     blFgCol, byte ptr Shadow8514Regs.Color_1
 ifidn <mode>, <mix>
rName bh BgCol
        mov     bhBgCol, byte ptr Shadow8514Regs.Color_0
 endif
endif

if bpp eq 4
        ; Get a byte of foreground colour and a byte of background colour.
        mov     al, byte ptr Shadow8514Regs.Color_1
        mov     ah, al
        shl     al, 4
        shr     ax, 4
        mov     fgPels, al
 ifidn <mode>, <mix>
        mov     al, byte ptr Shadow8514Regs.Color_0
        mov     ah, al
        shl     al, 4
        shr     ax, 4
        mov     bgPels, al
 endif
endif

        ; Keep a copy of the source index at the start of the line.
        mov     patStartAddressOfThisLine, esiPattIndex

        ; Set up the per line loop counter.
        mov     ax, Shadow8514Regs.dim2
        inc     ax
        mov     lineLoopCount, ax

        ; Enter the per line loop.
perLineLoop:

if bpp eq 4
        ; Get the mask for the first pel from the scratch pad.
rName bl DestMask
rName bh DestMaskInv
        mov     blDestMask, _messSpad.startMask
        mov     bhDestMaskInv, blDestMask
        not     bhDestMaskInv
endif

        ; Get the first byte of pattern data for this line and set up our
        ; position index in dh if the pattern is more than one byte wide.
rName dl PattByte
rName dh PattBytePos
        mov     dlPattByte, [esiPattIndex]
        mov     dhPattBytePos, 01h

        ; Adjust the pattern byte to get the first pel in the msb.
        mov     cl, patBitOffsetOfFirstPel
        shl     dlPattByte, cl
        shl     dhPattBytePos, cl

        ; Set up the per pel loop.
rName cx PelLoopCount
        mov     cxPelLoopCount, Shadow8514Regs.dim1
        inc     cxPelLoopCount


perPelLoop:
if bpp eq 4
 ifidn <mode>, <mix>
        ; Store the per pel loop count in the top of ecx so that we
        ; can use cl as a store for a copy of the destination byte.
rFree cx PelLoopCount
        swap    ecx
rName ecx_top PelLoopCount
 endif
endif

ifidn <mode>, <mix>
        ; Pick up a pel from the destination.
 if bpp eq 24
        mov     eax, [ediDestIndex]
 endif
 if bpp eq 16
        mov     ax, [ediDestIndex]
 endif
 if bpp eq 8
        mov     al, [ediDestIndex]
 endif
 if bpp eq 4
        mov     al, [ediDestIndex]

        ; Keep a copy of the dest byte so that we can combine it with
        ; the mixed pel before writing it back to the pixmap.
rName cl DestByteCopy
        mov     clDestByteCopy, al
 endif ; if bpp eq 4
endif ; ifidn <mode>, <mix>

        ; Shift out the corresponding pattern bit into the carry flag.
        rol     dlPattByte, 1


ifidn <mode>, <mix>


        jnc     short mixBgPel

        ; This pel is foreground - get the foreground colour and mix it.
 if bpp eq 24
        mov     ebx, Shadow8514Regs.Color_1
 endif
 if bpp eq 16
        mov     bx, Shadow8514Regs.Color_1
 endif
 if bpp eq 8
        mov     ah, blFgCol
 endif
 if bpp eq 4
        mov     ah, fgPels
 endif
        jmp     fgMixJumpAddress

mixBgPel:
        ; This pel is background - get the background colour and mix it.
 if bpp eq 24
        mov     ebx, Shadow8514Regs.Color_0
 endif
 if bpp eq 16
        mov     bx, Shadow8514Regs.Color_0
 endif
 if bpp eq 8
        mov     ah, bhBgCol
 endif
 if bpp eq 4
        mov     ah, bgPels
 endif
        jmp     bgMixJumpAddress

mixCodeBase:
 if bpp eq 24
        mixTrashSourceAll       ebx, eax
 else
 if bpp eq 16
        mixTrashSourceAll       bx, ax
 else
        mixTrashSourceAll       ah, al
 endif
 endif

 if bpp eq 24
        ; Put the resulting pel back
        stos byte ptr [ediDestIndex]
        ror eax,8
        stos byte ptr [ediDestIndex]
        ror eax,8
        stos byte ptr [ediDestIndex]
 endif
 if bpp eq 16
        ; Put the resulting pel back
        stos word ptr [ediDestIndex]
 endif
 if bpp eq 8
        ; Put the resulting pel back
        stos byte ptr [ediDestIndex]
 endif


else  ; ifidn <mode>, <mix>


        jnc     short leaveAloneBgPel

 if bpp eq 24
        ; Put the resulting pel back
        ;@DMS fix ebx before mixing
        mov eax,ebxFgCol
        ror eax,16
        mov [ediDestIndex],al
        rol eax,8
        mov [ediDestIndex+1],al
        rol eax,8
        mov [ediDestIndex+2],al
 endif
 if bpp eq 16
        ; Copy a fg pel into the destination.
        mov     [ediDestIndex], bxFgCol
 endif
 if bpp eq 8
        ; Copy a fg pel into the destination.
        mov     [ediDestIndex], blFgCol
 endif
 if bpp eq 4
        ; Get the fg pel into al, and get the destination byte into ah
        ; so that we can combine them using the masks.
rName ah DestByteCopy
        mov     al, fgPels
        mov     ahDestByteCopy, [ediDestIndex]
 endif


endif ; ifidn <mode>, <mix> else


if bpp eq 4
        ; We must combine this pel with the other pel in the destination
        ; byte before we write back the byte back to the pixmap.
        and     al, blDestMask          ; get the mixed pel (or copied pel)
 ifidn <mode>, <mix>
rFree cl DestByteCopy
        and     cl, bhDestMaskInv       ; get the unaltered pel
        or      al, cl                  ; stir them together
 else
rFree ah DestByteCopy
        and     ah, bhDestMaskInv       ; get the unaltered pel
        or      al, ah                  ; stir them together
 endif
        mov     [ediDestIndex], al      ; write the result
endif

ifidn <mode>, <fg>
leaveAloneBgPel:

 if bpp eq 24
        ; Adjust edi ready for the next pel.
        add     ediDestIndex, 3
 endif

 if bpp eq 16
        ; Adjust edi ready for the next pel.
        add     ediDestIndex, 2
 endif
 if bpp eq 8
        ; Adjust edi ready for the next pel.
        inc     ediDestIndex
 endif
endif ; ifidn <mode>, <fg>

if bpp eq 4
        ; Adjust the masks and edi ready for the next pel.
        ror     bhDestMaskInv, 4        ; shift the masks
        ror     blDestMask, 4           ; this sets the carry 1/2 the time
        adc     ediDestIndex, 0         ; increment edi if carry set

 ifidn <mode>, <mix>
        ; Get back the per pel loop count.
rFree ecx_top PelLoopCount
        swap    ecx
rName cx PelLoopCount
 endif
endif ; if bpp eq 4

        ; Do we need to get a new pattern byte ?
        shl     dhPattBytePos, 1
        jc      short getPatByte

        ; More pels ?
        dec     cxPelLoopCount
        jnz     short perPelLoop
        jmp     short lineEnd

getPatByte:
        ; Need to fetch a new pattern byte
        inc     esiPattIndex
        mov     dlPattByte, [esiPattIndex]
        mov     dhPattBytePos, 01h

        ; More pels ?
        dec     cxPelLoopCount
if bpp eq 8
        jnz     short perPelLoop
else
ifidn <mode>, <mix>
        jnz     perPelLoop
else
        jnz     short perPelLoop
endif
endif


lineEnd:

        ; Go on to do the next line of the blt...

        ; Move the destination pointer to the start of the next blt line.
        add     ediDestIndex, _messSpad.dstLineInc

        ; Move the pattern up one line.
        mov     esiPattIndex, patStartAddressOfThisLine
        sub     esiPattIndex, patWidthInBytes
        mov     patStartAddressOfThisLine, esiPattIndex

        ; More lines ?
        dec     lineLoopCount
        jnz     perLineLoop


endm

ELSE

;;;****************************************************************
;;;
;;; XGA Macros
;;;
;;; These are the counterparts to the 8514 macros defined in the
;;; previous section.  We have to duplicate this because MASM cannot
;;; handle IFDEFs inside a macro IF.
;;;
;;;****************************************************************


; This macro does pattern expand operations for 4, 8, and 16 bits
; per pel, producing special case code for blts with fg overpaint and
; bg leavealone mixes.

; This macro is very similar to the patDest macro in ffbltpd.asm, but
; handles operations in the other direction and the special cases are
; different. (ffbltpd.asm is optimised for bitblt and scanlines, ffbltpx.asm
; is optimised for text.)

; See individual function headers for more details.

patExp macro mode, bpp
        local perLineLoop, perPelLoop, mixBgPel, mixCodeBase
        local getPatByte, morePattern, lineEnd, vertWrapPattern
        local copyPel, copyFgPel, leaveAloneBgPel, exit

; First check that the mode and bpp parameters are valid.
    ifdif <mode>, <mix>
     ifdif <mode>, <fg>
      .err
      %out patExp macro mode parameter must be "mix" or "fg".
     endif
    endif
    if (bpp ne 4) and (bpp ne 8) and (bpp ne 16)
     .err
     %out patExp macro bits per pel parameter must be 4, 8, or 16.
    endif
; Now do the real code.

if bpp eq 4
        ; Work out the mask for the first pel.
rName ebx StartsOnOddPel
        mov     cl, byte ptr ShadowXGARegs.dest_map_x
        and     cl, 01h
        movzx   ebxStartsOnOddPel, cl
        shl     cl, 2
        mov     dl, 0F0h
        shr     dl, cl
        mov     _messSpad.startMask, dl
endif

        ; Work out the length of each blt line in bytes (ie how many times
        ; we will increment edi whilst doing each line).
rName edx BltLengthInBytes
        movzx   edxBltLengthInBytes, ShadowXGARegs.dim1
        inc     edxBltLengthInBytes
if bpp eq 16
        shl     edxBltLengthInBytes, 1
endif
if bpp eq 4
rFree ebx StartsOnOddPel
        add     edxBltLengthInBytes, ebx
        shr     edxBltLengthInBytes, 1
endif

        ; Set up the destination line increment.
rFree edx BltLengthInBytes
        movzx   eax, dstPixmap.xLen
        inc     eax
if bpp eq 16
        shl     eax, 1
endif
if bpp eq 4
        shr     eax, 1
endif
        add     edx, eax
        neg     edx
        mov     _messSpad.dstLineInc, edx


        ; Work out the start address of the destination.
        movzx   edx, ShadowXGARegs.dest_map_y
        mul     edx
        movzx   edx, ShadowXGARegs.dest_map_x
if bpp eq 16
        shl     edx, 1
endif
if bpp eq 4
        shr     edx, 1
endif
        add     eax, edx
        mov     edi, dstPixmap.startAddr
        add     edi, eax
rName edi DestIndex

        ; Now set up all the local variable values we can before we go
        ; into the main line loop.


        ; First work out the pattern pixmap width in bytes.
rName eax PatWidthInBytes
        movzx   eaxPatWidthInBytes, patPixmap.xLen
        shr     eaxPatWidthInBytes, 3
        inc     eaxPatWidthInBytes
        mov     patWidthInBytes, eaxPatWidthInBytes

        ; Get the pattern x start postion and work out how many bytes
        ; offset this corresponds to from the left edge of the pixmap.
rName ecx PatXInBytes
rName edx PatXInPels
        movzx   edxPatXInPels, ShadowXGARegs.patt_map_x
        mov     ecxPatXInBytes, edxPatXInPels
        shr     ecxPatXInBytes, 3

        ; Work out the offset of the first pel within the first byte
        ; of the pattern to be blted.
rFree edx PatXInPels
        and     dl, 07h
        mov     patBitOffsetOfFirstPel, dl


        ; Work out the the address of the first byte of the pattern
        ; to be blted.
rFree eax PatWidthInBytes
        movzx   edx, ShadowXGARegs.patt_map_y
        mul     edx
        add     eax, ecxPatXInBytes
        mov     esi, patPixmap.startAddr
        add     esi, eax
rName esi PattIndex
rFree ecx PatXInBytes

ifidn <mode>, <mix>
        ; Work out the address of the mix code to jump to for both
        ; foreground and background pels. (Note that if this operation
        ; is from BitBlt then the mixes will be the same, if it is from
        ; a scanLines operation then they may be different.)
        movzx   ebx, byte ptr ShadowXGARegs.fg_mix
 if bpp eq 16
        mov     eax, dword ptr mixTrashSourceAllDW[ebx*4]
 else
        mov     eax, dword ptr mixTrashSourceAllBY[ebx*4]
 endif
        add     eax, offset FLAT:mixCodeBase
        mov     fgMixJumpAddress, eax

        movzx   ebx, byte ptr ShadowXGARegs.bg_mix
 if bpp eq 16
        mov     eax, dword ptr mixTrashSourceAllDW[ebx*4]
 else
        mov     eax, dword ptr mixTrashSourceAllBY[ebx*4]
 endif
        add     eax, offset FLAT:mixCodeBase
        mov     bgMixJumpAddress, eax
endif ; ifidn <mode>, <mix>

if bpp eq 16
 ifidn <mode>, <fg>
        ; Get the fg colour into a register.
rName bx FgCol
        mov     bxFgCol, ShadowXGARegs.fg_colour
 endif
endif

if bpp eq 8
        ; Get the fg and bg colours into registers.
rName bl FgCol
        mov     blFgCol, byte ptr ShadowXGARegs.fg_colour
 ifidn <mode>, <mix>
rName bh BgCol
        mov     bhBgCol, byte ptr ShadowXGARegs.bg_colour
 endif
endif

if bpp eq 4
        ; Get a byte of foreground colour and a byte of background colour.
        mov     al, byte ptr ShadowXGARegs.fg_colour
        mov     ah, al
        shl     al, 4
        shr     ax, 4
        mov     fgPels, al
 ifidn <mode>, <mix>
        mov     al, byte ptr ShadowXGARegs.bg_colour
        mov     ah, al
        shl     al, 4
        shr     ax, 4
        mov     bgPels, al
 endif
endif

        ; Keep a copy of the source index at the start of the line.
        mov     patStartAddressOfThisLine, esiPattIndex

        ; Set up the per line loop counter.
        mov     ax, ShadowXGARegs.dim2
        inc     ax
        mov     lineLoopCount, ax

        ; Enter the per line loop.
perLineLoop:

if bpp eq 4
        ; Get the mask for the first pel from the scratch pad.
rName bl DestMask
rName bh DestMaskInv
        mov     blDestMask, _messSpad.startMask
        mov     bhDestMaskInv, blDestMask
        not     bhDestMaskInv
endif

        ; Get the first byte of pattern data for this line and set up our
        ; position index in dh if the pattern is more than one byte wide.
rName dl PattByte
rName dh PattBytePos
        mov     dlPattByte, [esiPattIndex]
        mov     dhPattBytePos, 01h

        ; Adjust the pattern byte to get the first pel in the msb.
        mov     cl, patBitOffsetOfFirstPel
        shl     dlPattByte, cl
        shl     dhPattBytePos, cl

        ; Set up the per pel loop.
rName cx PelLoopCount
        mov     cxPelLoopCount, ShadowXGARegs.dim1
        inc     cxPelLoopCount


perPelLoop:
if bpp eq 4
 ifidn <mode>, <mix>
        ; Store the per pel loop count in the top of ecx so that we
        ; can use cl as a store for a copy of the destination byte.
rFree cx PelLoopCount
        swap    ecx
rName ecx_top PelLoopCount
 endif
endif

ifidn <mode>, <mix>
        ; Pick up a pel from the destination.
 if bpp eq 16
        mov     ax, [ediDestIndex]
 endif
 if bpp eq 8
        mov     al, [ediDestIndex]
 endif
 if bpp eq 4
        mov     al, [ediDestIndex]

        ; Keep a copy of the dest byte so that we can combine it with
        ; the mixed pel before writing it back to the pixmap.
rName cl DestByteCopy
        mov     clDestByteCopy, al
 endif ; if bpp eq 4
endif ; ifidn <mode>, <mix>

        ; Shift out the corresponding pattern bit into the carry flag.
        rol     dlPattByte, 1


ifidn <mode>, <mix>


        jnc     short mixBgPel

        ; This pel is foreground - get the foreground colour and mix it.
 if bpp eq 16
        mov     bx, ShadowXGARegs.fg_colour
 endif
 if bpp eq 8
        mov     ah, blFgCol
 endif
 if bpp eq 4
        mov     ah, fgPels
 endif
        jmp     fgMixJumpAddress

mixBgPel:
        ; This pel is background - get the background colour and mix it.
 if bpp eq 16
        mov     bx, ShadowXGARegs.bg_colour
 endif
 if bpp eq 8
        mov     ah, bhBgCol
 endif
 if bpp eq 4
        mov     ah, bgPels
 endif
        jmp     bgMixJumpAddress

mixCodeBase:
 if bpp eq 16
        mixTrashSourceAll       bx, ax
 else
        mixTrashSourceAll       ah, al
 endif

 if bpp eq 16
        ; Put the resulting pel back
        stos word ptr [ediDestIndex]
 endif
 if bpp eq 8
        ; Put the resulting pel back
        stos byte ptr [ediDestIndex]
 endif


else  ; ifidn <mode>, <mix>


        jnc     short leaveAloneBgPel

 if bpp eq 16
        ; Copy a fg pel into the destination.
        mov     [ediDestIndex], bxFgCol
 endif
 if bpp eq 8
        ; Copy a fg pel into the destination.
        mov     [ediDestIndex], blFgCol
 endif
 if bpp eq 4
        ; Get the fg pel into al, and get the destination byte into ah
        ; so that we can combine them using the masks.
rName ah DestByteCopy
        mov     al, fgPels
        mov     ahDestByteCopy, [ediDestIndex]
 endif


endif ; ifidn <mode>, <mix> else


if bpp eq 4
        ; We must combine this pel with the other pel in the destination
        ; byte before we write back the byte back to the pixmap.
        and     al, blDestMask          ; get the mixed pel (or copied pel)
 ifidn <mode>, <mix>
rFree cl DestByteCopy
        and     cl, bhDestMaskInv       ; get the unaltered pel
        or      al, cl                  ; stir them together
 else
rFree ah DestByteCopy
        and     ah, bhDestMaskInv       ; get the unaltered pel
        or      al, ah                  ; stir them together
 endif
        mov     [ediDestIndex], al      ; write the result
endif

ifidn <mode>, <fg>
leaveAloneBgPel:

 if bpp eq 16
        ; Adjust edi ready for the next pel.
        add     ediDestIndex, 2
 endif
 if bpp eq 8
        ; Adjust edi ready for the next pel.
        inc     ediDestIndex
 endif
endif ; ifidn <mode>, <fg>

if bpp eq 4
        ; Adjust the masks and edi ready for the next pel.
        ror     bhDestMaskInv, 4        ; shift the masks
        ror     blDestMask, 4           ; this sets the carry 1/2 the time
        adc     ediDestIndex, 0         ; increment edi if carry set

 ifidn <mode>, <mix>
        ; Get back the per pel loop count.
rFree ecx_top PelLoopCount
        swap    ecx
rName cx PelLoopCount
 endif
endif ; if bpp eq 4

        ; Do we need to get a new pattern byte ?
        shl     dhPattBytePos, 1
        jc      short getPatByte

        ; More pels ?
        dec     cxPelLoopCount
        jnz     short perPelLoop
        jmp     short lineEnd

getPatByte:
        ; Need to fetch a new pattern byte
        inc     esiPattIndex
        mov     dlPattByte, [esiPattIndex]
        mov     dhPattBytePos, 01h

        ; More pels ?
        dec     cxPelLoopCount
if bpp eq 8
        jnz     short perPelLoop
else
ifidn <mode>, <mix>
        jnz     perPelLoop
else
        jnz     short perPelLoop
endif
endif


lineEnd:

        ; Go on to do the next line of the blt...

        ; Move the destination pointer to the start of the next blt line.
        add     ediDestIndex, _messSpad.dstLineInc

        ; Move the pattern up one line.
        mov     esiPattIndex, patStartAddressOfThisLine
        sub     esiPattIndex, patWidthInBytes
        mov     patStartAddressOfThisLine, esiPattIndex

        ; More lines ?
        dec     lineLoopCount
        jnz     perLineLoop


endm


ENDIF ;;; XGA Version of Macros


ENDIF ; IF1


;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExp16
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bx      - foreground colour
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExp16, <PUBLIC>

        localW  lineLoopCount
        localD  fgMixJumpAddress
        localD  bgMixJumpAddress
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
        patExp mix 16
rEnd
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExp81
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - foreground colour
;       bh      - background colour
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExp81, <PUBLIC>

        localW  lineLoopCount
        localD  fgMixJumpAddress
        localD  bgMixJumpAddress
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
        patExp mix 8
rEnd
cEnd

ifdef   BPP24 
;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExp24
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - foreground colour
;       bh      - background colour
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExp24, <PUBLIC>

        localW  lineLoopCount
        localD  fgMixJumpAddress
        localD  bgMixJumpAddress
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
       ; int     3
        patExp mix 24
rEnd
cEnd
endif   ;BPP24 

;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExp41
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - leave destination mask
;       bh      - change destination mask
;       ecx.hi  - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExp41, <PUBLIC>

        localW  lineLoopCount
        localD  fgMixJumpAddress
        localD  bgMixJumpAddress
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel
        localB  fgPels
        localB  bgPels

cBegin
rStart
        patExp mix 4
rEnd
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExpFg16
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.   The foreground
; mix is overpaint, the background mix is leavealone
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExpFg16, <PUBLIC>

        localW  lineLoopCount
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
        patExp fg 16
rEnd
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExpFg81
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.   The foreground
; mix is overpaint, the background mix is leavealone
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExpFg81, <PUBLIC>

        localW  lineLoopCount
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
        patExp fg 8
rEnd
cEnd

ifdef   BPP24 
;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExpFg24
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.   The foreground
; mix is overpaint, the background mix is leavealone
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExpFg24, <PUBLIC>

        localW  lineLoopCount
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel

cBegin
rStart
        patExp fg 24
rEnd
cEnd
endif   ;BPP24 

;-------------------------------------------------------------------------
;
; Function: eddf_MESSPatExpFg41
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.  The foreground mix is
; overpaint, the background one is leavealone.
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - leave destination mask
;       bh      - change destination mask
;       cx      - pel loop counter
;       dl      - byte of pattern data
;       dh      - pattern position data
;       edi     - destination position
;       esi     - pattern position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExpFg41, <PUBLIC>

        localW  lineLoopCount
        localD  patWidthInBytes
        localD  patStartAddressOfThisLine
        localB  patBitOffsetOfFirstPel
        localB  fgPels

cBegin
rStart
        patExp fg 4
rEnd
cEnd


;-------------------------------------------------------------------------
; Function: eddf_MESSPatExp11
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.  Because the
; the destination is 1,1 then its not very efficient to do this pel by
; pel.  Instead we will do it a byte at a time so that it will look
; suspiciously like a srcdest11 operation.  Unfortunately we also have
; to cope with different foreground and background mixes.  The sequence
; of operations to do this is..
;
;   Get a correctly aligned byte of pattern data
;   From this get a correctly aligned byte of source data
;   Apply fg mix to source and destination -> fg result
;   Apply bg mix to source and destination -> bg result
;   pattern byte AND fg result -> fg pels
;   NOT(pattern byte) AND bg result -> bg pels
;   fg pels OR bg pels -> result
;   Put result into destination (using start or end mask if necessary)
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - pattern byte
;       bh      - NOT(pattern byte)
;       ecx.lo  - srcToDestShift (cl)
;       ecx.hi  - lines loop counter
;       dx      - byte loop counter
;       es:di   - destination position
;       fs:si   - pattern/source position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExp11, <PUBLIC>                                     ;**

        localD  fgStartMixOffset        ; the offsets for mixing        ;**
        localD  fgFullMixOffset                                         ;**
        localD  fgEndMixOffset                                          ;**
        localD  bgStartMixOffset                                        ;**
        localD  bgFullMixOffset                                         ;**
        localD  bgEndMixOffset                                          ;**
        localB  srcInvertMask           ; see below
        localW  startMasks
        localW  endMasks

        ; srcInvertMask -
        ;   Either 00 or FF.  Xor'ing this with pattern gives us the source

        ; startMasks -
        ;   startMask and ~startMask

        ; endMasks -
        ;   endMask and ~endMask

cBegin
        cCall   eddf_MESSSetUpPatDest11

        ; Work out whether we need to invert the pattern to get the source.
        ; If the foreground colour is 1 then we do.
        ifndef _8514
        mov     ax, ShadowXGARegs.fg_colour
        else
        mov     ax, Shadow8514Regs.Color_1
        endif
        and     al, 01h
        xor     al, 01h
        mov     ah, 00h
        sub     ah, al
        mov     srcInvertMask, ah

        ; Now work out all the offsets
IFDEF _8514
        movzx   ebx, byte ptr Shadow8514Regs.Function_1                 ;**
        and     ebx, FUNC_ALU
ELSE
        movzx   ebx, byte ptr ShadowXGARegs.fg_mix                      ;**
ENDIF
        mov     edx, dword ptr [mixTrashSourceAllBY+ebx*4]              ;**

        mov     eax, offset FLAT:fgStartMixBasePE11                          ;**
        add     eax, edx                                                ;**
        mov     fgStartMixOffset, eax                                   ;**

        mov     eax, offset FLAT:fgFullMixBasePE11                           ;**
        add     eax, edx                                                ;**
        mov     fgFullMixOffset, eax                                    ;**

        mov     eax, offset FLAT:fgEndMixBasePE11                            ;**
        add     eax, edx                                                ;**
        mov     fgEndMixOffset, eax                                     ;**

IFDEF _8514
        mov     bl, Shadow8514Regs.Function_0
        and     bl, FUNC_ALU
ELSE
        mov     bl, ShadowXGARegs.bg_mix
ENDIF
        mov     edx, dword ptr [mixTrashSourceAllBY+ebx*4]              ;**

        mov     eax, offset FLAT:bgStartMixBasePE11                          ;**
        add     eax, edx                                                ;**
        mov     bgStartMixOffset, eax                                   ;**

        mov     eax, offset FLAT:bgFullMixBasePE11                           ;**
        add     eax, edx                                                ;**
        mov     bgFullMixOffset, eax                                    ;**

        mov     eax, offset FLAT:bgEndMixBasePE11                            ;**
        add     eax, edx                                                ;**
        mov     bgEndMixOffset, eax                                     ;**

        ; Now set up ebx with all those masks which we need
        mov     bl, _messSpad.endMask
        mov     bh, bl
        not     bh
        mov     endMasks, bx
        mov     bl, _messSpad.startMask
        mov     bh, bl
        not     bh
        mov     startMasks, bx

        ; And get the shift count into cl
        mov     cl, _messSpad.srcToDestShift
        swap    ecx

        ; Set up loop counter
IFDEF _8514
        mov     cx, Shadow8514Regs.dim2
ELSE
        mov     cx, ShadowXGARegs.dim2
ENDIF
        inc     cx

perLineLoopPE11:
        swap    ecx
        mov     dx, word ptr _messSpad.totalBytes

        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     bl, al                  ; save it
        mov     bh, al                  ; save NOT(pattern)
        not     bh
        xor     al, srcInvertMask       ; get source byte

        mov     ah, [edi]               ; get destination               ;**
        push    ax                      ; save source and destination

        jmp     fgStartMixOffset        ; do the foreground mix

fgStartMixBasePE11:
        mixTrashSourceAll       al, ah

        mov     ch, ah                  ; save result of foreground mix
        pop     ax                      ; get source and destination back

        jmp     bgStartMixOffset        ; do the background mix

bgStartMixBasePE11:
        mixTrashSourceAll       al, ah

        ; fg mix result is in ch
        ; bg mix result is in ah
        and     ch, bl                  ; get foreground pels
        and     ah, bh                  ; get background pels
        or      ah, ch                  ; squidge them together

        mov     bx, startMasks
        mov     ch, [edi]               ; get original destination      ;**
        and     ch, bh                  ; save some pels from it
        and     ah, bl                  ; get some pels from the source
        or      ah, ch                  ; merge them together
        mov     [edi], ah               ; write them out - see its easy ;**

        inc     esi                     ; bump pointers                 ;**
        inc     edi

        dec     dx
        jz      loopDonePE11

        dec     dx
        jz      endMaskPE11

        ; dx is the number of bytes to do
pelLoopPE11:
        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     bl, al                  ; save it
        mov     bh, al                  ; save NOT(pattern)
        not     bh
        xor     al, srcInvertMask       ; get source byte

        mov     ah, [edi]               ; get destination               ;**
        push    ax                      ; save source and destination

        jmp     fgFullMixOffset         ; do the foreground mix

fgFullMixBasePE11:
        mixTrashSourceAll       al, ah

        mov     ch, ah                  ; save result of foreground mix
        pop     ax                      ; get source and destination back

        jmp     bgFullMixOffset         ; do the background mix

bgFullMixBasePE11:
        mixTrashSourceAll       al, ah

        ; fg mix result is in ch
        ; bg mix result is in ah
        and     ch, bl                  ; get foreground pels
        and     ah, bh                  ; get background pels
        or      ah, ch                  ; cleave them together (look it up)

        mov     [edi], ah               ; write result                  ;**

        inc     esi                     ; bump pointers                 ;**
        inc     edi                                                     ;**

        dec     dx
        jnz     pelLoopPE11

endMaskPE11:
        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     bl, al                  ; save it
        mov     bh, al                  ; save NOT(pattern)
        not     bh
        xor     al, srcInvertMask       ; get source byte

        mov     ah, [edi]               ; get destination               ;**
        push    ax                      ; save source and destination

        jmp     fgEndMixOffset          ; do the foreground mix

fgEndMixBasePE11:
        mixTrashSourceAll       al, ah

        mov     ch, ah                  ; save result of foreground mix
        pop     ax                      ; get source and destination back

        jmp     bgEndMixOffset          ; do the background mix

bgEndMixBasePE11:
        mixTrashSourceAll       al, ah

        ; fg mix result is in ch
        ; bg mix result is in ah
        and     ch, bl                  ; get foreground pels
        and     ah, bh                  ; get background pels
        or      ah, ch                  ; mingle them together

        mov     bx, endMasks
        mov     ch, [edi]               ; get original destination      ;**
        and     ch, bh                  ; save some pels from it
        and     ah, bl                  ; get some pels from the source
        or      ah, ch                  ; merge them together
        mov     [edi], ah               ; write them out                ;**

        inc     esi                     ; bump pointers
        inc     edi

loopDonePE11:
        add     edi, _messSpad.dstLineInc     ; move to next line        ;**
        add     esi, _messSpad.srcLineInc                                ;**

        ; More lines ?
        swap    ecx
        dec     cx
        jnz     perLineLoopPE11

cEnd


;-------------------------------------------------------------------------
; Function: eddf_MESSPatExpFg11
;
; This is a pattern expansion (used for text).  It will always start
; from the bottom-left and proceed to the top-right.  Because the
; the destination is 1,1 then its not very efficient to do this pel by
; pel.  Instead we will do it a byte at a time so that it will look
; suspiciously like a srcdest11 operation.
;
;   Get a correctly aligned byte of pattern data
;   From this get a correctly aligned byte of source data
;   pattern byte AND source byte -> fg pels
;   NOT(pattern byte) AND destination byte -> bg pels
;   fg pels OR bg pels -> result
;   Put result into destination
;
; Parameters:
;       ShadowXGARegs, _messSpad, pixmap structures
;
; Returns:
;       None
;
; Internally:
;       bl      - endMask
;       bh      - startMask
;       ecx.lo  - srcToDestShift (cl)
;       ecx.hi  - lines loop counter
;       dx      - byte loop counter
;       es:di   - destination position
;       fs:si   - pattern/source position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSPatExpFg11, <PUBLIC>                                   ;**

        localB  srcInvertMask

        ; srcInvertMask -
        ;   Either 00 or FF.  Xor'ing this with pattern gives us the source

cBegin
        cCall   eddf_MESSSetUpPatDest11

        ; Work out whether we need to invert the pattern to get the source.
        ; If the foreground colour is 0 then we do.
IFDEF _8514
        mov     ax, Shadow8514Regs.Color_1
ELSE
        mov     ax, ShadowXGARegs.fg_colour
ENDIF
        and     al, 01h
        xor     al, 01h
        mov     ah, 00h
        sub     ah, al
        mov     srcInvertMask, ah

        ; Now set up ebx with all those masks which we need
        mov     bl, _messSpad.endMask
        mov     bh, _messSpad.startMask

        ; And get the shift count into cl
        mov     cl, _messSpad.srcToDestShift
        swap    ecx

IFDEF _8514
        mov     cx, Shadow8514Regs.dim2
ELSE
        mov     cx, ShadowXGARegs.dim2
ENDIF
        inc     cx

perLineLoopPEF11:
        swap    ecx
        mov     dx, word ptr _messSpad.totalBytes

        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     ch, al
        xor     ch, srcInvertMask       ; get source byte -> fg pels
        and     al, bh                  ; pattern AND start mask -> write mask
        and     ch, al                  ; fg pels AND write mask -> write pels
        mov     ah, [edi]               ; get dst                       ;**
        not     al
        and     ah, al                  ; dst AND NOT(write mask) -> keep pels
        or      ah, ch                  ; write pels OR keep pels
        mov     [edi], ah               ; result written to destination ;**

        inc     esi                     ; bump pointers                 ;**
        inc     edi

        dec     dx
        jz      short loopDonePEF11

        dec     dx
        jz      short endMaskPEF11

        ; dx is the number of bytes to do
pelLoopPEF11:

        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     ch, al
        xor     ch, srcInvertMask       ; get source byte -> fg pels
        and     ch, al                  ; source AND pattern -> fg pels
        mov     ah, [edi]               ; get dst                       ;**
        not     al
        and     ah, al                  ; dst AND NOT(pattern) -> keep pels
        or      ah, ch                  ; fg pels OR keep pels -> result
        mov     [edi], ah               ; write result                  ;**

        inc     esi                     ; bump pointers                 ;**
        inc     edi                                                     ;**

        dec     dx
        jnz     pelLoopPEF11

endMaskPEF11:
        mov     ax, [esi]               ; get pattern byte              ;**
        rol     ax, cl                  ; align it
        mov     ch, al
        xor     ch, srcInvertMask       ; get source byte -> fg pels
        and     al, bl                  ; pattern AND end mask -> write mask
        and     ch, al                  ; fg pels AND write mask -> write pels
        mov     ah, [edi]               ; get dst                       ;**
        not     al
        and     ah, al                  ; dst AND NOT(write mask) -> keep pels
        or      ah, ch                  ; write pels OR keep pels
        mov     [edi], ah               ; result written to destination ;**

        inc     esi                     ; bump pointers                 ;**
        inc     edi                                                     ;**

loopDonePEF11:
        add     edi, _messSpad.dstLineInc     ; next line                ;**
        add     esi, _messSpad.srcLineInc                                ;**

        ; More lines ?
        swap    ecx
        dec     cx
        jnz     perLineLoopPEF11

cEnd


_TEXT ends


END
