;*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.;
;*****************************************************************************/
;-------------------------------------------------------------------------
;
;   Module          = FFBLTD
;
;   Description     = 386 code for the software destination only blt
;                     operations in MESS.
;
;   Functions       = eddf_MESSBlockFill81
;                     eddf_MESSBlockFill16
;                     eddf_MESSBlockFill4111
;                     eddf_MESSFixedSrc81
;                     eddf_MESSFixedSrc16
;                     eddf_MESSFixedSrc4111
;
;
;-------------------------------------------------------------------------

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

IFDEF _8514
include 8514.inc
ENDIF



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




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

; Declare the external data elements we use
IFDEF _8514
externDP        Shadow8514Regs
ELSE
externDP        ShadowXGARegs
ENDIF
externDP        dstPixmap
ifdef   BPP24
externDP        patPixmap
endif
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        mixKeepSourcePartBY  : FAR
extrn        mixKeepSourcePartDW  : FAR

_DATA           ends


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





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


; These functions are defined in ffbltset.asm
externP eddf_MESSSetUpDest11
externP eddf_MESSSetUpDest41
externP eddf_MESSSetUpDest81
externP eddf_MESSSetUpDest16
ifdef   BPP24
externP eddf_MESSSetUpDest24
endif

IF1

;Define macros used in this module.

;;;******************************************************************
;;;
;;; 8514 Version of DestOnly.  Two separate versions are necessary
;;; because MASM is stupid.  It can't deal with IFDEFs located inside
;;; a macro.  Hence, 200+ lines of code must exist in two forms.
;;;
;;;
;;; @DMS 24 bpp case is a kludge on the 8bpp case !!!
;;;
;;;******************************************************************
IFDEF _8514

DestOnly macro mode, bpp
        local gotSourcePels, lineLoop, finishedLine, getOneBppPels
        local oneBpp, dwordLoop, dwordLoopEnd, byteLoop, byteLoopEnd
        local wordLoop, wordLoopEnd, dwordMixCodeBase, byteMixCodeBase
        local wordMixCodeBase, firstByteMixCodeBase, lastByteMixCodeBase

; Check that macro parameters are valid.
ifdif <mode>, <mix>
 ifdif <mode>, <copy>
  .err
  %out DestOnly macro mode parameter must be "mix" or "copy".
 endif
endif
if (bpp ne 16) and (bpp ne 8) and (bpp ne 4111) and (bpp ne 24)
 .err
 %out DestOnly macro bits per pel parameter must be 4111, 8, 16 or 24.
endif

        ; We will use rmacros to help police register usage.
rStart

        ; Need to set up the direction, increments and start positions
        ; for the blt and the destination width in bytes.
if bpp eq 24
        cCall   eddf_MESSSetUpDest24
endif
if bpp eq 16
        cCall   eddf_MESSSetUpDest16
endif
if bpp eq 8
        cCall   eddf_MESSSetUpDest81
endif
if bpp eq 4111
        test    byte ptr dstPixmap.format, FOUR_BPP
        jz      short oneBpp
        cCall   eddf_MESSSetUpDest41
        jmp     short @F
oneBpp:
        cCall   eddf_MESSSetUpDest11
@@:
endif
rName edi DestIndex


        ; First get the length of each blt in bytes into eax.
rName eax  ByteLength
if bpp eq 4111
        mov     eaxByteLength, _messSPad.totalBytes
else
        movzx   eaxByteLength, Shadow8514Regs.dim1
        inc     eaxByteLength
if bpp eq 16
        shl     eaxByteLength, 1
endif
endif

        ; Work out how many complete dwords there are in each line
        ; (byteLength/4).

        ; At 4bpp or 1bpp we must handle the first and last bytes
        ; specially using the start and end masks. We must take this
        ; into account here. We will use the sequence of sub 2, adc 0.
        ; This will subtract 2, but if the result is negative then it
        ; will add 1 back on. This ensures that we never get a negative
        ; result (byteLength is at least 1).
useCompleteDwordsReg = TRUE
rName edx CompleteDwords
if bpp eq 24    ; 24bpp will do bytes
        mov     edxCompleteDwords, eaxByteLength
else
        mov     edxCompleteDwords, eaxByteLength
if bpp eq 4111
        sub     edxCompleteDwords, 2    ; Special case 2 bytes...
        adc     edxCompleteDwords, 0    ; ...unless there is only one.
endif
        shr     edxCompleteDwords, 2

if bpp eq 16
        ; Work out how many stray words there are in each line (byteLength/2%2)
rName esi StrayWords
        mov     esiStrayWords, eaxByteLength
        shr     esiStrayWords, 1
        and     esiStrayWords, 01h
else
        ; Work out how many stray bytes there are in each line (byteLength%4)
rName esi StrayBytes
 if bpp ne 4111
        mov     esiStrayBytes, eaxByteLength
        and     esiStrayBytes, 03h
 else
        ; The number of stray bytes will be the number of bytes which are
        ; not done by the dword loop. This will be between 1 and 5. The
        ; first and last bytes are done as special cases, the remaining
        ; bytes (up to 3) are done by a rep stos byte instruction.
        mov     esiStrayBytes, eaxByteLength
        sub     esiStrayBytes, 2        ; Special case 2 bytes...
        adc     esiStrayBytes, 0        ; ...unless there is only one.
        and     esiStrayBytes, 03h      ; Bytes left not done as dwords.
        add     esiStrayBytes, 2        ; Add the 2 special cased bytes...
        cmp     eaxByteLength, 2        ; ...but adjust if there is only
        sbb     esiStrayBytes, 0        ; one byte on each line.
 endif ; if bpp ne 4111 else
endif ; if bpp eq 16 else
endif; ne 24bpp
rFree eax ByteLength


ifidn <mode>, <mix>
        ; Work out the addresses of the mix code to jump to.

        ; First get the offsets within each mix code block.
        movzx   ebx, byte ptr Shadow8514Regs.Function_1
        and     ebx, FUNC_ALU
        mov     eax, dword ptr [mixKeepSourcePartDW+ebx*4]
        if bpp ne 24
        mov     ebx, dword ptr [mixKeepSourcePartBY+ebx*4]
        endif

        ; Now add to the start addresses of the mix blocks.
        add     eax, offset FLAT:dwordMixCodeBase
        mov     dwordMixJumpAddress, eax

if bpp eq 4111
        mov     eax, ebx
        add     eax, offset FLAT:firstByteMixCodeBase
        mov     firstByteMixJumpAddress, eax
        mov     eax, ebx
        add     eax, offset FLAT:lastByteMixCodeBase
        mov     lastByteMixJumpAddress, eax
endif
if bpp eq 16
        add     ebx, offset FLAT:wordMixCodeBase
        mov     wordMixJumpAddress, ebx
else
if bpp ne 24
        add     ebx, offset FLAT:byteMixCodeBase
        mov     byteMixJumpAddress, ebx
endif
endif
endif ; idn <mode>, <mix>

if bpp eq 24
        ; Get two pels worth of source in eax.
        mov     eax, _messSPad.srcColour
endif
if bpp eq 16
        ; Get two pels worth of source in eax.
        mov     ax, _messSPad.srcColour
        shl     eax, 16
        mov     ax, _messSPad.srcColour
endif
if bpp eq 8
        ; Get four pels worth of source into eax.
        mov     al, byte ptr _messSPad.srcColour
        mov     ah, al
        mov     cx, ax
        shl     eax, 16
        mov     ax, cx
endif
if bpp eq 4111
        ; Fill eax with 8 pels (if 4 bpp) or 32 pels (if 1bbp) of source.
        test    byte ptr dstPixmap.format, FOUR_BPP
        jz      short getOneBppPels

        ; Fill eax with the correct fill value (ie. 8 pels worth)
        mov     al, byte ptr _messSPad.srcColour
        mov     ah, al
        shl     al, 4
        shl     ax, 4
        mov     al, ah
        mov     cx, ax
        shl     eax, 16
        mov     ax, cx
        jmp     short gotSourcePels

getOneBppPels:
        ; Work out what to fill with - either all 1s or all 0s
        mov     bl, byte ptr _messSPad.srcColour
        and     ebx, 01h
        xor     eax, eax        ; eax is now zero
        sub     eax, ebx        ; eax is now zero or minus one
endif
gotSourcePels:
rName eax SourcePels

        ; Now set up a loop to do each row in the operation
useLineLoopReg = TRUE
rName ebx LineLoopCount
        movzx   ebxLineLoopCount, Shadow8514Regs.dim2
        inc     ebxLineLoopCount

if bpp eq 4111
useLineLoopReg = FALSE
        mov     lineLoopCount, ebxLineLoopCount
rFree ebx LineLoopCount

        ; Get the start and end masks (and their inverses) into ebx.
        .erre startMaskInv eq startMask + 1
        .erre endMask eq startMaskInv + 1
        .erre endMaskInv eq endMask + 1
        mov     ebx, dword ptr _messSPad.startMask
        ; ebx is:
        ;  31             23           15               7            0
        ; | end mask inv |  end mask  | start mask inv |  start mask  |
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv
endif

ifidn <mode>, <mix>
useCompleteDwordsReg = FALSE
        mov     completeDwordsCount, edxCompleteDwords
rFree edx CompleteDwords

        ; Move the source pels into edx so we can use edx and eax when mixing
        ; the pels, and eax when reading and writing the pels (using stos).
        mov     edx, eaxSourcePels
rFree eax SourcePels
rName edx SourcePels

endif ; ifidn <mode>, <mix>


lineLoop:
if bpp eq 16
        ; Do the stray words (this will be between 0 and 1).
        mov     ecx, esiStrayWords
ifidn <mode>, <copy>
        rep stos word ptr [ediDestIndex]
else
        jecxz   wordLoopEnd
wordLoop:
        mov     ax, [ediDestIndex]
        jmp     wordMixJumpAddress

wordMixCodeBase:
        ; Do as dwords anyway and don't worry about what is in
        ; the top half of the registers.
        mixKeepSourcePart       edxSourcePels, eax

        stos    word ptr [ediDestIndex]
wordLoopEnd:
endif ; idn <mode>, <copy> else
endif ; bpp eq 16

if bpp eq 8
        ; Do the stray bytes (this will be between 0 and 3).
        mov     ecx, esiStrayBytes
ifidn <mode>, <copy>
        rep stos byte ptr [ediDestIndex]
else
        jecxz    byteLoopEnd
byteLoop:
        mov     al, [ediDestIndex]
        jmp     byteMixJumpAddress

byteMixCodeBase:
        mixKeepSourcePart       dlPartOfSourcePels, al

        stos    byte ptr [ediDestIndex]
        dec     ecx
        jnz     byteLoop
byteLoopEnd:
endif ; idn <mode>, <copy> else
endif ; if bpp eq 8

if bpp eq 4111
        ; Do the first byte using the start masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
ifidn <mode>, <copy>
        mov     cl, alPartOfSourcePels  ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     firstByteMixJumpAddress ; the destination pel.
firstByteMixCodeBase:
        mixKeepSourcePart dlPartOfSourcePels, cl
endif
        and     ch, bhStartMaskInv      ; Mask out pels to be changed.
        and     cl, blStartMask         ; Mask out pels not to be changed.
        or      ch, cl                  ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.
        inc     ediDestIndex            ; Update destination address.

        ; See if the line is more than one byte wide.
        mov     ecx, esiStrayBytes
        dec     ecx
        jz      finishedLine

        ; Do all but the last stray byte.
        dec     ecx
ifidn <mode>, <copy>
        rep stos byte ptr [ediDestIndex]
else
        jecxz    byteLoopEnd
byteLoop:
        mov     al, [ediDestIndex]
        jmp     byteMixJumpAddress

byteMixCodeBase:
        mixKeepSourcePart       dlPartOfSourcePels, al

        stos    byte ptr [ediDestIndex]
        dec     ecx
        jnz     byteLoop
byteLoopEnd:
endif ; idn <mode>, <copy> else
endif ; if bpp eq 4111

        ; Set up ecx to do whole dwords and do them
if useCompleteDwordsReg eq TRUE
        mov     ecx, edxCompleteDwords
else
        mov     ecx, completeDwordsCount
endif

ifidn <mode>, <copy>
        if bpp eq 24
@@:
        ror     eaxSourcePels,16
        stos byte ptr [ediDestIndex]
        rol     eaxSourcePels,8
        stos byte ptr [ediDestIndex]
        rol     eaxSourcePels,8
        stos byte ptr [ediDestIndex]
        loop    @b
        else
        rep stos dword ptr [ediDestIndex]
        endif
else
        jecxz   dwordLoopEnd
dwordLoop:
        mov     eax, [ediDestIndex]
        jmp     dwordMixJumpAddress

dwordMixCodeBase:
        mixKeepSourcePart       edxSourcePels, eax

        if bpp eq 24
        ror     eax,16
        stos byte ptr [ediDestIndex]
        rol     eax,8
        stos byte ptr [ediDestIndex]
        rol     eax,8
        stos byte ptr [ediDestIndex]
        else
        stos dword ptr [ediDestIndex]
        endif
        dec     ecx
        jnz     dwordLoop
dwordLoopEnd:
endif ; idn <mode>, <copy> else

if bpp eq 4111
        ; Get the end masks from the top of ebx.
rFree bl StartMask
rFree bh StartMaskInv
rFree ebx_top EndMaskAndInv
        swap    ebx
rName bl EndMask
rName bh EndMaskInv
rName ebx_top StartMaskAndInv

        ; Do the last byte using the end masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
ifidn <mode>, <copy>
        mov     cl, alPartOfSourcePels  ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     lastByteMixJumpAddress  ; the destination pel.
lastByteMixCodeBase:
        mixKeepSourcePart dlPartOfSourcePels, cl
endif
        and     ch, bhEndMaskInv        ; Mask out pels to be changed.
        and     cl, blEndMask           ; Mask out pels not be to changed.
        or      ch , cl                 ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.
        inc     ediDestIndex            ; Update destination address.

        ; Put the end masks back in the top of ebx.
rFree bl EndMask
rFree bh EndMaskInv
rFree ebx_top StartMaskAndInv
        swap    ebx
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv

endif

finishedLine:
        ; Apply the destination increment
        add     ediDestIndex, _messSPad.dstLineInc

        ; Go back and do the rest of the blt lines.
if useLineLoopReg eq TRUE
        dec     ebxLineLoopCount
else
        dec     lineLoopCount
endif
        jnz     lineLoop


rEnd

endm

      ;;;**************************************
ELSE  ;;; XGA Version of DestOnly Macro
      ;;;**************************************

DestOnly macro mode, bpp
        local gotSourcePels, lineLoop, finishedLine, getOneBppPels
        local oneBpp, dwordLoop, dwordLoopEnd, byteLoop, byteLoopEnd
        local wordLoop, wordLoopEnd, dwordMixCodeBase, byteMixCodeBase
        local wordMixCodeBase, firstByteMixCodeBase, lastByteMixCodeBase

; Check that macro parameters are valid.
ifdif <mode>, <mix>
 ifdif <mode>, <copy>
  .err
  %out DestOnly macro mode parameter must be "mix" or "copy".
 endif
endif
if (bpp ne 16) and (bpp ne 8) and (bpp ne 4111)
 .err
 %out DestOnly macro bits per pel parameter must be 4111, 8, or 16.
endif

        ; We will use rmacros to help police register usage.
rStart

        ; Need to set up the direction, increments and start positions
        ; for the blt and the destination width in bytes.
if bpp eq 16
        cCall   eddf_MESSSetUpDest16
endif
if bpp eq 8
        cCall   eddf_MESSSetUpDest81
endif
if bpp eq 4111
        test    byte ptr dstPixmap.format, FOUR_BPP
        jz      short oneBpp
        cCall   eddf_MESSSetUpDest41
        jmp     short @F
oneBpp:
        cCall   eddf_MESSSetUpDest11
@@:
endif
rName edi DestIndex


        ; First get the length of each blt in bytes into eax.
rName eax  ByteLength
if bpp eq 4111
        mov     eaxByteLength, _messSPad.totalBytes
else
        movzx   eaxByteLength, ShadowXGARegs.dim1
        inc     eaxByteLength
if bpp eq 16
        shl     eaxByteLength, 1
endif
endif

        ; Work out how many complete dwords there are in each line
        ; (byteLength/4).

        ; At 4bpp or 1bpp we must handle the first and last bytes
        ; specially using the start and end masks. We must take this
        ; into account here. We will use the sequence of sub 2, adc 0.
        ; This will subtract 2, but if the result is negative then it
        ; will add 1 back on. This ensures that we never get a negative
        ; result (byteLength is at least 1).
useCompleteDwordsReg = TRUE
rName edx CompleteDwords
        mov     edxCompleteDwords, eaxByteLength
if bpp eq 4111
        sub     edxCompleteDwords, 2    ; Special case 2 bytes...
        adc     edxCompleteDwords, 0    ; ...unless there is only one.
endif
        shr     edxCompleteDwords, 2

if bpp eq 16
        ; Work out how many stray words there are in each line (byteLength/2%2)
rName esi StrayWords
        mov     esiStrayWords, eaxByteLength
        shr     esiStrayWords, 1
        and     esiStrayWords, 01h
else
        ; Work out how many stray bytes there are in each line (byteLength%4)
rName esi StrayBytes
 if bpp ne 4111
        mov     esiStrayBytes, eaxByteLength
        and     esiStrayBytes, 03h
 else
        ; The number of stray bytes will be the number of bytes which are
        ; not done by the dword loop. This will be between 1 and 5. The
        ; first and last bytes are done as special cases, the remaining
        ; bytes (up to 3) are done by a rep stos byte instruction.
        mov     esiStrayBytes, eaxByteLength
        sub     esiStrayBytes, 2        ; Special case 2 bytes...
        adc     esiStrayBytes, 0        ; ...unless there is only one.
        and     esiStrayBytes, 03h      ; Bytes left not done as dwords.
        add     esiStrayBytes, 2        ; Add the 2 special cased bytes...
        cmp     eaxByteLength, 2        ; ...but adjust if there is only
        sbb     esiStrayBytes, 0        ; one byte on each line.
 endif ; if bpp ne 4111 else
endif ; if bpp eq 16 else
rFree eax ByteLength


ifidn <mode>, <mix>
        ; Work out the addresses of the mix code to jump to.

        ; First get the offsets within each mix code block.
        movzx   ebx, byte ptr ShadowXGARegs.fg_mix
        mov     eax, dword ptr [mixKeepSourcePartDW+ebx*4]
        mov     ebx, dword ptr [mixKeepSourcePartBY+ebx*4]

        ; Now add to the start addresses of the mix blocks.
        add     eax, offset FLAT:dwordMixCodeBase
        mov     dwordMixJumpAddress, eax

if bpp eq 4111
        mov     eax, ebx
        add     eax, offset FLAT:firstByteMixCodeBase
        mov     firstByteMixJumpAddress, eax
        mov     eax, ebx
        add     eax, offset FLAT:lastByteMixCodeBase
        mov     lastByteMixJumpAddress, eax
endif
if bpp eq 16
        add     ebx, offset FLAT:wordMixCodeBase
        mov     wordMixJumpAddress, ebx
else
        add     ebx, offset FLAT:byteMixCodeBase
        mov     byteMixJumpAddress, ebx
endif
endif ; idn <mode>, <mix>

if bpp eq 16
        ; Get two pels worth of source in eax.
        mov     ax, _messSPad.srcColour
        shl     eax, 16
        mov     ax, _messSPad.srcColour
endif
if bpp eq 8
        ; Get four pels worth of source into eax.
        mov     al, byte ptr _messSPad.srcColour
        mov     ah, al
        mov     cx, ax
        shl     eax, 16
        mov     ax, cx
endif
if bpp eq 4111
        ; Fill eax with 8 pels (if 4 bpp) or 32 pels (if 1bbp) of source.
        test    byte ptr dstPixmap.format, FOUR_BPP
        jz      short getOneBppPels

        ; Fill eax with the correct fill value (ie. 8 pels worth)
        mov     al, byte ptr _messSPad.srcColour
        mov     ah, al
        shl     al, 4
        shl     ax, 4
        mov     al, ah
        mov     cx, ax
        shl     eax, 16
        mov     ax, cx
        jmp     short gotSourcePels

getOneBppPels:
        ; Work out what to fill with - either all 1s or all 0s
        mov     bl, byte ptr _messSPad.srcColour
        and     ebx, 01h
        xor     eax, eax        ; eax is now zero
        sub     eax, ebx        ; eax is now zero or minus one
endif
gotSourcePels:
rName eax SourcePels

        ; Now set up a loop to do each row in the operation
useLineLoopReg = TRUE
rName ebx LineLoopCount
        movzx   ebxLineLoopCount, ShadowXGARegs.dim2
        inc     ebxLineLoopCount

if bpp eq 4111
useLineLoopReg = FALSE
        mov     lineLoopCount, ebxLineLoopCount
rFree ebx LineLoopCount

        ; Get the start and end masks (and their inverses) into ebx.
        .erre startMaskInv eq startMask + 1
        .erre endMask eq startMaskInv + 1
        .erre endMaskInv eq endMask + 1
        mov     ebx, dword ptr _messSPad.startMask
        ; ebx is:
        ;  31             23           15               7            0
        ; | end mask inv |  end mask  | start mask inv |  start mask  |
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv
endif

ifidn <mode>, <mix>
useCompleteDwordsReg = FALSE
        mov     completeDwordsCount, edxCompleteDwords
rFree edx CompleteDwords

        ; Move the source pels into edx so we can use edx and eax when mixing
        ; the pels, and eax when reading and writing the pels (using stos).
        mov     edx, eaxSourcePels
rFree eax SourcePels
rName edx SourcePels

endif ; ifidn <mode>, <mix>


lineLoop:

if bpp eq 16
        ; Do the stray words (this will be between 0 and 1).
        mov     ecx, esiStrayWords
ifidn <mode>, <copy>
        rep stos word ptr [ediDestIndex]
else
        jecxz   wordLoopEnd
wordLoop:
        mov     ax, [ediDestIndex]
        jmp     wordMixJumpAddress

wordMixCodeBase:
        ; Do as dwords anyway and don't worry about what is in
        ; the top half of the registers.
        mixKeepSourcePart       edxSourcePels, eax

        stos    word ptr [ediDestIndex]
wordLoopEnd:
endif ; idn <mode>, <copy> else
endif ; bpp eq 16

if bpp eq 8
        ; Do the stray bytes (this will be between 0 and 3).
        mov     ecx, esiStrayBytes
ifidn <mode>, <copy>
        rep stos byte ptr [ediDestIndex]
else
        jecxz    byteLoopEnd
byteLoop:
        mov     al, [ediDestIndex]
        jmp     byteMixJumpAddress

byteMixCodeBase:
        mixKeepSourcePart       dlPartOfSourcePels, al

        stos    byte ptr [ediDestIndex]
        dec     ecx
        jnz     byteLoop
byteLoopEnd:
endif ; idn <mode>, <copy> else
endif ; if bpp eq 8

if bpp eq 4111
        ; Do the first byte using the start masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
ifidn <mode>, <copy>
        mov     cl, alPartOfSourcePels  ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     firstByteMixJumpAddress ; the destination pel.
firstByteMixCodeBase:
        mixKeepSourcePart dlPartOfSourcePels, cl
endif
        and     ch, bhStartMaskInv      ; Mask out pels to be changed.
        and     cl, blStartMask         ; Mask out pels not to be changed.
        or      ch, cl                  ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.
        inc     ediDestIndex            ; Update destination address.

        ; See if the line is more than one byte wide.
        mov     ecx, esiStrayBytes
        dec     ecx
        jz      finishedLine

        ; Do all but the last stray byte.
        dec     ecx
ifidn <mode>, <copy>
        rep stos byte ptr [ediDestIndex]
else
        jecxz    byteLoopEnd
byteLoop:
        mov     al, [ediDestIndex]
        jmp     byteMixJumpAddress

byteMixCodeBase:
        mixKeepSourcePart       dlPartOfSourcePels, al

        stos    byte ptr [ediDestIndex]
        dec     ecx
        jnz     byteLoop
byteLoopEnd:
endif ; idn <mode>, <copy> else
endif ; if bpp eq 4111

        ; Set up ecx to do whole dwords and do them
if useCompleteDwordsReg eq TRUE
        mov     ecx, edxCompleteDwords
else
        mov     ecx, completeDwordsCount
endif

ifidn <mode>, <copy>
        rep stos dword ptr [ediDestIndex]
else
        jecxz   dwordLoopEnd
dwordLoop:
        mov     eax, [ediDestIndex]
        jmp     dwordMixJumpAddress

dwordMixCodeBase:
        mixKeepSourcePart       edxSourcePels, eax

        stos    dword ptr [ediDestIndex]
        dec     ecx
        jnz     dwordLoop
dwordLoopEnd:
endif ; idn <mode>, <copy> else

if bpp eq 4111
        ; Get the end masks from the top of ebx.
rFree bl StartMask
rFree bh StartMaskInv
rFree ebx_top EndMaskAndInv
        swap    ebx
rName bl EndMask
rName bh EndMaskInv
rName ebx_top StartMaskAndInv

        ; Do the last byte using the end masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
ifidn <mode>, <copy>
        mov     cl, alPartOfSourcePels  ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     lastByteMixJumpAddress  ; the destination pel.
lastByteMixCodeBase:
        mixKeepSourcePart dlPartOfSourcePels, cl
endif
        and     ch, bhEndMaskInv        ; Mask out pels to be changed.
        and     cl, blEndMask           ; Mask out pels not be to changed.
        or      ch , cl                 ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.
        inc     ediDestIndex            ; Update destination address.

        ; Put the end masks back in the top of ebx.
rFree bl EndMask
rFree bh EndMaskInv
rFree ebx_top StartMaskAndInv
        swap    ebx
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv

endif

finishedLine:
        ; Apply the destination increment
        add     ediDestIndex, _messSPad.dstLineInc

        ; Go back and do the rest of the blt lines.
if useLineLoopReg eq TRUE
        dec     ebxLineLoopCount
else
        dec     lineLoopCount
endif
        jnz     lineLoop


rEnd

endm

      ;;;************************************
ENDIF ;;; End of XGA Version of DestOnly macro
      ;;;************************************




IFDEF _8514

DestOnlyWithColComp macro mode, bpp
        local gotSourcePels, lineLoop, finishedLine
        local wordLoop, wordLoopEnd, byteLoop, byteLoopEnd
        local wordLoop, wordLoopEnd, byteMixCodeBase
        local wordMixCodeBase, firstByteMixCodeBase, lastByteMixCodeBase
        local doNextByte, doneFirstByte, doneLastByte, doNextWord

; Check that macro parameters are valid.
ifdif <mode>, <mix>
 ifdif <mode>, <copy>
  .err
  %out DestOnly macro mode parameter must be "mix" or "copy".
 endif
endif
if (bpp ne 16) and (bpp ne 8) and (bpp ne 4) and (bpp ne 24)
 .err
 %out DestOnly macro bits per pel parameter must be 4, 8, 16, or 24.
endif

        ; We will use rmacros to help police register usage.
rStart

        ; Need to set up the direction, increments and start positions
        ; for the blt and the destination width in bytes. Note that
        ; this macro is only valid for 16, 8, and 4 bits per pel. Any
        ; 1 bit per pel operations that required color compare functions
        ; will be handled by eddb_bitblt so that the color compare is
        ; implemented directly by adjusting the logic of the blt.
if bpp eq 24
        cCall   eddf_MESSSetUpDest24
endif
if bpp eq 16
        cCall   eddf_MESSSetUpDest16
endif
if bpp eq 8
        cCall   eddf_MESSSetUpDest81
endif
if bpp eq 4
        cCall   eddf_MESSSetUpDest41
endif
rName edi DestIndex


        ; First get the length of each blt in bytes into eax.
rName eax  ByteLength
if bpp eq 24
        movzx   eaxByteLength, Shadow8514Regs.dim1
        inc     eaxByteLength
endif
if bpp eq 16
        shl     eaxByteLength, 1
endif
if bpp eq 8
        movzx   eaxByteLength, Shadow8514Regs.dim1
        inc     eaxByteLength
endif
if bpp eq 4
        mov     eaxByteLength, _messSPad.totalBytes
endif

        ; If we are at 8 bits per pel or 4 bits per pel then we will
        ; do the blt a byte at a time. If we are at 16 bits per pel
        ; then we will do the blt a word at a time.
rFree eax ByteLength
        mov     esi, eax
if bpp eq 16
        shr     esi, 2
rName esi WordLength
else
if bpp eq 24
rName esi WordLength
else
rName esi ByteLength
endif
endif

ifidn <mode>, <mix>
        ; Work out the addresses of the mix code to jump to.

        ; First get the offsets within each mix code block.
        movzx   ebx, byte ptr Shadow8514Regs.Function_1
        and     ebx, FUNC_ALU
        mov     eax, dword ptr [mixKeepSourcePartDW+ebx*4]
        mov     ebx, dword ptr [mixKeepSourcePartBY+ebx*4]

        ; Now add to the start addresses of the mix blocks.
if bpp eq 4
        mov     eax, ebx
        add     eax, offset FLAT:firstByteMixCodeBase
        mov     lastByteMixJumpAddress, eax
        mov     eax, ebx
        add     eax, offset FLAT:lastByteMixCodeBase
        mov     firstByteMixJumpAddress, eax
endif

if bpp eq 16
        ; @DMS this should be eax - dont fix if it aint broke !!!
        add     ebx, offset FLAT:wordMixCodeBase
        mov     wordMixJumpAddress, ebx
else
if bpp eq 24
        add     eax, offset FLAT:wordMixCodeBase
        mov     wordMixJumpAddress, eax
else
        add     ebx, offset FLAT:byteMixCodeBase
        mov     byteMixJumpAddress, ebx
endif
endif

endif ; idn <mode>, <mix>


        ; Move the source pels into edx. Later we will use eax to read
        ; and write the pels from the destination using stos.
if bpp eq 24
        ; Get one pel of source into dx and one pel of color compare
        ; color into bp.
        mov     edx, _messSPad.srcColour
        mov     ebp, _Shadow8514Regs.Color_Comp
rName edx SourcePels
rName ebp ColorComparePels
endif

if bpp eq 16
        ; Get one pel of source into dx and one pel of color compare
        ; color into bp.
        mov     dx, _messSPad.srcColour
        mov     bp, _Shadow8514Regs.Color_Comp
rName dx SourcePels
rName bp ColorComparePels
endif

if bpp eq 8
        ; Get one pel of source into dl and one pel of color compare
        ; color into dh.
        mov     dl, byte ptr _messSPad.srcColour
        mov     dh, byte ptr _Shadow8514Regs.Color_Comp
rName dl SourcePels
rName dh ColorComparePels
endif

if bpp eq 4
        ; Get two pels of source into dl and two pels of color compare
        ; color into dh.
        mov     dl, byte ptr _Shadow8514Regs.Color_Comp
        mov     dh, dl
        shl     dl, 4
        shl     edx, 12
        mov     dl, byte ptr _messSPad.srcColour
        mov     dh, dl
        shl     dl, 4
        shl     dx, 4
        shr     edx, 8
rName dl SourcePels
rName dh ColorComparePels
endif

        ; Now set up a loop to do each row in the operation.
useLineLoopReg = TRUE
rName ebx LineLoopCount
        movzx   ebxLineLoopCount, Shadow8514Regs.dim2
        inc     ebxLineLoopCount


if bpp eq 4
useLineLoopReg = FALSE
        mov     lineLoopCount, ebxLineLoopCount
rFree ebx LineLoopCount

        ; Get the start and end masks (and their inverses) into ebx.
        .erre startMaskInv eq startMask + 1
        .erre endMask eq startMaskInv + 1
        .erre endMaskInv eq endMask + 1
        mov     ebx, dword ptr _messSPad.startMask
        ; ebx is:
        ;  31             23           15               7            0
        ; | end mask inv |  end mask  | start mask inv |  start mask  |
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv
endif


lineLoop:

if bpp eq 16
        ; Get the loop count into ecx.
        mov     ecx, esiWordLength

wordLoop:
        mov     ax, [ediDestIndex]
        cmp     ax, bpColorComparePels
        jne     short doNextWord

ifidn <mode>, <copy>
        mov     ax, dxSourcePels
else
        jmp     wordMixJumpAddress
wordMixCodeBase:
        ; Use edx and eax to do the mix even though we are only interested
        ; in dx and ax because it will be faster. Note we use "EDX" here
        ; override rmacros which would otherwise give an error.
        mixKeepSourcePart       EDX, eax
endif

        mov     word ptr [ediDestIndex], ax
doNextWord:
        add     ediDestIndex, 2
        dec     ecx
        jnz     wordLoop
wordLoopEnd:

else ; if bpp eq 16

if bpp eq 24
        ; Get the loop count into ecx.
        mov     ecx, esiWordLength

wordLoop:
        mov     eax, [ediDestIndex]
        and     eax,00ffffffh
        cmp     eax, ebpColorComparePels
        jne     short doNextWord

ifidn <mode>, <copy>
        mov     eax, edxSourcePels
else
        jmp     wordMixJumpAddress
wordMixCodeBase:
        ; Use edx and eax to do the mix even though we are only interested
        ; in dx and ax because it will be faster. Note we use "EDX" here
        ; override rmacros which would otherwise give an error.
        mixKeepSourcePart       EDX, eax
endif

        ror     eax,16
        mov     byte ptr [ediDestIndex], al
        rol     eax,8
        mov     byte ptr [ediDestIndex], al
        rol     eax,8
        mov     byte ptr [ediDestIndex], al
doNextWord:
        add     ediDestIndex, 3
        dec     ecx
        jnz     wordLoop
wordLoopEnd:
else  ; bpp 24
if bpp eq 4
        ; Do the first byte using the start masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
        cmp     ch, dhColorComparePels
        jne     short doneFirstByte

ifidn <mode>, <copy>
        mov     cl, dlSourcePels        ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     firstByteMixJumpAddress ; the destination pel.
firstByteMixCodeBase:
        mixKeepSourcePart dlSourcePels, cl
endif
        and     ch, bhStartMaskInv      ; Mask out pels to be changed.
        and     cl, blStartMask         ; Mask out pels not be to changed.
        or      ch, cl                  ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.

doneFirstByte:
        inc     ediDestIndex            ; Update destination address.

        ; See if the line is more than one byte wide.
        mov     ecx, esiByteLength
        dec     ecx
        jz      finishedLine

        ; Do all but the last byte.
        dec     ecx
        jecxz   byteLoopEnd
endif ; if bpp eq 4

if bpp eq 8
        ; Get the loop count into ecx.
        mov     ecx, esiByteLength
endif

byteLoop:
        mov     al, [ediDestIndex]
        cmp     al, dhColorComparePels
        jne     short doNextByte

ifidn <mode>, <copy>
        mov     al, dlSourcePels
else
        jmp     byteMixJumpAddress
byteMixCodeBase:
        mixKeepSourcePart       dlSourcePels, al
endif

        mov     byte ptr [ediDestIndex], al
doNextByte:
        inc     ediDestIndex
        dec     ecx
        jnz     byteLoop
byteLoopEnd:

if bpp eq 4
        ; Do the last byte using the end masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
        cmp     ch, dhColorComparePels
        jne     short doneLastByte

        ; Get the end masks from the top of ebx.
rFree bl StartMask
rFree bh StartMaskInv
rFree ebx_top EndMaskAndInv
        swap    ebx
rName bl EndMask
rName bh EndMaskInv
rName ebx_top StartMaskAndInv

ifidn <mode>, <copy>
        mov     cl, dlSourcePels        ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     lastByteMixJumpAddress  ; the destination pel.
lastByteMixCodeBase:
        mixKeepSourcePart dlSourcePels, cl
endif
        and     ch, bhEndMaskInv        ; Mask out pels to be changed.
        and     cl, blEndMask           ; Mask out pels not be to changed.
        or      ch , cl                 ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.

        ; Put the end masks back in the top of ebx.
rFree bl EndMask
rFree bh EndMaskInv
rFree ebx_top StartMaskAndInv
        swap    ebx
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv

doneLastByte:
        inc     ediDestIndex            ; Update destination address.

endif ; if bpp eq 4
endif ; if bpp eq 24

endif ; if bpp eq 16  else

finishedLine:
        ; Apply the destination increment
        add     ediDestIndex, _messSPad.dstLineInc

        ; Go back and do the rest of the blt lines.
if useLineLoopReg eq TRUE
        dec     ebxLineLoopCount
else
        dec     lineLoopCount
endif
        jnz     lineLoop

rEnd

endm




      ;;;*******************************************
ELSE  ;;; XGA Version of DestOnlyWithColComp macro
      ;;;*******************************************

DestOnlyWithColComp macro mode, bpp
        local gotSourcePels, lineLoop, finishedLine
        local wordLoop, wordLoopEnd, byteLoop, byteLoopEnd
        local wordLoop, wordLoopEnd, byteMixCodeBase
        local wordMixCodeBase, firstByteMixCodeBase, lastByteMixCodeBase
        local doNextByte, doneFirstByte, doneLastByte, doNextWord

; Check that macro parameters are valid.
ifdif <mode>, <mix>
 ifdif <mode>, <copy>
  .err
  %out DestOnly macro mode parameter must be "mix" or "copy".
 endif
endif
if (bpp ne 16) and (bpp ne 8) and (bpp ne 4)
 .err
 %out DestOnly macro bits per pel parameter must be 4, 8, or 16.
endif

        ; We will use rmacros to help police register usage.
rStart

        ; Need to set up the direction, increments and start positions
        ; for the blt and the destination width in bytes. Note that
        ; this macro is only valid for 16, 8, and 4 bits per pel. Any
        ; 1 bit per pel operations that required color compare functions
        ; will be handled by eddb_bitblt so that the color compare is
        ; implemented directly by adjusting the logic of the blt.
if bpp eq 16
        cCall   eddf_MESSSetUpDest16
endif
if bpp eq 8
        cCall   eddf_MESSSetUpDest81
endif
if bpp eq 4
        cCall   eddf_MESSSetUpDest41
endif
rName edi DestIndex


        ; First get the length of each blt in bytes into eax.
rName eax  ByteLength
if bpp eq 16
        shl     eaxByteLength, 1
endif
if bpp eq 8
        movzx   eaxByteLength, ShadowXGARegs.dim1
        inc     eaxByteLength
endif
if bpp eq 4
        mov     eaxByteLength, _messSPad.totalBytes
endif

        ; If we are at 8 bits per pel or 4 bits per pel then we will
        ; do the blt a byte at a time. If we are at 16 bits per pel
        ; then we will do the blt a word at a time.
rFree eax ByteLength
        mov     esi, eax
if bpp eq 16
        shr     esi, 2
rName esi WordLength
else
rName esi ByteLength
endif

ifidn <mode>, <mix>
        ; Work out the addresses of the mix code to jump to.

        ; First get the offsets within each mix code block.
        movzx   ebx, byte ptr ShadowXGARegs.fg_mix
        mov     eax, dword ptr [mixKeepSourcePartDW+ebx*4]
        mov     ebx, dword ptr [mixKeepSourcePartBY+ebx*4]

        ; Now add to the start addresses of the mix blocks.
if bpp eq 4
        mov     eax, ebx
        add     eax, offset FLAT:firstByteMixCodeBase
        mov     lastByteMixJumpAddress, eax
        mov     eax, ebx
        add     eax, offset FLAT:lastByteMixCodeBase
        mov     firstByteMixJumpAddress, eax
endif

if bpp eq 16
        add     ebx, offset FLAT:wordMixCodeBase
        mov     wordMixJumpAddress, ebx
else
        add     ebx, offset FLAT:byteMixCodeBase
        mov     byteMixJumpAddress, ebx
endif

endif ; idn <mode>, <mix>


        ; Move the source pels into edx. Later we will use eax to read
        ; and write the pels from the destination using stos.
if bpp eq 16
        ; Get one pel of source into dx and one pel of color compare
        ; color into bp.
        mov     dx, _messSPad.srcColour
        mov     bp, _ShadowXGARegs.colour_comp_colour
rName dx SourcePels
rName bp ColorComparePels
endif

if bpp eq 8
        ; Get one pel of source into dl and one pel of color compare
        ; color into dh.
        mov     dl, byte ptr _messSPad.srcColour
        mov     dh, byte ptr _ShadowXGARegs.colour_comp_colour
rName dl SourcePels
rName dh ColorComparePels
endif

if bpp eq 4
        ; Get two pels of source into dl and two pels of color compare
        ; color into dh.
        mov     dl, byte ptr _ShadowXGARegs.colour_comp_colour
        mov     dh, dl
        shl     dl, 4
        shl     edx, 12
        mov     dl, byte ptr _messSPad.srcColour
        mov     dh, dl
        shl     dl, 4
        shl     dx, 4
        shr     edx, 8
rName dl SourcePels
rName dh ColorComparePels
endif

        ; Now set up a loop to do each row in the operation.
useLineLoopReg = TRUE
rName ebx LineLoopCount
        movzx   ebxLineLoopCount, ShadowXGARegs.dim2
        inc     ebxLineLoopCount


if bpp eq 4
useLineLoopReg = FALSE
        mov     lineLoopCount, ebxLineLoopCount
rFree ebx LineLoopCount

        ; Get the start and end masks (and their inverses) into ebx.
        .erre startMaskInv eq startMask + 1
        .erre endMask eq startMaskInv + 1
        .erre endMaskInv eq endMask + 1
        mov     ebx, dword ptr _messSPad.startMask
        ; ebx is:
        ;  31             23           15               7            0
        ; | end mask inv |  end mask  | start mask inv |  start mask  |
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv
endif


lineLoop:

if bpp eq 16
        ; Get the loop count into ecx.
        mov     ecx, esiWordLength

wordLoop:
        mov     ax, [ediDestIndex]
        cmp     ax, bpColorComparePels
        jne     short doNextWord

ifidn <mode>, <copy>
        mov     ax, dxSourcePels
else
        jmp     wordMixJumpAddress
wordMixCodeBase:
        ; Use edx and eax to do the mix even though we are only interested
        ; in dx and ax because it will be faster. Note we use "EDX" here
        ; override rmacros which would otherwise give an error.
        mixKeepSourcePart       EDX, eax
endif

        mov     word ptr [ediDestIndex], ax
doNextWord:
        add     ediDestIndex, 2
        dec     ecx
        jnz     wordLoop
wordLoopEnd:

else ; if bpp eq 16

if bpp eq 4
        ; Do the first byte using the start masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
        cmp     ch, dhColorComparePels
        jne     short doneFirstByte

ifidn <mode>, <copy>
        mov     cl, dlSourcePels        ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     firstByteMixJumpAddress ; the destination pel.
firstByteMixCodeBase:
        mixKeepSourcePart dlSourcePels, cl
endif
        and     ch, bhStartMaskInv      ; Mask out pels to be changed.
        and     cl, blStartMask         ; Mask out pels not be to changed.
        or      ch, cl                  ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.

doneFirstByte:
        inc     ediDestIndex            ; Update destination address.

        ; See if the line is more than one byte wide.
        mov     ecx, esiByteLength
        dec     ecx
        jz      finishedLine

        ; Do all but the last byte.
        dec     ecx
        jecxz   byteLoopEnd
endif ; if bpp eq 4

if bpp eq 8
        ; Get the loop count into ecx.
        mov     ecx, esiByteLength
endif

byteLoop:
        mov     al, [ediDestIndex]
        cmp     al, dhColorComparePels
        jne     short doNextByte

ifidn <mode>, <copy>
        mov     al, dlSourcePels
else
        jmp     byteMixJumpAddress
byteMixCodeBase:
        mixKeepSourcePart       dlSourcePels, al
endif

        mov     byte ptr [ediDestIndex], al
doNextByte:
        inc     ediDestIndex
        dec     ecx
        jnz     byteLoop
byteLoopEnd:

if bpp eq 4
        ; Do the last byte using the end masks.
        mov     ch, [ediDestIndex]      ; Get a destination byte.
        cmp     ch, dhColorComparePels
        jne     short doneLastByte

        ; Get the end masks from the top of ebx.
rFree bl StartMask
rFree bh StartMaskInv
rFree ebx_top EndMaskAndInv
        swap    ebx
rName bl EndMask
rName bh EndMaskInv
rName ebx_top StartMaskAndInv

ifidn <mode>, <copy>
        mov     cl, dlSourcePels        ; Get a source byte.
else
        mov     cl, ch                  ; Get a source pel mixed with
        jmp     lastByteMixJumpAddress  ; the destination pel.
lastByteMixCodeBase:
        mixKeepSourcePart dlSourcePels, cl
endif
        and     ch, bhEndMaskInv        ; Mask out pels to be changed.
        and     cl, blEndMask           ; Mask out pels not be to changed.
        or      ch , cl                 ; Combined old and new pels.
        mov     [ediDestIndex], ch      ; Write byte back to the destination.

        ; Put the end masks back in the top of ebx.
rFree bl EndMask
rFree bh EndMaskInv
rFree ebx_top StartMaskAndInv
        swap    ebx
rName bl StartMask
rName bh StartMaskInv
rName ebx_top EndMaskAndInv

doneLastByte:
        inc     ediDestIndex            ; Update destination address.

endif ; if bpp eq 4

endif ; if bpp eq 16  else

finishedLine:
        ; Apply the destination increment
        add     ediDestIndex, _messSPad.dstLineInc

        ; Go back and do the rest of the blt lines.
if useLineLoopReg eq TRUE
        dec     ebxLineLoopCount
else
        dec     lineLoopCount
endif
        jnz     lineLoop

rEnd

endm

        ;;;**************************************************
ENDIF ; ;;; End of XGA Version of DestOnlyWithColComp macro
        ;;;**************************************************

ENDIF ; IF1


ifdef BPP24
;-------------------------------------------------------------------------
;
; Function: eddf_MESSBlockFill24
;
; This does a fast block fill for 16,1 format using string stores
;
; Parameters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       eax     - 2 pels of colour
;       ebx     - lines loop counter
;       edx     - complete dwords per row (length/2)
;       esi     - stray words per row (length%2)
;       edi     - dest position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSBlockFill24, <PUBLIC>, <ebp,ebx>
cBegin

IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      short standardBF24

        ; Code for color compare case.
        DestOnlyWithColComp copy 24
        jmp     exitBF24

standardBF24:
        ; Code for standard case.
        DestOnly copy 24
exitBF24:

cEnd
endif

;-------------------------------------------------------------------------
;
; Function: eddf_MESSBlockFill16
;
; This does a fast block fill for 16,1 format using string stores
;
; Parameters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       eax     - 2 pels of colour
;       ebx     - lines loop counter
;       edx     - complete dwords per row (length/2)
;       esi     - stray words per row (length%2)
;       edi     - dest position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSBlockFill16, <PUBLIC>, <ebp,ebx>
cBegin

IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      short standardBF16

        ; Code for color compare case.
        DestOnlyWithColComp copy 16
        jmp     exitBF16

standardBF16:
        ; Code for standard case.
        DestOnly copy 16
exitBF16:
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSBlockFill81
;
; This does a fast block fill for 8,1 format using string stores
;
; Parameters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       eax     - 4 pels of colour
;       ebx     - lines loop counter
;       edx     - complete dwords per row (length/4)
;       esi     - stray bytes per row (length%4)
;       edi     - dst position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSBlockFill81, <PUBLIC>, <ebx>
cBegin
IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      short standardBF8

        ; Code for color compare case.
        DestOnlyWithColComp copy 8
        jmp     exitBF8

standardBF8:
        ; Code for standard case.
        DestOnly copy 8
exitBF8:
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSBlockFill4111
;
; This does a fast block fill for 4,1 format and 1,1 format using string
; stores where possible
;
; Parameters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       eax     - one dword of source colour pels
;       ebx.lo  - startMask (bl) and ~startMask (bh)
;       ebx.hi  - endMask (bl) and ~endMask (bh)
;       edx     - number of dwords per row       (see comments in macro)
;       esi     - number of stray bytes per row  (see comments in macro)
;       edi     - dst position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSBlockFill4111, <PUBLIC>, <ebx>
        localD lineLoopCount
cBegin
IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      standardBF4111

        ; Code for color compare case.
        DestOnlyWithColComp copy 4
        jmp     exitBF4111

standardBF4111:
        ; Code for standard case.
        DestOnly copy 4111
exitBF4111:
cEnd

;-------------------------------------------------------------------------
;
; Function: eddf_MESSFixedSrc16
;
; This does a mix when the source data is fixed throughout the operation
;
; Parmeters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       ebx     - four pels of source
;       edx     - number of dwords
;       esi     - number of stray bytes
;       edi     - destination position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSFixedSrc16, <PUBLIC>, <ebp,ebx>

        localD  lineLoopCount
        localD  completeDwordsCount
        localD  dwordMixJumpAddress
        localD  wordMixJumpAddress
cBegin
IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      standardFS16

        ; Code for color compare case.
        DestOnlyWithColComp mix 16
        jmp     exitFS16

standardFS16:
        ; Code for standard case.
        DestOnly mix 16
exitFS16:
cEnd


;-------------------------------------------------------------------------
;
; Function: eddf_MESSFixedSrc81
;
; This does a mix when the source data is fixed throughout the operation
;
; Parmeters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       ebx     - four pels of source
;       edx     - number of dwords
;       esi     - number of stray bytes
;       edi     - destination position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSFixedSrc81, <PUBLIC>, <ebx>

        localD  lineLoopCount
        localD  completeDwordsCount
        localD  dwordMixJumpAddress
        localD  byteMixJumpAddress
cBegin
IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      standardFS8

        ; Code for color compare case.
        DestOnlyWithColComp mix 8
        jmp     exitFS8

standardFS8:
        ; Code for standard case.
        DestOnly mix 8
exitFS8:
cEnd

ifdef BPP24
;-------------------------------------------------------------------------
;
; Function: eddf_MESSFixedSrc24
;
; This does a mix when the source data is fixed throughout the operation
;
; Parmeters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       ebx     - four pels of source
;       edx     - number of dwords
;       esi     - number of stray bytes
;       edi     - destination position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSFixedSrc24, <PUBLIC>, <ebx>

        localD  lineLoopCount
        localD  completeDwordsCount
        localD  dwordMixJumpAddress
        localD  byteMixJumpAddress
cBegin

IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      standardFS24

        ; Code for color compare case.
        DestOnlyWithColComp mix 24
        jmp     exitFS24

standardFS24:
        ; Code for standard case.
        DestOnly mix 24
exitFS24:
cEnd
endif

;-------------------------------------------------------------------------
;
; Function: eddf_MESSFixedSrc4111
;
; This does a mix when the source data is fixed throughout the operation.
; It handles 4,1 and 1,1 formats
;
; Parmeters:
;       ShadowXGARegs, messSPad, pixmap structures
;
; Internally for standard case:
;       eax     - dword full of source colour pels
;       ebx.lo  - startMask (bl) and ~startMask (bh)
;       ebx.hi  - endMask (bl) and ~endMask (bh)
;       edx     - number of dwords       (see comments in macro)
;       esi     - number of bytes        (see comments in macro)
;       edi     - destination position
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSFixedSrc4111, <PUBLIC>, <ebx>

        localD  lineLoopCount
        localD  completeDwordsCount
        localD  dwordMixJumpAddress
        localD  byteMixJumpAddress
        localD  firstByteMixJumpAddress
        localD  lastByteMixJumpAddress
cBegin
IFDEF _8514
        mov     ebx, Shadow8514Regs.Mode
        and     ebx, MD_UNDERPAINT
        cmp     ebx, MD_UP_FALSE
ELSE
        cmp     ShadowXGARegs.colour_comp_fun, COLCOMP_ALWAYS
ENDIF
        je      standardFS4111

        ; Code for color compare case.
        DestOnlyWithColComp mix 4
        jmp     exitFS4111

standardFS4111:
        ; Code for standard case.
        DestOnly mix 4111
exitFS4111:
cEnd




_TEXT ends

END
