; Files *.asc routines by Maciej Guba
; Thanks to Reverend for integer/float/ascii conversion examples
read_asc:
    mov  eax,[fptr]
 .find_vert:
    cmp  dword[eax],'Vert'
    je	 @f
    inc  eax
    jmp  .find_vert
  @@:
    add   eax,4
    cmp   dword[eax],'ices'
    jne   .find_vert
    add   eax,3
  @@:
    inc   eax
    cmp   byte[eax],'0' 	  ; search end of ascii number of vertices string
    jb	  @b
    cmp   byte[eax],'9'
    ja	  @b
;    eax - start ascii number
  @@:
    inc    eax
    cmp    byte[eax],'0'
    jb	  .convert1
    cmp    byte[eax],'9'
    ja	  .convert1
    jmp   @b
  .convert1:
    dec   eax
    mov   ebx,eax
    push  eax
    call  ascii_to_integer
    mov   [points_count_var],dx
    pop   eax

  @@:
    inc   eax
    cmp   dword[eax],'Face'
    jne   @b
    add   eax,3
  @@:
    inc   eax
    cmp   byte[eax],'0'
    jb	  @b
    cmp   byte[eax],'9'
    ja	  @b
   ;    eax - start ascii number
  @@:
    inc    eax
    cmp    byte[eax],'0'
    jb	  .convert2
    cmp    byte[eax],'9'
    ja	  .convert2
    jmp   @b
   ;  eax - end ascii number
  .convert2:
    dec   eax
    mov   ebx,eax
    push  eax
    call  ascii_to_integer
    mov   [triangles_count_var],dx
    pop   eax

  @@:
    inc   eax
    cmp   dword[eax],'Vert'
    jnz   @b
    inc   eax

    mov   edi,[points_ptr]
    xor   ebx,ebx
   .decode_vertices:
    push   ebx
  @@:
    inc   eax
    cmp   dword[eax],'Vert'
    jne   @b
    xor   ecx,ecx

  .decode_coord:
    push  ecx
  @@:
    inc   eax
    mov   dl,byte[eax]
    cmp   dl,byte[XYZpartices+ecx]
    jne   @b
  @@:
    inc   eax
    cmp   byte[eax],'.'
    je	  .readF
    cmp   byte[eax],'-'
    je	  .readF
    cmp   byte[eax],'0'
    jb	  @b
    cmp   byte[eax],'9'
    ja	  @b
.readF: ; read float
    mov   esi,eax
    push  eax
    push  ecx

    call   atof   ; st0 - desired dword float

    pop   ecx
    pop   eax

    fstp  dword[edi]
    add   edi,4

    pop   ecx
    inc   ecx
    cmp   ecx,3
    jne   .decode_coord
    pop   ebx
    inc   ebx
    cmp   bx,[points_count_var]
    jne   .decode_vertices
    mov   dword[edi],-1



    mov   esi,eax
   @@:
    inc   esi
    cmp   dword[esi],'Face'
    jne   @b
    xor   edx,edx
    mov   edi,[triangles_ptr]
    cld
 .decode_face:

    push  edx
   @@:
    inc   esi
    cmp   dword[esi],'Face'
    jne   @b
 @@:
    inc   esi
    cmp   byte[esi],'0'    ; face number start
    jb	  @b
    cmp   byte[esi],'9'
    ja	  @b
  @@:
    inc    esi
    cmp    byte[esi],'0'
    jb	  @f
    cmp    byte[esi],'9'   ; face number end
    ja	  @f
    jmp   @b
  @@:
    xor ecx,ecx
 .next_vertex_number:

    push  ecx
  @@:
    inc   esi
    cmp   byte[esi],'0'
    jb	  @b
    cmp   byte[esi],'9'
    ja	  @b
    ;    eax - start ascii number
  @@:
    inc    esi
    cmp    byte[esi],'0'
    jb	  @f
    cmp    byte[esi],'9'
    ja	  @f
    jmp   @b
   ;  eax - end ascii number
  @@:
    dec   esi
    mov   ebx,esi
    push  esi
    call  ascii_to_integer
    mov   eax,edx

    stosw
    pop   esi
    add   esi,2

    pop   ecx
    inc   ecx
    cmp   ecx,3
    jne   .next_vertex_number
    pop   edx
    inc   edx
    cmp   dx,[triangles_count_var]
    jne   .decode_face
    mov   dword[edi],-1 ;dword[triangles+ebx+2],-1   ; end mark
    mov   eax,1  ;-> mark if ok
ret

ascii_to_integer:
; in ---  [ebx] -> end of ascii string
; out --  edx  -> desired number
    xor    edx,edx
    xor    ecx,ecx
  .again:
    movzx  eax,byte[ebx]
    sub    al,'0'
    cwde
    push   edx
    mul    dword[convert_muler+ecx]
    pop    edx
    add    edx,eax
    dec    ebx
    cmp    byte[ebx],'0'
    jb	   .end
    cmp    byte[ebx],'9'
    ja	   .end
    add    ecx,4
    jmp    .again
  @@:

  .end:
ret

;===============================================================================
;       ASCII to float conversion procedure
;
;       input:
;       esi - pointer to string
;
;       output:
;       st0 - number changed into float
;
;===============================================================================

atof:
	.string  equ ebp-4

	push	ebp
	mov	ebp,esp
	sub	esp,32
	push	eax ecx esi
	mov	[.string],esi
	fninit
	fldz
	fldz

	cld
	cmp	byte [esi], '-'
	jnz	@F
	inc	esi
    @@:
	xor	eax, eax
	align	4
  .loop.integer_part:
	lodsb
	cmp	al, '.'
	jz	.mantisa
	cmp	al,'0'
	jb	.exit
	cmp	al,'9'
	ja	.exit
	fimul	[i10]
	sub	al, '0'
	push	eax
	fiadd	dword [esp]
	add	esp, 4
	jmp	.loop.integer_part

  .mantisa:
	xor	 ecx, ecx
	xor	 eax, eax
	cld
	fxch	 st1
     @@:

	lodsb
	cmp	al,'0'
	jb	.exit
	cmp	al,'9'
	ja	.exit
	cmp	ecx,7*4
	je	.exit		; max 7 digits in mantisa
	sub	al,'0'
	push	eax
	fild	dword[esp]
	fidiv	dword[convert_muler+4+ecx]
	faddp
	add	esp,4
	add	ecx,4
	jmp	@b
  .exit:
	faddp

	mov	eax, [.string]
	cmp	byte [eax], '-'
	jnz	@F
	fchs
    @@:
	cld
	stc				; always returns no error
	pop	esi ecx eax
	mov	esp,ebp
	pop	ebp
	ret


itoa:		   ; unsigned dword integer to ascii procedure
;     in   eax - variable
;          esi - Pointer to ascii string
;   out    esi - desired ascii string
;          edi - end of ascii string  - ptr to memory
 .temp_string  equ dword[ebp-36]
 .ptr	       equ dword[ebp-40]
 .var	       equ dword[ebp-44]
	   push  ecx
	   push  ebp
	   mov	 ebp,esp
	   sub	 esp,64
	   mov	 .var,eax
	   mov	 eax,-1
	   lea	 edi,.temp_string
	   cld
	   mov	 ecx,9
	   rep	 stosd	    ; make floor


	   mov	 .ptr,esi
	   lea	 edi,.temp_string
	   add	 edi,34
	   std
	   xor	 eax,eax
	   stosb	       ; mark begin
	   mov	 eax,.var
	   mov	 esi,10
	@@:
	   xor	 edx,edx
	   div	 esi
	   xchg  eax,edx
	   add	 al,'0'
	   stosb
	   xchg  eax,edx
	   or	 eax,eax
	   jnz	 @b
	   stosb		     ; mark end

	   lea	 esi,.temp_string
	   cld
	@@:
	   lodsb
	   or	al,al
	   jnz	@b

	   mov	edi,.ptr
	 @@:
	   lodsb
	   stosb
	   or	al,al
	   jnz	@b

	   mov	esp,ebp
	   pop	ebp
	   pop	ecx
ret
if 1
ftoa_mac:
;   in  :  esi - pointer to  dword float
;          edi - pointer to ascii string
  .ptr_f     equ dword[ebp-4]
  .sign      equ dword[ebp-8]	;  0 ->   less than zero, 1 - otherwise
  .ptr_ascii equ dword[ebp-12]
  .integer   equ dword[ebp-20]
  .fraction  equ dword[ebp-28]
  .status_orginal equ word[ebp-32]
  .status_changed equ word[ebp-34]
	 push	  ecx
	 push	  ebp
	 mov	  ebp,esp
	 sub	  esp,64
	fninit
	fnstcw	.status_orginal
	mov	ax, .status_orginal
	or	ax, 0000110000000000b
	mov	.status_changed, ax
	fldcw	.status_changed
;       --------------------------------
;       check if signed
	xor	eax, eax
	fld	dword[esi]
	fst	.sign
	test	.sign, 80000000h
	setz	al
	mov	.sign, eax

	 mov	   .ptr_f,esi
	 mov	   .ptr_ascii,edi
	 fabs
	 fld	   st0
	 frndint
	 fist	   .integer
	 fsubp	   st1, st0

	 mov	   eax,.integer
	 mov	   esi,.ptr_ascii
	 call	   itoa
      ;  edi   ->   ptr to end of ascii string
	 dec	   edi
	 mov	   al,'.'
	 stosb

	mov	ecx, 6	 ; max 6 digits in fraction part
    .loop:
	fimul	[i10]
	fld	st0
	frndint
	fist	.fraction
	fsubp	st1, st0
	mov	esi,edi
	mov	eax,.fraction
	add	al,'0'
	stosb
	ftst
	fnstsw	ax
	test	ax, 0100000000000000b
	jz	@F
	test	ax, 0000010100000000b
	jz	.finish
    @@:
	loop	.loop
if 0
	fldcw	.status_orginal
	fimul	[i10]
	fist	.fraction
    ;    mov     esi,edi
	mov	eax,.fraction
	add	al,'0'
	stosb
    ;    call    itoa
;       --------------------------------
;       restore previous values
    .finish:
      ;  fstp    st0
	 ffree	   st
	 mov	   eax,.fraction
	 mov	   esi,edi
;         call      itoa

	 add	   al,'0'
	 stosb
end if
 .finish:
  ffree st
	 cmp	   .sign,0
	 jnz	   @f
	 mov	   esi,.ptr_ascii
	 dec	   esi
	 mov	   byte[esi],'-'
       @@:
	 mov	   esp,ebp
	 pop	   ebp
	 pop	   ecx

ret
end if
if 0
;===============================================================================
;       float to ASCII conversion procedure
;
;       input:
;       buffer - pointer to memory where output will be saved
;       precision - number of digits after dot
;
;       output:
;       no immediate output
;
;       notes:
;       separate integer and mantisa part with dot '.'
;       so GOOD   123.456
;          WRONG  123,456
;
;       coded by Reverend // HTB + RAG
;===============================================================================
proc	ftoa			buffer, precision
locals
  status_original	      dw ?
  status_changed	      dw ?
  integer		      dd ?
  mantisa		      dd ?
  signed		      dd ?
endl
	push	eax ecx;edi ecx
;       --------------------------------
;       set correct precision
	mov	eax, [precision]
	cmp	eax, 51
	jb	@F
	mov	eax, 51
    @@:
	mov	[precision], eax
;       --------------------------------
;       change control wortd of fpu to prevent rounding
	fnstcw	[status_original]
	mov	ax, [status_original]
	or	ax, 0000110000000000b
	mov	[status_changed], ax
	fldcw	[status_changed]
;       --------------------------------
;       check if signed
	xor	eax, eax
	fst	[signed]
	test	[signed], 80000000h
	setnz	al
	mov	[signed], eax
;       --------------------------------
;       cut integer and mantisa separately
	fld	st0
	fld	st0			; st0 = x, st1 = x
	frndint
	fist	[integer]		; st0 = x, st1 = x
	fabs
	fsubp	st1, st0		; st0 = mantisa(x)
;       --------------------------------
;       save integer part in buffer
    ;    mov     edi, [buffer]
	mov	esi,[buffer]
      ;  push    [signed]
      ;  push    edi
      ;  push    10
      ;  push    [integer]
	mov	eax,[integer]
	call	itoa
 ;       add     edi, eax
	mov	al, '.'
	stosb
	mov	esi,edi
;       --------------------------------
;       save mantisa part in buffer
	mov	ecx, [precision]
	dec	ecx
    .loop:
	fimul	[i10]
	fld	st0
	frndint
	fist	[mantisa]
	fsubp	st1, st0
;        push    0
;        push    edi
;        push    10
;        push    [mantisa]
	mov	esi,edi
	mov	eax,[mantisa]
	call	itoa
      ;  add     edi, eax
	ftst
	fnstsw	ax
	test	ax, 0100000000000000b
	jz	@F
	test	ax, 0000010100000000b
	jz	.finish
    @@:
	loop	.loop
	fldcw	[status_original]
	fimul	[i10]
	fist	[mantisa]
;        push    0
;        push    edi
;        push    10
;        push    [mantisa]
	mov	esi,edi
	mov	eax,[mantisa]
	call	itoa
;       --------------------------------
;       restore previous values
    .finish:
	fstp	st0
	cmp	[signed],1
	jnz   @f
	mov   byte[buffer],'-'
      @@:
	stc
	pop	ecx eax   ;edi eax
	ret
endp
end if
if 0
write_asc:
    .counter equ dword[ebp-4]
	push  ebp
	mov   ebp,esp
	sub   esp,64
	fninit
	mov   edi,asc_file_buffer
	mov   esi,asc_main_header
	cld
      @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
      @@:

	mov   esi,asc_info_header
      @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
     @@:
	push   esi  ; -> position in header info
	movzx  eax,[points_count_var]
	mov    esi,edi
	call   itoa		 ; unsigned dword integer to ascii procedure
	pop   esi
	inc   esi
      @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
      @@:
	push  esi
	movzx eax,[triangles_count_var]
	mov   esi,edi
	call  itoa
	pop   esi
	inc   esi
      @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
      @@:
;=============================================================
;================vertex list parser===========================
;=============================================================

       xor   ecx,ecx
     .again_vertex:
       push  ecx
       mov   esi,asc_one_vertex_formula
     @@:
       lodsb
       cmp   al,1
       jz    @f
       stosb
       jmp   @b
     @@:
       mov   eax,ecx
 ;      push  ecx
       push  esi
       mov   esi,edi
       call  itoa
       pop   esi
;       pop   ecx
       inc   esi
       xor   ebx,ebx
    .next_vertex_coef:
       push  ebx
     @@:
       lodsb
       cmp   al,1
       jz    @f
       stosb
       jmp   @b
     @@:
    ; int3
       push  esi
       lea   esi,[ecx*3]
       shl   esi,2
       add   esi,points_r
       add   esi,ebx
     ;  int3
       call  ftoa_mac
     ;  std
     ;  fld     dword[esi]


     ;  pushad
     ;  stdcall ftoa, edi, 30
     ;  popad
     ;  add   edi,20


       pop   esi
       pop   ebx
       add   ebx,4
       cmp   ebx,12
       jnz   .next_vertex_coef
     @@:
       lodsb
       cmp   al,1
       jz    @f
       stosb
       jmp   @b
     @@:
       pop   ecx
       inc   ecx
       cmp   cx,[points_count_var]
       jnz   .again_vertex


   ;   mov  edi,[temp_edi]


       mov  esi,asc_face_list_header
      @@:
	lodsb
	cmp   al,1	; all face header
	jz    @f
	stosb
	jmp   @b
      @@:
	   ;=====================================
	   ; ==============face list parser======
	   ;=====================================
       xor   ecx,ecx
     .again_face:
       push  ecx
       mov   .counter,ecx
       mov   esi,asc_one_face_formula
     @@:
       lodsb
       cmp   al,1
       jz    @f
       stosb
       jmp   @b
     @@:
       mov   eax,ecx
       push  esi
       mov   esi,edi
       call  itoa
       pop   esi
       inc   esi
     @@:
       lodsb
       cmp   al,1
       jz    @f
       stosb
       jmp   @b
     @@:

       xor    ebx,ebx
      .next_face_index:
	push   ebx
	mov    ecx,.counter
	lea    ecx,[ecx*3]
	add    ecx,ecx
	movzx  eax,word[triangles+ecx+ebx]
	push   esi
	mov    esi,edi
	call   itoa
	pop    esi
       @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
      @@:
	pop    ebx
	add    ebx,2
	cmp    ebx,6
	jnz    .next_face_index

;        push   esi
	mov   esi,asc_material
     @@:
	lodsb
	cmp   al,1
	jz    @f
	stosb
	jmp   @b
     @@:
;        pop   esi

	 pop	ecx
	inc    ecx
	cmp    cx,[triangles_count_var]
	jnz    .again_face

	; write file
    sub  edi,asc_file_buffer
  ;  mov  [file_buffer+2],edi
    mov  [FileSize],edi

    invoke  CreateFile,asc_file_name, GENERIC_WRITE, 0, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
    mov  [hfile],eax
    invoke  WriteFile,eax,asc_file_buffer,[FileSize], byteswritten, 0
    invoke  CloseHandle,[hfile]

    mov  esp,ebp
    pop  ebp
ret
end if
if 0
asc_file_buffer:
	      rd 65536
ascii_string  rb 50
ftoa_muler dd 1000000000
file_size dd ?
file_handle dd ?
end if

if 0
convert_muler:
dd 1, 10, 100, 1000, 10000
XYZpartices:
db 'X','Y','Z'
i10 dw 10
points_count_var dd ?
triangles_count_var dd ?
points rb 100
triangles rb 100
asc_file:

file "2TORUS.ASC"
end if