;*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          = EDDHSHRT
;
;   Description     = PM shortline drawing code
;
;   Function        = Does short line drawing work
;
;
;***********************************************************************

INCL_GPIBITMAPS EQU     1
include os2.inc
include eddinclt.inc

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

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

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

; External access for this module
ifndef   _8514
pXGARegs         equ <_pXGARegs>
else
include 8514.inc
p8514Regs        equ <_p8514Regs>
endif

ifndef   _8514
extrn pXGARegs          :dword
else
extrn p8514Regs         :dword
endif
extrn _AIxfer           :dword
extrn _SPad             :dword
extrn _LinePatternCur   :dword
extrn _pbHWPollRegister :dword

;***********************************************************************
; handle the soft draw/hard draw differences
;***********************************************************************
IFDEF HARD_DRAW
public  _eddh_PMSHORTLINES

PMShortLines    equ     <_eddh_PMSHORTLINES>
bitmap_address  equ     phys_addr

IF1             ; macro defined on pass 1 only
;----------------------------------------------------------------------
; macro for this code file

; this macro takes a plot step code in 'step' and attempts to add it to
; our collection in edx.  It can tell when it has filled edx because
; one of the bytes in edx has a 1 in it so when it adds dl and al the
; result will not equal 'step' for this byte.  If it finds this it must
; wait for the hardware and then output the plot steps in edx.  Note that
; edx is reloaded with the 1 in the lowest byte so that this case can
; fall through the ror edx, 8 at the end of the loop.  Also remember
; that the hardware will interpret the plot steps least significant
; byte to most significant byte.

IFNDEF _8514

addplotstep     macro   step
                local   morespace

                add     dl, step
                cmp     dl, step
                je      short morespace
                dec     dl
                ror     edx, 8
                waitshort
                memregwrite     dir_steps, edx
                mov     edx, 00000001h
morespace:
                ror     edx, 8
                endm

ELSE ; _8514

                ;@DMS is this ever hit !!!
addplotstep     macro   step
                int 3
                mov     ax,step
                mov     dx,SHORTSTROKE
                out     dx,ax

ENDIF ; _8514

ENDIF ; PASS 1
ENDIF ; HARD_DRAW

IFDEF SOFT_DRAW
public  _eddf_PMSHORTLINES

PMShortLines    equ     <_eddf_PMSHORTLINES>
bitmap_address  equ     virt_addr

extrn _eddf_MESS        :proc
ENDIF ; SOFT_DRAW

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

_DATA           segment dword use32 public 'DATA'                       ;**
_DATA           ends


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

; structure for parameter block

; This same structure must also appear in the eddffast.asm file
SHORTLINESPB    struc
ulPixelOp       dd      ?
usPatPos        dw      ?
usPatType       dw      ?
usXStart        dw      ?
usYStart        dw      ?
usYStop         dw      ?
pSteps          dd      ?
usPatEnd        dw      ?
SHORTLINESPB    ends

; structure for scratch pad

ShortLinesSP    struc
usYPlot         dw      ?
usDiagLeft      dw      ?
usDiagRight     dw      ?
usPatPosTmp     dw      ?
ShortLinesSP    ends


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

; equates for this code file

LINETYPE_SOLID  equ 007h
MAX_STEPS       equ 00Fh
PLOT            equ 010h
UP              equ 040h
DOWN            equ 0C0h
LEFT            equ 080h
RIGHT           equ 000h
UP_LEFT         equ 060h
UP_RIGHT        equ 020h
DOWN_LEFT       equ 0A0h
DOWN_RIGHT      equ 0E0h

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

;***********************************************************************
;
; Function: PMShortLines
;
; Called by: eddl_PolyShortLine in eddlshrt.c
;
; This is the only case.  Code handles..
;       Patterned lines set up
;
;
; 386 only code
;***********************************************************************

PMShortLines    proc
        push    edi
        push    esi
        push    ebx
        pushxga

; do a quick check for nothing to do
        mov     ax, _AIxfer.usYStop
        cmp     ax, _AIxfer.usYStart
        jz      fast_exit

; Do required set up to get access to hardware registers
        ifndef  _8514
        movxga  pXGARegs
        else
        movxga  p8514Regs
        endif

; and to the list of x coordinates
        mov     edi, dword ptr _AIxfer.pSteps                            ;**

; Is there a pattern which we need to set up
        cmp     _AIxfer.usPatType, LINETYPE_SOLID
        jz      short nopattern

; Set up the pattern pixel map as map C
        waitshort

; Get access to pixel map C and set up its parameters
        memregwrite     pi_map_index_C, SEL_PIX_MAP_C
        memregwrite     pi_map_width_C, LINE_PATTERN_LENGTH-1
        memregwrite     pi_map_height_C, 0
        memregwrite     pi_map_format_C, ONE_BPP+MOTOROLA
        mov     eax, dword ptr _LinePatternCur
        xor     edx, edx
        mov     dx, _AIxfer.usPatType
IFDEF IBMJ                                                  
 IFDEF XGA                                                  
        lea     eax, [eax+edx*4]
 ELSE 
        add     eax, edx
        add     eax, edx
 ENDIF 
ELSE 
        add     eax, edx
        add     eax, edx
ENDIF 
        memregwrite     pi_map_base_ptr_C, eax

; Set up the start position in the pattern
        memregwrite     patt_map_y, 0
        mov     ax, _AIxfer.usPatPos
        memregwrite     patt_map_x, ax

; Alter the pixel op to reflect the pattern
        mov     eax, _AIxfer.ulPixelOp
        and     eax, 0FFFF0FFFh
        or      eax, 000003000h
        mov     _AIxfer.ulPixelOp, eax

nopattern:
; All the lines are fully pre-clipped .'. we can assume that they will
; not cross the guard area so all we need to do is set the start point
; and then convert all the short lines into plot/step orders and spit
; them out..

; Set the start position
        waitshort
        mov     eax, dword ptr [_AIxfer].usXStart
        memregwrite     dest_map, eax

IFDEF HARD_DRAW

IFDEF _8514

        WaitQIdle

        WaitQ   4
        memregread      eax,dest_map
        outwQ   X0,ax
        swap    eax
        outwQ   Y0,ax
        outwQ   MODE,<MODE_2DECODE+MD_PS_COPY+MD_UP_FALSE>
        outwQ   CMD_FLAGS,<CMD_C_NULL+CMD_MA_ACCESS+CMD_CD_45+CMD_LP_NULL+CMD_PA_FOUR+CMD_RW_W>


ENDIF ; _8514

ELSE ; SOFT_DRAW
; Set up the pixel op register - we have set "draw and step read" as
; the function to indicate to _eddf_MESS that we are drawing shortlines
; directly. This avoids the need for multiple calls to eddf_DoPlotStep and
; so is much more efficient.
        mov     eax, _AIxfer.ulPixelOp
        and     eax, 0f0ffffffh         ;set "draw and step read" mode
        or      eax, 002000000h
        memregwrite     pixel_op, eax
        saveregs
        call    _eddf_MESS
        restoreregs
ENDIF ; SOFT_DRAW

IFDEF HARD_DRAW
; Determine the Y direction and the number of steps..
        mov     ax, _AIxfer.usYStop
        sub     ax, _AIxfer.usYStart
        js      short yisneg

; set up the plot step codes for a vertical step and a diagonal steps
; to the left or right
        mov     _SPad.usYPlot, DOWN + PLOT + 1
        mov     _SPad.usDiagLeft, DOWN_LEFT + PLOT + 1
        mov     _SPad.usDiagRight, DOWN_RIGHT + PLOT + 1
        jmp     short ydone

yisneg:
; set up the plot step codes for a vertical step and a diagonal steps
; to the left or right
        neg     ax
        mov     _SPad.usYPlot, UP + PLOT + 1
        mov     _SPad.usDiagLeft, UP_LEFT + PLOT + 1
        mov     _SPad.usDiagRight, UP_RIGHT + PLOT + 1

ydone:
; Hold on to the number of y steps
        mov     cx, ax

; save the pattern position
        mov     ax, _AIxfer.usPatPos
        mov     _SPad.usPatPosTmp, ax

; Now set up pixel op register - this will not actually start an operation
; because it is in draw and step mode
        mov     eax, _AIxfer.ulPixelOp
        memregwrite     pixel_op, eax

; Start to accumulate the plot/step orders in edx (the 1 in the most
; significant byte is a flag - see the description of addplotstep
; macro)
        mov     edx, 01000000h

xcoordloop:
; Pick up the next x coordinate
        mov     ax, [edi+4]                                             ;**

; is this a vertical step?
        sub     ax, [edi]                                               ;**
        jz      vertplot

; is it a negative step ?
        js      xisneg

; positive x move
        dec     ax

moresteps1:
; how many steps is it ?
        cmp     ax, MAX_STEPS
        jl      short onerun1

do_max_step:
; we will need more than one plot step order to complete this line
; do a maximum length step
        addplotstep <RIGHT + PLOT + MAX_STEPS>
        add     _SPad.usPatPosTmp, MAX_STEPS

; and find out how many steps are left
; find out how many steps are left
        sub     ax, MAX_STEPS
        cmp     ax, MAX_STEPS
        jg      do_max_step

onerun1:
; We can finish this line with just one plot step order
        add     _SPad.usPatPosTmp, ax
        or      ax, RIGHT + PLOT
        addplotstep al

; now do a vertical step in the same direction as the current line
        addplotstep <byte ptr _SPad.usDiagRight>

; move on to next coordinate and jump for the loop
        add     edi, 4                                                  ;**
        dec     cx
        jne     xcoordloop
        jmp     exit


xisneg:
; negative x move (need to decrease the count by one)
        neg     ax
        dec     ax

moresteps2:
; how many steps is it ?
        cmp     ax, MAX_STEPS
        jl      short onerun2

do_max_step1:
; we will need more than one plot step order to complete this line
; do a maximum length step
        addplotstep <LEFT + PLOT + MAX_STEPS>
        add     _SPad.usPatPosTmp, MAX_STEPS

; find out how many steps are left
        sub     ax, MAX_STEPS
        cmp     ax, MAX_STEPS
        jg      do_max_step1

onerun2:
; we can finish this line with just one plot step order
        add     _SPad.usPatPosTmp, ax
        or      ax, LEFT + PLOT
        addplotstep al

; now do a vertical step in the same direction as the current line
; (except when there are no more steps to do)
        addplotstep <byte ptr _SPad.usDiagLeft>

; move on to next coordinate and jump for the loop
        add     edi, 4                                                  ;**
        dec     cx
        jne     xcoordloop
        jmp     short exit

vertplot:
; do a vertical plot
        inc     _SPad.usPatPosTmp
        addplotstep <byte ptr _SPad.usYPlot>

; move on to next coordinate and jump for the loop
        add     edi, 4                                                  ;**
        dec     cx
        jne     xcoordloop
;       jmp     exit

exit:
; Now ensure that all the steps have been done by using 3 null plotsteps
        addplotstep 0
        addplotstep 0
        addplotstep 0

; Get back the pattern position for DC data
        mov     ax, _SPad.usPatPosTmp
        and     ax, 0Fh
        mov     _AIxfer.usPatEnd, ax

ENDIF ; HARD_DRAW

fast_exit:
; clear stack and quit
        popxga
        pop     ebx
        pop     esi
        pop     edi
        retn

PMShortLines    endp

_TEXT           ends

END
