; application : View3ds ver. 0.065 - tiny .3ds and .asc files viewer.
; compiler    : FASM
; system      : KolibriOS
; author      : Macgub aka Maciej Guba
; email       : macgub3@wp.pl
; web         : www.macgub.hekko.pl
; Fell free to use this intro in your own distribution of KolibriOS/MenuetOS.
; Special greetings to all MenuetOS maniax in the world.
; I hope because my intros Christian Belive will be near to each of You.


; Some adjustments made by Madis Kalme
; madis.kalme@mail.ee
; I tried optimizing it a bit, but don't know if it was successful. The objects
; can be:
; 1) Read from a file (*.3DS standard)
; 2) Written in manually (at the end of the code)
;include 'proc32.inc'

SIZE_X equ 512
SIZE_Y equ 512				     ;      /////     I want definitely
TIMEOUT equ 10				     ;     ------     say:
ROUND equ 10				     ;     \ @ @/     keep smiling every
TEX_X equ 512	 ; texture width             ;      \ ./    / day.
TEX_Y equ 512	 ;         height            ;       \/    /
TEX_SHIFT equ 9  ; texture width shifting    ;     __||__ /
TEXTURE_SIZE EQU (TEX_X * TEX_Y)-1	     ;   /|      |
TEX equ SHIFTING ; TEX={SHIFTING | FLUENTLY} ;  / \      /
FLUENTLY = 0				     ; /   |    |
SHIFTING = 1				     ;     ------
CATMULL_SHIFT equ 8			     ;      |  |
LIGHT_SIZE equ 22			     ;      |  |
NON   =   0				     ;     -/  \-
MMX   =   1
SSE   =   2
SSE2  =   3
Ext   =   SSE2		 ;Ext={ NON | MMX | SSE | SSE2 }

; 0 for short names (Menuet-compatible), 1 for long names (Kolibri features)
USE_LFN = 1

use32
	org    0x0
	db     'MENUET01'	; 8 byte id
	dd     0x01		; header version
	dd     START		; start of code
	dd     I_END		; size of image
	dd     MEM_END		; memory for app
	dd     MEM_END		; esp
	dd     I_Param		; I_Param
	dd     0x0		; I_Icon

START:	  ; start of execution
	cld
	call   alloc_buffer_mem
	call   read_param
	call   read_from_disk	 ; read, if all is ok eax = 0
	cmp    eax,0
	jne    .gen
	mov    esi,[fptr]
	cmp    [esi],word 4D4Dh
	jne    .asc
	call   read_tp_variables ; init points and triangles count variables
	cmp    eax,0
	je     .gen
	jmp    .malloc
    .gen:
     if USE_LFN
	mov    [triangles_count_var],1000
	mov    [points_count_var],1000
	call   alloc_mem_for_tp
     end if
	call   generate_object
	jmp    .opt
    .asc:
	mov    [triangles_count_var],10000
	mov    [points_count_var],10000
	call   alloc_mem_for_tp
	call   read_asc
	jmp    .opt
    .malloc:
     if USE_LFN
	call   alloc_mem_for_tp
     end if
	call   read_from_file
    .opt:
	call   optimize_object1     ;  proc in file b_procs.asm
				    ;  set point(0,0,0) in center and  calc all coords
				    ;  to be in <-1.0,1.0>
	call   normalize_all_light_vectors
	call   init_triangles_normals2
	call   init_point_normals
	call   init_envmap2
	call   init_envmap_cub
	call   generate_texture2
	call   init_sincos_tab

	call   do_color_buffer	 ; intit color_map
	mov    edi,bumpmap
	call   calc_bumpmap
	call   calc_bumpmap_coords   ; bump and texture mapping
	call   draw_window

still:

	mov	eax,23		; wait here for event with timeout
	mov	ebx,TIMEOUT
	cmp	[speed_flag],1
	jne	.skip
	mov	eax,11
    .skip:
	int	0x40

	cmp	eax,1		; redraw request ?
	je	red
	cmp	eax,2		; key in buffer ?
	je	key
	cmp	eax,3		; button in buffer ?
	je	button

	jmp	noclose

    red:			; redraw
	call	draw_window

	jmp	noclose

    key:			; key
	mov	eax,2		; just read it and ignore
	int	0x40
	jmp	noclose

    button:			; button
	mov	eax,17		; get id
	int	0x40

	cmp	ah,1		; button id=1 ?
	jne	@f

	mov	eax,-1		; close this program
	int	0x40
    @@:
	cmp	ah,30
	jge	add_vec_buttons
	call	update_flags	      ; update flags and write labels of flags

				      ; do other operations according to flag
	cmp	ah,3		      ; ah = 3 -> shading model
	jne	.next_m6
	cmp	[dr_flag],2
	jne	@f
   ;     call    init_envmap2    ;   <----! this don't works in env mode
				 ;          and more than ~18 kb objects
 ;       call    init_envmap_cub2
     @@:
	cmp	[dr_flag],4
	jne	@f
	call	generate_texture2

     @@:
     .next_m6:
				      ; ah = 5 -> scale-
	cmp	ah,5
	jne	@f
	mov	[scale],0.7
	fninit
	fld	[rsscale]
	fmul	[scale]
	fstp	[rsscale]

      @@:
	cmp	ah,6		     ; ah = 6 ->  scale+
	jne	@f
	mov	[scale],1.3
	fninit
	fld	[rsscale]
	fmul	[scale]
	fstp	[rsscale]

      @@:
	cmp	ah,9	; lights random                 ;    'flat'  0
	jne	.next_m5				;    'grd '  1
	call	make_random_lights			;    'env '  2
	call	normalize_all_light_vectors		;    'bump'  3
	call	do_color_buffer   ; intit color_map     ;    'tex '  4
      ;  cmp     [emboss_flag],1                         ;    'pos '  5
      ;  je      @f                                      ;    'dots'  6
      ;  cmp     [dr_flag],8
      ;  jge     @f
      ;  cmp     [dr_flag],2                             ;    'txgr'  7
      ;  jl      .next_m5                            ;    '2tex'  8
      ;  cmp     [dr_flag],3                             ;    'btex'  9
      ;  jg      .next_m5
    ; @@:
	call	init_envmap2	; update env map if shading model = environment or bump
    .next_m5:
	cmp	 ah,11
	je	 @f
	cmp	 ah,12
	je	 @f
	cmp	 ah,13
	jne	 .next_m4
      @@:
	call	 mirror
     .next_m4:
	cmp	 ah,14
	jne	 @f
	call	 exchange
     @@:
	cmp	 ah,15
	jne	 @f
	cmp	 [emboss_flag],1
	call	 init_envmap2
     @@:
;        cmp      ah,17
;        jne      .next_m
;        cmp      [move_flag],2
;        jne      @f
;        call     draw_window             ; redraw other labels to navigation buttons
;      @@:
;        cmp      [move_flag],0
;        jne      .next_m
;        call     draw_window             ; redraw other labels to navigation buttons
     .next_m:
	cmp	 ah,18
	jne	 .next_m2
     if USE_LFN
	mov	 [re_alloc_flag],1	 ; reallocate memory
	mov	 [triangles_count_var],1000
	mov	 [points_count_var],1000
	call	 alloc_mem_for_tp
	mov	 [re_alloc_flag],0
     end if
	mov	 bl,[generator_flag]
	or	 bl,bl
	jz	 .next_m2
	cmp	 bl,1
	jne	 @f
	call	 generate_object
	jmp	 .calc_norm
      @@:
	cmp	 bl,4
	jg	 @f
	movzx	 ax,bl		      ; ax < - object number
	call	 generate_object2
	jmp	.calc_norm
      @@:
	call	generate_object3
      .calc_norm:
	call	optimize_object1
	call	init_triangles_normals2
	call	init_point_normals
	call	calc_bumpmap_coords   ; bump and texture mapping

     .next_m2:
	cmp	 ah,19
	je	 @f
	cmp	 ah,20
	jne	 .next_m3
     @@:
	mov	 edi,bumpmap
	call	 calc_bumpmap
     .next_m3:
	cmp	ah,21		 ; re map bumps, texture coordinates
	jne	@f
	call	calc_bumpmap_coords
      @@:
	jmp	noclose


			       ; there are 6 navigation buttons each
   add_vec_buttons:	       ; can move: object, camera,.. list is open
			       ;
	cmp	ah,30
	jne	.next
	cmp	[move_flag],0
	jne	@f
;        cmp     [move_flag],2
;        je      .set_light1
	sub	[vect_y],10
	jmp	.next
      @@:
	cmp	[move_flag],1
	jne	@f
	sub	[yobs],10   ;  observator = camera position
	jmp	.next
      @@:
	sub	[sin_amplitude],10
;--------------------------------------------------
;      .set_light1:          ;  r -
;        movzx   ebx,[light_no_flag]  ; * 22
;        mov     ecx,ebx
;        shl     ebx,4
;        shl     ecx,1
;        add     ebx,ecx
;        shl     ecx,1
;        add     ebx,ecx
;        add     ebx,lights+6    ; 6 -> light vector size
;
;        movzx   ecx,[light_comp_flag]
;        lea     ecx,[ecx*3}
;        add     ebx,ecx         ; ebx ->  color to set

;---------------------------------------------------
      .next:
	cmp	ah,31
	jne	.next1
	cmp	[move_flag],1
	je	@f
	add	[vect_z],10
	jmp	.next1
      @@:
	add	[zobs],10	  ;  observator = camera position
     .next1:
	cmp	ah,33
	jne	.next2
	cmp	[move_flag],0
	jne	@f
	sub	[vect_x],10
	jmp	.next2
      @@:
	cmp	[move_flag],1
	jne	@f
	sub	[xobs],10	  ;  observator = camera position
	jmp	.next2
      @@:
	fninit
	fld	[sin_frq]
	fsub	[sin_delta]
	fstp	[sin_frq]
      .next2:
	cmp	ah,32
	jne	.next3
	cmp	[move_flag],0
	jne	@f
	add	[vect_x],10
	jmp	.next3
      @@:
	cmp	[move_flag],1
	jne	@f
	add	[xobs],10	  ;  observator = camera position
	jmp	.next3
      @@:
	fninit
	fld	[sin_frq]      ; change wave effect frequency
	fadd	[sin_delta]
	fstp	[sin_frq]
      .next3:
	cmp	ah,34
	jne	.next4
	cmp	[move_flag],1
	je	@f

	sub	[vect_z],10
	jmp	.next4
      @@:
	sub	[zobs],10	  ;  observator = camera position
      .next4:
	cmp	ah,35
	jne	.next5
	cmp	[move_flag],0
	jne	 @f
      ;  call    add_vector
	add	[vect_y],10
	jmp	.next5
      @@:
	cmp	[move_flag],1
	jne	@f
	add	[yobs],10	  ;  observator = camera position
	jmp	.next5
      @@:
	add	[sin_amplitude],10
      .next5:



    noclose:

	cmp	[r_flag],2
	jne	.no_x
	inc	[angle_x]
	and	[angle_x],0xff
	mov	[angle_z],0
	jmp	.end_rot

      .no_x:
	cmp	[r_flag],0
	jne	.no_y
	inc	[angle_y]
	and	[angle_y],0xff
	mov	[angle_z],0
	jmp	.end_rot

      .no_y:
	cmp	[r_flag],1
	jne	.end_rot
	mov	cx,[angle_x]
	inc	cx
	and	cx,0xff
	mov	[angle_z],0
	mov	[angle_y],cx
	mov	[angle_x],cx
     .end_rot:

	mov	esi,angle_x
	mov	edi,matrix
	call	make_rotation_matrix
    RDTSC
    push eax
	mov	esi,[points_normals_ptr]
	mov	edi,[points_normals_rot_ptr]
	mov	ebx,matrix
	movzx	ecx,[points_count_var]
	call	rotary

	mov	esi,matrix
	call	add_scale_to_matrix

	mov	esi,[points_ptr]
	mov	edi,[points_rotated_ptr]
	mov	ebx,matrix
	movzx	ecx,[points_count_var]
	call	rotary

;    RDTSC
;    pop    ebx
;    sub    eax,ebx
;    sub    eax,41
;    push   eax

	mov	esi,[points_rotated_ptr]
	mov	edi,[points_translated_ptr]
	movzx	ecx,[points_count_var]
	call	translate_points

;        cmp     [dr_flag],5
;        jne     @f
;        call    calc_attenuation_light
;     @@:
	cmp	[fire_flag],0
	jne	@f
	call	clrscr		; clear the screen
     @@:
	cmp	[catmull_flag],1  ;non sort if Catmull = on
	je	.no_sort
	call	sort_triangles
      .no_sort:
	cmp	[dr_flag],7	  ; fill if 2tex and texgrd
	jge	@f
	cmp	[catmull_flag],0  ;non fill if Catmull = off
	je	.non_f
	cmp	[dr_flag],6	  ; non fill if dots
	je	.non_f
      @@:
	call	fill_Z_buffer	  ; make background
     .non_f:
;    RDTSC
;    push eax
	cmp	[dr_flag],6
	jne	@f
	call	 draw_dots
	jmp	 .blurrr
      @@:
	call	draw_triangles	; draw all triangles from the list
      .blurrr:
	cmp  [sinus_flag],0
	je   @f
	call do_sinus
      @@:
	cmp	[fire_flag],0
	jne	@f
	cmp	[blur_flag],0
	je	.no_blur  ; no blur, no fire
	movzx	ecx,[blur_flag]
	call	blur_screen    ; blur and fire
	jmp	.no_blur
    @@:
	cmp	[emboss_flag],0
	jne	.emb	       ; if emboss=true -> no fire
	movzx	ecx,[fire_flag]
	call	blur_screen    ; blur and fire
    .no_blur:		       ; no blur, no fire
	cmp	[emboss_flag],0
	je	@f
     .emb:
	call	do_emboss

      @@:


    cmp     [inc_bright_flag],0 	  ; increase brightness
    je	    .no_inc_bright
    movzx   ebx,[inc_bright_flag]
    shl     ebx,4
    mov     esi,screen
    mov     ecx,SIZE_X*SIZE_Y*3
if (Ext = MMX)|(Ext = SSE)
    mov      bh,bl
    push     bx
    shl      ebx,16
    pop      bx
    push     ebx
    push     ebx
    movq     mm0,[esp]
    add      esp,8
else if Ext >= SSE2
    mov      bh,bl
    push     bx
    shl      ebx,16
    pop      bx
    movd     xmm0,ebx
    shufps   xmm0,xmm0,0
end if
  .oop:
if Ext=NON
    lodsb
    add     al,bl
    jnc     @f
    mov     byte[esi-1],255
    loop    .oop
   @@:
    mov     [esi-1],al
    loop    .oop
else if (Ext=MMX)|(Ext=SSE)
    movq    mm1,[esi]
    movq    mm2,[esi+8]
    paddusb mm1,mm0
    paddusb mm2,mm0
    movq    [esi],mm1
    movq    [esi+8],mm2
    add     esi,16
    sub     ecx,16
    jnz     .oop
else
    movaps  xmm1,[esi]
    paddusb xmm1,xmm0
    movaps  [esi],xmm1
    add     esi,16
    sub     ecx,16
    jnz     .oop
end if

.no_inc_bright:


    cmp     [dec_bright_flag],0
    je	    .no_dec_bright
    movzx   ebx,[dec_bright_flag]
    shl     ebx,4
    mov     esi,screen
    mov     ecx,SIZE_X*SIZE_Y*3
if (Ext = MMX)|(Ext = SSE)
    mov      bh,bl
    push     bx
    shl      ebx,16
    pop      bx
    push     ebx
    push     ebx
    movq     mm0,[esp]
    add      esp,8
else if Ext >=SSE2
    mov      bh,bl
    push     bx
    shl      ebx,16
    pop      bx
    movd     xmm0,ebx
    shufps   xmm0,xmm0,0
end if
 .oop1:
if Ext=NON
    lodsb
    sub     al,bl
    jb	    @f
    mov     [esi-1],al
    loop    .oop1
   @@:
    mov     byte[esi-1],0
    loop    .oop1
else if (Ext = MMX)|(Ext=SSE)
    movq    mm1,[esi]
    psubusb mm1,mm0
    movq    [esi],mm1
    add     esi,8
    sub     ecx,8
    jnz     .oop1
else
    movaps  xmm1,[esi]
    psubusb xmm1,xmm0
    movaps  [esi],xmm1
    add     esi,16
    sub     ecx,16
    jnz     .oop1
end if
  .no_dec_bright:
;======================================commmented====================
if 0
if Ext >= SSE
    cmp     [max_flag],0
    je	    .no_max
    ;movzx   ebx,[max_flag]
 .again_max:
;    push       ecx
    mov        edi,screen
    mov        ecx,SIZE_X*3/4
  ;   ;    pxor       mm5,mm5
    xor        eax,eax
    rep        stosd

    mov        ecx,(SIZE_X*(SIZE_Y-3))*3/8
  .calc_max:
  @@:
    movq       mm0,[edi+SIZE_X*3]
    movq       mm1,[edi-SIZE_X*3]
    movq       mm2,[edi-3]
    movq       mm3,[edi+3]

    pmaxub	mm0,mm1
    pmaxub	mm2,mm3
    pmaxub	mm0,mm2

    movq       [edi],mm0
    add 	edi,8
    loop	@b

    xor        eax,eax
    mov        ecx,SIZE_X*3/4
    rep        stosd
end if

.no_max:

if Ext >= SSE
    cmp     [min_flag],0
    je	    .no_min
;    push       ecx
    mov        edi,screen
    mov        ecx,SIZE_X*3/4
  ;   ;    pxor       mm5,mm5
    xor        eax,eax
    rep        stosd

    mov        ecx,(SIZE_X*(SIZE_Y-3))*3/8
  @@:
    movq       mm0,[edi+SIZE_X*3]
    movq       mm1,[edi-SIZE_X*3]
    movq       mm2,[edi-3]
    movq       mm3,[edi+3]

    pminub	mm0,mm1
    pminub	mm2,mm3
    pminub	mm0,mm2

    movq       [edi],mm0
    add 	edi,8
    loop	@b

    xor        eax,eax

    mov        ecx,SIZE_X*3/4
    rep        stosd
end if
.no_min:
end if

    RDTSC
    sub eax,[esp]
    sub eax,41
;    pop     eax

    mov     ecx,10
  .dc:
    xor     edx,edx
    mov     edi,10
    div     edi
    add     dl,30h
    mov     [STRdata+ecx-1],dl
    loop    .dc
    pop eax

    mov     eax,7	    ; put image
    mov     ebx,screen
    mov     ecx,SIZE_X shl 16 + SIZE_Y
    mov     edx,5 shl 16 + 25
    int     0x40

	mov  eax,13
    mov  ebx,530*65536+60
    mov  ecx,510*65536+9
    xor  edx,edx
    int  40h
	
    mov  eax,4			   ; function 4 : write text to window
    mov  ebx,530*65536+510	   ; [x start] *65536 + [y start]
    mov  ecx,0x00888888
    mov  edx,STRdata		   ; pointer to text beginning
    mov  esi,10 		   ; text length
    int  40h


   ; addsubps xmm0,xmm0


   jmp	   still

;--------------------------------------------------------------------------------
;-------------------------PROCEDURES---------------------------------------------
;--------------------------------------------------------------------------------
include "TEX3.INC"
include "FLAT_CAT.INC"
include "TEX_CAT.INC"
include "BUMP_CAT.INC"
include "3DMATH.INC"
include "GRD_LINE.INC"
include "GRD3.INC"
include "FLAT3.INC"
include "BUMP3.INC"
include "B_PROCS.INC"
include "A_PROCS.INC"
include "GRD_CAT.INC"
include "BUMP_TEX.INC"
include "GRD_TEX.INC"
include "TWO_TEX.INC"
include "ASC.INC"



alloc_buffer_mem:
    movzx    ecx,[size_x]
    movzx    eax,[size_y]
    mul      ecx
    lea      ecx,[eax*3]
    push     ecx
    shl      eax,2
    add      ecx,eax
    add      ecx,MEM_END
    mov      ebx,1
    mov      eax,64	; allocate mem  - resize app mem
    int      0x40
    mov      [screen_ptr],MEM_END
    mov      [Zbuffer_ptr],MEM_END
    pop      ecx
    add      [Zbuffer_ptr],ecx
ret

update_flags:
; updates flags and writing flag description
; in    ah - button number
	push	ax
	mov	edi,menu
      .ch_another:
	cmp	ah,byte[edi]	 ; ah = button id
	jne	@f
	mov	bl,byte[edi+11]  ; max_flag + 1
	cmp	bl,255
	je	.no_write
	inc	byte[edi+12]	 ; flag
	cmp	byte[edi+12],bl
	jne	.write
	mov	byte[edi+12],0
	jmp	.write
      @@:
	add	edi,17
	cmp	byte[edi],-1
	jne	.ch_another
     .write:
;     clreol   {pascal never dies}
;          * eax = 13 - function number
;  * ebx = [coordinate on axis x]*65536 + [size on axis x]
;  * ecx = [coordinate on axis y]*65536 + [size on axis y]
;  * edx = color 0xRRGGBB or 0x80RRGGBB for gradient fill

	mov	eax,13				 ; function 13 write rectangle
	movzx	ecx,byte[edi]
	sub	cl,2
	lea	ecx,[ecx*3]
	lea	ecx,[ecx*5]
	add	ecx,28
	shl	ecx,16
	add	ecx,14				;  ecx = [coord y]*65536 + [size y]
	mov	ebx,(SIZE_X+12+70)*65536+25	; [x start] *65536 + [size x]
	mov	edx,0x00000000			;  color  0x00RRGGBB
	int	0x40

	mov	eax,4				; function 4 : write text to window
	movzx	ebx,byte[edi]
	sub	bl,2
	lea	ebx,[ebx*3]
	lea	ebx,[ebx*5]
	add	ebx,(SIZE_X+12+70)*65536+28	; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff			; font 1 & color ( 0xF0RRGGBB )
	movzx	edx,byte[edi+12]		; current flag
	shl	edx,2				; * 4 = text length
	add	edx,dword[edi+13]		; pointer to text beginning
	mov	esi,4				; text length -
						; flag description 4 characters
	int	0x40

     .no_write:
	pop	ax
ret
normalize_all_light_vectors:
	mov	edi,lights
     @@:
	call	normalize_vector	   ;       3dmath.inc
	add	edi,LIGHT_SIZE
	cmp	edi,lightsend	;ecx
	jl	@b
ret

calc_bumpmap_coords:	  ; map texture, bump
;macro .comment222
;                                ; planar mapping
;        mov     esi,points
;        mov     edi,tex_points
;      @@:
;         add     esi,2
;         movsd
;         cmp     dword[esi],dword -1
;         jne     @b

;      .Pi2  equ dword[ebp-4]

;      mov   ebp,esp
;      sub   esp,4

      fninit
      fldpi
      fadd	st,st
      mov	esi,[points_ptr]
      mov	edi,tex_points
      movzx	ecx,[points_count_var]
      inc	ecx
;      cmp       [map_tex_flag],1
;      jne       .cylindric
      ; spherical mapping around y axle

   @@:
      fld	dword[esi]     ; x coord
      fld	dword[esi+8]   ; z coord
      fpatan		       ; arctg(st1/st)
;      fdiv      .Pi2
      fdiv	st0,st1
      fimul	[tex_x_div2]
      fiadd	[tex_x_div2]
      fistp	word[edi]      ; x

      fld	dword[esi+4]   ; y coord
      fld	dword[esi]     ; x
      fmul	st,st0
      fld	dword[esi+4]   ; y
      fmul	st,st0
      fld	dword[esi+8]   ; z
      fmul	st,st0
      faddp
      faddp
      fsqrt
      fpatan
      fldpi
      fdivp
      fimul    [tex_y_div2]
      fiadd    [tex_y_div2]
      fistp    word[edi+2]     ; y

      add      esi,12
      add      edi,4
      loop     @b
      ffree    st0
;      jmp      .end_map
;  .cylindric:
;       fld     dword[esi]     ; around y axle
;       fld     dword[esi+8]
;       fpatan
;       fdiv    st0,st1
;       fimul   [tex_x_div2]
;       fiadd   [tex_x_div2]
;       fistp   word[edi]

;       fld     dword[esi+4]
;       fimul   [tex_y_div2]
;       fiadd   [tex_y_div2]
;       fistp   word[edi+2]

;       add     esi,12
;       add     edi,4
;       loop    .cylindric
;       ffree    st0
;;      mov      esp,ebp
;   .end_map:
ret


init_envmap2:	      ; do env_map using many light sources
;env_map 512 x 512 x 3 bytes
.temp  equ word   [ebp-2]
.nEy   equ word  [ebp-4]
.nEx   equ word  [ebp-6]
.col_r equ    [ebp-8]
.col_g equ    [ebp-9]
.col_b equ    [ebp-10]

	 push	  ebp
	 mov	  ebp,esp
	 sub	  esp,20
	 mov	  edi,envmap
	 fninit

	 mov	  dx,- TEX_Y / 2 ;256   ; dx - vertical coordinate = y
    .ie_ver:
	 mov	  cx,- TEX_X / 2 ;256   ; cx - horizontal coord = x
    .ie_hor:
	 xor	  ebx,ebx
	 mov	  dword .col_b, 0
     .light:
	 lea	  esi,[lights+ebx]
	 fld	  dword[esi]	 ; light vector x cooficient
	 fimul	  [tex_x_div2] ;[i256]
	 mov	  .temp,cx
	 fisubr   .temp
	 fistp	  .nEx
	 fld	  dword[esi+4]	 ; light vector y cooficient
	 fimul	  [tex_y_div2] ;[i256]
	 mov	  .temp,dx
	 fisubr   .temp
	 fistp	  .nEy

	 cmp	  .nEx,- TEX_X / 2 ;256
	 jl	  .update_counters
	 cmp	  .nEy,- TEX_Y / 2 ;256
	 jl	  .update_counters
	 cmp	  .nEx,TEX_X / 2 ;256
	 jg	  .update_counters
	 cmp	  .nEy,TEX_Y / 2 ;256
	 jg	  .update_counters

	 fild	  .nEx
	 fmul	  st,st0
	 fild	  .nEy
	 fmul	  st,st0
	 faddp
	 fsqrt
	 fisubr   [i256]
	 fmul	  [env_const]
	 fidiv	  [i256]   ; st - 'virtual' dot product

	 fcom	  [dot_max]
	 fstsw	  ax
	 sahf
	 jb	  @f
	 ffree	  st
	 fld1	  ;[dot_max]
      @@:
	 fcom	  [dot_min]
	 fstsw	  ax
	 sahf
	 ja	  @f
	 ffree	  st
	 fldz	  ;[dot_min]
      @@:
	 push	  ebp
	 movzx	  ax,byte[esi+21]
	 push	  ax  ;- shines
	 mov	  al,byte[esi+14]   ; b    orginal color
	 push	  ax
	 mov	  al,byte[esi+13]   ; g
	 push	  ax
	 mov	  al,byte[esi+12]   ; r
	 push	  ax
	 mov	  al,byte[esi+20]   ; b     max color
	 push	  ax
	 mov	  al,byte[esi+19]   ; g
	 push	  ax
	 mov	  al,byte[esi+18]   ; r
	 push	  ax
	 mov	  al,byte[esi+17]   ; b    min col
	 push	  ax
	 mov	  al,byte[esi+16]   ; g
	 push	  ax
	 mov	  al,byte[esi+15]   ; r
	 push	  ax
	 push	  eax	      ; earlier - dot pr
      ;  fstp     .dot_product
      ;  push     .dot_product
	 call	  calc_one_col
	 pop	  ebp
	 ; eax-0x00rrggbb
	 cmp	  al,.col_b
	 jbe	  @f
	 mov	  .col_b,al
   @@:			      ;  eax - ggbb00rr
	 shr	  ax,8
	 cmp	  al,.col_g
	 jbe	  @f
	 mov	  .col_g,al
   @@:			      ;  eax - bb0000gg
	 shr	  eax,16
	 cmp	  al,.col_r
	 jbe	  @f
	 mov	  .col_r,al
   @@:
   .update_counters:			 ; update and jump when neccesery
	 add	  ebx,LIGHT_SIZE
	 cmp	  bx,[all_lights_size]
	 jl	  .light    ; next_light
	 mov	  eax,dword .col_b
	 stosd
	 dec	  edi

	 inc	  cx
	 cmp	  cx,TEX_X / 2 ;256
	 jne	  .ie_hor

	 inc	  dx
	 cmp	  dx,TEX_Y / 2 ;256
	 jne	 .ie_ver

	 mov	 esp,ebp
	 pop	 ebp
ret



do_color_buffer:	 ; do color buffer for Gouraud, flat shading
;env_map 512 x 512 x 3 bytes    ; many lights using
.temp  equ word   [ebp-2]
.nz    equ dword  [ebp-6]  ; dword
.ny    equ dword  [ebp-10]
.nx    equ dword  [ebp-14]
.col_r equ    [ebp-16]
.col_g equ    [ebp-17]
.col_b equ    [ebp-18]

	 push	  ebp
	 mov	  ebp,esp
	 sub	  esp,20
	 mov	  edi,color_map
	 fninit

	 mov	  dx,- TEX_Y / 2 ;-256   ; dx - vertical coordinate = y
    .ie_ver:
	 mov	  cx,- TEX_X / 2 ;256   ; cx - horizontal coord = x
    .ie_hor:
	 mov	  .temp,cx
	 fild	  .temp
	 fidiv	  [i256]   ;st = Nx - vector normal x cooficient
	 fst	  .nx
	 fmul	  st,st0
	 mov	  .temp,dx
	 fild	  .temp
	 fidiv	  [i256]   ; st = Ny - vector normal y coeficient
	 fst	  .ny
	 fmul	  st,st0
	 faddp
	 fld1
	 fchs
	 faddp
	 fabs
	 fsqrt
	 fchs
	 fstp	  .nz		   ; st - Nz - vect normal z coeficient
	 xor	  ebx,ebx
	 mov	  dword .col_b, 0
     .light:
	 push	  edi	;env_map
	 lea	  esi,[lights+ebx]
	 lea	  edi,.nx
	 call	  dot_product
	 pop	  edi
	 fcom	  [dot_min]
	 fstsw	  ax
	 sahf
	 ja	  .env_ok1  ;compare with dot_max
	 ffree	  st

	jmp	  .update_counters
      .env_ok1:
	 fcom	 [dot_max]
	 fstsw	 ax
	 sahf
	 jb	 .env_ok2     ; calc col
	 ffree	 st
	 jmp	 .update_counters
      .env_ok2: 	   ;calc col
	 push	  ebp
	 movzx	  ax,byte[esi+21]
	 push	  ax  ;- shines
	 mov	  al,byte[esi+14]   ; b    orginal color
	 push	  ax
	 mov	  al,byte[esi+13]   ; g
	 push	  ax
	 mov	  al,byte[esi+12]   ; r
	 push	  ax
	 mov	  al,byte[esi+20]   ; b     max color
	 push	  ax
	 mov	  al,byte[esi+19]   ; g
	 push	  ax
	 mov	  al,byte[esi+18]   ; r
	 push	  ax
	 mov	  al,byte[esi+17]   ; b    min col
	 push	  ax
	 mov	  al,byte[esi+16]   ; g
	 push	  ax
	 mov	  al,byte[esi+15]   ; r
	 push	  ax
	 push	  eax	      ; earlier - dot pr
      ;  fstp     .dot_product
      ;  push     .dot_product
	 call	  calc_one_col
	 pop	  ebp
	 ; eax-0x00rrggbb
	 cmp	  al,.col_b
	 jbe	  @f
	 mov	  .col_b,al
   @@:
	 shr	  ax,8
	 cmp	  al,.col_g
	 jbe	  @f
	 mov	  .col_g,al
   @@:
	 shr	  eax,16
	 cmp	  al,.col_r
	 jbe	  @f
	 mov	  .col_r,al
  @@:
 .update_counters:				    ; update and jump when neccesery
	add	ebx,LIGHT_SIZE
	cmp	bx,[all_lights_size]
	jl	.light	  ; next_light
	mov	eax,dword .col_b
	stosd
	dec	edi

	inc	cx
	cmp	cx,TEX_X / 2 ;256
	jne	.ie_hor

	inc	dx
	cmp	dx,TEX_X / 2 ;256
	jne	.ie_ver

    .env_done:
	 mov	 esp,ebp
	 pop	 ebp
ret
if 0
init_triangles_normals:
	mov	ebx,triangles_normals
	mov	ebp,triangles
     @@:
	push	ebx
	mov	ebx,vectors
	movzx	esi,word[ebp]	       ; first point index
	lea	esi,[esi*3]
	lea	esi,[points+esi*2]     ; esi - pointer to 1st 3d point
	movzx	edi,word[ebp+2]        ; second point index
	lea	edi,[edi*3]
	lea	edi,[points+edi*2]     ; edi - pointer to 2nd 3d point
	call	make_vector
	add	ebx,12
	mov	esi,edi
	movzx	edi,word[ebp+4]        ; third point index
	lea	edi,[edi*3]
	lea	edi,[points+edi*2]
	call	make_vector
	mov	edi,ebx 		; edi - pointer to 2nd vector
	mov	esi,ebx
	sub	esi,12			; esi - pointer to 1st vector
	pop	ebx
	call	cross_product
	mov	edi,ebx
	call	normalize_vector
	add	ebp,6
	add	ebx,12
	cmp	dword[ebp],-1
	jne	@b
ret
end if
init_point_normals:
.x equ dword [ebp-4]
.y equ dword [ebp-8]
.z equ dword [ebp-12]
.point_number equ word [ebp-26]
.hit_faces    equ word [ebp-28]

	fninit
	mov	  ebp,esp
	sub	  esp,28
	mov	  edi,[points_normals_ptr]
	mov	  .point_number,0
    .ipn_loop:
	mov	  .hit_faces,0
	mov	  .x,0
	mov	  .y,0
	mov	  .z,0
	mov	  esi,[triangles_ptr]
	xor	  ecx,ecx	       ; ecx - triangle number
    .ipn_check_face:
	xor	  ebx,ebx	       ; ebx - 'position' in one triangle
    .ipn_check_vertex:
	movzx	  eax,word[esi+ebx]    ;  eax - point_number
	cmp	  ax,.point_number
	jne	  .ipn_next_vertex
	push	  esi
	mov	  esi,ecx
	lea	  esi,[esi*3]
       ; lea       esi,[triangles_normals+esi*4]
	shl	  esi,2
	add	  esi,[triangles_normals_ptr]

	fld	  .x
	fadd	  dword[esi+vec_x]	 ; vec_x this defined in 3dmath.asm - x cooficient
	fstp	  .x			 ; of normal vactor
	fld	  .y
	fadd	  dword[esi+vec_y]
	fstp	  .y
	fld	  .z
	fadd	  dword[esi+vec_z]
	fstp	  .z
	pop	  esi
	inc	  .hit_faces
	jmp	  .ipn_next_face
    .ipn_next_vertex:
	add	  ebx,2
	cmp	  ebx,6
	jne	  .ipn_check_vertex
    .ipn_next_face:
	add	  esi,6
	inc	  ecx
	cmp	  cx,[triangles_count_var]
	jne	  .ipn_check_face

	fld	  .x
	fidiv	  .hit_faces
	fstp	  dword[edi+vec_x]
	fld	  .y
	fidiv	  .hit_faces
	fstp	  dword[edi+vec_y]
	fld	  .z
	fidiv	  .hit_faces
	fstp	  dword[edi+vec_z]
	call	  normalize_vector
	add	  edi,12  ;type vector 3d
	inc	  .point_number
	mov	  dx,.point_number
	cmp	  dx,[points_count_var]
	jne	  .ipn_loop

	mov	  esp,ebp
ret
;===============================================================

init_triangles_normals2:
	mov	ebx,[triangles_normals_ptr]
	mov	ebp,[triangles_ptr]
     @@:
	push	ebx
	mov	ebx,vectors
	movzx	esi,word[ebp]	       ; first point index
	lea	esi,[esi*3]
;        lea     esi,[points+esi*2]     ; esi - pointer to 1st 3d point
	shl	esi,2
	add	esi,[points_ptr]
	movzx	edi,word[ebp+2] 	 ; first point index
	lea	edi,[edi*3]
	shl	edi,2
	add	edi,[points_ptr]
;        movzx   edi,word[ebp+2]        ; second point index
;        lea     edi,[edi*3]
;        lea     edi,[points+edi*2]     ; edi - pointer to 2nd 3d point
	call	make_vector_r
	add	ebx,12
	mov	esi,edi
	movzx	edi,word[ebp+4]        ; third point index
	lea	edi,[edi*3]
	shl	edi,2
	add	edi,[points_ptr]
;        lea     edi,[points+edi*2]
	call	make_vector_r
	mov	edi,ebx 		; edi - pointer to 2nd vector
	mov	esi,ebx
	sub	esi,12			; esi - pointer to 1st vector
	pop	ebx
	call	cross_product
	mov	edi,ebx
	call	normalize_vector
	add	ebp,6
	add	ebx,12
	cmp	dword[ebp],-1
	jne	@b
ret


;=================================================================
sort_triangles:
	mov	esi,[triangles_ptr]
	mov	edi,triangles_with_z
	mov	ebp,[points_translated_ptr]

    make_triangle_with_z:	;makes list with triangles and z position
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	movzx	ecx,word[ebp+eax*2+4]

	movzx	eax,word[esi+2]
	lea	eax,[eax*3]
	add	cx,word[ebp+eax*2+4]

	movzx	eax,word[esi+4]
	lea	eax,[eax*3]
	add	cx,word[ebp+eax*2+4]

	mov	ax,cx
       ; cwd
       ; idiv    word[i3]
	movsd			; store vertex coordinates
	movsw
	stosw			; middle vertex coordinate  'z' in triangles_with_z list
	cmp	dword[esi],-1
	jne	make_triangle_with_z
	movsd			; copy end mark
	mov	eax,4
	lea	edx,[edi-8-trizdd]
     ;   lea     edx, [edi-8]
     ;   sub     edx,[triangles_w_z_ptr]
	mov	[high],edx
	call	quicksort
	mov	eax,4
	mov	edx,[high]
	call	insertsort
	jmp	end_sort

    quicksort:
	mov	ecx,edx
	sub	ecx,eax
	cmp	ecx,32
	jc	.exit
	lea	ecx,[eax+edx]
	shr	ecx,4
	lea	ecx,[ecx*8-4];
;        mov     edi,[triangles_w_z_ptr]
;        mov     ebx,[edi+eax]
;        mov     esi,[edi+ecx]
;        mov     edi,[edi+edx]
	mov	ebx,[trizdd+eax]; trizdd[l]
	mov	esi,[trizdd+ecx]; trizdd[i]
	mov	edi,[trizdd+edx]; trizdd[h]
	cmp	ebx,esi
	jg	@f		; direction NB! you need to negate these to invert the order
      if Ext=NON
	mov	[trizdd+eax],esi
	mov	[trizdd+ecx],ebx
	mov	ebx,[trizdd+eax-4]
	mov	esi,[trizdd+ecx-4]
	mov	[trizdd+eax-4],esi
	mov	[trizdd+ecx-4],ebx
	mov	ebx,[trizdd+eax]
	mov	esi,[trizdd+ecx]
      else
;        push    ebx
;        mov     ebx,[triangles_w_z_ptr]
;        movq    mm0,[ebx+eax-4]
;        movq    mm1,[ebx+ecx-4]
;        movq    [ebx+ecx-4],mm0
;        movq    [ebx+eax-4],mm1
;        pop     ebx
	movq	mm0,[trizdq+eax-4]
	movq	mm1,[trizdq+ecx-4]
	movq	[trizdq+ecx-4],mm0
	movq	[trizdq+eax-4],mm1
	xchg	ebx,esi
      end if
      @@:
	cmp	ebx,edi
	jg	@f		; direction
      if Ext=NON
	mov	[trizdd+eax],edi
	mov	[trizdd+edx],ebx
	mov	ebx,[trizdd+eax-4]
	mov	edi,[trizdd+edx-4]
	mov	[trizdd+eax-4],edi
	mov	[trizdd+edx-4],ebx
	mov	ebx,[trizdd+eax]
	mov	edi,[trizdd+edx]
      else
;        push    ebx
;        mov     ebx,[triangles_w_z_ptr]
;        movq    mm0,[ebx+eax-4]
;        movq    mm1,[ebx+edx-4]
;        movq    [ebx+edx-4],mm0
;        movq    [ebx+eax-4],mm1
	movq	mm0,[trizdq+eax-4]
	movq	mm1,[trizdq+edx-4]
	movq	[trizdq+edx-4],mm0
	movq	[trizdq+eax-4],mm1
;        pop     ebx
	xchg	ebx,edi
      end if
      @@:
	cmp	esi,edi
	jg	@f		; direction
      if Ext=NON
	mov	[trizdd+ecx],edi
	mov	[trizdd+edx],esi
	mov	esi,[trizdd+ecx-4]
	mov	edi,[trizdd+edx-4]
	mov	[trizdd+ecx-4],edi
	mov	[trizdd+edx-4],esi
      else
;        push    ebx
;        mov     ebx,[triangles_w_z_ptr]
;        movq    mm0,[ebx+ecx-4]
;        movq    mm1,[ebx+edx-4]
;        movq    [ebx+edx-4],mm0
;        movq    [ebx+ecx-4],mm1
;        pop     ebx

	movq	mm0,[trizdq+ecx-4]
	movq	mm1,[trizdq+edx-4]
	movq	[trizdq+edx-4],mm0
	movq	[trizdq+ecx-4],mm1
	xchg	ebx,esi
      end if
      @@:
	mov	ebp,eax 	; direction
	add	ebp,8	   ;   j
      if Ext=NON
	mov	esi,[trizdd+ebp]
	mov	edi,[trizdd+ecx]
	mov	[trizdd+ebp],edi
	mov	[trizdd+ecx],esi
	mov	esi,[trizdd+ebp-4]
	mov	edi,[trizdd+ecx-4]
	mov	[trizdd+ecx-4],esi
	mov	[trizdd+ebp-4],edi
      else
;        push    ebx
;        mov     ebx,[triangles_w_z_ptr]
;        movq    mm0,[ebx+ebp-4]
;        movq    mm1,[ebx+ecx-4]
;        movq    [ebx+ecx-4],mm0
;        movq    [ebx+ebp-4],mm1
;        pop     ebx

	movq	mm0,[trizdq+ebp-4]
	movq	mm1,[trizdq+ecx-4]
	movq	[trizdq+ecx-4],mm0
	movq	[trizdq+ebp-4],mm1
      end if
	mov	ecx,edx    ;   i; direction
	mov	ebx,[trizdd+ebp]; trizdd[j]
;        mov     ebx, [triangles_w_z_ptr]
;        add     ebx, ebp

 ;       push    eax
 ;       mov     eax, [triangles_w_z_ptr]
      .loop:
	sub	ecx,8		; direction
	cmp	[trizdd+ecx],ebx
;        cmp     [eax+ecx],ebx
	jl	.loop		; direction
      @@:
	add	ebp,8		; direction
	cmp	[trizdd+ebp],ebx
;        cmp     [eax+ebp],ebx
	jg	@b		; direction
	cmp	ebp,ecx
	jge	@f		; direction
      if Ext=NON
	mov	esi,[trizdd+ecx]
	mov	edi,[trizdd+ebp]
	mov	[trizdd+ebp],esi
	mov	[trizdd+ecx],edi
	mov	edi,[trizdd+ecx-4]
	mov	esi,[trizdd+ebp-4]
	mov	[trizdd+ebp-4],edi
	mov	[trizdd+ecx-4],esi
      else
;        movq    mm0,[eax+ecx-4]
;        movq    mm1,[eax+ebp-4]
;        movq    [eax+ebp-4],mm0
;        movq    [eax+ecx-4],mm1
	movq	mm0,[trizdq+ecx-4]
	movq	mm1,[trizdq+ebp-4]
	movq	[trizdq+ebp-4],mm0
	movq	[trizdq+ecx-4],mm1
      end if
	jmp	.loop
;        pop     eax
      @@:
      if Ext=NON
	mov	esi,[trizdd+ecx]
	mov	edi,[trizdd+eax+8]
	mov	[trizdd+eax+8],esi
	mov	[trizdd+ecx],edi
	mov	edi,[trizdd+ecx-4]
	mov	esi,[trizdd+eax+4]
	mov	[trizdd+eax+4],edi
	mov	[trizdd+ecx-4],esi
      else
;        push    edx
;        mov     edx,[triangles_w_z_ptr]
;        movq    mm0,[edx+ecx-4]
;        movq    mm1,[edx+eax+4]; dir
;        movq    [edx+eax+4],mm0; dir
;        movq    [edx+ecx-4],mm1
;        pop     edx

	movq	mm0,[trizdq+ecx-4]
	movq	mm1,[trizdq+eax+4]; dir
	movq	[trizdq+eax+4],mm0; dir
	movq	[trizdq+ecx-4],mm1
      end if
	add	ecx,8
	push	ecx edx
	mov	edx,ebp
	call	quicksort
	pop	edx eax
	call	quicksort
      .exit:
    ret
    insertsort:
	mov	esi,eax
      .start:
	add	esi,8
	cmp	esi,edx
	ja	.exit
	mov	ebx,[trizdd+esi]
;        mov     ebx,[triangles_w_z_ptr]
;        add     ebx,esi
      if Ext=NON
	mov	ecx,[trizdd+esi-4]
      else
;        push    ebx
;        mov     ebx,[triangles_w_z_ptr]
;        movq    mm1,[ebx+esi-4]
	movq	mm1,[trizdq+esi-4]
;        pop     ebx
      end if
	mov	edi,esi
      @@:
	cmp	edi,eax
	jna	@f
;        push    eax
;        mov     eax,[triangles_w_z_ptr]
;        cmp     [eax+edi-8],ebx
;        pop     eax
       cmp     [trizdd+edi-8],ebx
	jg	@f		   ; direction
      if Ext=NON
	mov	ebp,[trizdd+edi-8]
	mov	[trizdd+edi],ebp
	mov	ebp,[trizdd+edi-12]
	mov	[trizdd+edi-4],ebp
      else
;        push    eax
;        mov     eax,[triangles_w_z_ptr]
;        movq    mm0,[eax+edi-12]
;        movq    [eax+edi-4],mm0
	movq	mm0,[trizdq+edi-12]
	movq	[trizdq+edi-4],mm0
;        pop     eax
      end if
	sub	edi,8
	jmp	@b
      @@:
      if Ext=NON
	mov	[trizdd+edi],ebx
	mov	[trizdd+edi-4],ecx
      else
;        push    eax
;        mov     eax,[triangles_w_z_ptr]
;        movq    [eax+edi-4],mm1
	movq	[trizdq+edi-4],mm1
;        pop     eax
      end if
	jmp	.start
      .exit:
    ret
   end_sort:
    ; translate triangles_with_z to sorted_triangles
	mov	esi,triangles_with_z
;        mov      esi,[triangles_w_z_ptr]
      ;  mov     edi,sorted_triangles
	mov	 edi,[triangles_ptr]
    again_copy:
      if Ext=NON
	movsd
	movsw
	add	esi,2
      else
	movq	mm0,[esi]
	movq	[edi],mm0
	add	esi,8
	add	edi,6
      end if
	cmp	dword[esi],-1
	jne	again_copy
;      if Ext=MMX
;        emms
;      end if
	movsd  ; copy end mark too
ret

clrscr:
	mov	edi,screen
	mov	ecx,SIZE_X*SIZE_Y*3/4
	xor	eax,eax
      if Ext=NON
	rep	stosd
      else
	pxor	mm0,mm0
      @@:
	movq	[edi+00],mm0
	movq	[edi+08],mm0
	movq	[edi+16],mm0
	movq	[edi+24],mm0
	add	edi,32
	sub	ecx,8
	jnc	@b
      end if
ret


draw_triangles:
	mov esi,[triangles_ptr]
	mov [edges_counter],0
    .again_dts:
	mov ebp,[points_translated_ptr]
      if Ext=NON
	movzx	eax,word[esi]
	mov	[point_index1],ax
	lea	eax,[eax*3]
	add	eax,eax
	push	ebp
	add	ebp,eax
	mov	eax,[ebp]
	mov	dword[xx1],eax
	mov	eax,[ebp+4]
	mov	[zz1],ax
	pop	ebp


	movzx	eax,word[esi+2]
	mov	[point_index2],ax
	lea	eax,[eax*3]
	add	eax,eax
	push	ebp
	add	ebp,eax
	mov	eax,[ebp]
	mov	dword[xx2],eax
	mov	eax,[ebp+4]
	mov	[zz2],ax
	pop	ebp


	movzx	eax,word[esi+4]        ; xyz3 = [ebp+[esi+4]*6]
	mov	[point_index3],ax
	lea	eax,[eax*3]
	add	eax,eax
    ;    push    ebp
	add	ebp,eax
	mov	eax,[ebp]
	mov	dword[xx3],eax
	mov	eax,[ebp+4]
	mov	[zz3],ax
      else
	mov	eax,dword[esi]		 ; don't know MMX
	mov	dword[point_index1],eax
       ; shr     eax,16
       ; mov     [point_index2],ax
	mov	ax,word[esi+4]
	mov	[point_index3],ax
	movq	mm0,[esi]
	pmullw	mm0,qword[const6]
	movd	eax,mm0
	psrlq	mm0,16
	movd	ebx,mm0
	psrlq	mm0,16
	movd	ecx,mm0
	and	eax,0FFFFh
	and	ebx,0FFFFh
	and	ecx,0FFFFh
	movq	mm0,[ebp+eax]
	movq	mm1,[ebp+ebx]
	movq	mm2,[ebp+ecx]
	movq	qword[xx1],mm0
	movq	qword[xx2],mm1
	movq	qword[xx3],mm2
;        emms
      end if				  ; *********************************
	push esi			  ;
	fninit				  ; DO culling AT FIRST
	cmp	[culling_flag],1	  ; (if culling_flag = 1)
	jne	.no_culling
	mov	esi,point_index1	  ; *********************************
	mov	ecx,3			  ;
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]
;        lea     eax,[eax+point_normals_rotated]
	fld	dword[eax+8]		 ; *****************************
	ftst				 ; CHECKING OF Z COOFICIENT OF
	fstsw	ax			 ; NORMAL VECTOR
	sahf
	jb	@f
	ffree	st
	loop	@b
	jmp	.end_draw   ; non visable
      @@:
	ffree	st  ;is visable
      .no_culling:
	cmp	[dr_flag],0		  ; draw type flag
	je	.flat_draw
	cmp	[dr_flag],2
	je	.env_mapping
	cmp	[dr_flag],3
	je	.bump_mapping
	cmp	[dr_flag],4
	je	.tex_mapping
	cmp	[dr_flag],5
	je	.rainbow
	cmp	[dr_flag],7
	je	.grd_tex
	cmp	[dr_flag],8
	je	.two_tex
	cmp	[dr_flag],9
	je	.bump_tex
	cmp	[dr_flag],10
	je	.cubic_env_mapping
	cmp	[dr_flag],11
	je	.draw_smooth_line
				      ; ****************
	mov	esi,point_index3      ; do Gouraud shading
	mov	ecx,3
      .again_grd_draw:
	movzx	eax,word[esi]
	shl	eax,2
	lea	eax,[eax*3]
	add	eax,[points_normals_rot_ptr]
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]	 ; x cooficient of normal vector
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[esp-2]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]	  ; y cooficient
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[esp-4]

	movzx	 eax,word[esp-4]
	movzx	 ebx,word[esp-2]
	shl	 eax,TEX_SHIFT
	add	 eax,ebx
	lea	 eax,[eax*3+color_map]
	mov	 eax,dword[eax]
	cmp	[catmull_flag],1      ; put on stack z coordinate if necessary
	jne	 @f
	lea	 edx,[ecx*3]
	push	 word[edx*2+xx1-2]    ; zz1 ,2 ,3
      @@:
	ror	 eax,16 	      ; eax -0xxxrrggbb -> 0xggbbxxrr
	xor	 ah,ah
	push	 ax	    ;r
	rol	 eax,8		      ; eax-0xggbb00rr -> 0xbb00rrgg
	xor	 ah,ah
	push	 ax	    ;g
	shr	 eax,24
	push	 ax	    ;b

	sub	 esi,2
	dec	 cx
	jnz	 .again_grd_draw
	jmp	 .both_draw

   ;     movzx   edi,[point_index3]   ;gouraud shading according to light vector
   ;     lea     edi,[edi*3]
   ;     lea     edi,[4*edi+point_normals_rotated] ; edi - normal
   ;     mov     esi,light_vector
   ;     call    dot_product
   ;     fabs
   ;     fimul   [orginal_color_r]
   ;     fistp   [temp_col]
   ;     and     [temp_col],0x00ff
   ;     push    [temp_col]
   ;     push    [temp_col]
   ;     push    [temp_col]

   ;     movzx   edi,[point_index2]
   ;     lea     edi,[edi*3]
   ;     lea     edi,[4*edi+point_normals_rotated] ; edi - normal
   ;     mov     esi,light_vector
   ;     call    dot_product
   ;     fabs
   ;     fimul   [orginal_color_r]
   ;     fistp    [temp_col]
   ;     and     [temp_col],0x00ff
   ;     push    [temp_col]
   ;     push    [temp_col]
   ;     push    [temp_col]

   ;     movzx   edi,[point_index1]
   ;     lea     edi,[edi*3]
   ;     lea     edi,[4*edi+point_normals_rotated] ; edi - normal
   ;     mov     esi,light_vector
   ;     call    dot_product
   ;     fabs
   ;     fimul   [orginal_color_r]
   ;     fistp   [temp_col]
   ;     and     [temp_col],0x00ff
   ;     push    [temp_col]
   ;     push    [temp_col]
   ;     push    [temp_col]
   .rainbow:
	cmp	[catmull_flag],1      ; put on stack z coordinate if necessary
	jne	 @f
	push	 [zz3]
      @@:
	mov	 eax,dword[yy3]
	mov	 ebx,0x00ff00ff
	and	 eax,ebx
	push	 eax
	neg	 al
	push	 ax
	cmp	[catmull_flag],1
	jne	 @f
	push	 [zz2]
      @@:
	mov	 eax,dword[yy2]
	and	 eax,ebx
	push	 eax
	neg	 al
	push	 ax
	cmp	[catmull_flag],1
	jne	 @f
	push	 [zz1]
      @@:
	mov	 eax,dword[yy1]
	and	 eax,ebx
	push	 eax
	neg	 al
	push	 ax
    .both_draw:
	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	lea	edi,[screen]
	cmp	[catmull_flag],0
	je	@f
  ;      lea     esi,[Z_buffer]
	mov	esi,[Zbuffer_ptr]
	call	gouraud_triangle_z
	jmp	.end_draw
       @@:
	call	gouraud_triangle
	jmp	.end_draw

     .flat_draw:		     ;**************************
				     ; FLAT DRAWING
	movzx	eax,[point_index1]
	movzx	ebx,[point_index2]
	movzx	ecx,[point_index3]
	shl	eax,2
	shl	ebx,2
	shl	ecx,2
	lea	eax,[eax*3]  ;+point_normals_rotated]
	add	eax,[points_normals_rot_ptr]
	lea	ebx,[ebx*3]  ;+point_normals_rotated]
	add	ebx,[points_normals_rot_ptr]
	lea	ecx,[ecx*3]  ;+point_normals_rotated]
	add	ecx,[points_normals_rot_ptr]
	fld	dword[eax]	; x cooficient of normal vector
	fadd	dword[ebx]
	fadd	dword[ecx]
	fidiv	[i3]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	dword[esp-4]	; x temp variables
	fld	dword[eax+4]	; y cooficient of normal vector
	fadd	dword[ebx+4]
	fadd	dword[ecx+4]
	fidiv	[i3]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	dword[esp-8]   ;  y
	mov	edx,dword[esp-8]
	shl	edx,TEX_SHIFT
	add	edx,dword[esp-4]
	lea	eax,[3*edx+color_map]
	mov	edx,dword[eax]

	and	edx,0x00ffffff	  ; edx = 0x00rrggbb



     ;   mov     ax,[zz1]      ; z position depend draw
     ;   add     ax,[zz2]
     ;   add     ax,[zz3]
     ;   cwd
     ;   idiv    [i3] ;    = -((a+b+c)/3+130)
     ;   add     ax,130
     ;   neg     al
     ;   xor     edx,edx
     ;   mov     ah,al           ;set color according to z position
     ;   shl     eax,8
     ;   mov     edx,eax

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
       ; mov     edi,screen
	lea	edi,[screen]
	cmp	[catmull_flag],0
	je	@f
   ;     lea     esi,[Z_buffer]
	mov	esi,[Zbuffer_ptr]
	push	word[zz3]
	push	word[zz2]
	push	word[zz1]
	call	flat_triangle_z
	jmp	.end_draw
      @@:
	call	draw_triangle
	jmp	.end_draw
      .env_mapping:
       ; fninit
	cmp	[catmull_flag],0
	je	@f
	push	[zz3]
	push	[zz2]
	push	[zz1]
      @@:
	mov	esi,point_index1
	sub	esp,12
	mov	edi,esp
	mov	ecx,3
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]	   ;point_normals_rotated
; #
;        fld     dword[eax]
;        fmul    dword[eax+4]
;        fld1
;        fld1
;        faddp
;        fmulp
;        fimul   [correct_tex]
;        fiadd   [correct_tex]
;        fistp   word[edi]
;        mov     word[edi+2],0
;;        fistp   word[edi+2]
; # last change
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi+2]
; # end of last ch.
	add	edi,4
	add	esi,2
	loop	@b

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,envmap
	cmp	[catmull_flag],0
	je	@f
  ;      mov     edx,Z_buffer
	mov	edx,[Zbuffer_ptr]
	call	tex_triangle_z
	jmp	.end_draw
      @@:
	call	tex_triangle
	jmp	.end_draw
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     .cubic_env_mapping:
       ; fninit
	cmp	[catmull_flag],0
	je	@f
	push	[zz3]
	push	[zz2]
	push	[zz1]
      @@:
	mov	esi,point_index1
	sub	esp,12
	mov	edi,esp
	mov	ecx,3
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]  ;point_normals_rotated
; #
	fld	dword[eax]
	fmul	dword[eax+4]
	fld1
	fld1
	faddp
	fmulp
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi]
	mov	word[edi+2],0
;        fistp   word[edi+2]
; # last change
;        ; texture x=(rotated point normal -> x * 255)+255
;        fld     dword[eax]
;        fimul   [correct_tex]
;        fiadd   [correct_tex]
;        fistp   word[edi]
;        ; texture y=(rotated point normal -> y * 255)+255
;        fld     dword[eax+4]
;        fimul   [correct_tex]
;        fiadd   [correct_tex]
;        fistp   word[edi+2]
; # end of last ch.
	add	edi,4
	add	esi,2
	loop	@b

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,envmap_cub
	cmp	[catmull_flag],0
	je	@f
  ;      mov     edx,Z_buffer
	mov	edx,[Zbuffer_ptr]
	call	tex_triangle_z
	jmp	.end_draw
      @@:
	call	tex_triangle
	jmp	.end_draw

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      .bump_mapping:
	; fninit
	cmp	[catmull_flag],0
	je	@f
;        push    Z_buffer
	push	[Zbuffer_ptr]
	push	[zz3]
	push	[zz2]
	push	[zz1]
      @@:
	mov	esi,point_index1
	sub	esp,12
	mov	edi,esp
	mov	ecx,3
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]  ;point_normals_rotated
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi+2]

	add	edi,4
	add	esi,2
	loop	@b

	movzx  esi,[point_index3]      ; bump map coords
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index2]
	shl    esi,2
	add    esi,tex_points
;       lea    esi,[esi*3]
;       lea    esi,[points+2+esi*2]
	push   dword[esi]
  ;     push   dword[xx2]
	movzx  esi,[point_index1]
	shl    esi,2
	add    esi,tex_points
;       lea     esi,[esi*3]
;       lea     esi,[points+2+esi*2]
	push   dword[esi]
   ;    push     dword[xx1]

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,envmap
	mov	edx,bumpmap	       ;BUMP_MAPPING

	cmp	[catmull_flag],0
	je	@f
	call	bump_triangle_z
	jmp	.end_draw
      @@:
	call	bump_triangle
	jmp	.end_draw

      .tex_mapping:

	; fninit
	cmp	[catmull_flag],0
	je	@f
	push	[zz3]
	push	[zz2]
	push	[zz1]
      @@:
	movzx  esi,[point_index3]      ; tex map coords
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index2]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index1]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,texmap
	cmp	[catmull_flag],0
	je	@f
   ;     mov     edx,Z_buffer
	mov	edx,[Zbuffer_ptr]
	call	tex_triangle_z
 ;       call    tex_plus_grd_trianlgle
	jmp	.end_draw
      @@:
	call	tex_triangle
	jmp	.end_draw
;      .ray:
;        grd_triangle according to points index
;        cmp     [catmull_flag],0
;        je      @f
;        push    [zz3]                   ; spot light with attenuation
;     @@:
;        movzx   eax,[point_index3]      ; env_map - points color list
;        shl     eax,1                   ; each color as word, 0x00rr00gg00bb..
;        lea     eax,[3*eax+bumpmap]
;        push    word[eax]
;        push    word[eax+2]
;        push    word[eax+4]
;        cmp     [catmull_flag],0
;        je      @f
;        push    [zz2]
;    @@:
;        movzx   eax,[point_index2]      ; env_map - points color list
;        shl     eax,1                   ; each color as word, 0x00rr00gg00bb..
;        lea     eax,[eax*3+bumpmap]
;        push    word[eax]
;        push    word[eax+2]
;        push    word[eax+4]
;        cmp     [catmull_flag],0
;        je      @f
;        push    [zz1]
;     @@:
;        movzx   eax,[point_index1]      ; env_map - points color list
;        shl     eax,1                   ; each color as word, 0xrr00gg00bb00..
;        lea     eax,[eax*3+bumpmap]
;        push    word[eax]
;        push    word[eax+2]
;        push    word[eax+4]
;        jmp     .both_draw

     .grd_tex:		  ; smooth shading + texture
	 push	ebp
	 mov	ebp,esp
	 sub	esp,4
	 push	ebp

	 movzx	esi,[point_index3]	; tex map coords
	 shl	esi,2
	 add	esi,tex_points
	 push	dword[esi]		; texture coords as first
	 movzx	esi,[point_index2]	; group of parameters
	 shl	esi,2
	 add	esi,tex_points
	 push	dword[esi]
	 movzx	esi,[point_index1]
	 shl	esi,2
	 add	esi,tex_points
	 push	dword[esi]

	 mov	 esi,point_index3
	 mov	 ecx,3

      .aagain_grd_draw:

	lea	 edx,[ecx*3]
	push	 word[edx*2+xx1-2]    ; zz1 ,2 ,3

	movzx	eax,word[esi]
	shl	eax,2
	lea	eax,[eax*3] ;+point_normals_rotated]
	add	eax,[points_normals_rot_ptr]
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]	 ; x cooficient of normal vector
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[ebp-2]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]	  ; y cooficient
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[ebp-4]

	movzx	 eax,word[ebp-4]
	movzx	 ebx,word[ebp-2]
	shl	 eax,TEX_SHIFT
	add	 eax,ebx
	lea	 eax,[eax*3+color_map]
	mov	 eax,dword[eax]

	ror	 eax,16 	      ; eax -0xxxrrggbb -> 0xggbbxxrr
	xor	 ah,ah
	push	 ax	    ;r
	rol	 eax,8		      ; eax-0xggbb00rr -> 0xbb00rrgg
	xor	 ah,ah
	push	 ax	    ;g
	shr	 eax,24
	push	 ax	    ;b

	sub	 esi,2
	dec	 cx
	jnz	 .aagain_grd_draw

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	edx,texmap
	mov	esi,[Zbuffer_ptr]

	call	tex_plus_grd_triangle

	pop	ebp
	mov	esp,ebp
	pop	ebp
	jmp	.end_draw

      .two_tex:
	push	[Zbuffer_ptr]

	push	word[zz3]
	push	word[zz2]
	push	word[zz1]

	movzx  esi,[point_index3]      ; tex map coords
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index2]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index1]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]

	mov	esi,point_index1     ; env coords
	sub	esp,12
	mov	edi,esp
	mov	ecx,3
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi+2]

	add	edi,4
	add	esi,2
	loop	@b

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,texmap
	mov	edx,envmap

	call	two_tex_triangle_z
	jmp	.end_draw

   .bump_tex:
	movzx  esi,[point_index3]      ; tex map coords
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index2]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index1]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]

	push  dword texmap

	push  [Zbuffer_ptr]
	xor   edi,edi

	push	word[zz3]
	push	word[zz2]
	push	word[zz1]

	mov	esi,point_index1     ; env coords
	sub	esp,12
	mov	edi,esp
	mov	ecx,3
      @@:
	movzx	eax,word[esi]
	lea	eax,[eax*3]
	shl	eax,2
	add	eax,[points_normals_rot_ptr]
	; texture x=(rotated point normal -> x * 255)+255
	fld	dword[eax]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[edi+2]

	add	edi,4
	add	esi,2
	loop	@b

;        push  dword 1 shl 16 + 1  ; emap coords
;        push  dword 127 shl 16 + 1
;        push  dword 127 shl 16 + 127

	movzx  esi,[point_index3]      ; bump map coords
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]
	movzx  esi,[point_index2]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]

	movzx  esi,[point_index1]
	shl    esi,2
	add    esi,tex_points
	push   dword[esi]

;        push  dword 1 shl 16 + 127
;        push  dword 127 shl 16 + 127
;        push  dword 1 shl 16 + 1  ; bump coords

	mov	eax,dword[xx1]
	ror	eax,16
	mov	ebx,dword[xx2]
	ror	ebx,16
	mov	ecx,dword[xx3]
	ror	ecx,16
	mov	edi,screen
	mov	esi,envmap
	mov	edx,bumpmap

	call bump_tex_triangle_z

	jmp	.end_draw

      .draw_smooth_line:
	mov	esi,point_index3
	mov	ecx,3
      .again_line_param:
	movzx	eax,word[esi]
	shl	eax,2
	lea	eax,[eax*3]
	add	eax,[points_normals_rot_ptr]
	; texture ;x=(rotated point normal -> x * 255)+255
	fld	dword[eax]	 ; x cooficient of normal vector
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[esp-2]
	; texture y=(rotated point normal -> y * 255)+255
	fld	dword[eax+4]	  ; y cooficient
	fimul	[correct_tex]
	fiadd	[correct_tex]
	fistp	word[esp-4]

	movzx	 eax,word[esp-4]
	movzx	 ebx,word[esp-2]
	shl	 eax,TEX_SHIFT
	add	 eax,ebx
	lea	 eax,[eax*3+color_map]
	mov	 eax,dword[eax]
	lea	 ebx,[ecx-1]
	shl	 ebx,2
	mov	 [ebx+col1],eax

	sub	 esi,2
	dec	 ecx
	jnz	 .again_line_param

;        mov     eax,[edges_ptr]         ;   this not works correctly
;        add     eax,[edges_counter]     ;   I mean chosing overlapped  edges.
;        mov     bl,[eax]                ;
;        test    bl,00000001b            ;
;        jz      @f                      ;
	mov	edi,screen
	mov	esi,[Zbuffer_ptr]

	mov	eax,[col1]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz1]
	push	[yy1]
	push	[xx1]

	mov	eax,[col2]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz2]
	push	[yy2]
	push	[xx2]

	call	smooth_line
     @@:
;        mov     eax,[edges_ptr]       ;  this not works correctly
;        add     eax,[edges_counter]
;        mov     bl,[eax]
;        test    bl,00000010b
;        jz      @f

	mov	edi,screen
	mov	esi,[Zbuffer_ptr]

	mov	eax,[col1]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz1]
	push	[yy1]
	push	[xx1]

	mov	eax,[col3]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz3]
	push	[yy3]
	push	[xx3]

	call	smooth_line
      @@:

;        mov     eax,[edges_ptr]        ;  this not works correctly
;        add     eax,[edges_counter]    ;
;        mov     bl,[eax]               ;
;        test    bl,00000100b           ;
;        jz      @f                     ;

	mov	edi,screen
	mov	esi,[Zbuffer_ptr]

	mov	eax,[col3]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz3]
	push	[yy3]
	push	[xx3]

	mov	eax,[col2]
	movzx	bx,al
	push	bx		  ; b
	movzx	bx,ah
	push	bx
	rol	eax,16
	xor	ah,ah
	push	ax
	push	[zz2]
	push	[yy2]
	push	[xx2]

	call	smooth_line
      @@:

      .end_draw:
	pop	esi
	add	esi,6
	inc	[edges_counter]
	cmp	dword[esi],-1
	jne	.again_dts
ret


fill_Z_buffer:
	mov	eax,0x70000000
      ;  mov     edi,Z_buffer
	mov	edi,[Zbuffer_ptr]
	mov	ecx,SIZE_X*SIZE_Y
	rep	stosd
ret

read_tp_variables:	      ; read [triangles_count_var] and  [points_count_var]
			      ; and  allocate memory
	xor	ebx,ebx
	xor	ebp,ebp
	mov	[points_count_var],bx
	mov	[triangles_count_var],bx
   if USE_LFN = 0
	mov	esi,SourceFile
   else
	mov	esi,[fptr]
   end if

	cmp	[esi],word 4D4Dh
	je	@f ;Must be legal .3DS file
	xor	eax,eax
	ret
    @@:
	mov	eax,dword[esi+2]
	cmp	eax,[fsize] ;This must tell the length
	je	@f
	xor	eax,eax
	ret
     @@:
	add	eax,esi
	mov	[EndFile],eax	 ;

	add	esi,6
      @@:
	cmp	[esi],word 3D3Dh
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	add	esi,6
      .find4k:
	cmp	[esi],word 4000h
	je	@f
	add	esi,[esi+2]
	cmp	esi,[EndFile]
	jc	.find4k
	jmp	.exit
      @@:
	add	esi,6
      @@:
	cmp	[esi],byte 0
	je	@f
	inc	esi
	jmp	@b
      @@:
	inc	esi
      @@:
	cmp	[esi],word 4100h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	add	esi,6
      @@:
	cmp	[esi],word 4110h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	movzx	ecx,word[esi+6]
	add	[points_count_var],cx

	mov	edx,ecx
	add	esi,8
     @@:

	add	ebx,6
	add	esi,12
     ;   dec     ecx
	loop	 @b
      @@:

      @@:
	cmp	[esi],word 4120h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	movzx	ecx,word[esi+6]
	add	[triangles_count_var],cx
	add	esi,8

      @@:
	add	esi,8
	dec	ecx
	jnz	@b
;        xor     ecx,ecx
	add	ebp,edx
	jmp	.find4k
	mov	eax,-1 ;<---mark if OK
      .exit:
ret

read_from_file:
	fninit
	mov	edi,[triangles_ptr]
	xor	ebx,ebx
	xor	ebp,ebp
	mov	[points_count_var],0
	mov	[triangles_count_var],0
   if USE_LFN = 0
	mov	esi,SourceFile
   else
	mov	esi,[fptr]
   end if
	cmp	[esi],word 4D4Dh
	jne	.exit ;Must be legal .3DS file
;        cmp     dword[esi+2],EndFile-SourceFile
;        jne     .exit ;This must tell the length
	mov	eax,dword[esi+2]
  ;      cmp     eax,[fsize]
  ;      jne     .exit

	add	eax,esi
	mov	[EndFile],eax	 ;

	add	esi,6
      @@:
	cmp	[esi],word 3D3Dh
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	add	esi,6
      .find4k:
	cmp	[esi],word 4000h
	je	@f
	add	esi,[esi+2]
	cmp	esi,[EndFile]
	jc	.find4k
	jmp	.exit
      @@:
	add	esi,6
      @@:
	cmp	[esi],byte 0
	je	@f
	inc	esi
	jmp	@b
      @@:
	inc	esi
      @@:
	cmp	[esi],word 4100h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	add	esi,6
      @@:
	cmp	[esi],word 4110h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	movzx	ecx,word[esi+6]
	add	[points_count_var],cx

	mov	edx,ecx
	add	esi,8
     @@:
	push	edi
	mov	edi,[points_ptr]
	push	dword[esi+4]
	pop	dword[edi+ebx*2+0]
	push	dword[esi+8]
	pop	dword[edi+ebx*2+4]
	push	dword[esi+0]
	pop	dword[edi+ebx*2+8]
	pop	edi
;        fld     dword[esi+4]
;        fstp    dword[real_points+ebx*2+0]  ; x
;        fld     dword[esi+8]
;        fstp   dword[real_points+ebx*2+4]  ; y
;        fld     dword[esi+0]
;        fstp   dword[real_points+ebx*2+8]  ; z

	add	ebx,6
	add	esi,12
	dec	ecx
	jnz	@b
      @@:
  ;      mov     dword[points+ebx],-1
	push	edi
	mov	edi,[points_ptr]
	mov	dword[edi+ebx*2],-1	   ; end mark (not always in use)
	pop	edi
      @@:
	cmp	[esi],word 4120h
	je	@f
	add	esi,[esi+2]
	jmp	@b
      @@:
	movzx	ecx,word[esi+6]
	add	[triangles_count_var],cx
	add	esi,8
	;mov     edi,triangles
      @@:
	movsd
	movsw
	add	word[edi-6],bp
	add	word[edi-4],bp
	add	word[edi-2],bp
	add	esi,2
	dec	ecx
	jnz	@b
	add	ebp,edx
	jmp	.find4k
	mov	eax,-1 ;<---mark if OK
      .exit:
	mov	dword[edi],-1
ret

if USE_LFN
alloc_mem_for_tp:
	mov	eax, 68
	cmp	[re_alloc_flag],1
	jz	@f
	mov	ebx, 12
	jmp	.alloc
    @@:
	mov	ebx,20
    .alloc:

	movzx	ecx, [triangles_count_var]
	inc	ecx
	lea	ecx, [ecx*3]
	add	ecx, ecx
	mov	edx,[triangles_ptr]
	int	0x40		       ;  -> allocate memory to triangles
	mov	[triangles_ptr], eax   ;  -> eax = pointer to allocated mem

;        mov     eax, 68
;        movzx   ecx, [triangles_count_var]
;        inc     ecx
;        mov     edx,[edges_ptr]
;        int     0x40                   ;  -> allocate memory to edges
;        mov     [edges_ptr], eax   ;  -> eax = pointer to allocated mem

;        mov     eax,-1                       ; fill edges list
;        movzx   ecx,[triangles_count_var]    ; importand if object generated
;        shr     ecx,2
;        inc     ecx
;        mov     edi,[edges_ptr]
;        cld
;        rep     stosd


;        mov     eax, 68
;        mov     ebx, 12
;        movzx   ecx, [triangles_count_var]
;        shl     ecx, 4
;        int     0x40
;        mov     [triangles_w_z_ptr], eax   ; for trainagles_with_z list
					    ; ststic  memory

	mov	eax, 68
	movzx	ecx, [triangles_count_var]
	lea	ecx, [3+ecx*3]
	shl	ecx, 2
	mov	edx,[triangles_normals_ptr]
	int	0x40			       ;  -> allocate memory for triangles normals
	mov	[triangles_normals_ptr], eax   ;  -> eax = pointer to allocated mem

	mov	eax, 68
	movzx	ecx, [points_count_var]
	lea	ecx,[3+ecx*3]
	shl	ecx, 2
	mov	edx,[points_normals_ptr]
	int	0x40
	mov	[points_normals_ptr], eax

	mov	eax, 68
    ;    mov     ebx, 12
	movzx	ecx, [points_count_var]
	lea	ecx,[3+ecx*3]
	shl	ecx, 2
	mov	edx,[points_normals_rot_ptr]
	int	0x40
	mov	[points_normals_rot_ptr], eax

	mov	eax, 68
	mov	edx,[points_ptr]
	int	0x40
	mov	[points_ptr], eax

	mov	eax, 68
	mov	edx,[points_rotated_ptr]
	int	0x40
	mov	[points_rotated_ptr], eax

	mov	eax, 68
	movzx	ecx, [points_count_var]
	inc	ecx
	shl	ecx, 3
	mov	edx,[points_translated_ptr]
	int	0x40
	mov	[points_translated_ptr], eax
ret
end if


read_from_disk:
if USE_LFN
;-
    mov     eax, 70
    mov     ebx, file_info
    mov     dword[ebx], 5	   ;  -> subfunction number
    int     0x40		   ;  -> read file size
    mov     ebx, [fptr]
    mov     ebx, dword[ebx+32]
    inc     ebx
    mov     [fsize], ebx

    mov     eax, 68
    mov     ebx, 11
    int     0x40		   ;  -> create heap

    mov     eax, 68
    mov     ebx, 12
    mov     ecx, [fsize]
    int     0x40		   ;  -> allocate memory for file
    mov     [fptr], eax 	   ;  -> eax = pointer to allocated mem

    mov     eax, 70
    mov     ebx, file_info
    mov     dword[ebx],0
    int     0x40		   ; -> read file

    mov     [fsize],ebx

    cmp     eax,6
    jnz     @f
    xor     eax,eax	;;;;---
  @@:
else
    mov      eax,58
    mov      ebx,file_info
    int      0x40

    mov      eax,ebx
    shr      eax,9
    inc      eax
    mov      [fsize],eax
;    mov      ecx,ebx
;    add      ecx,MEM_END
;    mov      ebx,1
;    mov      eax,64     ; allocate mem  - resize app mem
			; for points and  triangles
    int      0x40

    mov      eax,58
    mov      ebx,file_info
    int      0x40
end if
  ;  eax = 0   -> ok file loaded
ret
read_param:
    mov        esi,I_Param
    cmp        dword[esi],0
    je	       .end
    cmp        byte[esi],'/'
    je	       .copy
    mov        edi,esi
    mov        ecx,25	; 25 - would be enought
    repe       scasb
    jne        .end
    dec        edi
    mov        esi,edi
 .copy:
    mov 	edi,file_name
    mov 	ecx,50
    rep 	movsd
 .end:
ret
buttons:				      ; draw some buttons (all but navigation and close )
	mov	edi,menu
      .again:
	mov	eax,8			      ; function 8 : define and draw button
	mov	ebx,(SIZE_X+10)*65536+62      ; [x start] *65536 + [x size]
	movzx	ecx,byte[edi]		      ; button id = position+2
	sub	cl,2
	lea	ecx,[ecx*5]
	lea	ecx,[ecx*3]
	add	ecx,25
	shl	ecx,16
	add	ecx,12
	movzx	edx,byte[edi]			; button id
	mov	esi,0x6688dd			; button color RRGGBB
	int	0x40
	 ; BUTTON  LABEL
	mov	eax,4				; function 4 : write text to window
	movzx	ebx,byte[edi]
	sub	bl,2				; button id, according to position
	lea	ebx,[ebx*3]
	lea	ebx,[ebx*5]
	add	ebx,(SIZE_X+12)*65536+28	; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff			; font 1 & color ( 0xF0RRGGBB )
	lea	edx,[edi+1]			; pointer to text beginning
	mov	esi,10				; text length
	int	0x40
	cmp	byte[edi+11],255		; if max_flag=255
	je	@f				; skip
	; flag description
;       mov     eax,4                           ; function 4 : write text to window
;       movzx   ebx,byte[edi]
;       sub     bl,2
;       lea     ebx,[ebx*3]
;       lea     ebx,[ebx*5]
;       add     ebx,(SIZE_X+12+70)*65536+28     ; [x start] *65536 + [y start]
	add	ebx,70*65536
;       mov     ecx,0x20ddeeff                  ; font 1 & color ( 0xF0RRGGBB )
	movzx	edx,byte[edi+12]		; current flag
	shl	edx,2				; * 4 = text length
	add	edx,dword[edi+13]		; pointer to text beginning
	mov	esi,4				; text length
	int	0x40

    @@:
	add	edi,17
	cmp	byte[edi],-1
	jnz	.again
ret
;   *********************************************
;   *******  WINDOW DEFINITIONS AND DRAW ********
;   *********************************************
    draw_window:
	mov	eax,12		; function 12:tell os about windowdraw
	mov	ebx,1		; 1, start of draw
	int	0x40

	; DRAW WINDOW
	mov	eax,0		; function 0 : define and draw window
	mov	ebx,100*65536;+SIZE_X;+80+30 ; [x start] *65536 + [x size]
	mov	ecx,100*65536;+SIZE_Y;+30    ; [y start] *65536 + [y size]
	mov	bx,[size_x]
	add	bx,115
	mov	cx,[size_y]
	add	cx,30
	mov	edx,0x14000000	; color of work area RRGGBB,8->color gl
	mov	edi,labelt	; WINDOW LABEL
	int	0x40

	call	buttons 	; more buttons

	.Y_ADD equ 1   ;-> offset of 'add vector' buttons

	; ADD VECTOR LABEL      ; add vector buttons - 30 ++
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+12)*65536+(168+15*(13+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelvector      ; pointer to text beginning
	mov	esi,labelvectorend-labelvector	   ; text length
    ;    cmp     [move_flag],2
    ;    jne     @f
    ;    add     edx,navigation_size
    ;  @@:
	int	0x40
	 ; VECTOR Y- BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+30)*65536+20     ; [x start] *65536 + [x size]
	mov	ecx,(165+15*(14+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,30		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR Y- LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+32)*65536+(168+15*(14+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelyminus      ; pointer to text beginning
	mov	esi,labelyminusend-labelyminus	   ; text length
	cmp	[move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:
	int	0x40
	; VECTOR Z+ BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+51)*65536+21     ; [x start] *65536 + [x size]
	mov	ecx,(165+15*(14+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,31		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR Z+ LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+53)*65536+(168+15*(14+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelzplus	    ; pointer to text beginning
	mov	esi,labelzplusend-labelzplus	 ; text length
   ;     cmp     [move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:

	int	0x40
	; VECTOR x- BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+10)*65536+21     ; [x start] *65536 + [x size]
	mov	ecx,(165+15*(15+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,32		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR x- LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+12)*65536+(168+15*(15+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelxminus      ; pointer to text beginning
	mov	esi,labelxminusend-labelxminus	   ; text length
   ;     cmp     [move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:
	int	0x40
	; VECTOR x+ BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+51)*65536+21     ; [x start] *65536 + [x size]
	mov	ecx,(165+15*(15+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,33		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR x+ LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+53)*65536+(168+15*(15+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelxplus	    ; pointer to text beginning
	mov	esi,labelxplusend-labelxplus	 ; text length
   ;     cmp     [move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:
	int	0x40
	; VECTOR z- BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+10)*65536+62-41	; [x start] *65536 + [x size]
	mov	ecx,(25+140+15*(16+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,34		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR z- LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+12)*65536+(168+15*(16+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelzminus      ; pointer to text beginning
	mov	esi,labelzminusend-labelzminus	   ; text length
   ;     cmp     [move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:
	int	0x40
       ;VECTOR Y+ BUTTON
	mov	eax,8		; function 8 : define and draw button
	mov	ebx,(SIZE_X+10+20)*65536+20	; [x start] *65536 + [x size]
	mov	ecx,(165+15*(16+.Y_ADD))*65536+12  ; [y start] *65536 + [y size]
	mov	edx,35		 ; button id
	mov	esi,0x6688dd	; button color RRGGBB
	int	0x40
	;VECTOR Y+ LABEL
	mov	eax,4		; function 4 : write text to window
	mov	ebx,(SIZE_X+32)*65536+(168+15*(16+.Y_ADD))   ; [x start] *65536 + [y start]
	mov	ecx,0x20ddeeff	; font 1 & color ( 0xF0RRGGBB )
	mov	edx,labelyplus	    ; pointer to text beginning
	mov	esi,labelyplusend-labelyplus	 ; text length
   ;     cmp     [move_flag],2
   ;     jne     @f
   ;     add     edx,navigation_size
   ;   @@:
	int	0x40

	mov	eax,12		; function 12:tell os about windowdraw
	mov	ebx,2		; 2, end of draw
	int	0x40
	ret


   ; DATA AREA  ************************************

   include 'DATA.INC'

MEM_END: