;math.inc - general math functions. ; point rotation is 16 bit and uses vmatrix ; camera rotation is 32 bit and uses ematrix ; frotate uses rotation along a plane and uses ematrix with precal147 ; point rotation ; bx = x cx = y bp = z 16 bit! ; clobbers dx,si,ax ; remember , matrix offsets are: ; ; 0 1 2 multiply those by 4 four the doublewords ; 3 4 5 ; 6 7 8 ; align 4 public rotate rotate: movsx ebx,bx ; x movsx ecx,cx ; y movsx ebp,bp ; z mov eax,vmatrix+8 ; solve x = bx(0)+cx(1)+bp(2) imul ebp shr eax,14 movsx edi,ax mov eax,vmatrix+4 imul ecx shr eax,14 movsx eax,ax add edi,eax mov eax,vmatrix+0 imul ebx shr eax,14 movsx eax,ax add edi,eax ; di = new x mov eax,vmatrix+20 ; solve y = bx(3)+cx(4)+bp(5) imul ebp shr eax,14 movsx esi,ax mov eax,vmatrix+16 imul ecx shr eax,14 movsx eax,ax add esi,eax mov eax,vmatrix+12 imul ebx shr eax,14 movsx eax,ax add esi,eax ; si = new y mov eax,vmatrix+32 ; solve z = bx(6)+cx(7)+bp(8) imul ebp shr eax,14 movsx ebp,ax mov eax,vmatrix+28 imul ecx shr eax,14 movsx eax,ax add ebp,eax mov eax,vmatrix+24 imul ebx shr eax,14 movsx eax,ax add ebp,eax ; bp = new z mov ecx,esi mov ebx,edi ret align 4 ; fast ratiox and ratioy are 320x and 464y ; multiplication has been substituted with fast lea ; trashes eax,edx,edi public make3d public make3dx public make3dy make3d: ; bp must always be positive if ratiox eq 320 lea eax,[ebx*4+ebx] ; 320 = %1 0100 0000 shl eax,6 cdq elseif not ratiox eq 320 imul eax,ratiox display "Note: Slow X multiplication used in make3d routine" endif idiv ebp mov ebx,eax make3dy: if ratioy eq 464 lea eax,[ecx*8+ecx] ; 464 = %1 1101 0000 shl ecx,2 lea ecx,[ecx*4+ecx] add eax,ecx shl eax,4 cdq elseif not ratioy eq 464 mov eax,ecx mov ecx,ratioy imul ecx display "Note: Slow Y multiplication used in make3dy routine" endif idiv ebp mov ecx,eax ret make3dx: ; bp must always be positive if ratiox eq 320 lea eax,[edi*4+edi] ; 320 = %1 0100 0000, eax=320*edi shl eax,6 cdq elseif not ratiox eq 320 mov eax,edi mov edi,ratiox imul edi display "Note: Slow X multiplication used in make3dx routine" endif idiv esi mov edi,eax ret ; checks if a side is visible. ; DI, SI, DX = x's ; BP, DS, ES = y's ; return: cx register... ; cx > 0: side visible...else not...routine courtesy of "RAZOR" ; eg: ; call checkfront ; cmp cx,0 ; jng dontdraw align 4 checkfront: cmp di,si jng s cfc mov ax,di mov di,si mov si,dx mov dx,ax mov ax,bp mov bp,dsq mov bx,esq mov dsq,bx mov esq,ax cfc: cmp di,si jng s cfc2 mov ax,di mov di,si mov si,dx mov dx,ax mov ax,bp mov bp,dsq mov bx,esq mov dsq,bx mov esq,ax cfc2: mov ax,dx ; ax = x3 sub ax,di ; ax = x3 - x1 mov bx,dsq ; bx = y2 sub bx,bp ; bx = y2 - y1 movsx eax,ax ; modification to allow large checks movsx ebx,bx imul ebx ; ax = (x3-x1)*(y2-y1) mov ecx,eax ; save it... mov ax,si ; ax = x2 sub ax,di ; ax = x2 - x1 mov bx,esq ; bx = y3 sub bx,bp ; bx = y3 - y1 movsx eax,ax movsx ebx,bx imul ebx ; ax = (x2-x1)*(y3-y1) sub ecx,eax ; cx = (x3-x1)*(y2-y1)-(x2-x1)*(y3-y1) ret ; point rotation for eye - solves all x,y,z parameters ; ebx = x ecx = y ebp = z 32 bit rotation! ; clobbers dx,si,di,ax align 4 public erotate erotate: mov eax,ematrix+8 imul ebp shrd eax,edx,14 mov edi,eax if usez eq yes mov eax,ematrix+4 imul ecx shrd eax,edx,14 add edi,eax endif mov eax,ematrix+0 imul ebx shrd eax,edx,14 add edi,eax ; di = new x mov eax,ematrix+20 imul ebp shrd eax,edx,14 mov esi,eax mov eax,ematrix+16 imul ecx shrd eax,edx,14 add esi,eax mov eax,ematrix+12 imul ebx shrd eax,edx,14 add esi,eax ; si = new y mov eax,ematrix+32 imul ebp shrd eax,edx,14 mov ebp,eax mov eax,ematrix+28 imul ecx shrd eax,edx,14 add ebp,eax mov eax,ematrix+24 imul ebx shrd eax,edx,14 add ebp,eax ; bp = new z mov ecx,esi mov ebx,edi ret ; solve z from ematrix - same as above erotate but only solves z for fast ; test of where object is - result is in esi align 4 public zsolve public ysolve public xsolve zsolve: mov eax,ematrix+32 imul ebp shrd eax,edx,14 mov esi,eax mov eax,ematrix+28 imul ecx shrd eax,edx,14 add esi,eax mov eax,ematrix+24 imul ebx shrd eax,edx,14 add esi,eax ; si = new z ret ; if object z test from above routine is positive, this routine will solve ; the rest of the rotation matrix. this is so we don't waste time solving ; for x and y locations if the object is not within screen parameters. ; saves imuls align 4 xsolve: mov eax,ematrix+8 imul ebp shrd eax,edx,14 mov edi,eax if usez eq yes mov eax,ematrix+4 imul ecx shrd eax,edx,14 add edi,eax endif mov eax,ematrix+0 imul ebx shrd eax,edx,14 add edi,eax ; di = new x ret align 4 ysolve: mov eax,ematrix+16 imul ecx shrd eax,edx,14 mov ecx,eax mov eax,ematrix+12 imul ebx shrd eax,edx,14 add ecx,eax mov eax,ematrix+20 imul ebp shrd eax,edx,14 add ecx,eax ; cx = new y mov ebx,edi ; final test, move into appropriate regs mov ebp,esi ret ; calculate sign into eax, from ax, smashes bx ; after imul by sign, shr eax,14 to compensate for decimal factor! align 4 public cosign public sign cosign: add ax,4000h sign: shr ax,2 cmp ax,2000h jge s q3o4 ; quadrant 3 or 4 cmp ax,1000h jl s q0 ; quad 1 mov bx,1fffh sub bx,ax jmp s halfsign ; quad 2 q0: mov bx,ax jmp s halfsign q3o4: cmp ax,3000h jl s q3 mov bx,3fffh sub bx,ax call halfsign ; quad 4 neg eax ret q3: and ax,0fffh mov bx,ax ; quad 3 call halfsign neg eax ret halfsign: shl bx,1 movsx eax,w sinus[bx] ret ; arctan, cx=rise,ax=run, returns ax as angle of triangle ; smashes cx,ax,dx,si align 4 public arctan arctan: cmp ax,0 jl s qd2or3 cmp cx,0 jge s halftax ; quadrant 1 neg cx ; quadrant 4, ax=-ax call halftan neg ax shl ax,2 ret qd2or3: neg ax cmp cx,0 jge s qd2 neg cx ; quad 3, ax=ax+8192 call halftan add ax,8192 shl ax,2 ret qd2: call halftan neg ax add ax,8192 shl ax,2 ret halftax: call halftan shl ax,2 ret align 4 halftan: movsx eax,ax movsx ecx,cx mov edx,0 ; cx=rise positive ; ax=run positive cmp eax,ecx jl s opptan ; greater than 45 degrees, other side... xchg ecx,eax ; ax