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