;*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          = EDDFFAST
;
;   Description     = 386 code for the MESS
;
;   Functions       = Many and varied.
;
;
;-------------------------------------------------------------------------

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 ffmacros.inc

ifdef   _8514
include 8514.inc
endif

                .386p


; Declare the external data elements we use
ifndef  _8514
externDP        ShadowXGARegs
else
externDP        Shadow8514Regs
extrn           _DDT     :byte
endif

externDP        srcPixmap
externDP        dstPixmap
externDP        patPixmap


; Declare the following functions before we use them in the jump tables so
; that the linker(?) works properly. Also we have to use "offset FLAT:" before
; the firewall entries in the tables to get the linker(?) to work.

public          eddf_MESSFirewallFunction
public          PatDestBlt8bppTo1bpp

; This function is in eddfmess.c
externP         eddf_MESSDoPlotStep                                     ;**

; These functions are in fflines.asm
externP         eddf_MESSDoBresenham
externP         eddf_MESSDoShortLines

; These functions are in ffbltsd.asm
externP         eddf_MESSBlockCopy4111
externP         eddf_MESSSrcDestMix4111
externP         eddf_MESSSrcDestWrapCopy41
externP         eddf_MESSSrcDestWrapMix41
externP         eddf_MESSBlockCopy81
externP         eddf_MESSSrcDestMix81
externP         eddf_MESSSrcDestWrapCopy81
externP         eddf_MESSSrcDestWrapMix81
externP         eddf_MESSBlockCopy16
externP         eddf_MESSSrcDestMix16
externP         eddf_MESSSrcDestWrapCopy16
externP         eddf_MESSSrcDestWrapMix16
ifdef BPP24
externP         eddf_MESSBlockCopy24
externP         eddf_MESSSrcDestMix24
externP         eddf_MESSSrcDestWrapCopy24
externP         eddf_MESSSrcDestWrapMix24
endif

; These functions are in ffbltd.asm
externP         eddf_MESSBlockFill4111
externP         eddf_MESSBlockFill4111
externP         eddf_MESSBlockFill81
externP         eddf_MESSBlockFill16
externP         eddf_MESSFixedSrc4111
externP         eddf_MESSFixedSrc4111
externP         eddf_MESSFixedSrc81
externP         eddf_MESSFixedSrc16
ifdef BPP24
externP         eddf_MESSBlockFill24
externP         eddf_MESSFixedSrc24
endif

; These functions are in ffbltpx.asm
externP         eddf_MESSPatExp11
externP         eddf_MESSPatExp41
externP         eddf_MESSPatExp81
externP         eddf_MESSPatExp16
externP         eddf_MESSPatExpFg11
externP         eddf_MESSPatExpFg41
externP         eddf_MESSPatExpFg81
externP         eddf_MESSPatExpFg16
;Do not use these two any more because we do not support
;AA text at 2.0.
;externP         eddf_MESSPatSrcExp81
;externP         eddf_MESSPatSrcExpFg81
ifdef BPP24
externP         eddf_MESSPatExp24
externP         eddf_MESSPatExpFg24
endif

; These functions are in ffbltpd.asm
externP         eddf_MESSPatDest11
externP         eddf_MESSPatDest41
externP         eddf_MESSPatDest81
externP         eddf_MESSPatDest16
externP         eddf_MESSPatCopy11
externP         eddf_MESSPatCopy41
externP         eddf_MESSPatCopy81
externP         eddf_MESSPatCopy16
externP         eddf_MESSPatDestMixes11
ifdef BPP24
externP         eddf_MESSPatDest24
externP         eddf_MESSPatCopy24
endif

externP         eddf_MESSPatDestByte11
externP         eddf_MESSPatDestByte41
externP         eddf_MESSPatDestByte81
externP         eddf_MESSPatDestByte16
externP         eddf_MESSPatCopyByte11
externP         eddf_MESSPatCopyByte41
externP         eddf_MESSPatCopyByte81
externP         eddf_MESSPatCopyByte16
externP         eddf_MESSPatDestMixesByte11
ifdef BPP24
externP         eddf_MESSPatDestByte24
externP         eddf_MESSPatCopyByte24
endif

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


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


; Here is the scratch pad - global
_messSPad        messSPadStruc <>
public _messSPad

ifndef  _8514
ropTypeTable    db      DEST_ONLY_FILL          ; 0   0's
                db      0                       ; 1
                db      0                       ; 2
                db      DEST_ONLY_FILL          ; 3   source
                db      0                       ; 4
                db      0                       ; 5
                db      0                       ; 6
                db      0                       ; 7
                db      0                       ; 8
                db      0                       ; 9
                db      0                       ; A
                db      0                       ; B
                db      DEST_ONLY_FILL          ; C    'source
                db      0                       ; D
                db      0                       ; E
                db      DEST_ONLY_FILL          ; F    1's
else
ropTypeTable    db      0                       ; 0
                db      DEST_ONLY_FILL          ; 1
                db      DEST_ONLY_FILL          ; 2
                db      0                       ; 3
                db      DEST_ONLY_FILL          ; 4
                db      0                       ; 5
                db      0                       ; 6
                db      DEST_ONLY_FILL          ; 7
                db      0                       ; 8
                db      0                       ; 9
                db      0                       ; A
                db      0                       ; B
                db      0                       ; C
                db      0                       ; D
                db      0                       ; E
                db      0                       ; F
endif


; Create the mix jump offset tables. These are created using the macros
; in ffmacros.inc. BY is for byte and DW is for word and DD is for DWORD.

        align   4

mixOffsetJumpTable mixTrashSourcePartDW

mixOffsetJumpTable mixTrashSourcePartBY

mixOffsetJumpTable mixKeepSourcePartDW

mixOffsetJumpTable mixKeepSourcePartBY

mixOffsetJumpTable mixTrashSourceAllBY

mixOffsetJumpTable mixTrashSourceAllDW

mixOffsetJumpTable mixTrashSourceAllDD



; These are the jump tables for the various functions.  The routines are the
; ones to be used for 1, 2, 4 and 8 bpp formats respectively.  The
; FirewallFunction is an int 3.

public MESSBlockFillBase
MESSBlockFillBase       dd      eddf_MESSBlockFill4111
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSBlockFill4111
                        dd      eddf_MESSBlockFill81
                        dd      eddf_MESSBlockFill16
ifdef BPP24
                        dd      eddf_MESSBlockFill24
endif

public MESSBlockCopyBase
MESSBlockCopyBase       dd      eddf_MESSBlockCopy4111
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSBlockCopy4111
                        dd      eddf_MESSBlockCopy81
                        dd      eddf_MESSBlockCopy16
ifdef BPP24
                        dd      eddf_MESSBlockCopy24
endif

public MESSFixedSrcBase
MESSFixedSrcBase        dd      eddf_MESSFixedSrc4111
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSFixedSrc4111
                        dd      eddf_MESSFixedSrc81
                        dd      eddf_MESSFixedSrc16
ifdef BPP24
                        dd      eddf_MESSFixedSrc24
endif

public MESSSrcDestMixBase
MESSSrcDestMixBase      dd      eddf_MESSSrcDestMix4111
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSSrcDestMix4111
                        dd      eddf_MESSSrcDestMix81
                        dd      eddf_MESSSrcDestMix16
ifdef BPP24
                        dd      eddf_MESSSrcDestMix24
endif

; The next two cases should only occur at 4,1 or 8,1 as they are for
; dithering
public MESSSrcDestWrapMixBase
MESSSrcDestWrapMixBase  dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSSrcDestWrapMix41
                        dd      eddf_MESSSrcDestWrapMix81
                        dd      eddf_MESSSrcDestWrapMix16
ifdef BPP24
                        dd      eddf_MESSSrcDestWrapMix24
endif

public MESSSrcDestWrapCopyBase
MESSSrcDestWrapCopyBase dd      offset FLAT:PatDestBlt8bppTo1bpp
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSSrcDestWrapCopy41
                        dd      eddf_MESSSrcDestWrapCopy81
                        dd      eddf_MESSSrcDestWrapCopy16
ifdef BPP24
                        dd      eddf_MESSSrcDestWrapCopy24
endif

public MESSPatDestBase
MESSPatDestBase         dd      eddf_MESSPatDest11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatDest41
                        dd      eddf_MESSPatDest81
                        dd      eddf_MESSPatDest16
ifdef BPP24
                        dd      eddf_MESSPatDest24
endif

public MESSPatCopyBase
MESSPatCopyBase         dd      eddf_MESSPatCopy11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatCopy41
                        dd      eddf_MESSPatCopy81
                        dd      eddf_MESSPatCopy16
ifdef BPP24
                        dd      eddf_MESSPatCopy24
endif

; This case is actually only different for the 1,1 format.  The 4,1 and
; 8,1 PatDest functions will handle different foreground and background
; mixes anyway
public MESSPatDestMixesBase
MESSPatDestMixesBase    dd      eddf_MESSPatDestMixes11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatDest41
                        dd      eddf_MESSPatDest81
                        dd      eddf_MESSPatDest16
ifdef BPP24
                        dd      eddf_MESSPatDest24
endif

public MESSPatDestByteBase
MESSPatDestByteBase     dd      eddf_MESSPatDestByte11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatDestByte41
                        dd      eddf_MESSPatDestByte81
                        dd      eddf_MESSPatDestByte16
ifdef BPP24
                        dd      eddf_MESSPatDestByte24
endif

public MESSPatCopyByteBase
MESSPatCopyByteBase     dd      eddf_MESSPatCopyByte11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatCopyByte41
                        dd      eddf_MESSPatCopyByte81
                        dd      eddf_MESSPatCopyByte16
ifdef BPP24
                        dd      eddf_MESSPatCopyByte24
endif

; This case is actually only different for the 1,1 format.  The 4,1 8,1 and
; 16,1 PatDest functions will handle different foreground and background
; mixes anyway
public MESSPatDestMixesByteBase
MESSPatDestMixesByteBase dd      eddf_MESSPatDestMixesByte11
                         dd      offset FLAT:eddf_MESSFirewallFunction
                         dd      eddf_MESSPatDestByte41
                         dd      eddf_MESSPatDestByte81
                         dd      eddf_MESSPatDestByte16
ifdef BPP24
                         dd      eddf_MESSPatDestByte24
endif

public MESSPatExpBase
MESSPatExpBase          dd      eddf_MESSPatExp11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatExp41
                        dd      eddf_MESSPatExp81
                        dd      eddf_MESSPatExp16
ifdef BPP24
                        dd      eddf_MESSPatExp24
endif

public MESSPatExpFgBase
MESSPatExpFgBase        dd      eddf_MESSPatExpFg11
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      eddf_MESSPatExpFg41
                        dd      eddf_MESSPatExpFg81
                        dd      eddf_MESSPatExpFg16
ifdef BPP24
                        dd      eddf_MESSPatExpFg24
endif

; The next two cases should only occur at 8,1 as they are for
; AA text
public MESSPatSrcExpBase
MESSPatSrcExpBase       dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
;Do not support AA text any more
;                        dd      eddf_MESSPatSrcExp81
                        dd      offset FLAT:eddf_MESSFirewallFunction

public MESSPatSrcExpFgBase
MESSPatSrcExpFgBase     dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
                        dd      offset FLAT:eddf_MESSFirewallFunction
;Do not support AA text any more
;                        dd      eddf_MESSPatSrcExpFg81
                        dd      offset FLAT:eddf_MESSFirewallFunction

_DATA           ends

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


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


; Dummy function header

;-------------------------------------------------------------------------
; Function:
;
; Parameters:
;
; Returns:
;
; Internally:
;
;-------------------------------------------------------------------------

;-------------------------------------------------------------------------
;
; ******************** G E N E R A L   P O I N T S ***********************
;
; Accessing source/pattern data -
;
; The operations which have to do some sort of alignment of source or pattern
; data (ie 4bpp and 1bpp operations because they have more than one pel stored
; in each byte) all use a similar method of fetching the source pattern where
; they fetch a word and rotate it to get a byte of data.  Using this method
; means that they may try to fetch the byte one before the start of the
; source/pattern or one after the end of the source/pattern.  If this is not
; allowed for then protection faults may occur.  There are several
; methods/assumptions used to allow for this -
;
; 1. Where the pattern has to be aligned it will either come from the
; patBuffer or the character cache.  The patBuffer is assumed not to be the
; first or last thing in a segment and the character cache segment is set
; up with a spare byte at each end.
;
; 2. Where the source has to be aligned it will always come from a single
; bitmap (huge bitmaps do not exist under 2.0 flat model). Bitmaps are
; always allocated to have a spare byte at the beginning and the end.
; This means we will never cause a protection violation.
;
; NB - these only apply to 1,1 and 4,1 bitmaps
;
; See also SetUpSrcToDestShift macro in ffbltset.asm for more details
; on getting aligned source/pattern bytes.
;
;-------------------------------------------------------------------------

;-------------------------------------------------------------------------
; Function: eddf_MESS
;
; The entry point for all MESS functions.  This routine handles setting
; up the src, dst, pat -pixmap structures and selecting the correct path
; through the rest of the MESS for the current operation.  For lines and
; shortlines this is just calling the function (MESSDoBresenham etc.)
; which use different paths internally depending on the format.  For PxBlt
; this function recognises which of the special case this is and calls the
; relevant function for the relevant format.
;
; Parameters:
;       ShadowXGARegs
;
; Returns:
;       Should update src/dst/pat positions - in practice this depends
;       on what operation its doing
;
; Preserves:
;       esi, edi, ebx - For C calling convention.  When eddf_MESS is
;                called from assembly code register save and restore is
;                handled by the calling routines
;       flags  - This is so that the direction flag is still set up correctly
;                for any C functions which might have been using it to perform
;                block copies etc.
;
; Destroys:
;       Everything else - including my sanity
;
;-------------------------------------------------------------------------
        align   4
cProc   eddf_MESS, <PUBLIC>, <esi, edi, ebx>                            ;**

        localW  tmpDim1
cBegin

        ; Save the flags on the stack so that the direction flag
        ; can be restored on exit.
        pushfd

        ; Set up the destination pixmap - this will always be necessary
        ifndef  _8514
        mov     eax, ShadowXGARegs.pixel_op
        else
        mov     eax, Shadow8514Regs.pixel_op
        endif
        and     eax, DST_PIX_MAP_MASK

; You may be wondering what this 12 is! This is a hardcoded dependency
; on the shadow structure which should at least be protected by a .erre
        .erre pi_map_index_B eq pi_map_index_A + 12

        ; top half of eax=1, 2 or 3 for pixmaps A, B or C.  Multiply by 12..
        shr     eax, 14         ; change from * 65536 to * 4
        mov     ebx, eax
        add     ebx, ebx        ; * 8
        add     ebx, eax        ; * 12

        ; Set up ebx ready for indexing into pixmap registers
        ifndef  _8514
        lea     ebx, [ebx].ShadowXGARegs.(pi_map_index_A-12)
        else
        lea     ebx, [ebx].Shadow8514Regs.(pi_map_index_A-12)
        endif

        ; Now set up the dstPixmap structure
        mov     eax, [ebx+2]                     ; pi_map_base          ;**
        mov     dstPixmap.startAddr, eax
        mov     eax, [ebx+6]                     ; pi_map_size          ;**
        mov     dword ptr dstPixmap.xLen, eax
        mov     al, [ebx+10]                     ; pi_map_format        ;**
        mov     dstPixmap.format, al

        ; At this point we want to test the format to see if we writing
        ; to 16 bits per pel. If we are then we want to swap the bytes
        ; within each word of the colors (fg_color and bg_color) so that
        ; in the rest of the MESS we can then pick these up and write
        ; them using the intel processor without having to convert to
        ; motorola format at each point. (Internal bitmaps are always
        ; stored in motorola format).
ifdef MATROX
        ; Actually the swap only needs doing if the internal bitmap
        ; is Motorola format (Matrox screen bitmap is intel format).
        cmp     al, SIXTEEN_BPP or INTEL
else ; MATROX
        ifdef BPP24
        mov     ax,dstPixmap.format
        and     ax,BPP_MASK
        cmp     ax,TWENTYFOUR_BPP
        jz      short got_correct_colour_format
        endif
        test    al, 4
endif ; MATROX
        jz      short got_correct_colour_format
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.fg_colour, ax
        mov     ax, word ptr ShadowXGARegs.bg_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.bg_colour, ax
        mov     ax, word ptr ShadowXGARegs.colour_comp_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.colour_comp_colour, ax
else
        mov     ax, word ptr Shadow8514Regs.Color_1
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_1, ax
        mov     ax, word ptr Shadow8514Regs.Color_0
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_0, ax
        mov     ax, word ptr Shadow8514Regs.Color_Comp
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_Comp, ax
endif

got_correct_colour_format:

        ; Check if there is a source pixmap
        ; Need the byte ptr here even though isUsed is a byte sized field
        ; because MASM is stupid
        mov     byte ptr srcPixmap.isUsed, FALSE
ifndef _8514
        mov     eax, ShadowXGARegs.pixel_op
else
        mov     eax, Shadow8514Regs.pixel_op
endif
        mov     edx, eax                ; save whilst we test BACK_SRC
        and     eax, BACK_SRC_MASK
        cmp     eax, BACK_SRC_SRC_PIX_MAP
        je      short source_used
        and     edx, FORE_SRC_MASK      ; now test FORE_SRC
        cmp     edx, FORE_SRC_SRC_PIX_MAP
        jne     short noSourcePixmap

source_used:
        ; There is a source pixmap so we need to worry about it
ifndef _8514
        mov     eax, ShadowXGARegs.pixel_op
else
        mov     eax, Shadow8514Regs.pixel_op
endif
        and     eax, SRC_PIX_MAP_MASK                                   ;**

        ; top half of eax= 16 * 1, 2 or 3 for pixmaps A, B or C.  Multiply by 12..
        shr     eax, 18          ; change from 16 * 65536 to * 4
        mov     ebx, eax                                                ;**
        add     ebx, ebx                                                ;**
        add     ebx, eax                                                ;**

        ; Set up ebx ready for indexing into pixmap registers
ifndef _8514
        lea     ebx, [ebx].ShadowXGARegs.(pi_map_index_A-12)
else
        lea     ebx, [ebx].Shadow8514Regs.(pi_map_index_A-12)
endif

        ; Now set up the srcPixmap structure
        mov     eax, [ebx+2]                     ; pi_map_base          ;**
        mov     srcPixmap.startAddr, eax
        mov     eax, [ebx+6]                     ; pi_map_size          ;**
        mov     dword ptr srcPixmap.xLen, eax
        mov     al, [ebx+10]                     ; pi_map_format        ;**
        mov     srcPixmap.format, al

        mov     byte ptr srcPixmap.isUsed, TRUE

noSourcePixmap:
        ; Now check for a pattern pixmap
        mov     byte ptr patPixmap.isUsed, FALSE

ifndef _8514
        mov     eax, ShadowXGARegs.pixel_op
else
        mov     eax, Shadow8514Regs.pixel_op
endif
        and     eax, PAT_PIX_MAP_MASK
        cmp     eax, PAT_PIX_MAP_FORE
        je      short noPatternPixmap

        ; There is a pattern pixmap so time to worry about it
        ; eax=4096 * 1, 2 or 3 for pixmaps A, B or C.  Multiply by 12..
        shr     eax, 10         ; change from * 4096 to * 4             ;**
        mov     ebx, eax                                                ;**
        add     ebx, ebx                                                ;**
        add     ebx, eax                                                ;**

        ; Set up bx ready for indexing into pixmap registers
ifndef _8514
        lea     ebx, [ebx].ShadowXGARegs.(pi_map_index_A-12)
else
        lea     ebx, [ebx].Shadow8514Regs.(pi_map_index_A-12)
endif

        ; Now set up the patPixmap structure
        mov     eax, [ebx+2]                     ; pi_map_base          ;**
        mov     patPixmap.startAddr, eax
        mov     eax, [ebx+6]                     ; pi_map_size          ;**
        mov     dword ptr patPixmap.xLen, eax
        mov     al, [ebx+10]                     ; pi_map_format        ;**
        mov     patPixmap.format, al

        mov     byte ptr patPixmap.isUsed, TRUE

noPatternPixmap:

ifdef   BPP24
        ; check if the dst is 24bpp
        mov     ax,dstPixmap.format
        and     ax,BPP_MASK
        cmp     ax,TWENTYFOUR_BPP
        jnz     not_24

        ; save the shadow reg that we will probably modify in the low level
        mov     ax,Shadow8514Regs.dim1
        mov     tmpDim1,ax

        ;Check to see if its a blt or a line call
        mov     eax, Shadow8514Regs.pixel_op
        and     eax, STEP_FN_MASK
        cmp     eax, STEP_PXBLT
        jz      short not_24

        ; @DMS Do this here only for lines
        mov     ax,dstPixmap.xLen
        inc     ax
        mov     dx,3
        mul     dx
        dec     ax
        mov     dstPixmap.xLen,ax

        mov     ax,Shadow8514Regs.src_map_x
        mov     dx,3
        mul     dx
        mov     Shadow8514Regs.src_map_x,ax

        mov     ax,Shadow8514Regs.dest_map_x
        mov     dx,3
        mul     dx
        mov     Shadow8514Regs.dest_map_x,ax

not_24:
endif

        ; Now we have set up these structures it is time to start
        ; recognising the various cases and passing them onto the
        ; appropriate routines.  First divide control flow into the
        ; three basic functions.

        ifndef  _8514
        mov     eax, ShadowXGARegs.pixel_op
        else
        mov     eax, Shadow8514Regs.pixel_op
        endif
        and     eax, STEP_FN_MASK
        cmp     eax, STEP_PXBLT
        je      short pxbltOp
        cmp     eax, STEP_PLOT_STEP
        je      short plotStepOp
        cmp     eax, STEP_FN_LINE_DRAW_WRITE
        je      short lineDrawOp

        ; The operation is a short line op (indicated as a "read plot step")
        cCall   eddf_MESSDoShortLines
        jmp     exitMESS

lineDrawOp:
        ; The operation is a line (bresenham) one..
        cCall   eddf_MESSDoBresenham
        jmp     exitMESS

plotStepOp:
        ; The operation is a plot step..
        cCall   eddf_MESSDoPlotStep
        jmp     exitMESS

pxbltOp:
        ; The operation is a pxblt..
        ; This is handled as many routines optimised for particular
        ; flavours of PxBlt.  There is no true general case - all the
        ; ways the driver uses the hardware for memory bitmaps are
        ; covered by these cases.

        ;  - Destination fill
        ;  - Source copy
        ;  - Destination only
        ;  - Source/destination
        ;    - No wrap-around (from a blt)
        ;    - With wrap-around (from a dither or screen format user pattern)
        ;  - Pattern/destination
        ;    - Top left to bottom right (from a blt etc)
        ;      - Pattern widths
        ;        - 8 pel (one byte)
        ;          - Pattern/destination operations
        ;            - Same foreground and background mixes (from a blt)
        ;            - Different foreground and background mixes (from scanlines)
        ;          - Pattern copy
        ;        - Other widths
        ;          - Pattern/destination operations
        ;            - Same foreground and background mixes (from a blt)
        ;            - Different foreground and background mixes (from scanlines)
        ;          - Pattern copy
        ;    - Bottom left to top right and no wrap-around (from text)
        ;      - Foreground overpaint background leavealone
        ;      - Any other mix combination
        ;  - Pattern/source/destination from bottom left to top right and
        ;    no wrap-around (eg from AA text)
        ;      - Foreground overpaint background leavealone
        ;      - Any other mix combination
        ; 
        ; Source/destination with wrap around applies to 8,1 and 4,1 only
        ; Patter/source/destination applies to 8,1 only

        cmp     byte ptr srcPixmap.isUsed, TRUE
        jz      short sourceIsSetup

        ; No source has been set up so lets see whether the operation
        ; requires a pattern
        cmp     byte ptr patPixmap.isUsed, TRUE
        jz      patternDestination

destinationOnlyOperation:
        ; No pattern either - this looks good but we might still need
        ; to do something other than a fill depending on the mix.  By now
        ; the only mix which can be relevant is the foreground one.  Get
        ; out magic-mix-cookie from the table.
        lea     ebx, ropTypeTable                                ;**
ifndef _8514
        mov     al, ShadowXGARegs.fg_mix
else
        mov     eax, Shadow8514Regs.Function_1
        and     eax, FUNC_ALU
endif
        xlatb
        test    al, DEST_ONLY_FILL
        jz      short fixedSourceOp

        ; This can be done with a simple destination fill - but we need to
        ; work out what to fill with.  Fast path source copy.
ifndef  _8514
        mov     dx, ShadowXGARegs.fg_colour
        mov     al, ShadowXGARegs.fg_mix
        cmp     al, HWMIX_SOURCE
else
        mov     edx, Shadow8514Regs.Color_1
        mov     eax, Shadow8514Regs.Function_1
        and     eax, FUNC_ALU
        cmp     eax, FUNC_S
endif
        jz      short gotFillIndex

ifndef  _8514
        and     al, al
else
        cmp     al, FUNC_ZEROS
endif
        jnz     short @f

        ; Zeroes mix
        xor     dx, dx
        jmp     short gotFillIndex

@@:
ifndef  _8514
        cmp     al, HWMIX_ONES
else
        cmp     al, FUNC_ONES
endif
        jnz     short @f

        ; Ones mix
        mov     edx, 0FFFFh
        jmp     short gotFillIndex

@@:
        ; Must be not source
        not     edx

gotFillIndex:
        mov     _messSPad.srcColour, edx

        lea     eax, MESSBlockFillBase                           ;**
        jmp     doOperation

fixedSourceOp:
        ; This can be done with a fixed source but it will require a mix
        ; to be applied.  The mix is the foreground mix and the source is
        ; the foreground colour
ifndef  _8514
        mov     ax, ShadowXGARegs.fg_colour
else
        mov     eax, Shadow8514Regs.Color_1
endif
        mov     _messSPad.srcColour, eax

        lea     eax, MESSFixedSrcBase                            ;**
        jmp     doOperation

sourceIsSetup:
        ; If a source is set up then it will be used for both foreground and
        ; background.  It is possible that there is a pattern as well eg
        ; anti-aliased text so check for this possibility first
        cmp     patPixmap.isUsed, TRUE
        jz      sourcePatternDestination

        ; This is a source destination operation but we need to know whether
        ; there is a possibility of the source wrapping (ie because its
        ; part of a dither or a user defined pattern at screen format)
        ; BUT this only ever happens if we are blting from the top left
        ; to the bottom right.

ifndef  _8514
        mov     ax, ShadowXGARegs.pixel_op.lo
else
        mov     ax, Shadow8514Regs.pixel_op.lo
endif
        test    ax, BLTDIR_RIGHTTOLEFT+BLTDIR_BOTTOMTOTOP
        jnz     short @F

        mov     ax, srcPixmap.xLen
ifndef  _8514
        sub     ax, ShadowXGARegs.src_map_x
        cmp     ax, ShadowXGARegs.dim1
else
        sub     ax, Shadow8514Regs.src_map_x
        cmp     ax, Shadow8514Regs.dim1
endif
        jb      short wrappedSource

        mov     ax, srcPixmap.yLen
ifndef  _8514
        sub     ax, ShadowXGARegs.src_map_y
        cmp     ax, ShadowXGARegs.dim2
else
        sub     ax, Shadow8514Regs.src_map_y
        cmp     ax, Shadow8514Regs.dim2
endif
        jb      short wrappedSource

@@:
        ; Now we know that this is a simple source destination operation
        ; What we want to do now is find out whether we can do a simple
        ; copy or whether it requires a mix.
ifndef _8514
        mov     al, ShadowXGARegs.fg_mix
        cmp     al, HWMIX_SOURCE
else
        mov     eax, Shadow8514Regs.Function_1
        and     eax, FUNC_ALU
        cmp     eax, FUNC_S
endif
        jnz     short sourceDestinationWithMix

        ; This is a source destination copy
        lea     eax, MESSBlockCopyBase                           ;**
        jmp     doOperation

sourceDestinationWithMix:
        ; This is a source destination with mix
        lea     eax, MESSSrcDestMixBase                          ;**
        jmp     doOperation

wrappedSource:
        ; Here the routine we use will have to cope with the source wrapping
        ; There are two cases we recognise - copy or anything else
ifndef  _8514
        mov     al, ShadowXGARegs.fg_mix
        cmp     al, HWMIX_SOURCE
else
        mov     eax, Shadow8514Regs.Function_1
        and     eax, FUNC_ALU
        cmp     eax, FUNC_S
endif
        jnz     short wrappedSourceWithMix

        ; This is a wrapped source copy
        lea     eax, MESSSrcDestWrapCopyBase                     ;**
        jmp     doOperation

wrappedSourceWithMix:
        ; This is a wrapped source destination with mix
        lea     eax, MESSSrcDestWrapMixBase                      ;**
        jmp     doOperation

patternDestination:
        ; This is a pattern destination only operation.
        ; First we will pass the case where fg colour = bg colour and
        ; fg mix = bg mix back to the code for handling destination only
        ; operations
        ; BUT must also check that we are going from top-left to bottom-right
        ; because this is the only case that destinationOnlyOperation can
        ; cope with.
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_mix
else
        mov     bx, word ptr Shadow8514Regs.Function_1
        and     bx, FUNC_ALU
        rol     bx, 8
        mov     ax, word ptr Shadow8514Regs.Function_0
        and     ax, FUNC_ALU
        or      ax, bx
endif
        xor     al, ah
        jnz     short needPattern

ifndef  _8514
        mov     ax, ShadowXGARegs.fg_colour
        xor     ax, ShadowXGARegs.bg_colour
else
        mov     eax, Shadow8514Regs.Color_1
        xor     eax, Shadow8514Regs.Color_0
endif
        jnz     short needPattern

ifndef  _8514
        mov     ax, ShadowXGARegs.pixel_op.lo
else
        mov     ax, Shadow8514Regs.pixel_op.lo
endif

        ; We test for righttoleft and bottomtotop and if either are set then
        ; we cannot take the special case path
        test    ax, BLTDIR_RIGHTTOLEFT or BLTDIR_BOTTOMTOTOP
        jz      destinationOnlyOperation

needPattern:
        ; First we want to know whether it is a blt operation (TL-BR) or
        ; a text operation (BL-TR) as we handle these cases seperately
ifndef  _8514
        mov     ax, ShadowXGARegs.pixel_op.lo
else
        mov     ax, Shadow8514Regs.pixel_op.lo
endif
        test    ax, BLTDIR_BOTTOMTOTOP
        jnz     patternDestinationText

        ; OK this came from a nice top-left to bottom-right call.  These
        ; handling routines will allow the pattern to wrap around.
        ; First stage is to seperate default (8 pel) width patterns
        mov     ax, patPixmap.xLen
        cmp     ax, 07h
        jne     short nonDefaultPatternWidth

        ; The pattern is one byte wide. If the byte is all ones and
        ; only one pel high then we can optimize by just doing a destination
        ; only operation.
        mov     eax, patPixmap.startAddr
        cmp     byte ptr [eax], 0FFh
        jne     short noSpecialOptimize
        cmp     patPixmap.yLen, 0
        je      destinationOnlyOperation
noSpecialOptimize:

        ; Special case pattern copy as its        popular.
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_mix
        cmp     ax, 0303h       ; fg mix SOURCE, bg mix SOURCE
else
        mov     edx, Shadow8514Regs.Function_1
        and     edx, FUNC_ALU
        mov     ah, dl
        mov     edx, Shadow8514Regs.Function_0
        and     edx, FUNC_ALU
        mov     al, dl
        cmp     ax, 0707h
endif
        jnz     short patternDestinationMixDef

        lea     eax, MESSPatCopyByteBase                         ;**
        jmp     doOperation

patternDestinationMixDef:
        ; Now here this could be from bitblt (where the foreground mix will
        ; equal the background mix) or a scanline (where they might not)
        ; Note that the routines used for these two cases are only
        ; different in the 1,1 case
        xor     ah, al          ; mixes are still here
        jz      short patternDestinationMixBitBltDef

        ; This is a scanline with different foreground and background
        ; mixes.  It is assumed (in the PatDestMixes11 routine) that
        ; this will only be one line high
        lea     eax, MESSPatDestMixesByteBase                    ;**
        jmp     doOperation

patternDestinationMixBitBltDef:
        lea     eax, MESSPatDestByteBase                         ;**
        jmp     doOperation

nonDefaultPatternWidth:
        ; Special case pattern copy as its        popular.
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_mix
        cmp     ax, 0303h       ; fg mix SOURCE, bg mix SOURCE
else
        mov     edx, Shadow8514Regs.Function_1
        and     edx, FUNC_ALU
        mov     ah, dl
        mov     edx, Shadow8514Regs.Function_0
        and     edx, FUNC_ALU
        mov     al, dl
        cmp     ax, 0707h
endif
        jnz     short patternDestinationMix

        lea     eax, MESSPatCopyBase                             ;**
        jmp     short doOperation

patternDestinationMix:
        ; Now here this could be from bitblt (where the foreground mix will
        ; equal the background mix) or a scanline (where they might not)
        ; Note that the routines used for these two cases are only
        ; different in the 1,1 case
        xor     ah, al          ; mixes are still here
        jz      short patternDestinationMixBitBlt

        ; This is a scanline with different foreground and background
        ; mixes.  It is assumed (in the PatDestMixes11 routine) that
        ; this will only be one line high
        lea     eax, MESSPatDestMixesBase                        ;**
        jmp     short doOperation

patternDestinationMixBitBlt:
        lea     eax, MESSPatDestBase                             ;**
        jmp     short doOperation

patternDestinationText:
        ; This came from a bottom-left to top-right call.  This means it
        ; was a text operation.  These operations use pattern destination
        ; to do a source expand operation so the 'pattern' will not wrap
        ; around.  Effectively this is a 1,1 to 8,1 source expansion blt
        ; with the added complication that it will often use different mixes
        ; for foreground and background.

        ; First we will special case background leavealone and foreground
        ; overpaint as its the common text mix
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_mix
        cmp     ax, 0503h       ; fg mix SOURCE bg mix LEAVEALONE
else
        mov     edx, Shadow8514Regs.Function_1
        and     edx, FUNC_ALU
        mov     ah, dl
        mov     edx, Shadow8514Regs.Function_0
        and     edx, FUNC_ALU
        mov     al, dl
        cmp     ax, 0703h       ; fg mix SOURCE bg mix LEAVEALONE
endif
        jz      short bgLeaveFgOverpaint

        lea     eax, MESSPatExpBase                              ;**
        jmp     short doOperation

bgLeaveFgOverpaint:
        lea     eax, MESSPatExpFgBase                            ;**
        jmp     short doOperation

sourcePatternDestination:
        ; This must have come from AA text.  We will special case background
        ; leavealone and foreground overpaint as this is the common
        ; operation
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_mix
        cmp     ax, 0503h       ; fg mix SOURCE bg mix LEAVEALONE
else
        mov     edx, Shadow8514Regs.Function_1
        and     edx, FUNC_ALU
        mov     ah, dl
        mov     edx, Shadow8514Regs.Function_0
        and     edx, FUNC_ALU
        mov     al, dl
        cmp     ax, 0703h       ; fg mix SOURCE bg mix LEAVEALONE
endif
        jz      short bgLeaveFgOverpaintAA

        lea     eax, MESSPatSrcExpBase                           ;**
        jmp     short doOperation

bgLeaveFgOverpaintAA:
        lea     eax, MESSPatSrcExpFgBase                         ;**
        jmp     short doOperation

doOperation:
        ; ax holds the base address of the function table - get the offset
        ; and call the function
        mov     bl, dstPixmap.format
        and     ebx, BPP_MASK                                           ;**

IFDEF FIREWALLS
        ; check to see that 1, 2, 4, 8, or 16 bits per pel is specified as
        ; the format. If 2 bits per pel then this will get firewalled by
        ; the bit per pel look up table for each particular function.
        ifndef  BPP24
        cmp     bl, SIXTEEN_BPP
        else
        cmp     bl, TWENTYFOUR_BPP
        endif
        jle     short @F
        int     3
@@:
ENDIF ; FIREWALLS

        mov     eax, [ebx*4+eax]                                        ;**
        cCall   eax                                                     ;**

exitMESS:

        ; Restore the colours if we converted them to motorola format
        ; earlier on.
ifdef MATROX
        cmp     byte ptr dstPixmap.format, SIXTEEN_BPP or INTEL
else ; MATROX
        ifdef BPP24
        mov     ax,dstPixmap.format
        and     ax,BPP_MASK
        cmp     ax,TWENTYFOUR_BPP
        jz      short got_back_correct_colour_format
        endif
        test    byte ptr dstPixmap.format, 4
endif ; MATROX
        jz      short got_back_correct_colour_format
ifndef  _8514
        mov     ax, word ptr ShadowXGARegs.fg_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.fg_colour, ax
        mov     ax, word ptr ShadowXGARegs.bg_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.bg_colour, ax
        mov     ax, word ptr ShadowXGARegs.colour_comp_colour
        xchg    ah, al
        mov     word ptr ShadowXGARegs.colour_comp_colour, ax
else
        mov     ax, word ptr Shadow8514Regs.Color_1
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_1, ax
        mov     ax, word ptr Shadow8514Regs.Color_0
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_0, ax
        mov     ax, word ptr Shadow8514Regs.Color_Comp
        xchg    ah, al
        mov     word ptr Shadow8514Regs.Color_Comp, ax
endif
got_back_correct_colour_format:

        ifdef   BPP24
        mov     al,dstPixmap.format
        and     al,BPP_MASK
        cmp     al,TWENTYFOUR_BPP
        jnz     short @f

        mov     eax, Shadow8514Regs.pixel_op
        and     eax, STEP_FN_MASK
        cmp     eax, STEP_PXBLT
        jnz     short  @f

        ; do not multiply the widths and x offsets if a pattern is involved
        cmp     byte ptr patPixmap.isUsed, TRUE
        jz      short @f

        mov     ax,tmpDim1
        mov     Shadow8514Regs.dim1,ax
@@:
        endif

        ;restore the direction flag from the stack (and the others too!)
        popfd
cEnd



;-------------------------------------------------------------------------
;
; Function: eddf_MESSFirewallFunction
;
; This function should never be called as it is in the call tables for
; functions which should never happen :-
;   2,1 format destination
;   source/destination with wrap around at 1,1
;   AA text
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSFirewallFunction, <PUBLIC,NODATA>             ;**

cBegin
        ; Halt.
        int     3
cEnd

;-------------------------------------------------------------------------
;
; Function: PatDestBlt8bppTo1bpp
;
; Defect 62334
; This function is called when the application is doing a BitBlt under
; the following conditions;
;
; ROP = ROP_PATCOPY
; Pattern is color (8 bpp)
; Pattern origin is not at 0,0
; Destination is a memory DC at 1 bpp
;
; Currently we do not handle this condition.  The only known application
; issueing this weird operation is "Draw" by MicroGrafx.  Previously we
; were hitting eddf_MESSFirewallFunction, causing the system to hang at
; an INT 3.  If we allow this operation to proceed everything works fine
; with no known side effects.  If we ever decide to support this operation
; the best way to handle it would be to use the "Convert_Colour_To_Mono"
; routine back up in eddb_BitBlt.  PATT_DST_BLT would have to be enhanced
; to detect this condition and convert the color bitmap to a mono bitmap.
; Special care must be taken to free all allocated resources.  The bitmap
; cache must also be left in a correct state.
;
;-------------------------------------------------------------------------

        align   4
cProc   PatDestBlt8bppTo1bpp, <PUBLIC,NODATA>             ;**

cBegin

ifdef FIREWALLS
        ; Halt.
        int     3
endif  ;FIREWALLS

cEnd




;-------------------------------------------------------------------------
;
; Function: eddf_MESSDummyMixesRoutine
;
; This function is never called. It contains expansions of the mix macros
; and these are used to create the mix jump tables used.
; (See mixOffsetJumpTable expanasions in the data segment).
;
;-------------------------------------------------------------------------

        align   4
cProc   eddf_MESSDummyMixesRoutine,<NODATA>
cBegin

        mixTrashSourcePart      ah,  al,  mixTrashSourcePartBY
        mixTrashSourcePart      eax, ebx, mixTrashSourcePartDW
        mixKeepSourcePart       eax, ebx, mixKeepSourcePartDW
        mixKeepSourcePart       ah,  al,  mixKeepSourcePartBY
        mixTrashSourceAll       ah,  al,  mixTrashSourceAllBY
        mixTrashSourceAll       ax,  bx,  mixTrashSourceAllDW
        mixTrashSourceAll       eax, ebx, mixTrashSourceAllDD

cEnd

_TEXT   ends

END
