r_drawa.asm 19 KB

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