;*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.;
;*****************************************************************************/
        page    ,132
;/*****************************************************************************
;*
;* SOURCE FILE NAME =  SCANLIN2.ASM
;*
;* DESCRIPTIVE NAME =  Scanline sub-function of Output
;*
;*
;* VERSION      V2.0
;*
;* DATE         02/22/87
;*
;* DESCRIPTION   This module contains the scanline sub-function of Output.  
;*              
;*              
;* FUNCTIONS    NONE
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*****************************************************************************/

        .386

        .xlist

INCL_GRE_CLIP           equ     1
INCL_GRE_SCANS          equ     1
INCL_GPIREGIONS         equ     1
INCL_GPIERRORS          equ     1
INCL_DDIMISC            equ     1
INCL_DEV                equ     1
INCL_DDICOMFLAGS        equ     1
DINCL_ROPS              equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include pmgre.inc
        include driver.inc
        include egafam.inc
        include display.inc
        include scanline.inc
        include assert.mac
        include extern.inc
        include protos.inc
ifdef EGAMEM_IS_STRUCT
        include egamem.inc
endif
if SCAN_CNT EQ 768
        include oem_macs.inc
endif
        .list

        .MODEL FLAT,SYSCALL

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT
.CODE
public rops_start
public ega_first_last
public ega_inner_latch
public ega_inner_stosb


page

;/***************************************************************************
;*
;* PUBLIC ROUTINE  ega_first_last  
;*
;* DESCRIPTION   = ega_first_last handles the first and last bytes of the raster
;*                 operations which can be performed in one pass, and the inner
;*                 loop of those raster operations which can be performed in one
;*                 pass that cannot use stosb.
;*               
;*                 The following conditions must be met:
;*               
;*                     a)  The destination is the EGA
;*                     b)  single pass rop
;*                     c)  rep stosb cannot be used if for the inner loop
;*               
;*               
;*                 This function can handle both opaque and transparent modes.
;*                 
;*                 Registers Preserved: 
;*                       BX,SI,DS,ES,BP 
;*                 Registers Destroyed: 
;*                       AX,DX,FLAGS    
;*
;* INPUT         = DS:DI    --> destination byte                            
;*                 ES:DI    --> destination byte                            
;*                    AL     =  transparency/first/last mask as appropriate 
;*                    CX     =  byte count                                  
;*                 GRAF_ADDR =  GRAF_BIT_MASK                               
;*
;* OUTPUT        = DS:DI    --> next destination word     
;*                 ES:DI    --> next destination word     
;*                    CX     =  0                         
;*                 GRAF_ADDR =  GRAF_BIT_MASK             
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
ega_first_last::

        mov     dx,EGA_BASE+GRAF_DATA
        out     dx,al
        xchg    eax,esi
        mov     esi,edi                 ;Must not destroy SI
        rep     movsb
        xchg    esi,eax

        ret

page

;/***************************************************************************
;*
;* PUBLIC ROUTINE   Raster Operation Subroutines  
;*
;* DESCRIPTION   = 
;*
;*       The following subroutines implement the foreground mix modes.
;*       They all have the same register interface.
;*      
;*       The code has been compressed so that the address table could
;*       be stored as bytes instead of words.  This is accomplished
;*       mainly by combining rops with their inverses. The inverse of
;*       rop A is rop B if
;*      
;*             rop A  maps  0 --> x, 1 --> y
;*       whereas
;*             rop B  maps  0 --> y, 1 --> x.
;*      
;*       The pattern will have been pre-inverted for all the "inverses"
;*       (look for the ALT_NEG_PATTERN flag in another_tbl to see which
;*       are the "inverses").
;*      
;*       In addition, some rops were embedded in others, code-wise, in
;*       such a way that the larger could be written to fall through to
;*       the smaller (e.g. transp_dpna and transp_dpa falling through to
;*       transp_ddx).  Unfortunately this makes the code harder to read.
;*      
;*       Many of the rops require a third work register, so BX is used
;*       and reloaded afterwards.
;*      
;*       Entry:
;*             AX = transparency mask
;*             BX = pattern
;*             CX = loop count
;*             SI = index into table of per-plane processor blocks
;*             DS:DI --> destination
;*             ES:DI --> destination
;*             direction flag cleared
;*       Returns:
;*             CX = 0
;*             DS:DI --> next destination
;*             ES:DI --> next destination
;*             direction flag cleared
;*       Registers Preserved:
;*             BX,SI,BP,DS,ES
;*       Registers Destroyed:
;*             AX,DX,flags
;*      
;*      ---------------------------------------------------------------;
;*      
;*       The following table describes the boolean logic necessary for
;*       creating any desired masks from the transparency mask and pattern.
;*       To use it, determine what mask behavior you want (remember to invert
;*       AND masks), look it up, then look across to see how to set it up.
;*       The columns indicate the mask bits for foreground 1's, foreground 0's,
;*       background 1's, and background 0's, respectively.
;*      
;*      
;*                                          s s s s
;*                                         1 0 1 0
;*      
;*                                       g g k k
;*                                      f f b b
;*      
;*              transparency mask (AX)  1 1 0 0
;*                        pattern (BX)  1 0 1 0
;*                                      -------
;*                                      0 0 0 0         0
;*                                      0 0 0 1         not (AX or BX)
;*                                      0 0 1 0         not AX and BX
;*                                      0 0 1 1         not AX
;*                                      0 1 0 0         AX and not BX
;*                                      0 1 0 1         not BX
;*                                      0 1 1 0         AX xor BX
;*                                      0 1 1 1         not (AX and BX)
;*                                      1 0 0 0         AX and BX
;*                                      1 0 0 1         not (AX xor BX)
;*                                      1 0 1 0         BX
;*                                      1 0 1 1         not AX or BX
;*                                      1 1 0 0         AX
;*                                      1 1 0 1         AX or not BX
;*                                      1 1 1 0         AX or BX
;*                                      1 1 1 1         1
;*      
;*      
;*       For example, take the rop DPon with opaque background.  On a plane
;*       by plane basis, the rop's effect is to write 0's where the pattern
;*       is 1, and invert the destination where the pattern is 0.  This can
;*       be done with an AND mask and an XOR mask.  The AND mask clears out
;*       all the bits corresponding to foreground 1's or to background bits.
;*       The XOR mask flips bits corresponding to foreground 0's or
;*       background 1's. The AND mask must be applied first to get the
;*       correct background color.
;*      
;*       DPon: inverse (source or destination), mix mode 10
;*      
;*           pattern
;*          foreground  effective
;*             bit         rop
;*           -------------------
;*              0   -->   ~dest
;*              1   -->     0
;*      
;*              background mix = OverPaint (P):
;*      
;*              AND mask behavior: 0 1 0 0  ==> mask logic: (AX and not BX)
;*      
;*                                 | | | |
;*                                 | | | +----- clear background 0's
;*                                 | | |
;*                                 | | +------- clear background 1's
;*                                 | |
;*                                 | +--------- don't touch foreground 0's
;*                                 |
;*                                 +----------- clear foreground 1's
;*      
;*      
;*              XOR mask behavior: 0 1 1 0  ==> mask logic: (AX xor BX)
;*      
;*                                 | | | |
;*                                 | | | +----- don't touch background 0's
;*                                 | | |
;*                                 | | +------- invert (i.e. set) background 1's
;*                                 | |
;*                                 | +--------- invert foreground 0's
;*                                 |
;*                                 +----------- don't touch foreground 1's
;*      
;*      
;*      ---------------------------------------------------------------;
;*       The following table describes the behavior of each raster operation
;*       plane by plane, bit by bit. The mapping is from pattern bits to
;*       effective rops (DDx, Dn, D, DDxn) on the destination.  This table
;*       is a convenient reference for figuring out the necessary masks for
;*       rop subroutines, as well as a good display of the symmetry of rop
;*       behavior.
;*      
;*             DDx             PDna            DPa             P
;*               0 ->  0         0 ->  0         0 ->  0         0 ->  0
;*               1 ->  0         1 -> ~dest      1 ->  dest      1 ->  1
;*      
;*             DPon            Dn              DPxn            PDno
;*               0 -> ~dest      0 -> ~dest      0 -> ~dest      0 -> ~dest
;*               1 ->  0         1 -> ~dest      1 ->  dest      1 ->  1
;*      
;*             DPna            DPx             D               DPo
;*               0 ->  dest      0 ->  dest      0 ->  dest      0 ->  dest
;*               1 ->  0         1 -> ~dest      1 ->  dest      1 ->  1
;*      
;*             Pn              DPan            DPno            DDxn
;*               0 ->  1         0 ->  1         0 ->  1         0 ->  1
;*               1 ->  0         1 -> ~dest      1 ->  dest      1 ->  1
;*      
;*      
;*      ---------------------------------------------------------------;
;*       Catalog of masks for raster operations:
;*      
;*             If the inverse is mentioned at the right, then the
;*             rop has been implemented by pre-inverting the pattern
;*             and executing the inverse rop's subroutine.
;*      
;*             DDx
;*                 D
;*                     AND:    not AX
;*                 P
;*                     AND:    not AX and BX
;*      
;*             DPon                                    inverse of PDna
;*                 D
;*                     AND:    not (AX and BX)
;*                     XOR:    AX and not BX
;*                 P
;*                     AND:    AX and not BX
;*                     XOR:    AX xor BX
;*      
;*             DPna                                    inverse of DPa
;*                 D
;*                     AND:    not (AX and BX)
;*                 P
;*                     AND:    AX and not BX
;*                     XOR:    not AX and BX
;*      
;*             Pn                                      inverse of P
;*                 D   no masks (uses double-xor trick)
;*                 P   no masks (uses rep stosw)
;*      
;*             PDna
;*                 D
;*                     AND:    not AX or BX
;*                     XOR:    AX and BX
;*                 P
;*                     AND:    AX and BX
;*                     XOR:    BX
;*      
;*             Dn
;*                 D
;*                     XOR:    AX
;*                 P
;*                     AND:    AX
;*                     XOR:    AX or BX
;*      
;*             DPx
;*                 D
;*                     XOR:    AX and BX
;*                 P
;*                     AND:    AX
;*                     XOR:    BX
;*      
;*             DPan
;*                 D
;*                     OR:     AX and not BX
;*                     XOR:    AX and BX
;*                 P
;*                     OR:     not (AX and BX)
;*                     XOR:    not (AX xor BX)
;*      
;*             DPa
;*                 D
;*                     AND:    not AX or BX
;*                 P
;*                     AND:    AX and BX
;*                     XOR:    not AX and BX
;*      
;*             DPxn                                    inverse of DPx
;*                 D
;*                     XOR:    AX and not BX
;*                 P
;*                     AND:    AX
;*                     XOR:    AX xor BX
;*      
;*             D
;*                 D   no masks (just advance destination pointer)
;*                 P
;*                     AND:    AX
;*                     XOR:    not AX and BX
;*      
;*             DPno                                    inverse of DPo
;*                 D
;*                     OR:     AX and not BX
;*                 P
;*                     AND:    AX and BX
;*                     XOR:    AX xor BX
;*      
;*             P
;*                 D   no masks (uses double-xor trick)
;*                 P   no masks (uses rep stosw)
;*      
;*      
;*             PDno                                    inverse of DPan
;*                 D
;*                     AND:    not (AX and BX)
;*                     XOR:    AX
;*                 P
;*                     AND:    AX and not BX
;*                     XOR:    AX or BX
;*      
;*             DPo
;*                 D
;*                     OR:     AX and BX
;*                 P
;*                     AND:    AX and not BX
;*                     XOR:    BX
;*      
;*             DDxn
;*                 D
;*                     OR:     AX
;*                 P
;*                     OR:     AX or BX
;*                 
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
rops_start      label   byte

do_nothing      PROC

                RET

do_nothing      ENDP

ALIGN 4
transp_dpna     PROC

transp_dpa      PROC

        not     eax
        or      eax,ebx
        not     eax                     ;compensate for "not ax" in transp_ddx

transp_dpa      ENDP

transp_dpna     ENDP

transp_ddx      PROC

        not     eax
@@:
        and     WORD PTR [edi],ax
        inc     edi
        inc     edi
        dec     ecx
        jnz     @B

                RET

transp_ddx      ENDP

ALIGN 4
transp_pn       PROC

transp_p        PROC

        not     eax                     ;Need inverse for unaltered bits
        xchg    eax,edx                 ;Need to use the work register
@@:
        mov     ax,WORD PTR [edi]       ;Quicker to dest into a register
        xor     eax,ebx                 ;Invert bits which will not change
        and     eax,edx                 ;Set new bits to 0
        xor     eax,ebx                 ;Invert unchanged again, set new bits
        stosw                           ;Store and update destination ptr
        dec     ecx
        jnz     @B                      ;Until all have been processed     

                RET

transp_p        ENDP

transp_pn       ENDP

ALIGN 4
transp_dpon     PROC

transp_pdna     PROC

        push    ebx
        mov     edx,ebx                 ;Need to use the work register
        and     ebx,eax                 ;XOR mask
        not     eax
        or      edx,eax                 ;AND mask
@@:
        mov     ax,WORD PTR [edi]       ;Quicker to have dest into a register
        xor     eax,ebx                 ;Invert bits as needed
        and     eax,edx                 ;Set bits to 0 as needed
        stosw                           ;Store and update destination ptr
        dec     ecx
        jnz     @B
        pop     ebx

                RET

transp_pdna     ENDP

transp_dpon     ENDP

transp_dpxn     PROC

ALIGN 4
transp_dpx      PROC

        and     eax,ebx

transp_dpx      ENDP

transp_dpxn     ENDP

transp_dn       PROC

@@:
        xor     WORD PTR [edi],ax
        inc     edi
        inc     edi
        dec     ecx
        jnz     @B

                RET

transp_dn       ENDP

ALIGN 4
transp_pdno     PROC

transp_dpan     PROC

        push    ebx
        mov     edx,ebx                 ;Need to use the work register
        and     ebx,eax                 ;XOR mask
        not     edx                     ;Map 0 ==> 1 for ORing
        and     edx,eax                 ;OR mask

@@:
        mov     ax,WORD PTR [edi]       ;Quicker to have dest into a register
        xor     eax,ebx                 ;Invert bits as needed
        or      eax,edx                 ;Set bits to 1 as needed
        stosw                           ;Store and update destination ptr
        dec     ecx
        jnz     @B                      ;Until all have been processed   
        pop     ebx

        RET

transp_dpan     ENDP

transp_pdno     ENDP

ALIGN 4
transp_dpno     PROC

transp_dpo      PROC

        and     eax,ebx

transp_dpo      ENDP

transp_dpno     ENDP

transp_ddxn     PROC

@@:
        or      WORD PTR [edi],ax
        inc     edi
        inc     edi
        dec     ecx
        jnz     @B

                RET

transp_ddxn     ENDP

;/*
;** transp_d
;**
;** This is only used when the foreground is D, the background
;** is P, and there are clipped words to output.  The pointer
;** must be updated so the inner loop code will fill in the
;** background bits correctly.
;*/

ALIGN 4
transp_d        PROC

        add     ecx,ecx
        add     edi,ecx                 ;just advance the pointer
        xor     ecx,ecx

                RET

transp_d        ENDP

page

;/***************************************************************************
;*
;* PUBLIC ROUTINE  ega_inner_latch
;*
;* DESCRIPTION   = 
;*
;*        ega_inner_latch handles the inner loop bytes of a scanline when all
;*        of the following conditions are met:
;*     
;*            a)  The destination is the EGA
;*            b)  The raster op is either P or Pn
;*            c)  No transparency
;*            d)  The brush is non-solid
;*     
;*        The pattern which is stored at EGAMem:current_brush[0] will
;*        be loaded into the latches and stored into the destination.
;*                 
;*        Registers Preserved:           
;*              BX,SI,DS,ES,BP           
;*        Registers Destroyed:           
;*              AX,DX,FLAGS              
;*
;* INPUT         = DS:DI    --> destination byte 
;*                 ES:DI    --> destination byte 
;*                    AL     =  0FFh             
;*                    CX     =  byte count       
;*                 GRAF_ADDR =  GRAF_BIT_MASK    
;*
;* OUTPUT        = DS:DI    --> next destination word  
;*                 ES:DI    --> next destination word  
;*                    CX     =  0                      
;*                 GRAF_ADDR =  GRAF_BIT_MASK          
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
ega_inner_latch::
        mov     edx,EGA_BASE+SEQ_DATA
        mov     al,MM_ALL
        out     dx,al
        mov     dl,GRAF_DATA
        xor     eax,eax                 ;Setting all bits to 0 will cause
        out     dx,al                   ;  the latches to be used
        push    edi
        mov     edi,pVRAMInstance
        OVAccess        ;access offscreen VRAM
ifdef EGAMEM_IS_STRUCT
        lea     edi,[edi].EGAMem.current_brush[0]   ;Use the first location of the brush
else
        lea     edi,[edi+current_brush] ;Use the first location of the brush
endif
        mov     al,BYTE PTR [edi]       ;Load the latches with the pattern
        OVRestore                       ;Restore VGA to previouse state
        pop     edi
        rep     stosb

        ret
page

;/***************************************************************************
;*
;* PUBLIC ROUTINE  ega_inner_stosb 
;*
;* DESCRIPTION   = ega_inner_stosb handles the inner loop bytes of a scanline 
;*                 when all of the following conditions are met:              
;*                                                                            
;*                 a)  The destination is the EGA  
;*                 b)  No transparency             
;*                 c)  rep stosb can be used       
;*
;*                 Registers Preserved:  
;*                       BX,SI,DS,ES,BP  
;*                 Registers Destroyed:  
;*                       AX,DX,FLAGS     
;*
;* INPUT         = DS:DI    --> destination byte 
;*                 ES:DI    --> destination byte 
;*                    AL     =  0FFh             
;*                    CX     =  byte count       
;*                 GRAF_ADDR =  GRAF_BIT_MASK    
;*
;* OUTPUT        = DS:DI    --> next destination word 
;*                 ES:DI    --> next destination word 
;*                    CX     =  0                     
;*                 GRAF_ADDR =  GRAF_BIT_MASK         
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
ega_inner_stosb::

        mov     edx,EGA_BASE+GRAF_DATA  ;Transparency mask must be FF
        out     dx,al
        rep     stosb

        ret
end
