ztriangle.inc
mxlgv_KolibriDev/build_iso/kolibrios/develop/fasm/tinygl/ztriangle.inc
;
; We draw a triangle with various interpolations
;
; Порядок преобразований цветов вершин:
; ZBufferPoint.r -> r1 (+drdl_min or +drdl_max) -> or1 (+drdx) -> [pixel buffer]
; ZBufferPoint.g -> g1 (+dgdl_min or +dgdl_max) -> og1 (+dgdx) -> [pixel buffer]
; ZBufferPoint.b -> b1 (+dbdl_min or +dbdl_max) -> ob1 (+dbdx) -> [pixel buffer]
;
; В некоторых случаях значения цвета (во 2-м байте переменных: or1,og1,ob1)
; может становиться < 0 или > 255, тогда появляються пиксели не правильного
; цвета. Скорее всего это связано с ошибками округления дробных чисел,
; при вычислении коэфициентов для плавного перехода цвета.
;
; Для лечения этой проблемы в версии на C++ специально ограничиваються
; минимальные и максимальные значения цвета точек (например от 3 до 252).
; Потому цвета граней могут немного отличаться от указанных в программе.
;
; В даной версии алгоритм немного другой. В наиболее вероятных местах появления
; пикселей не правильного цвета (обычно начало и конец линии) иправляеться
; цвет испорченных пикселей. Цвет получаеться наиболее близким к указанному
; пользователем.

	pr1 dd ? ;ZBufferPoint*
	pr2 dd ? ;ZBufferPoint*
	l1 dd ? ;ZBufferPoint*
	l2 dd ? ;ZBufferPoint*
	fdx1 dd ? ;float
	fdx2 dd ? ;float
	fdy1 dd ? ;float
	fdy2 dd ? ;float
	fz dd ? ;float - переменная отвечающая за геометрию фигуры
	d1 dd ? ;float
	d2 dd ? ;float
	pz1 dd ? ;unsigned short*
	pp1 dd ? ;PIXEL*
	part dd ?
	update_left dd ?
	update_right dd ?

	nb_lines dd ? ;число горизонтальных линий в половине треугольника
	dx1 dd ?
	dy1 dd ?
	;dx2 dd ?
	dy2 dd ?

	error dd ? ;int
	derror dd ? ;int
	x1 dd ? ;int
	dxdy_min dd ? ;int
	dxdy_max dd ? ;int
	; warning: x2 is multiplied by 2^16
	x2 dd ? ;int
	dx2dy2 dd ? ;int

	z dd ? ;uint
	n dd ? ;int - длинна горизонтальной линии в пикселях

if INTERP_Z eq 1
	z1 dd ? ;int
	dzdx dd ? ;int
	dzdy dd ? ;int
	dzdl_min dd ? ;int
	dzdl_max dd ? ;int
end if
if INTERP_RGB eq 1
	r1 dd ? ;int
	drdx dd ?
	drdy dd ?
	drdl_min dd ?
	drdl_max dd ?
	g1 dd ?
	dgdx dd ?
	dgdy dd ?
	dgdl_min dd ?
	dgdl_max dd ?
	b1 dd ?
	dbdx dd ?
	dbdy dd ?
	dbdl_min dd ?
	dbdl_max dd ?
	or1 dd ? ;uint
	og1 dd ? ;uint
	ob1 dd ? ;uint
end if
if INTERP_ST eq 1
	s1 dd ? ;int
	dsdy dd ? ;int
	dsdl_min dd ? ;int
	dsdl_max dd ? ;int
	t1 dd ? ;int
	dtdy dd ? ;int
	dtdl_min dd ? ;int
	dtdl_max dd ? ;int
end if
if INTERP_STZ eq 1
	sz1 dd ? ;float
	dszdx dd ? ;float
	dszdy dd ? ;float
	dszdl_min dd ? ;float
	dszdl_max dd ? ;float
	tz1 dd ? ;float
	dtzdx dd ? ;float
	dtzdy dd ? ;float
	dtzdl_min dd ? ;float
	dtzdl_max dd ? ;float
	s_z dd ? ;float
	t_z dd ? ;float
end if
if (INTERP_ST eq 1) | (DRAW_LINE_M eq 1)
	s dd ? ;uint
	t dd ? ;uint
	dsdx dd ? ;int
	dtdx dd ? ;int
end if
endl
pushad

	; we sort the vertex with increasing y
	mov ebx,[p0]
	mov ecx,[p1]
	mov edx,[p2]
	mov eax,[edx+ZBufferPoint.y]
	cmp [ecx+ZBufferPoint.y],eax ;(2-1)
	jle @f
		xchg edx,ecx
	@@:
	mov eax,[ecx+ZBufferPoint.y]
	cmp [ebx+ZBufferPoint.y],eax ;(1-0)
	jle @f
		xchg ecx,ebx
	@@:
	mov eax,[edx+ZBufferPoint.y]
	cmp [ecx+ZBufferPoint.y],eax ;(2-1)
	jle @f
		xchg edx,ecx
	@@:
	mov [p0],ebx
	mov [p1],ecx
	mov [p2],edx

	; we compute dXdx and dXdy for all interpolated values
	mov eax,[ecx+ZBufferPoint.x]
	sub eax,[ebx+ZBufferPoint.x]
	mov [fdx1],eax ;p1.x - p0.x
	mov eax,[ecx+ZBufferPoint.y]
	sub eax,[ebx+ZBufferPoint.y]
	mov [fdy1],eax ;p1.y - p0.y

	mov eax,[edx+ZBufferPoint.x]
	sub eax,[ebx+ZBufferPoint.x]
	mov [fdx2],eax ;p2.x - p0.x
	mov eax,[edx+ZBufferPoint.y]
	sub eax,[ebx+ZBufferPoint.y]
	mov [fdy2],eax ;p2.y - p0.y

	fild dword[fdx1]
	fimul dword[fdy2]
	fild dword[fdx2]
	fimul dword[fdy1]
	fsubp ;st0 = st1-st0
	fst dword[fz] ;fz = fdx1 * fdy2 - fdx2 * fdy1
	fldz
	fcompp ;if (fz == 0) return
	fstsw ax
	sahf
	je .end_f

	fld1
	fdiv dword[fz] ;fz = 1.0 / fz
	fst dword[fz]  ;st0 = fz

	fild dword[fdx1]
	fmul st0,st1
	fstp dword[fdx1] ;fdx1 *= fz
	fild dword[fdy1]
	fmul st0,st1
	fstp dword[fdy1] ;fdy1 *= fz
	fild dword[fdx2]
	fmul st0,st1
	fstp dword[fdx2] ;fdx2 *= fz
	fild dword[fdy2]
	fmulp
	fstp dword[fdy2] ;fdy2 *= fz

if INTERP_Z eq 1
	mov eax,[ecx+ZBufferPoint.z]
	sub eax,[ebx+ZBufferPoint.z]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.z]
	sub eax,[ebx+ZBufferPoint.z]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.z - p0.z
	fild dword[d2] ;d2 = p2.z - p0.z

	;dzdx = (int) (fdy2*d1 - fdy1*d2)
	;dzdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, dzdx, dzdy
end if

if INTERP_RGB eq 1
	mov eax,[ecx+ZBufferPoint.r]
	sub eax,[ebx+ZBufferPoint.r]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.r]
	sub eax,[ebx+ZBufferPoint.r]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.r - p0.r
	fild dword[d2] ;d2 = p2.r - p0.r

	;drdx = (int) (fdy2*d1 - fdy1*d2)
	;drdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, drdx, drdy

	mov eax,[ecx+ZBufferPoint.g]
	sub eax,[ebx+ZBufferPoint.g]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.g]
	sub eax,[ebx+ZBufferPoint.g]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.g - p0.g
	fild dword[d2] ;d2 = p2.g - p0.g

	;dgdx = (int) (fdy2*d1 - fdy1*d2)
	;dgdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, dgdx, dgdy

	mov eax,[ecx+ZBufferPoint.b]
	sub eax,[ebx+ZBufferPoint.b]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.b]
	sub eax,[ebx+ZBufferPoint.b]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.b - p0.b
	fild dword[d2] ;d2 = p2.b - p0.b

	;dbdx = (int) (fdy2*d1 - fdy1*d2)
	;dbdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, dbdx, dbdy
end if

if INTERP_ST eq 1
	mov eax,[ecx+ZBufferPoint.s]
	sub eax,[ebx+ZBufferPoint.s]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.s]
	sub eax,[ebx+ZBufferPoint.s]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.s - p0.s
	fild dword[d2] ;d2 = p2.s - p0.s

	;dsdx = (int) (fdy2*d1 - fdy1*d2)
	;dsdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, dsdx, dsdy

	mov eax,[ecx+ZBufferPoint.t]
	sub eax,[ebx+ZBufferPoint.t]
	mov [d1],eax
	mov eax,[edx+ZBufferPoint.t]
	sub eax,[ebx+ZBufferPoint.t]
	mov [d2],eax
	fild dword[d1] ;d1 = p1.t - p0.t
	fild dword[d2] ;d2 = p2.t - p0.t

	;dtdx = (int) (fdy2*d1 - fdy1*d2)
	;dtdy = (int) (fdx1*d2 - fdx2*d1)
	calc_d1d2 fi, dtdx, dtdy
end if

if INTERP_STZ eq 1
	fild dword[ebx+ZBufferPoint.z]
	fild dword[ebx+ZBufferPoint.s]
	fmul st0,st1
	fstp dword[ebx+ZBufferPoint.fsz] ;p0.sz = (float) p0.s * p0.z
	fild dword[ebx+ZBufferPoint.t]
	fmulp
	fstp dword[ebx+ZBufferPoint.tz] ;p0.tz = (float) p0.t * p0.z

	fild dword[ecx+ZBufferPoint.z]
	fild dword[ecx+ZBufferPoint.s]
	fmul st0,st1
	fstp dword[ecx+ZBufferPoint.fsz] ;p1.sz = (float) p1.s * p1.z
	fild dword[ecx+ZBufferPoint.t]
	fmulp
	fstp dword[ecx+ZBufferPoint.tz] ;p1.tz = (float) p1.t * p1.z

	fild dword[edx+ZBufferPoint.z]
	fild dword[edx+ZBufferPoint.s]
	fmul st0,st1
	fstp dword[edx+ZBufferPoint.fsz] ;p2.sz = (float) p2.s * p2.z
	fild dword[edx+ZBufferPoint.t]
	fmulp
	fstp dword[edx+ZBufferPoint.tz] ;p2.tz = (float) p2.t * p2.z

	fld dword[ecx+ZBufferPoint.fsz]
	fsub dword[ebx+ZBufferPoint.fsz] ;d1 = p1.sz - p0.sz
	fld dword[edx+ZBufferPoint.fsz]
	fsub dword[ebx+ZBufferPoint.fsz] ;d2 = p2.sz - p0.sz

	;dszdx = (fdy2*d1 - fdy1*d2)
	;dszdy = (fdx1*d2 - fdx2*d1)
	calc_d1d2 f, dszdx, dszdy

	fld dword[ecx+ZBufferPoint.tz]
	fsub dword[ebx+ZBufferPoint.tz] ;d1 = p1.tz - p0.tz
	fld dword[edx+ZBufferPoint.tz]
	fsub dword[ebx+ZBufferPoint.tz] ;d2 = p2.tz - p0.tz

	;dtzdx = (fdy2*d1 - fdy1*d2)
	;dtzdy = (fdx1*d2 - fdx2*d1)
	calc_d1d2 f, dtzdx, dtzdy
end if

	; screen coordinates
	mov eax,[zb]
	mov edx,[eax+ZBuffer.linesize]
	imul edx,[ebx+ZBufferPoint.y]
	add edx,[eax+ZBuffer.pbuf]
	mov [pp1],edx ;pp1 = zb.pbuf + zb.linesize * p0.y
	mov edx,[eax+ZBuffer.xsize]
	imul edx,[ebx+ZBufferPoint.y]
	shl edx,1
	add edx,[eax+ZBuffer.zbuf]
	mov [pz1],edx ;pz1 = zb.zbuf + zb.xsize * p0.y

	DRAW_INIT

	mov dword[part],0
	.cycle_0:
		mov ebx,[p0]
		mov ecx,[p1]
		mov edx,[p2]
		cmp dword[part],0 ;if (part == 0)
		jne .els_0
			mov dword[update_left],1
			mov dword[update_right],1
			mov [l1],ebx
			mov [pr1],ebx
			fldz
			fld dword[fz]
			fcompp ;if (fz > 0)
			fstsw ax
			sahf
			jbe .els_1
				mov [l2],edx
				mov [pr2],ecx
				jmp .end_1
align 4
			.els_1:
				mov [l2],ecx
				mov [pr2],edx
			.end_1:
			mov eax,[ecx+ZBufferPoint.y]
			sub eax,[ebx+ZBufferPoint.y]
			mov [nb_lines],eax ;nb_lines = p1.y - p0.y
			jmp .end_0
align 4
		.els_0:
			; second part
			fldz
			fld dword[fz]
			fcompp ;if (fz > 0)
			fstsw ax
			sahf
			jbe .els_2
				mov dword[update_left],0
				mov dword[update_right],1
				mov [pr1],ecx
				mov [pr2],edx
				jmp .end_2
align 4
			.els_2:
				mov dword[update_left],1
				mov dword[update_right],0
				mov [l1],ecx
				mov [l2],edx
			.end_2:
			mov eax,[edx+ZBufferPoint.y]
			sub eax,[ecx+ZBufferPoint.y]
			inc eax
			mov [nb_lines],eax ;nb_lines = p2.y - p1.y + 1
		.end_0:

	; compute the values for the left edge
	cmp dword[update_left],0 ;if (update_left)
	je .end_upd_l
		mov ebx,[l1]
		mov ecx,[l2]
		mov edx,[ecx+ZBufferPoint.y]
		sub edx,[ebx+ZBufferPoint.y]
		mov [dy1],edx ;dy1 = l2.y - l1.y
		mov eax,[ecx+ZBufferPoint.x]
		sub eax,[ebx+ZBufferPoint.x]
		mov [dx1],eax ;dx1 = l2.x - l1.x
		cmp edx,0 ;if (dy1 > 0) 
		jle .els_3
			xor edx,edx
			cmp eax,0
			jl .otr_dx1
			shl eax,16
			div dword[dy1] ;eax = (dx1 << 16) / dy1
			jmp .end_3
align 4
			.otr_dx1:
			neg eax
			inc eax
			shl eax,16
			div dword[dy1] ;eax = (-dx1 << 16) / dy1
			neg eax
			inc eax
			jmp .end_3
align 4
		.els_3:
			xor eax,eax
		.end_3:
		mov edx,[ebx+ZBufferPoint.x]
		mov [x1],edx ;x1 = l1.x
		mov dword[error],0 ;error = 0
		mov dword[derror],eax
		and dword[derror],0xffff ;derror = eax & 0x0000ffff
		sar eax,16
		mov [dxdy_min],eax ;dxdy_min = eax >> 16
		inc eax
		mov [dxdy_max],eax

if INTERP_Z eq 1
	mov eax,[l1]
	mov eax,[eax+ZBufferPoint.z]
	mov [z1],eax ;z1 = l1.z
	mov eax,[dzdx]
	imul eax,[dxdy_min]
	add eax,[dzdy]
	mov [dzdl_min],eax ;dzdl_min = (dzdy +dzdx*dxdy_min)
	add eax,[dzdx]
	mov [dzdl_max],eax ;dzdl_max = dzdl_min +dzdx
end if
if INTERP_RGB eq 1
	mov ebx,[l1]
	mov eax,[ebx+ZBufferPoint.r]
	mov [r1],eax ;r1 = l1.r
	mov eax,[drdx]
	imul eax,[dxdy_min]
	add eax,[drdy]
	mov [drdl_min],eax ;drdl_min = (drdy +drdx*dxdy_min)
	add eax,[drdx]
	mov [drdl_max],eax ;drdl_max = drdl_min +drdx

	mov eax,[ebx+ZBufferPoint.g]
	mov [g1],eax ;g1 = l1.g
	mov eax,[dgdx]
	imul eax,[dxdy_min]
	add eax,[dgdy]
	mov [dgdl_min],eax ;dgdl_min = (dgdy +dgdx*dxdy_min)
	add eax,[dgdx]
	mov [dgdl_max],eax ;dgdl_max = dgdl_min +dgdx

	mov eax,[ebx+ZBufferPoint.b]
	mov [b1],eax ;b1 = l1.b
	mov eax,[dbdx]
	imul eax,[dxdy_min]
	add eax,[dbdy]
	mov [dbdl_min],eax ;dbdl_min = (dbdy +dbdx*dxdy_min)
	add eax,[dbdx]
	mov [dbdl_max],eax ;dbdl_max = dbdl_min +dbdx
end if
if INTERP_ST eq 1
	mov ebx,[l1]
	mov eax,[ebx+ZBufferPoint.s]
	mov [s1],eax ;s1 = l1.s
	mov eax,[dsdx]
	imul eax,[dxdy_min]
	add eax,[dsdy]
	mov [dsdl_min],eax ;dsdl_min = (dsdy +dsdx*dxdy_min)
	add eax,[dsdx]
	mov [dsdl_max],eax ;dsdl_max = dsdl_min +dsdx

	mov eax,[ebx+ZBufferPoint.t]
	mov [t1],eax ;t1 = l1.t
	mov eax,[dtdx]
	imul eax,[dxdy_min]
	add eax,[dtdy]
	mov [dtdl_min],eax ;dtdl_min = (dtdy +dtdx*dxdy_min)
	add eax,[dtdx]
	mov [dtdl_max],eax ;dtdl_max = dtdl_min +dtdx
end if
if INTERP_STZ eq 1
	mov ebx,[l1]
	mov eax,[ebx+ZBufferPoint.fsz]
	mov [sz1],eax ;sz1 = l1.sz - преобразований нет, потому без сопроцессора
	fild dword[dxdy_min]
	fmul dword[dszdx]
	fadd dword[dszdy]
	fst dword[dszdl_min] ;dszdl_min = (dszdy +dszdx*dxdy_min)
	fadd dword[dszdx]
	fstp dword[dszdl_max] ;dszdl_max = dszdl_min +dszdx

	mov eax,[ebx+ZBufferPoint.tz]
	mov [tz1],eax ;tz1 = l1.tz - преобразований нет, потому без сопроцессора
	fild dword[dxdy_min]
	fmul dword[dtzdx]
	fadd dword[dtzdy]
	fst dword[dtzdl_min] ;dtzdl_min = (dtzdy +dtzdx*dxdy_min)
	fadd dword[dtzdx]
	fstp dword[dtzdl_max] ;dtzdl_max = dtzdl_min +dtzdx
end if
	.end_upd_l:

	; compute values for the right edge

	cmp dword[update_right],0 ;if(update_right)
	je .end_upd_r
		mov ebx,[pr1]
		mov ecx,[pr2]
		mov edx,[ebx+ZBufferPoint.x]
		mov eax,[ecx+ZBufferPoint.x]
		sub eax,edx
		;mov [dx2],eax ;dx2 = pr2.x - pr1.x
		shl edx,16
		mov [x2],edx ; x2 = pr1.x << 16
		mov edx,[ecx+ZBufferPoint.y]
		sub edx,[ebx+ZBufferPoint.y]
		mov [dy2],edx ;dy2 = pr2.y - pr1.y
		cmp edx,0 ;if (dy2 > 0) 
		jle .els_4
			xor edx,edx
			cmp eax,0
			jl .otr_dx2
			shl eax,16
			div dword[dy2] ;eax = (dx2 << 16) / dy2
			jmp .end_4
align 4
			.otr_dx2:
			neg eax
			inc eax ;dx2 *= -1
			shl eax,16
			div dword[dy2] ;eax = (-dx2 << 16) / dy2
			neg eax
			inc eax
			jmp .end_4
align 4
		.els_4:
			xor eax,eax
		.end_4:
		mov [dx2dy2],eax
	.end_upd_r:

	; we draw all the scan line of the part
if DEBUG ;[nb_lines]
push ecx edi
	mov eax,[nb_lines]
	mov ecx,80
	lea edi,[buf_param]
	stdcall convert_int_to_str,ecx

	stdcall str_n_cat,edi,txt_nl,2
	stdcall dbg_print,f_fill_tr_nl,buf_param
pop edi ecx
end if

	.beg_w_lin:
	cmp dword[nb_lines],0 ;while (nb_lines>0)
	jle .end_w_lin
		dec dword[nb_lines]
if DRAW_LINE_M eq 1
		DRAW_LINE
else
		; generic draw line
		mov eax,[x2]
		sar eax,16
		mov edi,[x1]
		sub eax,edi
		mov [n],eax ;n = (x2 >> 16) - x1
		imul edi,PSZB
		add edi,[pp1] ;pp = pp1 + x1 * PSZB

if INTERP_Z eq 1
		mov esi,[x1]
		shl esi,1
		add esi,[pz1]
		mov eax,[z1]
		mov [z],eax
end if
if INTERP_RGB eq 1
		mov eax,[r1]
		bt eax,31 ; коректирование испорченных пикселей (в начале линии)
		jnc @f
			xor eax,eax
		@@:
		bt eax,16
		jnc @f
			mov eax,0xff00
		@@:
		mov [or1],eax
		mov eax,[g1]
		bt eax,31
		jnc @f
			xor eax,eax
		@@:
		bt eax,16
		jnc @f
			mov eax,0xff00
		@@:
		mov [og1],eax
		mov eax,[b1]
		bt eax,31
		jnc @f
			xor eax,eax
		@@:
		bt eax,16
		jnc @f
			mov eax,0xff00
		@@:
		mov [ob1],eax
end if
if INTERP_ST eq 1
		mov eax,[s1]
		mov [s],eax
		mov eax,[t1]
		mov [t],eax
end if
if INTERP_STZ eq 1
		mov eax,[sz1]
		mov [s_z],eax
		mov eax,[tz1]
		mov [t_z],eax
end if

align 4
		.cycle_1: ;while (n>=3)
if INTERP_RGB eq 1
		cmp dword[n],5
		jl .cycle_2
else
		cmp dword[n],3
		jl .cycle_2
end if
			PUT_PIXEL 0
			PUT_PIXEL 1
			PUT_PIXEL 2
			PUT_PIXEL 3
if INTERP_Z eq 1
			add esi,8 ;=4*sizeof(uint)
end if
			add edi,4*PSZB
			sub dword[n],4
		jmp .cycle_1
align 4
		.cycle_2: ;while (n>=0)
		cmp dword[n],0
		jl .cycle_2_end
if INTERP_RGB eq 1
		; коректирование испорченных пикселей (в конце линии)
		bt dword[or1],31
		jnc @f
			mov dword[or1],0
			jmp .end_r
align 4
		@@:
		bt dword[or1],16
		jnc .end_r
			mov dword[or1],0xff00
		.end_r:
		bt dword[og1],31
		jnc @f
			mov dword[og1],0
			jmp .end_g
align 4
		@@:
		bt dword[og1],16
		jnc .end_g
			mov dword[og1],0xff00
		.end_g:
		bt dword[ob1],31
		jnc @f
			mov dword[ob1],0
			jmp .end_b
align 4
		@@:
		bt dword[ob1],16
		jnc .end_b
			mov dword[ob1],0xff00
		.end_b:
end if
			PUT_PIXEL 0
if INTERP_Z eq 1
			add esi,2 ;=sizeof(uint)
end if
			add edi,PSZB
			dec dword[n]
		jmp .cycle_2
align 4
		.cycle_2_end:
end if ;проверка от макроса DRAW_LINE

	; left edge
	mov eax,[derror]
	add [error],eax
	cmp dword[error],0 ;if (error > 0)
	jle .els_er
		sub dword[error],0x10000
		mov eax,[dxdy_max]
		add [x1],eax
if INTERP_Z eq 1
		mov eax,[dzdl_max]
		add [z1],eax
end if      
if INTERP_RGB eq 1
		mov eax,[drdl_max]
		add [r1],eax
		mov eax,[dgdl_max]
		add [g1],eax
		mov eax,[dbdl_max]
		add [b1],eax
end if
if INTERP_ST eq 1
		mov eax,[dsdl_max]
		add [s1],eax
		mov eax,[dtdl_max]
		add [t1],eax
end if
if INTERP_STZ eq 1
		fld dword[dszdl_max]
		fadd dword[sz1]
		fstp dword[sz1]
		fld dword[dtzdl_max]
		fadd dword[tz1]
		fstp dword[tz1]
end if
		jmp .end_er
align 4
	.els_er:
		mov eax,[dxdy_min]
		add [x1],eax
if INTERP_Z eq 1
		mov eax,[dzdl_min]
		add [z1],eax
end if
if INTERP_RGB eq 1
		mov eax,[drdl_min]
		add [r1],eax
		mov eax,[dgdl_min]
		add [g1],eax
		mov eax,[dbdl_min]
		add [b1],eax
end if
if INTERP_ST eq 1
		mov eax,[dsdl_min]
		add [s1],eax
		mov eax,[dtdl_min]
		add [t1],eax
end if
if INTERP_STZ eq 1
		fld dword[dszdl_min]
		fadd dword[sz1]
		fstp dword[sz1]
		fld dword[dtzdl_min]
		fadd dword[tz1]
		fstp dword[tz1]
end if
	.end_er:
			; right edge
			mov eax,[dx2dy2]
			add [x2],eax

			; screen coordinates
			mov ebx,[zb]
			mov eax,[ebx+ZBuffer.linesize]
			add [pp1],eax
			mov eax,[ebx+ZBuffer.xsize]
			shl eax,1
			add [pz1],eax
			jmp .beg_w_lin
align 4
		.end_w_lin:
		inc dword[part]
		cmp dword[part],2
		jl .cycle_0
	.end_f:
popad
	ret
endp

restore INTERP_Z
restore INTERP_RGB
restore INTERP_ST
restore INTERP_STZ
restore DRAW_LINE_M

purge DRAW_INIT
purge DRAW_LINE
purge PUT_PIXEL
