org 100h
section .text
%macro init_gfx 0
mov ax,0x13
int 0x10
%endmacro
%macro usleep 2 ; usecs hi, lo
mov ax,0x8600
mov cx, %1
mov dx, %2
int 0x15
%endmacro
%macro create_texture 0
mov di,texture
mov dx,4
mov bx,80
mov cx,20
mov ax,1
%%again:
rep stosb
mov cx,ax
mov ax,1
sub ax,cx
mov cx,20
dec bx
jnz %%again
mov cx,ax
mov ax,1
sub ax,cx
mov bx,80
mov cx,20
dec dx
jnz %%again
%endmacro
%macro blit 5 ; src, x,y, w,h
mov ax,0xA000
mov es,ax
mov si,%1
mov di,%2+320*%3
mov bx,%4
mov cx,%5
%%again:
rep movsb
add di,320-%4
mov cx,%4
dec bx
jnz %%again
%endmacro
%macro cls 0
; xor di,di
mov di,offscreen
mov al,50 ; 200
cl1:
mov dx,0x3c8
out dx,al ; 0x3c8 ;al
inc dx
; mov ah,al
; shr al,2
out dx,al ; 0x3c8 ;al
out dx,al ; 0x3c8 ;al
out dx,al ; 0x3c8 ;al
mov cx,320*4 ; *200
; mov al,ah
rep stosb
dec al
jnz cl1
%endmacro
%macro puts 1 ; str
mov dx,%1
mov ah,0x09
int 0x21
%endmacro
%macro exit 0
int 0x20
%endmacro
%macro angle_setup 0
fild word [angle]
fild word [Rads]
fdivp ; deg2rad
fsincos ; sin(a) and cos(a)
fstp dword [sine]
fstp dword [cosine]
%endmacro
%macro transform_point 0
; d - dist of screen from COP
; x / z = sx / d
; d * (x/z) = screen-x
fild word [pntX] ; [si+Points-4] ; x
fisub word [Size]
;fimul word [Scale]
fst st1
fild word [pntY]
fisub word [Size]
;fimul word [Scale]
;fild word [si+Points-6] ; y
call rotate
; x,y
;fst st2
;fst st3
;fstp st4
; y,_,_,x
; fimul word [Dist]
fistp dword [tmp1d]
;fistp dword [tmp2d]
; tmp1d = -y * sin(a) + x * cos(a))
; tmp2d = x * sin(a) + y * cos(a)
;fild word [tmp2d] ; y (tmp2d)
;add si,4
fst st1
fild word [pntZ]
fisub word [Size]
;fimul word [Scale]
;fild word [si+Points-2] ; y
call rotate
; t3,t4,x
; fiadd 150
fistp dword [tmp3d]
;fimul word [Dist]
;fidiv dword [tmp3d]
fistp dword [tmp4d]
; tmp3d = -z * sin(a) + y * cos(a)
; tmp4d = y * sin(a) + z * cos(a)
;fld st4
;fistp dword [tmp1d]
mov cx,[tmp3d] ; [si+Points-2] ; z
add cx,180
;mov cx,[si+Points-2] ; z
; X
; mov ax,0
mov ax,[tmp1d] ; x
call project_worker
;mov dx,45
;imul dx
;idiv cx
add ax,160
add ax,offscreen
mov di,ax
; Y
mov ax,[tmp4d] ; [tmp2d] ; y
;mov ax,[tmp2d] ; y
call project_worker
;mov dx,45
;imul dx
;idiv cx
add ax,100
; lea eax,[eax*4+eax]
; shl ax,6
mov dx,320
imul dx
add di,ax
; draw
shr cl,1
sub cl,65 ; 130
mov al,cl
; mov ax,1
cmp al,[di]
jge over_pixel
stosb
stosb
add di,318
stosb
stosb
over_pixel:
;stosb
;add di,318
;stosb
;stosb
%endmacro
start:
; program code
init_gfx
; create_texture
; blit texture, 100, 100, 80, 80
; usleep 0x1,0xFFFF
; cls
; exit
; I think ss might already be same as ds
push ds
pop ss
;mov ax,0xA000
;mov es,ax
; loop for different angles
loop1:
; usleep 0,0x0080
push ds
pop es
cls
angle_setup
;; loop over the points
; mov si,24+24
; ;mov si,8 ; idea is use bit0, bit1, bit2 for sign of the point's x,y,z coords respectively
; ; 40x40x40 = 64000
;more_pnts:
; transform_point
; ; call xform_display
; sub si,10
; jne more_pnts
mov word [pntZ],80
moreZ:
mov word [pntY],80
moreY:
mov word [pntX],80
moreX:
call xform_display
; transform_point
dec word [pntX]
jnz moreX
dec word [pntY]
jnz moreY
dec word [pntZ]
jnz moreZ
; sub word [pntZ],80
; jge moreZ
;
;
; mov word [pntY],80
; moreZ2:
; mov word [pntZ],80
; moreY2:
; mov word [pntX],80
; moreX2:
; call xform_display
; ; transform_point
; dec word [pntX]
; jnz moreX2
; dec word [pntZ]
; jnz moreY2
; ; dec word [pntZ]
; sub word [pntY],80
; jge moreZ2
;
;
; mov word [pntX],80
; moreZ3:
; mov word [pntZ],80
; moreY3:
; mov word [pntY],80
; moreX3:
; call xform_display
; ; transform_point
; dec word [pntY]
; jnz moreX3
; dec word [pntZ]
; jnz moreY3
; ; dec word [pntZ]
; sub word [pntX],80
; jge moreZ3
; wait for vertical retrace
; mov dx,0x3da
; in al,dx
; and al,8
; jnz loop1 ; wait_retrace1
; copy offscreen to screen
mov ax,0xA000
mov es,ax
mov si,offscreen
mov cx,320*200
xor di,di
again_pix:
; movsb
mov al,byte [ds:si]
mov [es:di],al
inc di
inc si
dec cx
jnz again_pix
; rep movsb
dec word [angle]
dec word [angle]
jnz loop1
exit
xform_display:
transform_point
ret
project_worker:
mov dx,90 ; 150 ; 45
imul dx
idiv cx
;add ax,100
ret
rot_worker:
fld dword [sine]
; cos,y, x, x, y
fmulp
; y*cos, x, x, y
fld dword [cosine]
; sin, y*cos, x, x, y
fmulp st2
ret
rotate:
; mov bp,sp
;fldz
fst st3
call rot_worker
; ; y, x, x, y
; fld dword [sine]
; ; cos,y, x, x, y
; fmulp
; ; y*cos, x, x, y
; fld dword [cosine]
; ; sin, y*cos, x, x, y
; fmulp st2
; ; y*cos, x*sin, x, y
fsubp
; y*cos - x*sin, x, y
fstp st3
call rot_worker
; ; x, y, y*cos - x*sin
; fld dword [sine]
; ; cos, x, y, y*cos - x*sin
; fmulp
; ; x*cos, y, y*cos - x*sin
; fld dword [cosine]
; ; sin, x*cos, y, y*cos - x*sin
; fmulp st2
; ; x*cos, y*sin, y*cos - x*sin
faddp
; x*cos + y*sin, y*cos - x*sin
; 1) sine * [bp+4] - cosine * [bp+2]
; 0) sine * [bp+2] + cosine * [bp+4]
retn ; 4
section .data
;Hello db 'Hello world', 0xD, 0xA, '$'
angle dw 360
Rads dw 58
; Dist dw 45
Size dw 40
; Points dw -50,-50,-50, -50,50,-50, -50,50,50, -50,-50,50
; Points2 dw 50,-50,-50, 50,50,-50, 50,50,50, 50,-50,50
section .bss
; uninitialized data
pntX: resw 1
pntY: resw 1
pntZ: resw 1
tmp1w: resw 1
tmp2w: resw 1
tmp0d: resd 1
tmp1d: resd 1
tmp2d: resd 1
tmp3d: resd 1
tmp4d: resd 1
sine: resd 1
cosine: resd 1
; texture: resb 6400 ; 80x80
offscreen: resb 64000