;
; 3D POLYGONAL CUBE - ASCL
;
; Pavlushin Evgeni
; mail: waptap@mail.ru       site: www.deck4.narod.ru
;
; Create on base 3D test sample
; Mikolaj Felix mfelix@polbox.com
;

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

MAX_POINTS equ 8
MAX_TRIANGLES equ 12
SCREEN_X equ 320
SCREEN_Y equ 200

include 'lang.inc'
include 'ascl.inc'
include 'ascgl.inc'
include 'macros.inc'
START:
    call draw_window
   	call init_sin_cos

still:
;    mov eax,23  ; wait for system event with 10 ms timeout
;    mov ebx,1   ; wait 10 ms, then continue
;    int  0x40

    mov eax,11
    int 0x40

    dec eax
;    cmp  eax,1                  ; window redraw request ?
    jz   red
    dec eax
;    cmp  eax,2                  ; key in buffer ?
    jz   key
    dec eax
;    cmp  eax,3                  ; button in buffer ?
    jz   button

    fps  280,8,cl_White,cl_Black

main_loop:

	mov esi,object
	mov edi,object_rotated
	mov ecx,MAX_POINTS*3
	cld
	rep movsw

	mov esi,angle_x
	mov edi,object_rotated
	mov ecx,MAX_POINTS
	call rotate_points

	mov esi,object_rotated
	mov edi,object_translated
	mov ecx,MAX_POINTS
	call translate_points

	call draw_faces

	call clear_screen_buffer

	add [angle_x],2
	add [angle_y],3
	add [angle_z],1

     jmp still

red:
     call draw_window
     jmp still
key:
     mov eax,2
     int 0x40
     jmp still
button:
     mov eax,17
     int 0x40
     cmp ah,1
     jne still
exit:
     mov eax,-1
     int 0x40

;Draw window
draw_window:
    mov eax,12  ;Start
    mov ebx,1
    int 0x40

    mov eax,0   ;Draw window
    mov ebx,100*65536+(SCREEN_X+9) ;x start*65536+x size
    mov ecx,100*65536+(SCREEN_Y+26) ;y start*65536+y size
    mov edx,0x03000000         ;0x03 use skinned window
    int 0x40

    mov eax,4   ;Out Text
    mov ebx,8*65536+8          ;x start*65536+y start
    mov ecx,0x00ffffff         ;color White
    mov edx,head_label
    mov esi,hl_end-head_label
    int 0x40

    mov eax,12  ;End
    mov ebx,2
    int 0x40
    ret

head_label: db "3D TEST SAMPLE FOR MENUETOS"
hl_end:



; Draw faces procedure

draw_faces:

	mov esi,link
	mov ecx,MAX_TRIANGLES
df_draw:
	push ecx
	mov ecx,3
	mov edi,@@tx1 ;bp
df_get_point:
	xor bh,bh
	mov bl,byte [esi]
	shl bx,2
	mov ax,word [object_translated+bx]
	mov word [edi],ax
	mov ax,word [object_translated+bx+2]
	mov word [edi+2],ax
	inc esi
	add edi,4
	dec ecx
	jnz df_get_point

	mov ax,[@@ty1]
	sub ax,[@@ty3]
	mov bx,[@@tx2]
	sub bx,[@@tx1]
	imul bx
	shl edx,16
	mov dx,ax
	push edx
	mov ax,[@@tx1]
	sub ax,[@@tx3]
	mov bx,[@@ty2]
	sub bx,[@@ty1]
	imul bx
	shl edx,16
	mov dx,ax
	pop ebx
	sub ebx,edx
	or ebx,ebx
	jge df_next

	xor ah,ah
	mov al,byte [si]
	
 mov  [@@xcol],ax

	call filled_triangle
df_next:
	inc si
	pop ecx
	dec ecx
	jnz df_draw
	ret

;modify
;include graphlib.asm

clear_screen_buffer:

;outscrbuf
 mov ebx,scrbuf
 mov ecx,SCREEN_X*65536+SCREEN_Y
 mov edx,5*65536+22
 mov ax,7
 int 0x40

;White background
 mov edi,scrbuf
 mov ecx,(SCREEN_X*SCREEN_Y*3)/4
 mov eax,0xffffffff
 cld
 rep stosd

	ret

;include triangle.asm
; Mikolaj Felix 14/5/2001
; mfelix@polbox.com

;filled trangle procedure

@@tx1  dw 0
@@ty1  dw 0
@@tx2  dw 0
@@ty2  dw 0
@@tx3  dw 0
@@ty3  dw 0
@@xcol dw 0

@@dx12 dw 0
@@dx13 dw 0
@@dx23 dw 0

filled_triangle:

 mov ax,[@@xcol]  ;trnsforming color
 mov bl,al        ;byte bbbggrrx
 mov dl,al        ;to 3 byte
 mov dh,al        ;bbbxxxxx ggxxxxxx rrxxxxxx
 and dh,00000001b

 and al,11100000b
 and bl,00011000b
 and dl,00000110b
 shl bl,3
 shl dl,5

 cmp dh,1
 jne no_bitup
 or  al,00011111b
 or  bl,00111111b
 or  dl,00111111b
no_bitup:

 shl eax,8 ;puck colors
 mov al,bl
 shl eax,8
 mov al,dl
 mov dword [@@rgb],eax
 mov eax,0 ; for 16 bit instructions

	mov ax,[@@ty1]
	cmp ax,[@@ty3]
	jb ft_check1

	xchg ax,[@@ty3]
	mov [@@ty1],ax

	mov ax,[@@tx1]
	xchg ax,[@@tx3]
	mov [@@tx1],ax
ft_check1:
	mov ax,[@@ty2]
	cmp ax,[@@ty3]
	jb ft_check2

	xchg ax,[@@ty3]
	mov [@@ty2],ax

	mov ax,[@@tx2]
	xchg ax,[@@tx3]
	mov [@@tx2],ax
ft_check2:
	mov ax,[@@ty1]
	cmp ax,[@@ty2]
	jb ft_check3

	xchg ax,[@@ty2]
	mov [@@ty1],ax

	mov ax,[@@tx1]
	xchg ax,[@@tx2]
	mov [@@tx1],ax
ft_check3:

	mov bx,[@@ty2]
	sub bx,[@@ty1]
	jnz ft_dx12_make

	mov [@@dx12],word 0
	jmp ft_dx12_done
ft_dx12_make:
	mov ax,[@@tx2]
	sub ax,[@@tx1]
	shl ax,7
	cwd
	idiv bx
	mov [@@dx12],ax			; dx12 = (x2-x1)/(y2-y1)
ft_dx12_done:

	mov bx,[@@ty3]
	sub bx,[@@ty1]
	jnz ft_dx13_make

	mov [@@dx13],word 0
	jmp ft_dx13_done
ft_dx13_make:
	mov ax,[@@tx3]
	sub ax,[@@tx1]
	shl ax,7
	cwd
	idiv bx
	mov [@@dx13],ax			; dx13 = (x3-x1)/(y3-y1)
ft_dx13_done:

	mov bx,[@@ty3]
	sub bx,[@@ty2]
	jnz ft_dx23_make

	mov [@@dx23],word 0
	jmp ft_dx23_done
ft_dx23_make:
	mov ax,[@@tx3]
	sub ax,[@@tx2]
	shl ax,7
	cwd
	idiv bx
	mov [@@dx23],ax			; dx23 = (x3-x2)/(y3-y2)
ft_dx23_done:

	mov ax,[@@tx1]
	shl ax,7
	mov bx,ax

	mov cx,[@@ty1]
ft_loop1:

 pushad

	mov [@@ly],cx
	mov dx,bx
	shr dx,7
	mov [@@lx2],dx
	mov dx,ax
	shr dx,7
	mov [@@lx1],dx
	mov ax,[@@xcol]
 mov [@@lcol],ax
 call horizontal_line

 popad

	add ax,[@@dx13]
	add bx,[@@dx12]
	inc cx
	cmp cx,[@@ty2]
	jb ft_loop1

	
	mov bx,[@@tx2]
	shl bx,7
	mov cx,[@@ty2]
ft_loop2:

 pushad

	mov [@@ly],cx
	mov dx,bx
	shr dx,7
	mov [@@lx2],dx
	mov dx,ax
	shr dx,7
	mov [@@lx1],dx
 mov ax,[@@xcol]
 mov [@@lcol],ax
	call horizontal_line

 popad

	add ax,[@@dx13]
	add bx,[@@dx23]
	inc ecx
	cmp cx,[@@ty3]
	jb ft_loop2

	ret

;horizontal line subproc

@@lx1  dw 0
@@lx2  dw 0
@@ly   dw 0
@@lcol dw 0

@@rgb  dd 0

horizontal_line:

 mov ecx,0
 mov cx,[@@lx1]
 cmp cx,[@@lx2]
 ja  x12
 je  ext
; ret
 mov cx,[@@lx2]
 sub cx,[@@lx1]
 mov edi,3
 jmp xx
x12:
 mov cx,[@@lx1]
 sub cx,[@@lx2]
 mov edi,-3
 jmp xx
ext:
 mov ecx,-1 ;1
; sub ebp,3
xx:
 mov eax,0
 mov ax,[@@ly]
 mov ebx,SCREEN_X ;320
 mul ebx
 mov ebp,0
 mov bp,[@@lx1] ;for correct 16 bit size
 add eax,ebp
 mov ebx,3
 mul ebx
 mov ebp,eax
 sub ebp,3   ;for delete  white dots
 add ecx,2
loo:

 mov eax,dword [@@rgb]
 mov bl,al
 shr eax,8 ;puck colors

 mov byte [scrbuf+ebp],ah
 mov byte [scrbuf+ebp+1],al
 mov byte [scrbuf+ebp+2],bl
 add ebp,edi
 dec ecx
 jnz loo

	ret

;include fixed3d.asm
; Mikolaj Felix 25/5/2001
; mfelix@polbox.com

;------------------------------------------------------------
;	ds:si	- offset to angles
;	ds:di	- offset to 3d points
;	cx	- number of points
;------------------------------------------------------------

@@sin_x dw 0
@@cos_x dw 0
@@sin_y dw 0
@@cos_y dw 0
@@sin_z dw 0
@@cos_z dw 0

@@px equ word [edi]
@@py equ word [edi+2]
@@pz equ word [edi+4]

rotate_points:

 push edi
	mov edi,@@sin_x
	mov edx,3
rp_sin_cos:
	mov bx,word [esi]
	and bx,511
	shl bx,1
	mov ax,word [sin_table+bx]
	mov word [edi],ax
	mov ax,word [cos_table+bx]
	mov word [edi+2],ax

	add esi,2
	add edi,4
	dec edx
	jnz rp_sin_cos
	pop edi

rp_rotate:

	; rotate around x-axis

	mov ax,@@py
	imul [@@cos_x]
	mov bx,ax
	mov si,dx

	mov ax,@@pz
	imul [@@sin_x]
	sub bx,ax
	sbb si,dx
	shrd bx,si,14
	push bx

	mov ax,@@py
	imul [@@sin_x]
	mov bx,ax
	mov si,dx

	mov ax,@@pz
	imul [@@cos_x]
	add bx,ax
	adc si,dx
	shrd bx,si,14

	pop @@py
	mov @@pz,bx

	; rotate around y-axis

	mov ax,@@px
	imul [@@cos_y]
	mov bx,ax
	mov si,dx

	mov ax,@@pz
	imul [@@sin_y]
	sub bx,ax
	sbb si,dx
	shrd bx,si,14
	push bx

	mov ax,@@px
	imul [@@sin_y]
	mov bx,ax
	mov si,dx

	mov ax,@@pz
	imul [@@cos_y]
	add bx,ax
	adc si,dx
	shrd bx,si,14

	pop @@px
	mov @@pz,bx

	; rotate around z-axis

	mov ax,@@px
	imul [@@cos_z]
	mov bx,ax
	mov si,dx

	mov ax,@@py
	imul [@@sin_z]
	sub bx,ax
	sbb si,dx
	shrd bx,si,14
	push bx

	mov ax,@@px
	imul [@@sin_z]
	mov bx,ax
	mov si,dx

	mov ax,@@py
	imul [@@cos_z]
	add bx,ax
	adc si,dx
	shrd bx,si,14

	pop @@px
	mov @@py,bx

	add edi,6
	dec ecx
	jnz rp_rotate

	ret

;------------------------------------------------------------
;	ds:si	- offset to 3d points
;	es:di	- offset to 2d points
;	cx	- number of points
;------------------------------------------------------------

 mx dw 0
 my dw 0

translate_points:
 pushad
 mov eax,37
 mov ebx,1
 int 0x40
 mov ebx,eax
 shr eax,16
 and ebx,0xffff
 cmp ax,SCREEN_X
 jna x_n
 mov ax,0 ;SCREEN_X
x_n:
 cmp bx,SCREEN_Y
 jna y_n
 mov bx,0 ;SCREEN_Y
y_n:
 mov [mx],ax
 mov [my],bx
 popad

 mov ebx,0  ;?
	mov bx,word [esi+4]
 mov ax,[my]
 cmp ax,0
 jng no_m
 shl ax,3
 add bx,ax
no_m:
 add bx,256  ; Z factor (zoom)

 mov eax,0  ;?
	mov ax,word [esi]
	shl ax,8
	cwd
	idiv bx; bx
	add ax,(SCREEN_X/2) ;160         ;X factor (center X)
	stosw

 mov eax,0  ;?
	mov ax,word [esi+2]
	shl ax,8
	cwd
	idiv bx
	add ax,(SCREEN_Y/2) ;100         ;Y factor (center Y)
	stosw

	add esi,6
	dec ecx
	jnz translate_points
	ret

init_sin_cos:
	finit
	fldz
	fstp [temp]
	xor edi,edi
	mov ecx,512
isc_make:
	fld [temp]
	fld st0
	fld st0
	fsin
	fmul [fixed_point_const]
	fistp word [sin_table+edi]
	fcos
	fmul [fixed_point_const]
	fistp word [cos_table+edi]

	fadd [inc_angle]
	fstp [temp]

	add edi,2
	loop isc_make
	ret

temp dd 0

fixed_point_const dd 16384.0
inc_angle dd 0.01227184630309			; pi/256

angle_x dw 0
angle_y dw 0
angle_z dw 0

object	dw -50,-50,-50, 50,-50,-50, 50,50,-50, -50,50,-50
      	dw -50,-50, 50, 50,-50, 50, 50,50, 50, -50,50, 50

link:
 db  0,1,2,10000011b, 0,2,3,10000011b ;purpure   side
 db  5,4,7,00000111b, 5,7,6,00000111b ;soft-red  side
 db  1,5,6,00011000b, 1,6,2,00011000b ;soft-lime side
 db  4,0,3,11100001b, 4,3,7,11100001b ;soft-blue side
 db  4,5,1,00011111b, 1,0,4,00011111b ;yellow    side
 db  3,2,6,00000000b, 3,6,7,00000000b ;black     side

sin_table:
rw 512
cos_table:
rw 512

object_rotated:
rw MAX_POINTS*3
object_translated:
rw MAX_POINTS*2

scrbuf:
I_END: