Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_drawa.asm (19575B)


      1  .386P
      2  .model FLAT
      3 ;
      4 ; r_drawa.s
      5 ; x86 assembly-language edge clipping and emission code
      6 ;
      7 
      8 include qasm.inc
      9 include d_if.inc
     10 
     11 if	id386
     12 
     13 ; !!! if these are changed, they must be changed in r_draw.c too !!!
     14 FULLY_CLIPPED_CACHED	equ		080000000h
     15 FRAMECOUNT_MASK			equ		07FFFFFFFh
     16 
     17 _DATA SEGMENT	
     18 
     19 Ld0 dd 0.0	
     20 Ld1 dd 0.0	
     21 Lstack dd 0	
     22 Lfp_near_clip dd NEAR_CLIP	
     23 Lceilv0 dd 0	
     24 Lv dd 0	
     25 Lu0 dd 0	
     26 Lv0 dd 0	
     27 Lzi0 dd 0	
     28 
     29 _DATA ENDS
     30 _TEXT SEGMENT	
     31 
     32 ;----------------------------------------------------------------------
     33 ; edge clipping code
     34 ;----------------------------------------------------------------------
     35 
     36 pv0		equ		4+12
     37 pv1		equ		8+12
     38 clip	equ		12+12
     39 
     40  align 4	
     41  public _R_ClipEdge	
     42 _R_ClipEdge:	
     43  push esi	; preserve register variables
     44  push edi	
     45  push ebx	
     46  mov ds:dword ptr[Lstack],esp	; for clearing the stack later
     47 
     48 ;	float		d0, d1, f;
     49 ;	mvertex_t	clipvert;
     50 
     51  mov ebx,ds:dword ptr[clip+esp]	
     52  mov esi,ds:dword ptr[pv0+esp]	
     53  mov edx,ds:dword ptr[pv1+esp]	
     54 
     55 ;	if (clip)
     56 ;	{
     57  test ebx,ebx	
     58  jz Lemit	
     59 
     60 ;		do
     61 ;		{
     62 
     63 Lcliploop:	
     64 
     65 ;			d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
     66 ;			d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
     67  fld ds:dword ptr[mv_position+0+esi]	
     68  fmul ds:dword ptr[cp_normal+0+ebx]	
     69  fld ds:dword ptr[mv_position+4+esi]	
     70  fmul ds:dword ptr[cp_normal+4+ebx]	
     71  fld ds:dword ptr[mv_position+8+esi]	
     72  fmul ds:dword ptr[cp_normal+8+ebx]	
     73  fxch st(1)	
     74  faddp st(2),st(0)	; d0mul2 | d0add0
     75 
     76  fld ds:dword ptr[mv_position+0+edx]	
     77  fmul ds:dword ptr[cp_normal+0+ebx]	
     78  fld ds:dword ptr[mv_position+4+edx]	
     79  fmul ds:dword ptr[cp_normal+4+ebx]	
     80  fld ds:dword ptr[mv_position+8+edx]	
     81  fmul ds:dword ptr[cp_normal+8+ebx]	
     82  fxch st(1)	
     83  faddp st(2),st(0)	; d1mul2 | d1add0 | d0mul2 | d0add0
     84  fxch st(3)	; d0add0 | d1add0 | d0mul2 | d1mul2
     85 
     86  faddp st(2),st(0)	; d1add0 | dot0 | d1mul2 
     87  faddp st(2),st(0)	; dot0 | dot1
     88 
     89  fsub ds:dword ptr[cp_dist+ebx]	; d0 | dot1
     90  fxch st(1)	; dot1 | d0
     91  fsub ds:dword ptr[cp_dist+ebx]	; d1 | d0
     92  fxch st(1)	
     93  fstp ds:dword ptr[Ld0]	
     94  fstp ds:dword ptr[Ld1]	
     95 
     96 ;			if (d0 >= 0)
     97 ;			{
     98  mov eax,ds:dword ptr[Ld0]	
     99  mov ecx,ds:dword ptr[Ld1]	
    100  or ecx,eax	
    101  js Lp2	
    102 
    103 ; both points are unclipped
    104 
    105 Lcontinue:	
    106 
    107 ;
    108 ;				R_ClipEdge (&clipvert, pv1, clip->next);
    109 ;				return;
    110 ;			}
    111 ;		} while ((clip = clip->next) != NULL);
    112  mov ebx,ds:dword ptr[cp_next+ebx]	
    113  test ebx,ebx	
    114  jnz Lcliploop	
    115 
    116 ;	}
    117 
    118 ;// add the edge
    119 ;	R_EmitEdge (pv0, pv1);
    120 Lemit:	
    121 
    122 ;
    123 ; set integer rounding to ceil mode, set to single precision
    124 ;
    125 ; FIXME: do away with by manually extracting integers from floats?
    126 ; FIXME: set less often
    127  fldcw ds:word ptr[_fpu_ceil_cw]	
    128 
    129 ;	edge_t	*edge, *pcheck;
    130 ;	int		u_check;
    131 ;	float	u, u_step;
    132 ;	vec3_t	local, transformed;
    133 ;	float	*world;
    134 ;	int		v, v2, ceilv0;
    135 ;	float	scale, lzi0, u0, v0;
    136 ;	int		side;
    137 
    138 ;	if (r_lastvertvalid)
    139 ;	{
    140  cmp ds:dword ptr[_r_lastvertvalid],0	
    141  jz LCalcFirst	
    142 
    143 ;		u0 = r_u1;
    144 ;		v0 = r_v1;
    145 ;		lzi0 = r_lzi1;
    146 ;		ceilv0 = r_ceilv1;
    147  mov eax,ds:dword ptr[_r_lzi1]	
    148  mov ecx,ds:dword ptr[_r_u1]	
    149  mov ds:dword ptr[Lzi0],eax	
    150  mov ds:dword ptr[Lu0],ecx	
    151  mov ecx,ds:dword ptr[_r_v1]	
    152  mov eax,ds:dword ptr[_r_ceilv1]	
    153  mov ds:dword ptr[Lv0],ecx	
    154  mov ds:dword ptr[Lceilv0],eax	
    155  jmp LCalcSecond	
    156 
    157 ;	}
    158 
    159 LCalcFirst:	
    160 
    161 ;	else
    162 ;	{
    163 ;		world = &pv0->position[0];
    164 
    165  call near ptr LTransformAndProject	; v0 | lzi0 | u0
    166 
    167  fst ds:dword ptr[Lv0]	
    168  fxch st(2)	; u0 | lzi0 | v0
    169  fstp ds:dword ptr[Lu0]	; lzi0 | v0
    170  fstp ds:dword ptr[Lzi0]	; v0
    171 
    172 ;		ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
    173  fistp ds:dword ptr[Lceilv0]	
    174 
    175 ;	}
    176 
    177 LCalcSecond:	
    178 
    179 ;	world = &pv1->position[0];
    180  mov esi,edx	
    181 
    182  call near ptr LTransformAndProject	; v1 | lzi1 | u1
    183 
    184  fld ds:dword ptr[Lu0]	; u0 | v1 | lzi1 | u1
    185  fxch st(3)	; u1 | v1 | lzi1 | u0
    186  fld ds:dword ptr[Lzi0]	; lzi0 | u1 | v1 | lzi1 | u0
    187  fxch st(3)	; lzi1 | u1 | v1 | lzi0 | u0
    188  fld ds:dword ptr[Lv0]	; v0 | lzi1 | u1 | v1 | lzi0 | u0
    189  fxch st(3)	; v1 | lzi1 | u1 | v0 | lzi0 | u0
    190 
    191 ;	r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
    192  fist ds:dword ptr[_r_ceilv1]	
    193 
    194  fldcw ds:word ptr[_fpu_chop_cw]	; put back normal floating-point state
    195 
    196  fst ds:dword ptr[_r_v1]	
    197  fxch st(4)	; lzi0 | lzi1 | u1 | v0 | v1 | u0
    198 
    199 ;	if (r_lzi1 > lzi0)
    200 ;		lzi0 = r_lzi1;
    201  fcom st(1)	
    202  fnstsw ax	
    203  test ah,1	
    204  jz LP0	
    205  fstp st(0)	
    206  fld st(0)	
    207 LP0:	
    208 
    209  fxch st(1)	; lzi1 | lzi0 | u1 | v0 | v1 | u0
    210  fstp ds:dword ptr[_r_lzi1]	; lzi0 | u1 | v0 | v1 | u0
    211  fxch st(1)	
    212  fst ds:dword ptr[_r_u1]	
    213  fxch st(1)	
    214 
    215 ;	if (lzi0 > r_nearzi)	// for mipmap finding
    216 ;		r_nearzi = lzi0;
    217  fcom ds:dword ptr[_r_nearzi]	
    218  fnstsw ax	
    219  test ah,045h	
    220  jnz LP1	
    221  fst ds:dword ptr[_r_nearzi]	
    222 LP1:	
    223 
    224 ; // for right edges, all we want is the effect on 1/z
    225 ;	if (r_nearzionly)
    226 ;		return;
    227  mov eax,ds:dword ptr[_r_nearzionly]	
    228  test eax,eax	
    229  jz LP2	
    230 LPop5AndDone:	
    231  mov eax,ds:dword ptr[_cacheoffset]	
    232  mov edx,ds:dword ptr[_r_framecount]	
    233  cmp eax,07FFFFFFFh	
    234  jz LDoPop	
    235  and edx,offset FRAMECOUNT_MASK	
    236  or edx,offset FULLY_CLIPPED_CACHED	
    237  mov ds:dword ptr[_cacheoffset],edx	
    238 
    239 LDoPop:	
    240  fstp st(0)	; u1 | v0 | v1 | u0
    241  fstp st(0)	; v0 | v1 | u0
    242  fstp st(0)	; v1 | u0
    243  fstp st(0)	; u0
    244  fstp st(0)	
    245  jmp Ldone	
    246 
    247 LP2:	
    248 
    249 ; // create the edge
    250 ;	if (ceilv0 == r_ceilv1)
    251 ;		return;		// horizontal edge
    252  mov ebx,ds:dword ptr[Lceilv0]	
    253  mov edi,ds:dword ptr[_edge_p]	
    254  mov ecx,ds:dword ptr[_r_ceilv1]	
    255  mov edx,edi	
    256  mov esi,ds:dword ptr[_r_pedge]	
    257  add edx,offset et_size	
    258  cmp ebx,ecx	
    259  jz LPop5AndDone	
    260 
    261  mov eax,ds:dword ptr[_r_pedge]	
    262  mov ds:dword ptr[et_owner+edi],eax	
    263 
    264 ;	side = ceilv0 > r_ceilv1;
    265 ;
    266 ;	edge->nearzi = lzi0;
    267  fstp ds:dword ptr[et_nearzi+edi]	; u1 | v0 | v1 | u0
    268 
    269 ;	if (side == 1)
    270 ;	{
    271  jc LSide0	
    272 
    273 LSide1:	
    274 
    275 ;	// leading edge (go from p2 to p1)
    276 
    277 ;		u_step = ((u0 - r_u1) / (v0 - r_v1));
    278  fsubp st(3),st(0)	; v0 | v1 | u0-u1
    279  fsub st(0),st(1)	; v0-v1 | v1 | u0-u1
    280  fdivp st(2),st(0)	; v1 | ustep
    281 
    282 ;	r_emitted = 1;
    283  mov ds:dword ptr[_r_emitted],1	
    284 
    285 ;	edge = edge_p++;
    286  mov ds:dword ptr[_edge_p],edx	
    287 
    288 ; pretouch next edge
    289  mov eax,ds:dword ptr[edx]	
    290 
    291 ;		v2 = ceilv0 - 1;
    292 ;		v = r_ceilv1;
    293  mov eax,ecx	
    294  lea ecx,ds:dword ptr[-1+ebx]	
    295  mov ebx,eax	
    296 
    297 ;		edge->surfs[0] = 0;
    298 ;		edge->surfs[1] = surface_p - surfaces;
    299  mov eax,ds:dword ptr[_surface_p]	
    300  mov esi,ds:dword ptr[_surfaces]	
    301  sub edx,edx	
    302  sub eax,esi	
    303  shr eax,offset SURF_T_SHIFT	
    304  mov ds:dword ptr[et_surfs+edi],edx	
    305  mov ds:dword ptr[et_surfs+2+edi],eax	
    306 
    307  sub esi,esi	
    308 
    309 ;		u = r_u1 + ((float)v - r_v1) * u_step;
    310  mov ds:dword ptr[Lv],ebx	
    311  fild ds:dword ptr[Lv]	; v | v1 | ustep
    312  fsubrp st(1),st(0)	; v-v1 | ustep
    313  fmul st(0),st(1)	; (v-v1)*ustep | ustep
    314  fadd ds:dword ptr[_r_u1]	; u | ustep
    315 
    316  jmp LSideDone	
    317 
    318 ;	}
    319 
    320 LSide0:	
    321 
    322 ;	else
    323 ;	{
    324 ;	// trailing edge (go from p1 to p2)
    325 
    326 ;		u_step = ((r_u1 - u0) / (r_v1 - v0));
    327  fsub st(0),st(3)	; u1-u0 | v0 | v1 | u0
    328  fxch st(2)	; v1 | v0 | u1-u0 | u0
    329  fsub st(0),st(1)	; v1-v0 | v0 | u1-u0 | u0
    330  fdivp st(2),st(0)	; v0 | ustep | u0
    331 
    332 ;	r_emitted = 1;
    333  mov ds:dword ptr[_r_emitted],1	
    334 
    335 ;	edge = edge_p++;
    336  mov ds:dword ptr[_edge_p],edx	
    337 
    338 ; pretouch next edge
    339  mov eax,ds:dword ptr[edx]	
    340 
    341 ;		v = ceilv0;
    342 ;		v2 = r_ceilv1 - 1;
    343  dec ecx	
    344 
    345 ;		edge->surfs[0] = surface_p - surfaces;
    346 ;		edge->surfs[1] = 0;
    347  mov eax,ds:dword ptr[_surface_p]	
    348  mov esi,ds:dword ptr[_surfaces]	
    349  sub edx,edx	
    350  sub eax,esi	
    351  shr eax,offset SURF_T_SHIFT	
    352  mov ds:dword ptr[et_surfs+2+edi],edx	
    353  mov ds:dword ptr[et_surfs+edi],eax	
    354 
    355  mov esi,1	
    356 
    357 ;		u = u0 + ((float)v - v0) * u_step;
    358  mov ds:dword ptr[Lv],ebx	
    359  fild ds:dword ptr[Lv]	; v | v0 | ustep | u0
    360  fsubrp st(1),st(0)	; v-v0 | ustep | u0
    361  fmul st(0),st(1)	; (v-v0)*ustep | ustep | u0
    362  faddp st(2),st(0)	; ustep | u
    363  fxch st(1)	; u | ustep
    364 
    365 ;	}
    366 
    367 LSideDone:	
    368 
    369 ;	edge->u_step = u_step*0x100000;
    370 ;	edge->u = u*0x100000 + 0xFFFFF;
    371 
    372  fmul ds:dword ptr[fp_1m]	; u*0x100000 | ustep
    373  fxch st(1)	; ustep | u*0x100000
    374  fmul ds:dword ptr[fp_1m]	; ustep*0x100000 | u*0x100000
    375  fxch st(1)	; u*0x100000 | ustep*0x100000
    376  fadd ds:dword ptr[fp_1m_minus_1]	; u*0x100000 + 0xFFFFF | ustep*0x100000
    377  fxch st(1)	; ustep*0x100000 | u*0x100000 + 0xFFFFF
    378  fistp ds:dword ptr[et_u_step+edi]	; u*0x100000 + 0xFFFFF
    379  fistp ds:dword ptr[et_u+edi]	
    380 
    381 ; // we need to do this to avoid stepping off the edges if a very nearly
    382 ; // horizontal edge is less than epsilon above a scan, and numeric error
    383 ; // causes it to incorrectly extend to the scan, and the extension of the
    384 ; // line goes off the edge of the screen
    385 ; // FIXME: is this actually needed?
    386 ;	if (edge->u < r_refdef.vrect_x_adj_shift20)
    387 ;		edge->u = r_refdef.vrect_x_adj_shift20;
    388 ;	if (edge->u > r_refdef.vrectright_adj_shift20)
    389 ;		edge->u = r_refdef.vrectright_adj_shift20;
    390  mov eax,ds:dword ptr[et_u+edi]	
    391  mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20]	
    392  cmp eax,edx	
    393  jl LP4	
    394  mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20]	
    395  cmp eax,edx	
    396  jng LP5	
    397 LP4:	
    398  mov ds:dword ptr[et_u+edi],edx	
    399  mov eax,edx	
    400 LP5:	
    401 
    402 ; // sort the edge in normally
    403 ;	u_check = edge->u;
    404 ;
    405 ;	if (edge->surfs[0])
    406 ;		u_check++;	// sort trailers after leaders
    407  add eax,esi	
    408 
    409 ;	if (!newedges[v] || newedges[v]->u >= u_check)
    410 ;	{
    411  mov esi,ds:dword ptr[_newedges+ebx*4]	
    412  test esi,esi	
    413  jz LDoFirst	
    414  cmp ds:dword ptr[et_u+esi],eax	
    415  jl LNotFirst	
    416 LDoFirst:	
    417 
    418 ;		edge->next = newedges[v];
    419 ;		newedges[v] = edge;
    420  mov ds:dword ptr[et_next+edi],esi	
    421  mov ds:dword ptr[_newedges+ebx*4],edi	
    422 
    423  jmp LSetRemove	
    424 
    425 ;	}
    426 
    427 LNotFirst:	
    428 
    429 ;	else
    430 ;	{
    431 ;		pcheck = newedges[v];
    432 ;
    433 ;		while (pcheck->next && pcheck->next->u < u_check)
    434 ;			pcheck = pcheck->next;
    435 LFindInsertLoop:	
    436  mov edx,esi	
    437  mov esi,ds:dword ptr[et_next+esi]	
    438  test esi,esi	
    439  jz LInsertFound	
    440  cmp ds:dword ptr[et_u+esi],eax	
    441  jl LFindInsertLoop	
    442 
    443 LInsertFound:	
    444 
    445 ;		edge->next = pcheck->next;
    446 ;		pcheck->next = edge;
    447  mov ds:dword ptr[et_next+edi],esi	
    448  mov ds:dword ptr[et_next+edx],edi	
    449 
    450 ;	}
    451 
    452 LSetRemove:	
    453 
    454 ;	edge->nextremove = removeedges[v2];
    455 ;	removeedges[v2] = edge;
    456  mov eax,ds:dword ptr[_removeedges+ecx*4]	
    457  mov ds:dword ptr[_removeedges+ecx*4],edi	
    458  mov ds:dword ptr[et_nextremove+edi],eax	
    459 
    460 Ldone:	
    461  mov esp,ds:dword ptr[Lstack]	; clear temporary variables from stack
    462 
    463  pop ebx	; restore register variables
    464  pop edi	
    465  pop esi	
    466  ret	
    467 
    468 ; at least one point is clipped
    469 
    470 Lp2:	
    471  test eax,eax	
    472  jns Lp1	
    473 
    474 ;			else
    475 ;			{
    476 ;			// point 0 is clipped
    477 
    478 ;				if (d1 < 0)
    479 ;				{
    480  mov eax,ds:dword ptr[Ld1]	
    481  test eax,eax	
    482  jns Lp3	
    483 
    484 ;				// both points are clipped
    485 ;				// we do cache fully clipped edges
    486 ;					if (!leftclipped)
    487  mov eax,ds:dword ptr[_r_leftclipped]	
    488  mov ecx,ds:dword ptr[_r_pedge]	
    489  test eax,eax	
    490  jnz Ldone	
    491 
    492 ;						r_pedge->framecount = r_framecount;
    493  mov eax,ds:dword ptr[_r_framecount]	
    494  and eax,offset FRAMECOUNT_MASK	
    495  or eax,offset FULLY_CLIPPED_CACHED	
    496  mov ds:dword ptr[_cacheoffset],eax	
    497 
    498 ;					return;
    499  jmp Ldone	
    500 
    501 ;				}
    502 
    503 Lp1:	
    504 
    505 ;			// point 0 is unclipped
    506 ;				if (d1 >= 0)
    507 ;				{
    508 ;				// both points are unclipped
    509 ;					continue;
    510 
    511 ;			// only point 1 is clipped
    512 
    513 ;				f = d0 / (d0 - d1);
    514  fld ds:dword ptr[Ld0]	
    515  fld ds:dword ptr[Ld1]	
    516  fsubr st(0),st(1)	
    517 
    518 ;			// we don't cache partially clipped edges
    519  mov ds:dword ptr[_cacheoffset],07FFFFFFFh	
    520 
    521  fdivp st(1),st(0)	
    522 
    523  sub esp,offset mv_size	; allocate space for clipvert
    524 
    525 ;				clipvert.position[0] = pv0->position[0] +
    526 ;						f * (pv1->position[0] - pv0->position[0]);
    527 ;				clipvert.position[1] = pv0->position[1] +
    528 ;						f * (pv1->position[1] - pv0->position[1]);
    529 ;				clipvert.position[2] = pv0->position[2] +
    530 ;						f * (pv1->position[2] - pv0->position[2]);
    531  fld ds:dword ptr[mv_position+8+edx]	
    532  fsub ds:dword ptr[mv_position+8+esi]	
    533  fld ds:dword ptr[mv_position+4+edx]	
    534  fsub ds:dword ptr[mv_position+4+esi]	
    535  fld ds:dword ptr[mv_position+0+edx]	
    536  fsub ds:dword ptr[mv_position+0+esi]	; 0 | 1 | 2
    537 
    538 ; replace pv1 with the clip point
    539  mov edx,esp	
    540  mov eax,ds:dword ptr[cp_leftedge+ebx]	
    541  test al,al	
    542 
    543  fmul st(0),st(3)	
    544  fxch st(1)	; 1 | 0 | 2
    545  fmul st(0),st(3)	
    546  fxch st(2)	; 2 | 0 | 1
    547  fmulp st(3),st(0)	; 0 | 1 | 2
    548  fadd ds:dword ptr[mv_position+0+esi]	
    549  fxch st(1)	; 1 | 0 | 2
    550  fadd ds:dword ptr[mv_position+4+esi]	
    551  fxch st(2)	; 2 | 0 | 1
    552  fadd ds:dword ptr[mv_position+8+esi]	
    553  fxch st(1)	; 0 | 2 | 1
    554  fstp ds:dword ptr[mv_position+0+esp]	; 2 | 1
    555  fstp ds:dword ptr[mv_position+8+esp]	; 1
    556  fstp ds:dword ptr[mv_position+4+esp]	
    557 
    558 ;				if (clip->leftedge)
    559 ;				{
    560  jz Ltestright	
    561 
    562 ;					r_leftclipped = true;
    563 ;					r_leftexit = clipvert;
    564  mov ds:dword ptr[_r_leftclipped],1	
    565  mov eax,ds:dword ptr[mv_position+0+esp]	
    566  mov ds:dword ptr[_r_leftexit+mv_position+0],eax	
    567  mov eax,ds:dword ptr[mv_position+4+esp]	
    568  mov ds:dword ptr[_r_leftexit+mv_position+4],eax	
    569  mov eax,ds:dword ptr[mv_position+8+esp]	
    570  mov ds:dword ptr[_r_leftexit+mv_position+8],eax	
    571 
    572  jmp Lcontinue	
    573 
    574 ;				}
    575 
    576 Ltestright:	
    577 ;				else if (clip->rightedge)
    578 ;				{
    579  test ah,ah	
    580  jz Lcontinue	
    581 
    582 ;					r_rightclipped = true;
    583 ;					r_rightexit = clipvert;
    584  mov ds:dword ptr[_r_rightclipped],1	
    585  mov eax,ds:dword ptr[mv_position+0+esp]	
    586  mov ds:dword ptr[_r_rightexit+mv_position+0],eax	
    587  mov eax,ds:dword ptr[mv_position+4+esp]	
    588  mov ds:dword ptr[_r_rightexit+mv_position+4],eax	
    589  mov eax,ds:dword ptr[mv_position+8+esp]	
    590  mov ds:dword ptr[_r_rightexit+mv_position+8],eax	
    591 
    592 ;				}
    593 ;
    594 ;				R_ClipEdge (pv0, &clipvert, clip->next);
    595 ;				return;
    596 ;			}
    597  jmp Lcontinue	
    598 
    599 ;			}
    600 
    601 Lp3:	
    602 
    603 ;			// only point 0 is clipped
    604 ;				r_lastvertvalid = false;
    605 
    606  mov ds:dword ptr[_r_lastvertvalid],0	
    607 
    608 ;				f = d0 / (d0 - d1);
    609  fld ds:dword ptr[Ld0]	
    610  fld ds:dword ptr[Ld1]	
    611  fsubr st(0),st(1)	
    612 
    613 ;			// we don't cache partially clipped edges
    614  mov ds:dword ptr[_cacheoffset],07FFFFFFFh	
    615 
    616  fdivp st(1),st(0)	
    617 
    618  sub esp,offset mv_size	; allocate space for clipvert
    619 
    620 ;				clipvert.position[0] = pv0->position[0] +
    621 ;						f * (pv1->position[0] - pv0->position[0]);
    622 ;				clipvert.position[1] = pv0->position[1] +
    623 ;						f * (pv1->position[1] - pv0->position[1]);
    624 ;				clipvert.position[2] = pv0->position[2] +
    625 ;						f * (pv1->position[2] - pv0->position[2]);
    626  fld ds:dword ptr[mv_position+8+edx]	
    627  fsub ds:dword ptr[mv_position+8+esi]	
    628  fld ds:dword ptr[mv_position+4+edx]	
    629  fsub ds:dword ptr[mv_position+4+esi]	
    630  fld ds:dword ptr[mv_position+0+edx]	
    631  fsub ds:dword ptr[mv_position+0+esi]	; 0 | 1 | 2
    632 
    633  mov eax,ds:dword ptr[cp_leftedge+ebx]	
    634  test al,al	
    635 
    636  fmul st(0),st(3)	
    637  fxch st(1)	; 1 | 0 | 2
    638  fmul st(0),st(3)	
    639  fxch st(2)	; 2 | 0 | 1
    640  fmulp st(3),st(0)	; 0 | 1 | 2
    641  fadd ds:dword ptr[mv_position+0+esi]	
    642  fxch st(1)	; 1 | 0 | 2
    643  fadd ds:dword ptr[mv_position+4+esi]	
    644  fxch st(2)	; 2 | 0 | 1
    645  fadd ds:dword ptr[mv_position+8+esi]	
    646  fxch st(1)	; 0 | 2 | 1
    647  fstp ds:dword ptr[mv_position+0+esp]	; 2 | 1
    648  fstp ds:dword ptr[mv_position+8+esp]	; 1
    649  fstp ds:dword ptr[mv_position+4+esp]	
    650 
    651 ; replace pv0 with the clip point
    652  mov esi,esp	
    653 
    654 ;				if (clip->leftedge)
    655 ;				{
    656  jz Ltestright2	
    657 
    658 ;					r_leftclipped = true;
    659 ;					r_leftenter = clipvert;
    660  mov ds:dword ptr[_r_leftclipped],1	
    661  mov eax,ds:dword ptr[mv_position+0+esp]	
    662  mov ds:dword ptr[_r_leftenter+mv_position+0],eax	
    663  mov eax,ds:dword ptr[mv_position+4+esp]	
    664  mov ds:dword ptr[_r_leftenter+mv_position+4],eax	
    665  mov eax,ds:dword ptr[mv_position+8+esp]	
    666  mov ds:dword ptr[_r_leftenter+mv_position+8],eax	
    667 
    668  jmp Lcontinue	
    669 
    670 ;				}
    671 
    672 Ltestright2:	
    673 ;				else if (clip->rightedge)
    674 ;				{
    675  test ah,ah	
    676  jz Lcontinue	
    677 
    678 ;					r_rightclipped = true;
    679 ;					r_rightenter = clipvert;
    680  mov ds:dword ptr[_r_rightclipped],1	
    681  mov eax,ds:dword ptr[mv_position+0+esp]	
    682  mov ds:dword ptr[_r_rightenter+mv_position+0],eax	
    683  mov eax,ds:dword ptr[mv_position+4+esp]	
    684  mov ds:dword ptr[_r_rightenter+mv_position+4],eax	
    685  mov eax,ds:dword ptr[mv_position+8+esp]	
    686  mov ds:dword ptr[_r_rightenter+mv_position+8],eax	
    687 
    688 ;				}
    689  jmp Lcontinue	
    690 
    691 ; %esi = vec3_t point to transform and project
    692 ; %edx preserved
    693 LTransformAndProject:	
    694 
    695 ;	// transform and project
    696 ;		VectorSubtract (world, modelorg, local);
    697  fld ds:dword ptr[mv_position+0+esi]	
    698  fsub ds:dword ptr[_modelorg+0]	
    699  fld ds:dword ptr[mv_position+4+esi]	
    700  fsub ds:dword ptr[_modelorg+4]	
    701  fld ds:dword ptr[mv_position+8+esi]	
    702  fsub ds:dword ptr[_modelorg+8]	
    703  fxch st(2)	; local[0] | local[1] | local[2]
    704 
    705 ;		TransformVector (local, transformed);
    706 ;	
    707 ;		if (transformed[2] < NEAR_CLIP)
    708 ;			transformed[2] = NEAR_CLIP;
    709 ;	
    710 ;		lzi0 = 1.0 / transformed[2];
    711  fld st(0)	; local[0] | local[0] | local[1] | local[2]
    712  fmul ds:dword ptr[_vpn+0]	; zm0 | local[0] | local[1] | local[2]
    713  fld st(1)	; local[0] | zm0 | local[0] | local[1] |
    714 ;  local[2]
    715  fmul ds:dword ptr[_vright+0]	; xm0 | zm0 | local[0] | local[1] | local[2]
    716  fxch st(2)	; local[0] | zm0 | xm0 | local[1] | local[2]
    717  fmul ds:dword ptr[_vup+0]	; ym0 |  zm0 | xm0 | local[1] | local[2]
    718  fld st(3)	; local[1] | ym0 |  zm0 | xm0 | local[1] |
    719 ;  local[2]
    720  fmul ds:dword ptr[_vpn+4]	; zm1 | ym0 | zm0 | xm0 | local[1] |
    721 ;  local[2]
    722  fld st(4)	; local[1] | zm1 | ym0 | zm0 | xm0 |
    723 ;  local[1] | local[2]
    724  fmul ds:dword ptr[_vright+4]	; xm1 | zm1 | ym0 |  zm0 | xm0 |
    725 ;  local[1] | local[2]
    726  fxch st(5)	; local[1] | zm1 | ym0 | zm0 | xm0 |
    727 ;  xm1 | local[2]
    728  fmul ds:dword ptr[_vup+4]	; ym1 | zm1 | ym0 | zm0 | xm0 |
    729 ;  xm1 | local[2]
    730  fxch st(1)	; zm1 | ym1 | ym0 | zm0 | xm0 |
    731 ;  xm1 | local[2]
    732  faddp st(3),st(0)	; ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
    733  fxch st(3)	; xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
    734  faddp st(4),st(0)	; ym0 | zm2 | ym1 | xm2 | local[2]
    735  faddp st(2),st(0)	; zm2 | ym2 | xm2 | local[2]
    736  fld st(3)	; local[2] | zm2 | ym2 | xm2 | local[2]
    737  fmul ds:dword ptr[_vpn+8]	; zm3 | zm2 | ym2 | xm2 | local[2]
    738  fld st(4)	; local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
    739  fmul ds:dword ptr[_vright+8]	; xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
    740  fxch st(5)	; local[2] | zm3 | zm2 | ym2 | xm2 | xm3
    741  fmul ds:dword ptr[_vup+8]	; ym3 | zm3 | zm2 | ym2 | xm2 | xm3
    742  fxch st(1)	; zm3 | ym3 | zm2 | ym2 | xm2 | xm3
    743  faddp st(2),st(0)	; ym3 | zm4 | ym2 | xm2 | xm3
    744  fxch st(4)	; xm3 | zm4 | ym2 | xm2 | ym3
    745  faddp st(3),st(0)	; zm4 | ym2 | xm4 | ym3
    746  fxch st(1)	; ym2 | zm4 | xm4 | ym3
    747  faddp st(3),st(0)	; zm4 | xm4 | ym4
    748 
    749  fcom ds:dword ptr[Lfp_near_clip]	
    750  fnstsw ax	
    751  test ah,1	
    752  jz LNoClip	
    753  fstp st(0)	
    754  fld ds:dword ptr[Lfp_near_clip]	
    755 
    756 LNoClip:	
    757 
    758  fdivr ds:dword ptr[float_1]	; lzi0 | x | y
    759  fxch st(1)	; x | lzi0 | y
    760 
    761 ;	// FIXME: build x/yscale into transform?
    762 ;		scale = xscale * lzi0;
    763 ;		u0 = (xcenter + scale*transformed[0]);
    764  fld ds:dword ptr[_xscale]	; xscale | x | lzi0 | y
    765  fmul st(0),st(2)	; scale | x | lzi0 | y
    766  fmulp st(1),st(0)	; scale*x | lzi0 | y
    767  fadd ds:dword ptr[_xcenter]	; u0 | lzi0 | y
    768 
    769 ;		if (u0 < r_refdef.fvrectx_adj)
    770 ;			u0 = r_refdef.fvrectx_adj;
    771 ;		if (u0 > r_refdef.fvrectright_adj)
    772 ;			u0 = r_refdef.fvrectright_adj;
    773 ; FIXME: use integer compares of floats?
    774  fcom ds:dword ptr[_r_refdef+rd_fvrectx_adj]	
    775  fnstsw ax	
    776  test ah,1	
    777  jz LClampP0	
    778  fstp st(0)	
    779  fld ds:dword ptr[_r_refdef+rd_fvrectx_adj]	
    780 LClampP0:	
    781  fcom ds:dword ptr[_r_refdef+rd_fvrectright_adj]	
    782  fnstsw ax	
    783  test ah,045h	
    784  jnz LClampP1	
    785  fstp st(0)	
    786  fld ds:dword ptr[_r_refdef+rd_fvrectright_adj]	
    787 LClampP1:	
    788 
    789  fld st(1)	; lzi0 | u0 | lzi0 | y
    790 
    791 ;		scale = yscale * lzi0;
    792 ;		v0 = (ycenter - scale*transformed[1]);
    793  fmul ds:dword ptr[_yscale]	; scale | u0 | lzi0 | y
    794  fmulp st(3),st(0)	; u0 | lzi0 | scale*y
    795  fxch st(2)	; scale*y | lzi0 | u0
    796  fsubr ds:dword ptr[_ycenter]	; v0 | lzi0 | u0
    797 
    798 ;		if (v0 < r_refdef.fvrecty_adj)
    799 ;			v0 = r_refdef.fvrecty_adj;
    800 ;		if (v0 > r_refdef.fvrectbottom_adj)
    801 ;			v0 = r_refdef.fvrectbottom_adj;
    802 ; FIXME: use integer compares of floats?
    803  fcom ds:dword ptr[_r_refdef+rd_fvrecty_adj]	
    804  fnstsw ax	
    805  test ah,1	
    806  jz LClampP2	
    807  fstp st(0)	
    808  fld ds:dword ptr[_r_refdef+rd_fvrecty_adj]	
    809 LClampP2:	
    810  fcom ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]	
    811  fnstsw ax	
    812  test ah,045h	
    813  jnz LClampP3	
    814  fstp st(0)	
    815  fld ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]	
    816 LClampP3:	
    817  ret	
    818 
    819 
    820 _TEXT ENDS
    821 endif	;id386
    822  END