num equ 180 num2 equ 46080/num num3 equ 360 num4 equ 46080/num3 num5 equ num*num3 numrotate equ num5+num3 radius1 equ 16 num6 equ 7 radius2 equ 35 .486 SEG_CODE SEGMENT BYTE PUBLIC USE16 ASSUME CS:SEG_CODE org 100h START: mov ax,cs ;this line should always be first mov ds,ax ;the data segment mov ss,ax mov bx,OFFSET ds:[dummy] ;add bx,100 shl bx,1 mov sp,bx shr bx,4 add ax,bx add ax,32769 mov di,18 LABELSEG: mov ds:[temp+di],ax sub ax,4096 dec di dec di jnz LABELSEG mov ax,13h int 10h ;initialize graphics mode mov ax,ds:[SEG_T] mov es,ax mov di, 61336 mov ecx,80*865 mov dh, cl LABELB: shr byte ptr es:[di-320*2], 2 mov ah, dh sar ah, 2 inc ah mov al, es:[di-1] add al, es:[di-319] rcr al, 1 add al, ah rol dh, cl stosb xor dh, al dec ecx jne LABELB ;----------------------------------------------------------------------------- ;CALCYTABLE ;Calculate the Y table ;----------------------------------------------------------------------------- mov bx,400 YTABLE: mov ax,160 mul bx mov ds:[YTab+bx],ax dec bx dec bx jnz YTABLE ;xor bx,bx mov ah,9 mov dx, OFFSET ds:[Text] int 21h ;----------------------------------------------------------------------------- ;FLIPTEXT ;----------------------------------------------------------------------------- push 0a000h pop fs FLABELBACK: cmp fs:[bx],byte ptr 0 jz FLABEL2BACK mov es:[bx],byte ptr 127 FLABEL2BACK: dec bx jnz FLABELBACK ;----------------------------------------------------------------------------- ;CALCSINTAB ;Calculate the sine and cosine tables ;----------------------------------------------------------------------------- mov bx,1300 STABLE: fninit mov ds:[temp],bx fldpi fimul ds:[temp] fidiv ds:[const180] fsin fimul ds:[const127] fist ds:[temp] mov ax,ds:[temp] mov ds:[SinTab+bx],al dec bx jnl STABLE mov ax,ds:[SEG_X] mov es,ax mov ax,ds:[SEG_Y] mov gs,ax mov ax,ds:[SEG_Z] mov fs,ax ;----------------------------------------------------------------------------- ;CALCOBJ ;Calculate the torus ;----------------------------------------------------------------------------- mov di,num CREATE: mov bx,di shl bx,1 movsx ax,byte ptr ds:[SinTab+450-bx] mov cl,num6 idiv cl add al,radius2 mov es:[di],al movsx ax,byte ptr ds:[SinTab+bx] idiv cl mov gs:[di],al xor al,al mov fs:[di],al dec di jnz CREATE ;one toric slice is built mov es:[num+1],byte ptr radius2 mov gs:[num+1],al mov fs:[num+1],al ;the center is built ;xor edi,edi mov di,num+2 mov bp,di CREATE2: cmp bp,num+2 jnz CREATE3 inc ds:[temp4] xor bp,bp inc bp CREATE3: mov si,ds:[temp4] mov dl,ds:[SinTab+si] mov dh,ds:[SinTab+450-si] mov al,fs:[bp] imul dl xchg si,ax mov al,es:[bp] imul dh sub ax,si sar ax,7 mov es:[di],al mov al,es:[bp] imul dl xchg si,ax mov al,fs:[bp] imul dh add ax,si sar ax,7 mov fs:[di],al mov al,gs:[bp] mov gs:[di],al inc di inc bp cmp di,numrotate+1 jnz CREATE2 ;the torus is complete ;-------- ;PALETTE ;Set up the colors ;-------- mov dx,3c8h xor ax,ax out dx,al inc dx PALETTE: push ax xor al,al out dx,al out dx,al pop ax out dx,al inc ax cmp ax,64d jnz PALETTE PALETTE2: out dx,al out dx,al push ax mov al,63d out dx,al pop ax inc ax cmp ax,128d jnz PALETTE2 mov bx,ax mov al,63 PALETTE3: out dx,al out dx,al out dx,al inc bl jnz PALETTE3 KEY: ;The preparations are complete. Let's get down to business... ;------------------ ;Clear the z-buffer ;------------------ mov ax,7F7Fh push ds:[SEG_ZB] pop es xor di,di mov cx,31999d rep stosw ;------------------------- ;Clear the back buffer ;------------------------- xor ax,ax push ds:[SEG_VS] pop es xor di,di mov cx,31999d rep stosw mov bx,ds:[anglex] add bx,5 ;Calculate the rotation angle cmp bx,600d jl NOT360 mov bx,130d inc ds:[frame] and ds:[frame],7 jnz NOT360 xor ds:[wobble],0FFh NOT360: mov ds:[anglex],bx ;----------- ;CALCMATRIX ;----------- mov dl,ds:[SinTab+bx] mov dh,ds:[SinTab+450-bx] mov al,dl imul dl sar ax,7 neg ax mov ds:[yz],ax neg ax imul dl sar ax,7 mov ds:[xx],ax mov al,dh imul dh sar ax,7 add ds:[xx],ax mov ds:[yy],ax mov ds:[zz],ax mov al,dh imul dl sar ax,7 mov ds:[xy],ax mov ds:[xz],ax push ax push ax neg ax mov ds:[zx],ax mov ds:[yx],ax imul dl sar ax,7 add ds:[xz],ax ;SUB with NEG = ADD pop ax imul dl sar ax,7 add ds:[yx],ax pop ax imul dh sar ax,7 sub ds:[yz],ax xchg al,dl cbw mov ds:[zy],ax ;----------------------------------------------------------------------------- ;ROTATE ;Rotate the points ;----------------------------------------------------------------------------- mov di,numrotate ROT: mov ax,ds:[SEG_X] mov es,ax mov ax,ds:[SEG_Y] mov gs,ax mov ax,ds:[SEG_Z] mov fs,ax movsx bx,byte ptr es:[di] ; Move x to bx movsx cx,byte ptr gs:[di] ; Move y to cx movsx dx,byte ptr fs:[di] ; Move z to dx mov si,OFFSET ds:[xx] ; Source offset of the matrix mov ax,ds:[SEG_XN] mov es,ax lodsw ; Load next value from the matrix imul ax,bx ; Multiply by x xchg bp,ax lodsw ; Load next value from the matrix imul ax,cx ; Multiply by y add bp,ax lodsw ; Load next value from the matrix imul ax,dx ; Multiply by z add ax,bp sar ax,7 mov es:[di],al ; Store rotated coordinate mov ax,es add ax,1000h mov es,ax lodsw ; Load next value from the matrix imul ax,bx ; Multiply by x xchg bp,ax lodsw ; Load next value from the matrix imul ax,cx ; Multiply by y add bp,ax lodsw ; Load next value from the matrix imul ax,dx ; Multiply by z add ax,bp sar ax,7 mov es:[di],al ; Store rotated coordinate mov ax,es add ax,1000h mov es,ax lodsw ; Load next value from the matrix imul ax,bx ; Multiply by x xchg bp,ax lodsw ; Load next value from the matrix imul ax,cx ; Multiply by y add bp,ax lodsw ; Load next value from the matrix imul ax,dx ; Multiply by z add ax,bp sar ax,6 mov es:[di],al ; Store rotated coordinate dec di jnz ROT mov ax,ds:[SEG_YN] mov gs,ax mov ax,ds:[SEG_ZN] mov fs,ax mov di,numrotate mov bp,num+1 RENDER: cmp bp,num+1 jnz RENDER2 mov si,di xor bp,bp RENDER2: movsx ax,byte ptr es:[di] cmp ds:[wobble],0 jz WOBBLEFREE MOV BX,DI AND BX,16383 SHR BX,5 MOVSX DX,byte ptr ds:[SinTab+BX] SAR DX,6 ADD AX,DX WOBBLEFREE: movsx bx,byte ptr gs:[di] add ax,ds:[anglex] sal bx,1 mov bx,ds:[YTab+bx+200] sub ax,50+170 jl RENDER5 cmp ax,319 jg RENDER5 add bx,ax ;project to the screen mov al,fs:[si] sub al,fs:[di] jg RENDER3 ;backface culling xor ax,ax jmp AFTER3 RENDER3: cbw mov cx,ax imul cx sar ax,3 mov cx,ds:[frame] push ds:[SEG_T] pop es push bx dec cx inc cx jz AFTER31 dec cx dec cx jz AFTER1 dec cx jz AFTER2 dec cx jz AFTER1 dec cx jz AFTER31 dec cx dec cx jz AFTER1 mov bx,si ;texture mapping sub bx,di shr bx,2 mov ax,ds:[YTab] add bx,ax mov al,es:[bx] shl al,1 jmp AFTER31 AFTER1: push ax ;texture phong ;cwd ;xor dx,dx mov ax,si mov bx,327 div bx mov bx,si sub bx,di shr ax,3 shr bx,4 mov bx,ds:[YTab+bx+160] add bx,ax movzx ax,byte ptr es:[bx] shl al,1 pop bx add ax,bx shr ax,1 cmp ds:[frame],4 jnz AFTER31 AFTER2: MOV BX,DI AND BX,2047 SHR BX,3 MOVSX DX,byte ptr ds:[SinTab+BX] SAR DX,3 ADD AX,DX jg AFTER31 xor ax,ax AFTER31: pop bx AFTER3: push ds:[SEG_ZB] pop es mov cl,fs:[di] cmp cl,byte ptr es:[bx] jg RENDER5 mov es:[bx],cl push ds:[SEG_VS] pop es mov es:[bx],al RENDER5: mov ax,ds:[SEG_XN] mov es,ax inc bp dec di jnz RENDER ;----------------------------------- ;Fill the screen outside the torus ;----------------------------------- push ds push ds:[SEG_T] mov ax,ds:[SEG_VS] mov ds,ax ;needed for FLIP later mov di,63680 PLABEL: xor bx,bx PLABEL4: cmp ds:[di+bx],byte ptr 0 jnz PLABEL5 dec byte ptr ds:[di+bx] inc bx jmp PLABEL4 PLABEL5: mov bx,319 PLABEL2: cmp ds:[di+bx],byte ptr 0 jnz PLABEL3 dec byte ptr ds:[di+bx] dec bx jnz PLABEL2 PLABEL3: mov bx,cs:[anglex] sub bx,50+170 cmp ds:[di+bx+2],byte ptr 0 jnz PLABEL7 PLABEL6: cmp ds:[di+bx],byte ptr 0 jnz PLABEL7 dec byte ptr ds:[di+bx] inc bx jmp PLABEL6 PLABEL7: sub di,320 jnz PLABEL ;--------------------- ;Remove hollow pixels ;--------------------- mov di,63500 RLABEL: mov al,ds:[di] cmp al,0 jnz RLABEL2 cmp al,ds:[di+1] jz RLABEL3 mov al,ds:[di+1] jmp RLABEL6 RLABEL3: cmp al,ds:[di-1] jz RLABEL4 mov al,ds:[di-1] jmp RLABEL6 RLABEL4: mov al,ds:[di+320] RLABEL6: mov ds:[di],al RLABEL2: dec di jnz RLABEL ;----- ;FLIP ;----- pop fs push 0a000h pop es FLABEL: movzx ax,byte ptr ds:[di] cmp al,255d jnz FLABEL3 mov al,fs:[di] FLABEL3: cmp frame,5 ;<-CS jl FLABEL4 movzx bx,byte ptr fs:[di] add ax,bx shr ax,1 FLABEL4: mov es:[di],al dec di jnz FLABEL pop ds ;mov ah,1 ;int 16h ;key-press test jmp KEY ;ENDING: ;mov ax,3 ;int 10h ;go back to text mode ;ret ;exit const180 dw 180 const127 dw 127 anglex dw 130 frame dw 0 temp4 dw 0 Text db ' ' Text2 db ' 1024' Text3 db ' by Vladlen$' wobble db 0 YTab dw 200 dup (?) SinTab db 2000 dup (?) xx dw ? xy dw ? xz dw ? yx dw ? yy dw ? yz dw ? zx dw ? zy dw ? zz dw ? temp2 db ? temp dw ? SEG_X dw ? SEG_Y dw ? SEG_Z dw ? SEG_XN dw ? SEG_YN dw ? SEG_ZN dw ? SEG_VS dw ? SEG_ZB dw ? SEG_T dw ? dummy dd ? SEG_CODE ends END START