;/**************************************************************************** ;** MODULE: acalc.asm ;** AUTHOR: Sami Tammilehto / Fennosoftec OY ;** DOCUMENT: ? ;** VERSION: 1.0 ;** REFERENCE: - ;** REVISED BY: - ;***************************************************************************** ;** ;** Assembler / Calculations ;** ;****************************************************************************/ include a.inc asm_code SEGMENT para public use16 'CODE' ASSUME cs:asm_code ;entry: bx=angle (0..65535) ; exit: ax=sin(angle) [range -unit..unit] sin PROC NEAR shr bx,4-1 and bx,not 1 mov ax,ds:_sintable[bx] ret sin ENDP ;entry: bx=angle (0..65535) ; exit: ax=cos(angle) [range -unit..unit] cos PROC NEAR shr bx,4-1 add bx,1024*2 and bx,not (8192 or 1) mov ax,ds:_sintable[bx] ret cos ENDP ;entry: bx=angle (0..65535) ; exit: ax=sin(angle) [range -unit..unit] ; bx=cos(angle) [range -unit..unit] sincos PROC NEAR shr bx,4-1 and bx,not 1 mov ax,ds:_sintable[bx] add bx,1024*2 and bx,not (8192 or 1) mov bx,ds:_sintable[bx] ret sincos ENDP ;used for matrix multiply EXPECTS the matrices to be of integer size mulmacro MACRO row,col mov eax,ds:[si+0+row*12] imul dword ptr es:[di+0+col*4] mov ebx,eax mov eax,ds:[si+4+row*12] imul dword ptr es:[di+12+col*4] add ebx,eax mov eax,ds:[si+8+row*12] imul dword ptr es:[di+24+col*4] add ebx,eax sar ebx,unitshr ENDM ;entry: fs:si=matrix1, es:di=matrix2 ; exit: fs:si=matrix1*matrix2 (matrix 1 overwritten) mulmatrices PROC NEAR push ds mov ax,fs mov ds,ax mulmacro 0,0 push ebx mulmacro 0,1 push ebx mulmacro 0,2 push ebx mulmacro 1,0 push ebx mulmacro 1,1 push ebx mulmacro 1,2 push ebx mulmacro 2,0 push ebx mulmacro 2,1 push ebx mulmacro 2,2 mov ds:[si+8+24],ebx pop dword ptr ds:[si+4+24] pop dword ptr ds:[si+0+24] pop dword ptr ds:[si+8+12] pop dword ptr ds:[si+4+12] pop dword ptr ds:[si+0+12] pop dword ptr ds:[si+8] pop dword ptr ds:[si+4] pop dword ptr ds:[si+0] pop ds ret mulmatrices ENDP ;entry: fs:si=matrix1, es:di=matrix2 ; exit: es:di=matrix1*matrix2 (matrix 2 overwritten) mulmatrices2 PROC NEAR push ds mov ax,fs mov ds,ax mulmacro 0,0 push ebx mulmacro 0,1 push ebx mulmacro 0,2 push ebx mulmacro 1,0 push ebx mulmacro 1,1 push ebx mulmacro 1,2 push ebx mulmacro 2,0 push ebx mulmacro 2,1 push ebx mulmacro 2,2 mov es:[di+8+24],ebx pop dword ptr es:[di+4+24] pop dword ptr es:[di+0+24] pop dword ptr es:[di+8+12] pop dword ptr es:[di+4+12] pop dword ptr es:[di+0+12] pop dword ptr es:[di+8] pop dword ptr es:[di+4] pop dword ptr es:[di+0] pop ds ret mulmatrices2 ENDP ;entry: ax=rotx, bx=roty, cx=rotz, es:di=rmatrix.m ; exit: (writes rmatrix.m) calcmatrixsep PROC NEAR ;calc 3 separate matrices push bp mov bp,sp sub sp,12 ;for local variables push ds push di push bx push cx mov bx,ax neg bx call sincos mov ss:[bp-12+0],ax ;rxsin mov ss:[bp-12+2],bx ;rxcos pop bx neg bx call sincos mov ss:[bp-12+4],ax ;rysin mov ss:[bp-12+6],bx ;rycos pop bx neg bx call sincos mov ss:[bp-12+8],ax ;rzsin mov ss:[bp-12+10],bx ;rzcos mov ebx,0 mov ecx,unit mov ax,es mov ds,ax ;rX mov ds:[di+2*0],ecx mov ds:[di+2*2],ebx mov ds:[di+2*4],ebx mov ds:[di+2*6],ebx movsx eax,word ptr ss:[bp-12+2] mov ds:[di+2*8],eax movsx eax,word ptr ss:[bp-12+0] mov ds:[di+2*10],eax mov ds:[di+2*12],ebx movsx eax,word ptr ss:[bp-12+0] neg eax mov ds:[di+2*14],eax movsx eax,word ptr ss:[bp-12+2] mov ds:[di+2*16],eax add di,36 ;rY movsx eax,word ptr ss:[bp-12+6] mov ds:[di+2*0],eax mov ds:[di+2*2],ebx movsx eax,word ptr ss:[bp-12+4] neg eax mov ds:[di+2*4],eax mov ds:[di+2*6],ebx mov ds:[di+2*8],ecx mov ds:[di+2*10],ebx movsx eax,word ptr ss:[bp-12+4] mov ds:[di+2*12],eax mov ds:[di+2*14],ebx movsx eax,word ptr ss:[bp-12+6] mov ds:[di+2*16],eax add di,36 ;rZ movsx eax,word ptr ss:[bp-12+10] mov ds:[di+2*0],eax movsx eax,word ptr ss:[bp-12+8] mov ds:[di+2*2],eax mov ds:[di+2*4],ebx movsx eax,word ptr ss:[bp-12+8] neg eax mov ds:[di+2*6],eax movsx eax,word ptr ss:[bp-12+10] mov ds:[di+2*8],eax mov ds:[di+2*10],ebx mov ds:[di+2*12],ebx mov ds:[di+2*14],ebx mov ds:[di+2*16],ecx pop di pop ds mov sp,bp pop bp ret calcmatrixsep ENDP ;北北北北 _calc_setrmatrix_ident(rmatrix *matrix) 北北北北 ;entry: matrix=destination matrix (only rotation fields modified) ; exit: (data written to matrix) ;descr: Writes an identity rotation matrix to rmatrix _calc_setrmatrix_ident PROC FAR CBEG lespar di,0 mov edx,unit xor eax,eax mov es:[di+rmatrix_m+0*4],edx mov es:[di+rmatrix_m+1*4],eax mov es:[di+rmatrix_m+2*4],eax mov es:[di+rmatrix_m+3*4],eax mov es:[di+rmatrix_m+4*4],edx mov es:[di+rmatrix_m+5*4],eax mov es:[di+rmatrix_m+6*4],eax mov es:[di+rmatrix_m+7*4],eax mov es:[di+rmatrix_m+8*4],edx CEND _calc_setrmatrix_ident ENDP ;北北北北 _calc_setrmatrix_rotyxz(rmatrix *matrix,angle rotx,angle roty,angle rotz) 北北北北 ;entry: matrix=destination matrix (only rotation fields modified) ; rotx/y/z=rotation angles ; exit: (data written to matrix) ;descr: Calculates a rotation matrix _calc_setrmatrix_rotyxz PROC FAR CBEGR 36*3 mov ax,ss mov es,ax mov fs,ax movpar ax,2 movpar bx,3 movpar cx,4 lea di,[bp-36*3] call calcmatrixsep lea si,[bp-36*3+36*1] lea di,[bp-36*3+36*0] call mulmatrices ;Y*=X lea si,[bp-36*3+36*1] lea di,[bp-36*3+36*2] call mulmatrices ;Y*=Z lespar di,0 zzz=0 REPT 9 mov eax,fs:[si+zzz] mov es:[di+rmatrix_m+zzz],eax zzz=zzz+4 ENDM CENDR _calc_setrmatrix_rotyxz ENDP ;北北北北 _calc_setrmatrix_rotxyz(rmatrix *matrix,angle rotx,angle roty,angle rotz) 北北北北 ;entry: matrix=destination matrix (only rotation fields modified) ; rotx/y/z=rotation angles ; exit: (data written to matrix) ;descr: Calculates a rotation matrix _calc_setrmatrix_rotxyz PROC FAR CBEGR 36*3 mov ax,ss mov es,ax mov fs,ax movpar ax,2 movpar bx,3 movpar cx,4 lea di,[bp-36*3] call calcmatrixsep lea si,[bp-36*3+36*0] lea di,[bp-36*3+36*1] call mulmatrices ;X*=Y lea si,[bp-36*3+36*0] lea di,[bp-36*3+36*2] call mulmatrices ;X*=Z lespar di,0 zzz=0 REPT 9 mov eax,fs:[si+zzz] mov es:[di+rmatrix_m+zzz],eax zzz=zzz+4 ENDM CENDR _calc_setrmatrix_rotxyz ENDP ;北北北北 _calc_setrmatrix_rotzyx(rmatrix *matrix, ; angle rotx,angle roty,angle rotz) 北北北北 ;entry: matrix=destination matrix (only rotation fields modified) ; rotx/y/z=rotation angles ; exit: (data written to matrix) ;descr: Calculates a rotation matrix _calc_setrmatrix_rotzyx PROC FAR CBEGR 36*3 mov ax,ss mov es,ax mov fs,ax movpar ax,2 movpar bx,3 movpar cx,4 lea di,[bp-36*3] call calcmatrixsep lea si,[bp-36*3+36*2] lea di,[bp-36*3+36*1] call mulmatrices ;Z*=Y lea si,[bp-36*3+36*2] lea di,[bp-36*3+36*0] call mulmatrices ;Z*=X lespar di,0 zzz=0 REPT 9 mov eax,fs:[si+zzz] mov es:[di+rmatrix_m+zzz],eax zzz=zzz+4 ENDM CENDR _calc_setrmatrix_rotzyx ENDP ;北北北北 _calc_mulrmatrix(rmatrix *dest, rmatrix *source) 北北北北 ;entry: dest=destination matrix (matrix modified) ; source=source matrix (modifying matrix) ; exit: (data written to dest matrix) ;descr: dest=source*dest. Transposition first, rotation second. _calc_mulrmatrix PROC FAR CBEG ;fs:si=dest, es:di=source lfspar si,0 lespar di,2 call mulmatrices ;fs:si now has the new rotation matrix, next rotate position push bp lespar di,0 add di,rmatrix_x ldspar si,2 ;DS destroyed lfspar bp,0 add bp,rmatrix_x call rotatesingle pop bp ;translate (inverse) lespar di,2 lfspar si,0 mov eax,es:[di+rmatrix_x] add fs:[si+rmatrix_x],eax mov eax,es:[di+rmatrix_y] add fs:[si+rmatrix_y],eax mov eax,es:[di+rmatrix_z] add fs:[si+rmatrix_z],eax @@x: CEND _calc_mulrmatrix ENDP ;北北北北 _calc_applyrmatrix(rmatrix *dest, rmatrix *apply) 北北北北 ;entry: dest=destination matrix (matrix modified) ; apply=apply matrix (modifying matrix) ; exit: (data written to dest matrix) ;descr: The apply matrix is the camera matrix, the dest contains ; the objects own rotation/position, which is modified ; according to the camera. _calc_applyrmatrix PROC FAR CBEG ;fs:si=source, es:di=dest lfspar si,2 lespar di,0 call mulmatrices2 ;es:di now has the new rotation matrix, next rotate position push bp lespar di,0 add di,rmatrix_x ldspar si,2 ;rotate according to apply matrix lfspar bp,0 add bp,rmatrix_x call rotatesingle pop bp ;translate lespar di,2 lfspar si,0 mov eax,es:[di+rmatrix_x] add fs:[si+rmatrix_x],eax mov eax,es:[di+rmatrix_y] add fs:[si+rmatrix_y],eax mov eax,es:[di+rmatrix_z] add fs:[si+rmatrix_z],eax @@x: CEND _calc_applyrmatrix ENDP rotatesingle PROC NEAR ;ds:si=rmatrix ;fs:bp=source[]: x,y,z (long) ;es:di=destination[]: x,y,z (long) ;destination and source can be same mov eax,fs:[bp+0] imul dword ptr ds:[si+rmatrix_m+2*0] mov ebx,eax mov ecx,edx mov eax,fs:[bp+4] imul dword ptr ds:[si+rmatrix_m+2*2] add ebx,eax adc ecx,edx mov eax,fs:[bp+8] imul dword ptr ds:[si+rmatrix_m+2*4] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr push ebx mov eax,fs:[bp+0] imul dword ptr ds:[si+rmatrix_m+2*6] mov ebx,eax mov ecx,edx mov eax,fs:[bp+4] imul dword ptr ds:[si+rmatrix_m+2*8] add ebx,eax adc ecx,edx mov eax,fs:[bp+8] imul dword ptr ds:[si+rmatrix_m+2*10] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr push ebx mov eax,fs:[bp+0] imul dword ptr ds:[si+rmatrix_m+2*12] mov ebx,eax mov ecx,edx mov eax,fs:[bp+4] imul dword ptr ds:[si+rmatrix_m+2*14] add ebx,eax adc ecx,edx mov eax,fs:[bp+8] imul dword ptr ds:[si+rmatrix_m+2*16] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr mov es:[di+8],ebx pop dword ptr es:[di+4] pop dword ptr es:[di+0] ret rotatesingle ENDP ;北北北北 _calc_sftranslate(int count,vlist *dest,long tx,long ty,long tz) 北北北北 ;entry: count=number of vertices to sftranslate ; dest=destination 3D list ; matrix=rmatrix containing rotation / moving ; exit: - ;descr: Translates dest with matrix and and (starfield) _calc_sftranslate PROC FAR CBEG movpar ax,0 or ax,ax jz @@0 ldspar si,1 ;destination movpar bx,3 movpar cx,5 movpar dx,7 mov bp,ax @@1: mov ax,ds:[si+vlist_x] add ax,bx mov ds:[si+vlist_x],ax mov ax,ds:[si+vlist_y] add ax,cx mov ds:[si+vlist_y],ax mov ax,ds:[si+vlist_z] add ax,dx mov ds:[si+vlist_z],ax add si,vlist_size dec bp jnz @@1 @@0: CEND _calc_sftranslate ENDP ;北北北北 _calc_rotate(int count,vlist *dest,vlist *source,rmatrix *matrix) 北北北北 ;entry: count=number of vertices to rotate/move ; dest=destination 3D list ; source=source 3D list ; matrix=rmatrix containing rotation / moving ; exit: - ;descr: Rotates (and moves) the given list _calc_rotate PROC FAR CBEG movpar cx,0 jcxz @@0 lespar di,1 ;destination ldspar si,5 ;matrix - dataseg not used in procedure, so DS can be used lfspar bp,3 ;source - NOTE: bp/parameter pointer destroyed! @@1: push cx movsx eax,word ptr ds:[si+rmatrix_m+2*0] imul dword ptr fs:[bp+vlist_x] mov ebx,eax mov ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*2] imul dword ptr fs:[bp+vlist_y] add ebx,eax adc ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*4] imul dword ptr fs:[bp+vlist_z] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr add ebx,ds:[si+rmatrix_x] mov dword ptr es:[di+vlist_x],ebx movsx eax,word ptr ds:[si+rmatrix_m+2*6] imul dword ptr fs:[bp+vlist_x] mov ebx,eax mov ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*8] imul dword ptr fs:[bp+vlist_y] add ebx,eax adc ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*10] imul dword ptr fs:[bp+vlist_z] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr add ebx,ds:[si+rmatrix_y] mov dword ptr es:[di+vlist_y],ebx movsx eax,word ptr ds:[si+rmatrix_m+2*12] imul dword ptr fs:[bp+vlist_x] mov ebx,eax mov ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*14] imul dword ptr fs:[bp+vlist_y] add ebx,eax adc ecx,edx movsx eax,word ptr ds:[si+rmatrix_m+2*16] imul dword ptr fs:[bp+vlist_z] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr add ebx,ds:[si+rmatrix_z] mov dword ptr es:[di+vlist_z],ebx mov ax,word ptr fs:[bp+vlist_normal] mov word ptr es:[di+vlist_normal],ax ;next point add bp,vlist_size add di,vlist_size pop cx loop @@1 @@0: CEND _calc_rotate ENDP ;北北北北 _calc_singlez(int vertex,vlist *vertexlist,rmatrix *matrix) 北北北北 ;entry: vertex=number of vertex to process ; vertexlist=list from which to pick the vertex ; exit: - ;descr: Rotates the single vertex and returns the resulting Z coordinate. _calc_singlez PROC FAR CBEG ldspar si,3 ;matrix - dataseg not used in procedure, so DS can be used movpar ax,0 lfspar bp,1 ;source - NOTE: bp/parameter pointer destroyed! shl ax,vlist_sizeshl add bp,ax mov eax,ds:[si+rmatrix_m+24] imul dword ptr fs:[bp+vlist_x] mov ebx,eax mov ecx,edx mov eax,ds:[si+rmatrix_m+28] imul dword ptr fs:[bp+vlist_y] add ebx,eax adc ecx,edx mov eax,ds:[si+rmatrix_m+32] imul dword ptr fs:[bp+vlist_z] add ebx,eax adc ecx,edx shrd ebx,ecx,unitshr add ebx,ds:[si+rmatrix_z] mov ax,bx shr ebx,16 mov dx,bx CEND _calc_singlez ENDP ;北北北北 _calc_nrotate(int count,nlist *dest,nlist *source,rmatrix *matrix) 北北北北 ;entry: count=number of normals to rotate ; dest=destination 3Dnormal list ; source=source 3Dnormal list ; matrix=rmatrix containing rotation (moving part of rmatrix not used) ; exit: - ;descr: Rotates the given normal list _calc_nrotate PROC FAR CBEG movpar cx,0 jcxz @@0 lespar di,1 ;destination ldspar si,5 ;matrix - dataseg not used in procedure, so DS can be used lfspar bp,3 ;source - NOTE: bp/parameter pointer destroyed! @@1: push cx mov ax,word ptr fs:[bp+nlist_x] imul word ptr ds:[si+rmatrix_m+2*0] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+nlist_y] imul word ptr ds:[si+rmatrix_m+2*2] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+nlist_z] imul word ptr ds:[si+rmatrix_m+2*4] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+nlist_x],bx mov ax,word ptr fs:[bp+nlist_x] imul word ptr ds:[si+rmatrix_m+2*6] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+nlist_y] imul word ptr ds:[si+rmatrix_m+2*8] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+nlist_z] imul word ptr ds:[si+rmatrix_m+2*10] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+nlist_y],bx mov ax,word ptr fs:[bp+nlist_x] imul word ptr ds:[si+rmatrix_m+2*12] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+nlist_y] imul word ptr ds:[si+rmatrix_m+2*14] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+nlist_z] imul word ptr ds:[si+rmatrix_m+2*16] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+nlist_z],bx ;next point add bp,nlist_size add di,nlist_size pop cx loop @@1 @@0: CEND _calc_nrotate ENDP ;北北北北 _calc_rotate16(int count,nlist *dest,nlist *source,rmatrix *matrix) 北北北北 ;entry: count=number of normals to rotate ; dest=destination 3Dnormal list ; source=source 3Dnormal list ; matrix=rmatrix containing rotation (moving part of rmatrix not used) ; exit: - ;descr: Rotates the given normal list _calc_rotate16 PROC FAR CBEG movpar cx,0 jcxz @@0 lespar di,1 ;destination ldspar si,5 ;matrix - dataseg not used in procedure, so DS can be used lfspar bp,3 ;source - NOTE: bp/parameter pointer destroyed! @@1: push cx mov ax,word ptr fs:[bp+vlist_x] imul word ptr ds:[si+rmatrix_m+2*0] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+vlist_y] imul word ptr ds:[si+rmatrix_m+2*2] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+vlist_z] imul word ptr ds:[si+rmatrix_m+2*4] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+vlist_x],bx mov ax,word ptr fs:[bp+vlist_x] imul word ptr ds:[si+rmatrix_m+2*6] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+vlist_y] imul word ptr ds:[si+rmatrix_m+2*8] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+vlist_z] imul word ptr ds:[si+rmatrix_m+2*10] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+vlist_y],bx mov ax,word ptr fs:[bp+vlist_x] imul word ptr ds:[si+rmatrix_m+2*12] mov bx,ax mov cx,dx mov ax,word ptr fs:[bp+vlist_y] imul word ptr ds:[si+rmatrix_m+2*14] add bx,ax adc cx,dx mov ax,word ptr fs:[bp+vlist_z] imul word ptr ds:[si+rmatrix_m+2*16] add bx,ax adc cx,dx shrd bx,cx,unitshr mov word ptr es:[di+vlist_z],bx ;next point add bp,vlist_size add di,vlist_size pop cx loop @@1 @@0: CEND _calc_rotate16 ENDP ;北北北北 _calc_project(int count,pvlist *dest,vlist *source) 北北北北 ;entry: count=number of vertices to project ; dest=destination projected list ; source=source 3D list ; (_proj* variables in data segment define the projection) ; exit: logical and of visibility flags for all vertices (!=0 == object invis.) ;descr: Projects the given list = does perspective transformation _calc_project PROC FAR CBEG lfspar si,3 lespar di,1 mov ax,0ffffh movpar cx,0 jcxz @@0 @@1: push cx push ax mov ecx,fs:[si+vlist_x] mov eax,fs:[si+vlist_y] mov ebx,fs:[si+vlist_z] xor bp,bp cmp ebx,ds:_projclipz[CLIPMIN] jge @@21 or bp,VF_NEAR mov ebx,ds:_projclipz[CLIPMIN] jmp @@22 @@21: cmp ebx,ds:_projclipz[CLIPMAX] jle @@22 or bp,VF_FAR @@22: ; imul ds:_projmuly idiv ebx add eax,ds:_projaddy cmp eax,ds:_projclipy[CLIPMAX] jng @@41 or bp,VF_DOWN @@41: cmp eax,ds:_projclipy[CLIPMIN] jnl @@42 or bp,VF_UP @@42: mov es:[di+pvlist_y],ax ;store Y ; mov eax,ds:_projmulx imul ecx idiv ebx add eax,ds:_projaddx cmp eax,ds:_projclipx[CLIPMAX] jng @@43 or bp,VF_RIGHT @@43: cmp eax,ds:_projclipx[CLIPMIN] jnl @@44 or bp,VF_LEFT @@44: mov es:[di+pvlist_x],ax ;store X @@5: mov es:[di+pvlist_vf],bp ;store visiblity flags ;next point add si,vlist_size add di,pvlist_size pop ax pop cx and ax,bp loop @@1 @@0: CEND _calc_project ENDP ;北北北北 _calc_project16(int count,pvlist *dest,vlist *source) 北北北北 ;entry: count=number of vertices to project ; dest=destination projected list ; source=source 3D list ; (_proj* variables in data segment define the projection) ; exit: logical and of visibility flags for all vertices (!=0 == object invis.) ;descr: Projects the given list = does perspective transformation _calc_project16 PROC FAR CBEG lfspar si,3 lespar di,1 mov ax,0ffffh movpar cx,0 jcxz @@0 @@1: push cx push ax movsx ecx,word ptr fs:[si+vlist_x] movsx eax,word ptr fs:[si+vlist_y] movsx ebx,word ptr fs:[si+vlist_z] xor bp,bp cmp ebx,ds:_projclipz[CLIPMIN] jge @@21 or bp,VF_NEAR mov ebx,ds:_projclipz[CLIPMIN] jmp @@22 @@21: cmp ebx,ds:_projclipz[CLIPMAX] jle @@22 or bp,VF_FAR @@22: ; imul ds:_projmuly idiv ebx add eax,ds:_projaddy cmp eax,ds:_projclipy[CLIPMAX] jng @@41 or bp,VF_DOWN @@41: cmp eax,ds:_projclipy[CLIPMIN] jnl @@42 or bp,VF_UP @@42: mov es:[di+pvlist_y],ax ;store Y ; mov eax,ds:_projmulx imul ecx idiv ebx add eax,ds:_projaddx cmp eax,ds:_projclipx[CLIPMAX] jng @@43 or bp,VF_RIGHT @@43: cmp eax,ds:_projclipx[CLIPMIN] jnl @@44 or bp,VF_LEFT @@44: mov es:[di+pvlist_x],ax ;store X @@5: mov es:[di+pvlist_vf],bp ;store visiblity flags ;next point add si,vlist_size add di,pvlist_size pop ax pop cx and ax,bp loop @@1 @@0: CEND _calc_project16 ENDP asm_code ENDS END