;TEX_X = 512
;TEX_Y = 512
;ROUND equ 8
;SIZE_X = 512
;SIZE_Y = 512
;TEX_SHIFT = 9
CATMULL_SHIFT equ 8

;------------------------------------------------------------------------
;- Procedure drawing textured triangle using Catmull Z-buffer algorithm -
;------------------------------------------------------------------------
tex_triangle_z:
;----------in - eax - x1 shl 16 + y1
;-------------- ebx - x2 shl 16 + y2
;---------------ecx - x3 shl 16 + y3
;---------------edx - pointer to Z-buffer
;---------------esi - pointer to texture buffer
;---------------edi - pointer to screen buffer
;-------------stack - texture coordinates
;------------------ - z coordinates
.tex_x1 equ  ebp+4
.tex_y1 equ  ebp+6
.tex_x2 equ  ebp+8
.tex_y2 equ  ebp+10
.tex_x3 equ  ebp+12
.tex_y3 equ  ebp+14
.z1	equ  word[ebp+16]
.z2	equ  word[ebp+18]
.z3	equ  word[ebp+20]

.tex_ptr equ dword[ebp-4]	 ; pointer to texture
.z_ptr	 equ dword[ebp-8]	 ; pointer to z-buffer
.x1	 equ word[ebp-10]
.y1	 equ word[ebp-12]
.x2	 equ word[ebp-14]
.y2	 equ word[ebp-16]
.x3	 equ word[ebp-18]
.y3	 equ word[ebp-20]

.dx12	  equ dword[ebp-24]
.tex_dx12 equ dword[ebp-28]
.tex_dy12 equ dword[ebp-32]
.dz12	  equ dword[ebp-36]

.dx13	  equ dword[ebp-40]
.tex_dx13 equ dword[ebp-44]
.tex_dy13 equ dword[ebp-48]
.dz13	  equ dword[ebp-52]

.dx23	  equ dword[ebp-56]
.tex_dx23 equ dword[ebp-60]
.tex_dy23 equ dword[ebp-64]
.dz23	  equ dword[ebp-68]

.scan_x1  equ dword[ebp-72]
.scan_x2  equ dword[ebp-76]
.scan_y1  equ dword[ebp-80]
.scan_y2  equ dword[ebp-84]
.cz1	  equ dword[ebp-88]
.cz2	  equ dword[ebp-92]

if Ext >= MMX
	emms
end if
	mov	ebp,esp
	push	esi		  ; store memory pointers
	push	edx
.tt_sort3:
	cmp	ax,bx			  ;sort all parameters
	jle	.tt_sort1
	xchg	eax,ebx
	mov	edx,dword [.tex_x1]
	xchg	edx,dword [.tex_x2]
	mov	dword[.tex_x1],edx
	mov	dx,.z1
	xchg	dx,.z2
	mov	.z1,dx
.tt_sort1:
	cmp	bx,cx
	jle	.tt_sort2
	xchg	ebx,ecx
	mov	edx,dword [.tex_x2]
	xchg	edx,dword [.tex_x3]
	mov	dword [.tex_x2],edx
	mov	dx,.z2
	xchg	dx,.z3
	mov	.z2,dx
	jmp	.tt_sort3
.tt_sort2:

	push	eax	; and store to user friendly variables
	push	ebx
	push	ecx

	mov	 edx,80008000h	; eax,ebx,ecx are ANDd together into edx which means that
	and	 edx,ebx	; if *all* of them are negative a sign flag is raised
	and	 edx,ecx
	and	 edx,eax
	test	 edx,80008000h	; Check both X&Y at once
	jne	 .tt_loop2_end
	cmp	 ax,SIZE_Y
	jl	 @f
	cmp	 bx,SIZE_Y
	jl	 @f
	cmp	 cx,SIZE_Y
	jl	 @f
	ror	 eax,16
	ror	 ebx,16
	ror	 ecx,16
	cmp	 ax,SIZE_X
	jl	 @f
	cmp	 bx,SIZE_X
	jl	 @f
	cmp	 cx,SIZE_X
	jl	 @f
	jmp	 .tt_loop2_end
     @@:
	mov	 eax,dword[.tex_x1] ; texture coords must be in [0..TEX_X(Y)]
	mov	 ebx,dword[.tex_x2]
	mov	 ecx,dword[.tex_x3]
	mov	 edx,eax
	or	 edx,ebx
	or	 edx,ecx
	test	 edx,80008000h
	jne	 .tt_loop2_end
	cmp	 ax,TEX_X
	jge	 .tt_loop2_end
	cmp	 bx,TEX_X
	jge	 .tt_loop2_end
	cmp	 cx,TEX_X
	jge	 .tt_loop2_end
	ror	 eax,16
	ror	 ebx,16
	ror	 ecx,16
	cmp	 ax,TEX_Y
	jge	 .tt_loop2_end
	cmp	 bx,TEX_Y
	jge	 .tt_loop2_end
	cmp	 cx,TEX_Y
	jge	 .tt_loop2_end


	movsx	 ebx,.y2    ; calc delta
	sub	 bx,.y1
	jnz	 .tt_dx12_make
	xor	 edx,edx
	mov	 ecx,4
    @@:
	push	 edx
	loop	 @b
	jmp	 .tt_dx12_done
    .tt_dx12_make:
	mov	 ax,.x2
	sub	 ax,.x1
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
       ; mov      .dx12,eax                      ; dx12 = (x2-x1)/(y2-y1)
	push	 eax

	mov	 ax,word[.tex_x2]
	sub	 ax,word[.tex_x1]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
       ; mov     [.tex_dx12],eax               ; tex_dx12 = (tex_x2-tex_x1)/(y2-y1)
	push	 eax

	mov	 ax,word[.tex_y2]
	sub	 ax,word[.tex_y1]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
     ;   mov    [.tex_dy12],eax              ; tex_dy12 = (tex_y2-tex_y1)/(y2-y1)
	push	 eax

	mov	 ax,.z2
	sub	 ax,.z1
	cwde
	shl	 eax,CATMULL_SHIFT
	cdq
	idiv	 ebx
	push	 eax
   .tt_dx12_done:

	movsx	 ebx,.y3    ; calc delta
	sub	 bx,.y1
	jnz	 .tt_dx13_make
	xor	 edx,edx
	mov	 ecx,4
    @@:
	push	 edx
	loop	 @b
	jmp	 .tt_dx13_done
    .tt_dx13_make:
	mov	 ax,.x3
	sub	 ax,.x1
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
       ; mov      .dx12,eax                      ; dx13 = (x3-x1)/(y3-y1)
	push	  eax

	mov	 ax,word[.tex_x3]
	sub	 ax,word[.tex_x1]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
       ; mov     [.tex_dx12],eax               ; tex_dx13 = (tex_x3-tex_x1)/(y3-y1)
	push	 eax

	mov	 ax,word[.tex_y3]
	sub	 ax,word[.tex_y1]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
     ;   mov    [.tex_dy12],eax              ; tex_dy13 = (tex_y3-tex_y1)/(y3-y1)
	push	 eax

	mov	 ax,.z3
	sub	 ax,.z1
	cwde
	shl	 eax,CATMULL_SHIFT
	cdq
	idiv	 ebx
	push	 eax
   .tt_dx13_done:

	mov	 bx,.y3    ; calc delta
	sub	 bx,.y2
	jnz	 .tt_dx23_make
	xor	 edx,edx
	mov	 ecx,4
    @@:
	push	 edx
	loop	 @b
	jmp	 .tt_dx23_done
    .tt_dx23_make:
	mov	 ax,.x3
	sub	 ax,.x2
	cwde
	shl	 eax,ROUND
	cdq
	movzx	 ebx,bx
	idiv	 ebx
       ; mov      .dx23,eax                      ; dx23 = (x3-x2)/(y3-y2)
	push	  eax

	mov	 ax,word[.tex_x3]
	sub	 ax,word[.tex_x2]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
       ; mov     [.tex_dx23],eax               ; tex_dx23 = (tex_x3-tex_x2)/(y3-y2)
	push	 eax

	mov	 ax,word[.tex_y3]
	sub	 ax,word[.tex_y2]
	cwde
	shl	 eax,ROUND
	cdq
	idiv	 ebx
     ;   mov    [.tex_dy23],eax              ; tex_dy23 = (tex_y3-tex_y2)/(y3-y2)
	push	 eax

	mov	 ax,.z3
	sub	 ax,.z2
	cwde
	shl	 eax,CATMULL_SHIFT
	cdq
	idiv	 ebx
	push	 eax
   .tt_dx23_done:

	movsx	 eax,.x1     ;eax - cur x1
	shl	 eax,ROUND   ;ebx - cur x2
	mov	 ebx,eax

	movsx	 edx, word[.tex_x1]
	shl	 edx,ROUND
      ;  mov [.scan_x1],edx
      ;  mov [.scan_x2],edx
	push	 edx
	push	 edx
	movsx	 edx, word[.tex_y1]
	shl	 edx,ROUND
       ; mov [.scan_y1],edx
       ; mov [.scan_y2],edx
	push	 edx
	push	 edx
	movsx	 edx,.z1
	shl	 edx,CATMULL_SHIFT
	push	 edx
	push	 edx
	mov	 cx,.y1
	cmp	 cx,.y2
	jge	 .tt_loop1_end

   .tt_loop1:
	pushad

	push	.z_ptr
	push	.cz1	  ; z coords shifted shl catmull_shift
	push	.cz2
	push	.scan_y2
	push	.scan_x2
	push	.scan_y1
	push	.scan_x1
	push	esi		  ;[.tex_ptr]

	push	cx
	sar	ebx,ROUND
	push	bx
	sar	eax,ROUND
	push	ax
	call	textured_line_z

	popad
	mov	edx,.dz13
	add	.cz1,edx
	mov	edx,.dz12
	add	.cz2,edx

	mov	edx, .tex_dx13
	add	.scan_x1, edx
	mov	edx, .tex_dx12
	add	.scan_x2, edx
	mov	edx, .tex_dy13
	add	.scan_y1, edx
	mov	edx, .tex_dy12
	add	.scan_y2, edx

	add	eax, .dx13
	add	ebx, .dx12
	inc	cx
	cmp	cx,.y2
	jl	.tt_loop1

  .tt_loop1_end:


	mov	cx,.y2
	cmp	cx,.y3
	jge	.tt_loop2_end

	movsx	ebx,.x2
	shl	ebx,ROUND
	movsx	edx,.z2
	shl	edx,CATMULL_SHIFT
	mov	.cz2,edx
	movzx	edx, word [.tex_x2]
	shl	edx,ROUND
	mov	.scan_x2,edx
	movzx	edx, word[.tex_y2]
	shl	edx,ROUND
	mov	.scan_y2,edx

.tt_loop2:

	pushad

	push	.z_ptr
	push	.cz1	  ; z coords shifted shl catmull_shift
	push	.cz2

	push	.scan_y2
	push	.scan_x2
	push	.scan_y1
	push	.scan_x1
	push	esi		  ;[.tex_ptr]

	push	cx
	sar	ebx,ROUND
	push	bx
	sar	eax,ROUND
	push	ax
	call	textured_line_z

	popad


	mov	edx,.dz13
	add	.cz1,edx
	mov	edx,.dz23
	add	.cz2,edx

	mov	edx, .tex_dx13
	add	.scan_x1, edx
	mov	edx, .tex_dx23
	add	.scan_x2, edx
	mov	edx, .tex_dy13
	add	.scan_y1, edx
	mov	edx, .tex_dy23
	add	.scan_y2, edx

	add	eax, .dx13
	add	ebx, .dx23
	inc	cx
	cmp	cx,.y3
	jl	.tt_loop2

.tt_loop2_end:

.tt_end:
	mov esp,ebp
ret 18

textured_line_z:
;-----in -edi screen buffer pointer
;------------ stack:
  .x1 equ word [ebp+4]
  .x2 equ word [ebp+6]
  .y  equ word [ebp+8]

  .tex_ptr equ dword [ebp+10]
  .tex_x1  equ ebp+14
  .tex_y1  equ ebp+18
  .tex_x2  equ ebp+22
  .tex_y2  equ ebp+26
  .z2	   equ dword [ebp+30]	  ;z1, z2  coords shifted shl CATMULL_SHIFT
  .z1	   equ dword [ebp+34]
  .z_ptr   equ dword [ebp+38]

  .tex_dy  equ dword [ebp-4]
  .tex_dx  equ dword [ebp-8]
  .dz	   equ dword [ebp-12]
  .cz	   equ dword [ebp-16]
  .c_tex_x equ dword [ebp-20]  ; current tex x
  .m_sft1 equ ebp-28
  .m_sft2 equ ebp-32
;  .c_tex_xM equ ebp+14
  .tex_dxM  equ ebp-8

	mov	ebp,esp

	mov	ax,.y
	or	ax,ax
	jl	.tl_quit
	cmp	ax,SIZE_Y
	jge	.tl_quit

	mov	ax,.x1
	cmp	ax,.x2
	je	.tl_quit
	jl	.tl_ok

	xchg	ax,.x2	  ; sort params
	mov	.x1,ax
if Ext >= MMX
	movq	mm0,[.tex_x1]
	movq	mm1,[.tex_x2]
	movq	[.tex_x2],mm0
	movq	[.tex_x1],mm1

else
	mov	eax,dword[.tex_x1]
	xchg	eax,dword[.tex_x2]
	mov	dword[.tex_x1],eax

	mov	eax,dword[.tex_y1]
	xchg	eax,dword[.tex_y2]
	mov	dword[.tex_y1],eax

end if

	mov	eax,.z1
	xchg	eax,.z2
	mov	.z1,eax

     .tl_ok:
	cmp	.x1,SIZE_X
	jge	.tl_quit
	cmp	.x2,0
	jle	.tl_quit

	mov	bx,.x2
	sub	bx,.x1
	movsx	ebx,bx

	mov	eax,dword[.tex_y2]	 ; calc .dty
	sub	eax,dword[.tex_y1]
	cdq
	idiv	ebx
	push	eax

	mov	eax,dword[.tex_x2]	 ; calc .dtx
	sub	eax,dword[.tex_x1]
	cdq
	idiv	ebx
	push	eax

	mov	eax,.z2       ; calc .dz
	sub	eax,.z1
	cdq
	idiv	ebx
	push	eax

	cmp    .x1,0	      ; clipping
	jg     @f

	movsx	ebx,.x1
	neg	ebx
	imul	ebx	      ; eax = .dz * abs(.x1)
	add	.z1,eax
	mov	.x1,0

	mov	eax,.tex_dy
	imul	ebx
	add	dword[.tex_y1],eax

	mov	eax,.tex_dx
	imul	ebx
	add	dword[.tex_x1],eax

      @@:
	cmp	.x2,SIZE_X
	jl	@f
	mov	.x2,SIZE_X
      @@:

	movsx	ebx,.y	      ; calc mem begin in buffers
	mov	eax,SIZE_X
	mul	ebx
	movsx	ebx,.x1
	add	eax,ebx
	mov	ebx,eax

	lea	eax,[eax*3]
	add	edi,eax 	      ; edi - scr buff
	shl	ebx,2
	add	.z_ptr,ebx	      ; z buffer pointer

	mov	cx,.x2
	sub	cx,.x1
	movzx	ecx,cx

;if Ext >= MMX
;        movq    mm0,[.tex_x1]
;        movq    mm4,mm0
;        movq    mm1,qword[.tex_dxM]
;        mov     ebx,.z1
;        mov     eax,.dz
;else
	mov	eax,dword[.tex_x1]
	mov	ebx,dword[.tex_y1]
	push	.z1	      ; .cz
	push	eax	      ;.c_tex_x
;end if
	mov	edx,.z_ptr

     .tl_loop:

;if Ext >= MMX
;        cmp     ebx,[edx]                       ;  ebx - current z
;        jge     @f
;        movq    mm2,mm0
;        psrad   mm2,ROUND
;        movq    mm3,mm2
;        psrlq   mm2,32-TEX_SHIFT
;        paddd   mm3,mm2
;        movd    esi,mm3
;        mov     dword[edx],ebx    ; renew z buffer
;else
							;  eax - temp
	mov	eax,.cz 			;  ebx - cur tex y shl ROUND
	cmp	eax,[edx]			;  ecx - l.lenght
	jge	@f	   ; ebx - cur tex_y ;  edx - temp
	mov	esi,ebx 		;  edi - scr buff
	sar	esi,ROUND		;  esi - tex_ptr temp
	shl	esi,TEX_SHIFT		;  .z_ptr - cur pointer to z buff
	mov	eax,.c_tex_x		;  .cz - cur z coord shl CATMULL_SHIFT
	sar	eax,ROUND
	add	esi,eax
	mov	eax,.cz
	mov	dword[edx],eax	  ; renew z buffer
;end if
	and	esi,TEXTURE_SIZE
	lea	esi,[esi*3]
	add	esi,.tex_ptr
	movsd
	dec	edi
	jmp	.no_skip
      @@:
	add	edi,3
     .no_skip:
	add	edx,4
;if Ext >= MMX
;        add     ebx,eax
;        paddd   mm0,mm1
;else
	mov	eax,.dz
	add	.cz,eax
	mov	eax,.tex_dx
	add	.c_tex_x,eax
	add	ebx,.tex_dy
;end if
	loop	.tl_loop
 .tl_quit:

	mov	esp,ebp

ret 30+8

