;*DDK*************************************************************************/
;
; COPYRIGHT (C) Lexmark Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;*****************************************************************************
;*
;* SOURCE FILE NAME = ASMUTILS
;*
;* DESCRIPTIVE NAME =
;*
;*
;* VERSION
;*
;* DATE
;*
;* DESCRIPTION
;*
;* FUNCTIONS   prdu_dwordset
;*             prdu_bitcopy
;*             prdu_writerow
;*
;* NOTES
;*
;* STRUCTURES
;*
;* EXTERNAL REFERENCES
;*
;* EXTERNAL FUNCTIONS
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG          APAR     CHANGE DESCRIPTION
;*   --------  ----------    -----    --------------------------------------
;*  10/11/91 Randy O'Neal    - PD00481 : Created new .ASM module to hold
;*                             common .ASM routines for all three drivers.
;*                             Removed these functions from BITMOUT.ASM to
;*                             reduce driver size.
;*
;*  01/16/92 Brian Hillenburg- PD00629 : Add new routine to create the
;*                             vertical raster bytes for 24 wire printers
;*
;*  01/29/92 Brian Hillenburg- PD00645 : Check to make sure that the offset
;*                             of the current raster pointer is greater than
;*                             the one currently stored in LastSetRasterPtr
;*  03/11/92 Sue Murch       - INKJET : Add new routine that merges to raster
;*                             output buffers into a third buffer.
;*
;*  12/15/92 L. Cheatham     - PD00775 : Save and restore additional used
;*                             registers.
;*
;******************************************************************************

.386p
INCL_NOCOMMON    EQU   1
.xlist
INCLUDE 32cmacro.inc
?PLM = CC_SYSCALL
INCLUDE os2.inc
.list

wordpart      struc
   lo         dw         ?
   hi         dw         ?
wordpart      ends


MINRULE equ 4

;;      extrn     prdd_HugeInc:proc

CODE32    SEGMENT DWORD USE32 PUBLIC 'CODE'
    ASSUME      CS:FLAT, SS:FLAT, ES:FLAT, DS:FLAT

;--------------------------------------------------------------
;
; PD00406 : Set supplied DWORD into bitmap Count times.
;
;--------------------------------------------------------------
;--------------------------------------------------------------
; PD00775 : Save cx, di, si registers
;--------------------------------------------------------------
cProc   prdu_dwordset,<PUBLIC,NODATA,NONWIN>,<ecx,ds,edi,esi>
        parmD   lpTrg
        parmD   lpSrc
        parmW   Count

cBegin
        mov     edi,lpTrg
        mov     esi,lpSrc
        movzx   ecx,Count
        jz      ps_exit1
        mov     eax,dword ptr [esi]
next_dword:
        mov     dword ptr [edi],eax
       ;inc     edi
        add     edi,4
        dec     ecx
        jnz     next_dword

ps_exit1:
cEnd

;--------------------------------------------------------------
;
; PD00474 : Copy usCount bits of data from source to target
;           starting from bit 'Start' and wrapping at bit 'width'
;           Assumes that only one DWORD is being written
;
;--------------------------------------------------------------
;--------------------------------------------------------------
; PD00775 : Save cx, di, si registers
;--------------------------------------------------------------
cProc   prdu_bitcopy,<PUBLIC,NODATA,NONWIN>,<ecx,ds,edi,esi>

        parmD   lpDst
        parmD   lpSrc
        parmW   usCount
        ParmW   usStart
        ParmW   usWidth

cBegin

        mov     esi,lpSrc               ; get the source address
        mov     edi,esi                 ; edi will be the last byte in the source

        movzx   eax, usWidth            ; width is in bits
        shr     eax, 3                  ; now in bytes
        add     edi,eax                 ; 
        dec     edi                     ; edi is now address of last byte

        movzx   eax, usStart            ; 
        mov     ecx, eax                ; 
        and     ecx, 7                  ; ecx is the bits to shift

        shr     eax, 3
        add     esi, eax                ; esi is now the address of the first byte

;       Now get a DWORD into DX and AX

        mov     ah, byte ptr [esi]    ; get the first byte
        cmp     esi, edi
        jne     $0001
        mov     esi, dword ptr lpSrc
        jmp     $8001

$0001:  inc     esi
$8001:  mov     al, byte ptr [esi]
        cmp     esi, edi
        jne     $0002
        mov     esi, dword ptr lpSrc
        jmp     $8002

$0002:  inc     esi
$8002:  mov     dh, byte ptr [esi]
        cmp     esi, edi
        jne     $0003
        mov     esi, dword ptr lpSrc
        jmp     $8003

$0003:  inc     esi
$8003:  mov     dl, byte ptr [esi]


;       Rotate DX and AX by the required amount

        rol   ax, cl
        rol   dx, cl

        mov   ch, 1
        shl   ch, cl
        dec   ch
        shr   cx, 8

        mov   si, ax
        mov   di, dx

        or    ax, cx
        or    dx, cx

        not   cx

        or    si, cx
        or    di, cx

        and   ax, di
        and   dx, si

;       Write the DWORD back into the target

        mov    esi,lpDst
        mov    byte ptr [esi  ], ah
        mov    byte ptr [esi+1], al
        mov    byte ptr [esi+2], dh
        mov    byte ptr [esi+3], dl

bit_copy_exit:

cEnd

;--------------------------------------------------------------
;
; PD00474 : This function writes usCount DWORDS into LPDst.
;           Each time ulPatdword is written in, the first DWORD
;           is written using ulStartMask, the last using ulEndMask.
;
;--------------------------------------------------------------
;--------------------------------------------------------------
; PD00775 : Save bx, cx, di, si registers
;--------------------------------------------------------------
cProc   prdu_writerow,<PUBLIC,NODATA,NONWIN>,<ebx,ecx,ds,edi,esi>

        parmD   lpDst
        parmD   ulPatDword
        parmD   ulStartMask
        ParmD   ulEndMask
        ParmD   ulMidMask
        parmW   usCount
        parmW   usBGMix

cBegin

start_write_row:
        mov     edi, lpDst                ; get the target address
        movzx   esi, usCount               ; get the count

        dec     esi
        jnz     many_dwords

one_dword:
        mov     eax, ulPatDword          ; get the pattern dword
        mov     edx, ulStartMask         ; get the start mask
        and     edx, dword ptr ulEndMask  ; combine with end mask

        mov     ecx, dword ptr [edi]     ; copy the target dword
        mov     ebx, eax                 ; foreground mix is always overpaint
        and     ebx, edx                 ; mask the update bits
        not     edx                      ; invert the mask
        and     ecx, edx                 ; mask the non update bits
        or      ebx, ecx                 ; combine the two target dwords
        mov     dword ptr[edi], ebx      ; write the target word

        jmp     write_row_exit

many_dwords:

first_dword_1:
   ;    push    edi                      ; save the start address
   ;    push    esi                      ; save the count

        mov     eax, ulPatDword          ; get the pattern dword
        mov     edx, ulStartMask ; get the start mask

        mov     ecx, dword ptr [edi]       ; copy the target word
        mov     ebx, eax                   ; combine with the pattern
        and     ebx, edx                   ; mask the update bits

        not     edx                       ; invert the mask
        and     ecx, edx                   ; mask the non update bits

        or      ebx, ecx                   ; combine the two target words
        mov     dword ptr [edi], ebx     ; write the target word

middle_1:
        add     edi, 4
        dec     esi
        jz      last_dword_1

        cmp     word ptr usBGMix, 2           ;  BM_OVERPAINT
        jz      overpaint_1

leavealone_1:
        mov     edx, ulMidMask   ; get the start mask
        mov     ecx, dword ptr [edi]     ; copy the target word
        mov     ebx, eax                   ; combine with the pattern
        and     ebx, edx                   ; mask the update bits

        not     edx                       ; invert the mask
        and     ecx, edx                   ; mask the non uptate bits

        or      ebx, ecx                   ; combine the two target words
        mov     dword ptr [edi], ebx     ; write the target word

        jmp     middle_1

overpaint_1:
        mov     dword ptr [edi], eax
        jmp     middle_1

last_dword_1:
        mov     edx, ulEndMask           ; get the start mask
        mov     ecx, dword ptr [edi]     ; copy the target word
        mov     ebx, eax                   ; combine with the pattern
        and     ebx, edx                   ; mask the update bits

        not     edx                       ; invert the mask
        and     ecx, edx                   ; mask the non uptate bits

        or      ebx, ecx                   ; combine the two target words
        mov     dword ptr [edi], ebx       ; write the target word

write_row_exit:

cEnd

;--------------------------------------------------------------
;
; PD00629 : This function creates vertical raster from the buffer
;           that is passed to the function.
;
;--------------------------------------------------------------
;--------------------------------------------------------------
; PD00775 : Save bx, cx, di, si registers
;--------------------------------------------------------------
cProc   prdu_createraster,<PUBLIC,NODATA,NONWIN>,<ebx,ecx,ds,edi,esi>

        parmD   InitRasterPtr
        parmD   TestRasterPtr
        parmD   CurrScanPtr
        parmD   LastSetRasterPtr
        parmB   ScanMask
        parmB   RasterMask

cBegin

        sub     edx, edx
        mov     esi,CurrScanPtr
        mov     ebx,dword ptr [esi]
        mov     al, byte ptr [ebx]
        mov     cl, ScanMask
        mov     edi, InitRasterPtr
        mov     ah, byte ptr [edi]
        mov     ch, RasterMask
        jmp     teststate
increment:
        add     edi, 0003
        jmp     teststate
checkptr:
        add     edi, 0003
        cmp     TestRasterPtr, edi
        jbe     endproc
        mov     al, byte ptr [ebx]
        jmp     endoftest
teststate:
        cmp     TestRasterPtr, edi
        jbe     endproc
endoftest:
        mov     ah, byte ptr [edi]
        test    al, cl
        jz      setbit
        cmp     al, 0ffh
        jnz     endofif
        add     edi, 0015h
        inc     ebx
        cmp     ebx, 0000
        jmp     checkptr
setbit:
        or      ah, ch
        mov     byte ptr [edi], ah
        mov     edx, edi
endofif:
        shr     cl, 1
        cmp     cl, 0
        jnz     increment
        mov     cl, 80h
        inc     ebx
        cmp     ebx, 0000
        jmp     checkptr
endproc:
        mov     dword ptr [esi], ebx
        cmp     edx, 0000
        jz      finalend
        mov     esi, LastSetRasterPtr
        mov     eax, dword ptr [esi]
        cmp     edx, eax
        jbe     finalend
        mov     dword ptr [esi], edx
finalend:

cEnd

;------------------------------------------------------------------------------;
; INKJET: Routine to merger OutputBuffer1 and OutputBuffer2 into OutputBuffer3 ;
;         by alternating every 3 bytes from buffers 1 and 2.  This is for      ;
;         360 x 360 resolution,  it is a one pass procedure for the inkjet     ;
;         PPDS printers 4070 and 4072                                          ;
;------------------------------------------------------------------------------;
;--------------------------------------------------------------
; PD00775 : Save bx, cx, di, si registers
;--------------------------------------------------------------
cProc prdu_mergeraster,<PUBLIC,NODATA,NONWIN>,<ebx,ecx,ds,edi,esi>

parmD   OutputBuffer3
parmD   OutputBuffer1
parmD   OutputBuffer2
parmW   RasterLength

cBegin

        ;Load the RasterLength into a register
        mov cx, RasterLength

        ;Load the segment registers with each of the three
        mov edi, OutputBuffer3               ;Get OutputBuffer3

mainloop:
        mov  esi, OutputBuffer1             ;Get OutputBuffer1
        cmp RasterLength, cx                ;Restore offset of OutputBuffer1
        jz next1                            ;for all but the first time through
        mov esi, eax

next1:  mov dx, [esi]                        ;Load the first word of
        mov [edi], dx                        ;OutputBuffer1 into the dx register
        inc esi                              ;and then into OutputBuffer3.  Then
        inc edi                              ;increment the pointers to both.

        mov dx, [esi]                     ;Second byte
        mov [edi], dx
        inc esi
        inc edi

        mov dx, [esi]                     ;Third byte
        mov [edi], dx
        inc esi
        inc edi

        mov eax, esi                          ;Save the Offset of OutputBuffer1

        mov esi, OutputBuffer2               ;Get OutputBuffer2
        cmp RasterLength, cx                ;Restore offset of OutputBuffer2
        jz next2                            ;for all but the first time through
        mov esi, ebx

next2:  mov dx, [esi]                       ;Load the first byte of
        mov [edi], dx                     ;OutputBuffer2 into the dx register
        inc esi                              ;and then into OutputBuffer3.  Then
        inc edi                              ;increment the pointers to both.

        mov dx, [esi]                     ;Second byte
        mov [edi], dx
        inc esi
        inc edi

        mov dx, [esi]                     ;Third byte
        mov [edi], dx
        inc esi
        inc edi

        mov ebx, esi                          ;Save the Offset of OutputBuffer2

        ;Subtract off three from RasterLength and then repeat the loop if
        ;not zero.  RasterLength is the length of OutputBuffers 1 and 2.  So
        ;when RasterLength is zero then both of these buffers are empty and
        ;OutputBuffer3 has been created.
        sub cx, 3
        jge mainloop

cEnd

CODE32  ENDS

        end
