;=================================================================
;
; Copyright (c) Microsoft Corporation 1999 - All Rights Reserved.
;
;=================================================================

	.486
	.model	flat, c
;	OPTION	PROC:PRIVATE		; only public procs explicitly
	OPTION	CASEMAP:NONE		; mixed case allowed for C compatibility
	OPTION	SCOPED			; labels are local inside PROCs
	OPTION	EXPR32			; 32-bit expression word size

include grf.inc
include chunk.inc

.DATA

; this should be done by h2inc, but it requires a "C" which h2inc can't handle.
extrn g_grdChunkData:ChunkData

LineReversed    dw  0

.CODE

GRFaddr macro   __X,__Y
        mov     edi,[g_grdChunkData.cbScreenPitch]
        imul    edi,__Y
        push    ecx
        mov     ecx,[g_grdChunkData.cPixDouble]
        shl     __X,cl
        pop     ecx
        lea     edi,[edi+__X*2]
        add     edi,[g_grdChunkData.pbScreen]
endm

X1      equ     eax
X2      equ     ebx
Y1      equ     edx
Y2      equ     ecx

soff    equ     4*(4+1)
arg0    equ     [esp+soff+ 0]
arg1    equ     [esp+soff+ 4]
arg2    equ     [esp+soff+ 8]
arg3    equ     [esp+soff+12]
arg4    equ     [esp+soff+16]

;
; Points
;
GRF_PointNoClip proc	;color, X, Y
        mov     eax,[esp+8]
        mov     edx,[esp+12]
		imul    edx,[g_grdChunkData.cbScreenPitch]

		cmp		[g_grdChunkData.cPixDouble],0
		jnz		DoDouble

        lea     edx,[edx+eax*2]
        add     edx,[g_grdChunkData.pbScreen]
        mov     eax,[esp+4]

        mov     [edx],ax

        ret

DoDouble:
        lea     edx,[edx+eax*4]
        add     edx,[g_grdChunkData.pbScreen]
        mov     eax,[esp+4]
		mov		ecx,eax
		shl		ecx,16
		and		eax,0ffffh
		or		eax,ecx

        mov     [edx],eax
		add		edx,[g_grdChunkData.cbScanDoubleOffset]
        mov     [edx],eax

		ret

GRF_PointNoClip      endp

;
; Lines
;
GRF_LineNoClip proc               ;color,  X1, Y1, X2, Y2
        push    ebx
        push    esi
        push    edi
        push    ebp

        mov     eax,arg1
        mov     edx,arg2
        mov     ebx,arg3
        mov     ecx,arg4

        mov     [LineReversed],0

        sub     Y2,Y1
        jnz     l0
;------------------------------------------------
HorLine:
        sub     X2,X1
        jge     h1
        add     X1,X2
        neg     X2
        mov     [LineReversed],1

h1:
        mov     ecx,X2
        GRFaddr X1,Y1
        inc     ecx
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      DrawHL          ;draw the whole line
        dec     ecx             ;don't draw one pixel
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     DrawHL          ;skip the last pixel
        add     edi,2           ;skip the first pixel
DrawHL:
        cld
        mov     eax,arg0

		cmp		[g_grdChunkData.cPixDouble],0
		jnz		DoDoubleHorz

        rep     stosw
        jmp     _exit

DoDoubleHorz:
		mov		esi,eax
		shl		eax,16
		and		esi,0ffffh
		or		eax,esi
        push    ecx
        push    edi
        rep     stosd
        pop     edi
        pop     ecx
        add     edi,[g_grdChunkData.cbScanDoubleOffset]
        rep     stosd

        jmp     _exit

;----------------------------------------------------
l0:
        jg      l1
        add     Y1,Y2
        neg     Y2
        xchg    X1,X2
        mov     [LineReversed],1

l1:
        mov     esi,[g_grdChunkData.cbScreenPitch]
        sub     X2,X1
        jg      l3
        jl      l2

        GRFaddr X1,Y1
        jmp     VLine

l2:
        neg     esi
        neg     X2

l3:
        GRFaddr X1,Y1

        cmp     X2,Y2
        jg      X_Line
        jl      Y_Line

;----------------------------------------------------
; actually handles not only vertical but also 45 degree lines

        mov     ebx,[g_grdChunkData.cPixDouble]
        shl     ebx,1
        lea     esi,[esi+ebx+2]
        cmp     esi,0
        jge     VLine
        neg     esi
VLine:
        inc     ecx
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      DrawVL          ;draw the whole line
        dec     ecx             ;don't draw one pixel
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     DrawVL          ;skip the last pixel
        add     edi,esi         ;skip the first pixel
DrawVL:
        mov     eax,arg0

		cmp		[g_grdChunkData.cPixDouble],0
		jnz		DoDoubleVert
VLoop:
        mov     [edi],ax
        add     edi,esi
		dec		ecx
        jnz     VLoop
        jmp     _exit

DoDoubleVert:
		mov		ebx,eax
		shl		eax,16
		and		ebx,0ffffh
		or		eax,ebx
        mov     edx,[g_grdChunkData.cbScanDoubleOffset]
VLoop2:
        mov     [edi],eax
        mov     [edi+edx],eax
        add     edi,esi
		dec		ecx
        jnz     VLoop2

        jmp     _exit
;----------------------------------------------------

Y_Line:
		cmp		[g_grdChunkData.cPixDouble],0
		jnz		DoDoubleY_Line
        mov     eax,arg0
        mov     edx,X2
        mov     ebp,Y2
        mov     ebx,ecx
        shr     ebx,1
        inc     ecx
        cmp     esi,0
        jng     yl22_setup
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      yl21            ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     yl21            ;skip the last pixel
                                ;skip the first pixel
yl20:
        add     edi,esi
        sub     ebx,edx
        jge     yl21
        add     ebx,ebp
        add     edi,2
yl21:
        mov     [edi],ax
		dec		ecx
        jnz     yl20
        jmp     _exit

yl22_setup:
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      yl23            ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     yl23            ;skip the last pixel
                                ;skip the first pixel
yl22:
        sub     edi,esi
        sub     ebx,edx
        jge     yl23
        add     ebx,ebp
        sub     edi,2
yl23:
        mov     [edi],ax
		dec		ecx
        jnz     yl22
        jmp     _exit

DoDoubleY_Line:
        mov     eax,arg0
        mov     ebp,eax
        shl     eax,16
        and     ebp,0ffffh
        or      eax,ebp
        mov     edx,X2
        mov     ebp,Y2
        mov     ebx,ecx
        shr     ebx,1
        inc     ecx
        mov     [g_grdChunkData.SaveESP],esp
        mov     esp,[g_grdChunkData.cbScanDoubleOffset]
        cmp     esi,0
        jng     y122_2x_setup
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      yl21_2x         ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     yl21_2x         ;skip the last pixel
                                ;skip the first pixel
yl20_2x:
        add     edi,esi
        sub     ebx,edx
        jge     yl21_2x
        add     ebx,ebp
        add     edi,4
yl21_2x:
        mov     [edi],eax
        mov     [edi+esp],eax
		dec		ecx
        jnz     yl20_2x
        mov     esp,[g_grdChunkData.SaveESP]
        jmp     _exit

y122_2x_setup:
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      yl23_2x         ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     yl23_2x         ;skip the last pixel
                                ;skip the first pixel
yl22_2x:
        sub     edi,esi
        sub     ebx,edx
        jge     yl23_2x
        add     ebx,ebp
        sub     edi,4
yl23_2x:
        mov     [edi],eax
        mov     [edi+esp],eax
		dec		ecx
        jnz     yl22_2x
        mov     esp,[g_grdChunkData.SaveESP]
        jmp     _exit

X_Line:
		cmp		[g_grdChunkData.cPixDouble],0
		jnz		DoDoubleX_Line
        mov     eax,arg0
        mov     edx,Y2
        mov     ecx,X2
        mov     ebp,X2
        mov     ebx,ecx
        inc     ecx
        shr     ebx,1
        cmp     esi,0
        jl      xl22_setup
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      xl21            ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     xl21            ;skip the last pixel
                                ;skip the first pixel
xl20:
        add     edi,2
        sub     ebx,edx
        jge     xl21
        add     ebx,ebp
        add     edi,esi
xl21:
        mov     [edi],ax
		dec		ecx
        jnz     xl20
        jmp     _exit

xl22_setup:
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      xl23            ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     xl23            ;skip the last pixel
                                ;skip the first pixel
xl22:
        sub     edi,2
        sub     ebx,edx
        jge     xl23
        add     ebx,ebp
        sub     edi,esi
xl23:
        mov     [edi],ax
		dec		ecx
        jnz     xl22
        jmp     _exit

DoDoubleX_Line:
        mov     eax,arg0
        mov     ebp,eax
        shl     eax,16
        and     ebp,0ffffh
        or      eax,ebp

        mov     edx,Y2
        mov     ecx,X2
        mov     ebp,X2
        mov     ebx,ecx
        inc     ecx
        shr     ebx,1
        mov     [g_grdChunkData.SaveESP],esp
        mov     esp,[g_grdChunkData.cbScanDoubleOffset]
        cmp     esi,0
        jl      xl22_2x_setup
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      xl21_2x         ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     xl21_2x         ;skip the last pixel
                                ;skip the first pixel
xl20_2x:
        add     edi,4
        sub     ebx,edx
        jge     xl21_2x
        add     ebx,ebp
        add     edi,esi
xl21_2x:
        mov     [edi],eax
        mov     [edi+esp],eax
		dec		ecx
        jnz     xl20_2x
        mov     esp,[g_grdChunkData.SaveESP]
        jmp     _exit

xl22_2x_setup:
; handle lastpixel
        cmp     [g_grdChunkData.fSkipLastPixel],0
        jz      xl23_2x         ;draw the whole line
        dec     ecx             ;don't draw the last point
        jz      _exit           ;done if there was only one pixel
        cmp     [LineReversed],1
        jnz     xl23_2x         ;skip the last pixel
                                ;skip the first pixel
xl22_2x:
        sub     edi,4
        sub     ebx,edx
        jge     xl23_2x
        add     ebx,ebp
        sub     edi,esi
xl23_2x:
        mov     [edi],eax
        mov     [edi+esp],eax
		dec		ecx
        jnz     xl22_2x
        mov     esp,[g_grdChunkData.SaveESP]

_exit:

        pop     ebp
        pop     edi
        pop     esi
        pop     ebx
        ret

GRF_LineNoClip      endp

OPTION PROLOGUE:    PrologueDef
OPTION EPILOGUE:    EpilogueDef

END
