kolibrios/programs/demos/3DS/ASC.INC
Kirill Lipatov (Leency) 4d5495cfb5 View3DS 0.65: ASC file format support with examples.
git-svn-id: svn://kolibrios.org@5486 a494cfbc-eb01-0410-851d-a64ba20cac60
2015-02-27 18:04:22 +00:00

815 lines
15 KiB
Plaintext

; 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