1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 //
20 // $Source: r:/prj/lib/src/3d/RCS/points.asm $
21 // $Revision: 1.17 $
22 // $Author: jaemz $
23 // $Date: 1994/09/28 19:00:52 $
24 //
25 // Point definition routines
26 //
27 
28 //#include <FixMath.h>
29 #include "3d.h"
30 #include "GlobalV.h"
31 #include "lg.h"
32 
33 // prototypes
34 void rotate_norm(g3s_vector *v, fix *x, fix *y, fix *z);
35 void do_norm_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz);
36 
37 void do_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz);
38 
39 // void xlate_rotate_point(g3s_vector *v, fix *x, fix *y, fix *z);
40 #define xlate_rotate_point(v, x, y, z) \
41     do_rotate(v->gX - _view_position.gX, v->gY - _view_position.gY, v->gZ - _view_position.gZ, x, y, z)
42 
43 extern int code_point(g3s_point *pt);
44 extern char SubLongWithOverflow(int32_t *result, int32_t src, int32_t dest);
45 extern bool AddLongWithOverflow(int32_t *result, int32_t src, int32_t dest);
46 
47 // for temp use in rotate_list, etc.
48 g3s_codes g_codes;
49 
50 // rotate a normal or gradient vector. esi=vector, returns edi=point, bl=codes.
51 // assumes perspective mapper scale factor will be set to _scrw.
g3_rotate_norm(g3s_vector * v)52 g3s_phandle g3_rotate_norm(g3s_vector *v) {
53     fix x, y, z;
54     fix temp, temp2, temp3;
55     g3s_point *point;
56 
57     rotate_norm(v, &x, &y, &z);
58 
59     temp = fix_div(z, _matrix_scale.gZ);
60     temp2 = fix_div(x, _matrix_scale.gX);
61     temp3 = fix_div(y, _matrix_scale.gY);
62 
63     temp3 = -fix_mul_div(temp3, _scrw, _scrh); // because projecting negates too, of course. Grrr.
64 
65     getpnt(point);
66     point->gX = temp2;
67     point->gY = temp3;
68     point->gZ = temp;
69     point->p3_flags = 0;
70 
71     return (point);
72 }
73 
g3_rotate_point(g3s_vector * v)74 g3s_phandle g3_rotate_point(g3s_vector *v) {
75     g3s_point *point;
76 
77     getpnt(point);
78     xlate_rotate_point(v, &point->gX, &point->gY, &point->gZ);
79     point->p3_flags = 0;
80 
81     code_point(point);
82     return (point);
83 }
84 
85 // matrix multiply and project a point. esi=vector, returns edi=point
g3_transform_point(g3s_vector * v)86 g3s_phandle g3_transform_point(g3s_vector *v) {
87     g3s_phandle tempH;
88 
89     // printf("g3_transform_point\n");
90 
91     tempH = g3_rotate_point(v);
92     g3_project_point(tempH);
93     return (tempH);
94 }
95 
96 // takes edi = ptr to point. projects, fills in sx,sy, sets flag.
97 // returns 0 if z<=0, 1 if z>0.
98 // trashes eax,ecx,edx.
g3_project_point(g3s_phandle p)99 int g3_project_point(g3s_phandle p) {
100     fix x, y, z, res;
101 
102 #ifdef stereo_on
103     test _g3d_stereo,
104         1 jz no_stereo1
105             // is this a sister point?
106             cmp edi,
107         _g3d_stereo_list jl not_sister
108 
109             // debug_brk 'yo, found projecting sister'
110 
111             // copy the point and add
112             mov esi,
113         edi sub esi, _g3d_stereo_base mov ecx,
114         (size g3s_point) / 4 rep movsd
115 
116                                mov eax,
117         _g3d_eyesep sub edi,
118         (size g3s_point) // restore edi
119         add[edi]
120             .x,
121         eax
122 
123             // call clip encoder on this point
124             mov ecx,
125         ebx call code_point mov ebx,
126         ecx
127 
128             // project point like a normal point
129             mov _g3d_stereo,
130         0 pop esi call g3_project_point mov _g3d_stereo,
131         1
132 
133         ret
134 
135             not_sister :
136         // copy the point
137         mov esi,
138         edi add edi,
139         _g3d_stereo_base mov ecx,
140         (size g3s_point) / 4 rep movsd mov eax,
141         _g3d_eyesep sub edi,
142         (size g3s_point) // restore edi
143         add[edi]
144             .x,
145         eax
146 
147             // call clip encoder
148             mov ecx,
149         ebx call code_point mov ebx,
150         ecx
151 
152             sub edi,
153         _g3d_stereo_base no_stereo1 :
154 #endif
155 
156         /*printf("g3_project_point\n");
157 
158         char printy[100];
159         fix_sprint(printy, p->gX);
160         printf("%s\n", printy);
161 
162         fix_sprint(printy, p->gY);
163         printf("%s\n", printy);
164 
165         fix_sprint(printy, p->gZ);
166         printf("%s\n", printy);*/
167 
168         // check if this point is in front of the back plane.
169         z = p->gZ;
170     if (z <= 0)
171         return 0;
172     x = p->gX;
173     y = p->gY;
174 
175     // point is in front of back plane---do projection.
176     // project y coordinate.
177     res = fix_mul_div(y, _scrh, z);
178     if (gOVResult) {
179         p->codes |= CC_CLIP_OVERFLOW;
180         return 1;
181     }
182     res = -res;
183     if (AddLongWithOverflow(&res, res, _biasy)) {
184         p->codes |= CC_CLIP_OVERFLOW;
185         return 1;
186     }
187     p->sy = res;
188 
189     // now project x point
190     res = fix_mul_div(x, _scrw, z);
191     if (gOVResult) {
192         p->codes |= CC_CLIP_OVERFLOW;
193         return 1;
194     }
195     if (AddLongWithOverflow(&res, res, _biasx)) {
196         p->codes |= CC_CLIP_OVERFLOW;
197         return 1;
198     }
199     p->sx = res;
200 
201     // modify point flags to indicate projection.
202     p->p3_flags |= PF_PROJECTED;
203 
204 #ifdef stereo_on
205     test _g3d_stereo, 1 jz no_stereo2 mov eax,
206         [edi].sy // copy over old sy
207             add edi,
208         _g3d_stereo_base // load twin address
209             mov[edi]
210                 .sy,
211         eax // make new sy, could add the .5 addition here too
212 
213             mov eax,
214         [edi].x
215             // reproject the x coord
216             imul _scrw                //* screen width
217                 proj_div_2 : idiv ecx /// z
218                                  add eax,
219         _biasx //+center
220             mov[edi]
221                 .sx,
222         eax // save
223 
224             // indicate projection
225             or [edi].p3_flags,
226         PF_PROJECTED
227 
228             // restore edi
229             sub edi,
230         _g3d_stereo_base no_stereo2 :
231 #endif
232 
233         // point has been projected.
234         return 1;
235 }
236 
237 // MLA - all the divide exception handler overflow stuff was removed, and
238 // checked before each divide.  So all of this stuf isn't needed
239 /*
240         public  proj_div_0,proj_div_1,divide_overflow_3d
241 ifdef  stereo_on
242         public  proj_div_2,divide_overflow_r3d
243 endif
244 
245 //this gets called by the system divide overflow handler when there is an
246 //overflow at proj_div_0, proj_div_1
247 divide_overflow_3d:
248 //       fall    project_overflow
249 project_overflow:
250         or      [edi].codes,CC_CLIP_OVERFLOW
251 
252 ifdef stereo_on
253         test    _g3d_stereo,1
254         jz      no_stereo3
255         add     edi,_g3d_stereo_base
256 divide_overflow_r3d:
257         or      [edi].codes,CC_CLIP_OVERFLOW
258         sub     edi,_g3d_stereo_base
259 no_stereo3:
260 endif
261 
262         cspew   "!"     //"project overflow!"
263         // this did not use to restore this
264         ex_set_div_action esi
265         pop     esi
266         ret
267 */
268 
269 // takes esi=ptr to array of vectors, edi=ptr to list for point handles,
270 // ecx=count
g3_transform_list(short n,g3s_phandle * dest_list,g3s_vector * v)271 g3s_codes g3_transform_list(short n, g3s_phandle *dest_list, g3s_vector *v) {
272     int i;
273     g3s_phandle temphand;
274 
275     g_codes.or_ = 0;
276     g_codes.and_ = 0xff;
277 
278     for (i = n; i > 0; i--) {
279         temphand = g3_transform_point(v++);
280         g_codes.or_ |= temphand->codes;
281         g_codes.and_ &= temphand->codes;
282 
283         *(dest_list++) = temphand;
284     }
285     return (g_codes);
286 }
287 
288 // takes esi=ptr to array of vectors, edi=ptr to list for point handles,
289 // ecx=count  returns bh=codes and, bl=codes or
g3_rotate_list(short n,g3s_phandle * dest_list,g3s_vector * v)290 g3s_codes g3_rotate_list(short n, g3s_phandle *dest_list, g3s_vector *v) {
291     int i;
292     g3s_phandle temphand;
293 
294     g_codes.or_ = 0;
295     g_codes.and_ = 0xff;
296 
297     for (i = n; i > 0; i--) {
298         temphand = g3_rotate_point(v++);
299         g_codes.or_ |= temphand->codes;
300         g_codes.and_ &= temphand->codes;
301 
302         *(dest_list++) = temphand;
303     }
304     return (g_codes);
305 }
306 
307 // takes esi=ptr to array of point handles, ecx=count
g3_project_list(short n,g3s_phandle * point_list)308 g3s_codes g3_project_list(short n, g3s_phandle *point_list) {
309     int i;
310     g3s_phandle temphand;
311 
312     g_codes.or_ = 0;
313     g_codes.and_ = 0xff;
314 
315     for (i = n; i > 0; i--) {
316         temphand = *(point_list++);
317         g_codes.or_ |= temphand->codes;
318         g_codes.and_ &= temphand->codes;
319 
320         g3_project_point(temphand);
321     }
322 
323     return (g_codes);
324 }
325 
326 // takes esi=ptr to array of vectors, edi=ptr to dest vectors
g3_rotate_light_norm(g3s_vector * v)327 g3s_phandle g3_rotate_light_norm(g3s_vector *v) {
328     g3s_point *point;
329 
330     getpnt(point);
331     do_rotate(v->gX, v->gY, v->gZ, &point->gX, &point->gY, &point->gZ);
332     return (point);
333 }
334 
335 // takes esi=ptr to normal vector. returns in <ecx,esi,eax>. trashes all regs
rotate_norm(g3s_vector * v,fix * x,fix * y,fix * z)336 void rotate_norm(g3s_vector *v, fix *x, fix *y, fix *z) { do_norm_rotate(v->gX, v->gY, v->gZ, x, y, z); }
337 
338 // does the rotate with the view matrix.
339 // takes <x,y,z> = <esi,edi,ebp>, returns <x,y,z> = <ecx,esi,eax>
do_norm_rotate(fix x,fix y,fix z,fix * rx,fix * ry,fix * rz)340 void do_norm_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz) {
341     int64_t r;
342 
343     // this matrix multiply here will someday be optimized for zero and one terms
344     // uses unscaled rotation matrix.
345 
346     // first column
347     r = fix64_mul(x, uvm1) + fix64_mul(y, uvm4) + fix64_mul(z, uvm7);
348     *rx = fix64_to_fix(r);
349 
350     // second column
351     r = fix64_mul(x, uvm2) + fix64_mul(y, uvm5) + fix64_mul(z, uvm8);
352     *ry = fix64_to_fix(r);
353 
354     // third column
355     r = fix64_mul(x, uvm3) + fix64_mul(y, uvm6) + fix64_mul(z, uvm9);
356     *rz = fix64_to_fix(r);
357 }
358 
359 // made this a define - MLA
360 /*//takes esi=ptr to vector. returns <x,y,z> in <ecx,esi,eax>. trashes all regs
361 void xlate_rotate_point(g3s_vector *v, fix *x, fix *y, fix *z)
362  {
363         do_rotate(v->gX-_view_position.gX, v->gY-_view_position.gY,
364 v->gZ-_view_position.gZ,x,y,z);
365  }*/
366 
367 // does the rotate with the view matrix.
368 // takes <x,y,z> = <esi,edi,ebp>, returns <x,y,z> = <ecx,esi,eax>
do_rotate(fix x,fix y,fix z,fix * rx,fix * ry,fix * rz)369 void do_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz) {
370     // this matrix multiply here will someday be optimized for zero and one terms
371     int64_t r;
372     // first column
373     r = fix64_mul(x, vm1) + fix64_mul(y, vm4) + fix64_mul(z, vm7);
374     *rx = fix64_to_fix(r);
375 
376     // second column
377     r = fix64_mul(x, vm2) + fix64_mul(y, vm5) + fix64_mul(z, vm8);
378     *ry = fix64_to_fix(r);
379 
380     // third column
381     r = fix64_mul(x, vm3) + fix64_mul(y, vm6) + fix64_mul(z, vm9);
382     *rz = fix64_to_fix(r);
383 }
384 
385 // rotate an x delta. takes edi=dest vector, eax=dx
386 // trashes eax,ebx,edx
g3_rotate_delta_x(g3s_vector * dest,fix dx)387 void g3_rotate_delta_x(g3s_vector *dest, fix dx) {
388     dest->gX = fix_mul(dx, vm1);
389     dest->gY = fix_mul(dx, vm2);
390     dest->gZ = fix_mul(dx, vm3);
391 }
392 
393 // rotate a y delta. takes edi=dest vector, eax=dy
394 // trashes eax,ebx,edx
g3_rotate_delta_y(g3s_vector * dest,fix dy)395 void g3_rotate_delta_y(g3s_vector *dest, fix dy) {
396     dest->gX = fix_mul(dy, vm4);
397     dest->gY = fix_mul(dy, vm5);
398     dest->gZ = fix_mul(dy, vm6);
399 }
400 
401 // rotate a z delta. takes edi=dest vector, eax=dz
402 // trashes eax,ebx,edx
g3_rotate_delta_z(g3s_vector * dest,fix dz)403 void g3_rotate_delta_z(g3s_vector *dest, fix dz) {
404     dest->gX = fix_mul(dz, vm7);
405     dest->gY = fix_mul(dz, vm8);
406     dest->gZ = fix_mul(dz, vm9);
407 }
408 
409 // rotate an xz delta. takes edi=dest vector, eax=dx, ebx=dz
410 // trashes eax,ebx,edx
g3_rotate_delta_xz(g3s_vector * dest,fix dx,fix dz)411 void g3_rotate_delta_xz(g3s_vector *dest, fix dx, fix dz) {
412     int64_t r;
413 
414     // first column
415     r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
416     dest->gX = fix64_to_fix(r);
417 
418     // second column
419     r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
420     dest->gY = fix64_to_fix(r);
421 
422     // third column
423     r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
424     dest->gZ = fix64_to_fix(r);
425 }
426 
427 // rotate an xy delta. takes edi=dest vector, eax=dx, ebx=dy
428 // trashes eax,ebx,edx
g3_rotate_delta_xy(g3s_vector * dest,fix dx,fix dy)429 void g3_rotate_delta_xy(g3s_vector *dest, fix dx, fix dy) {
430     int64_t r;
431 
432     // first column
433     r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
434     dest->gX = fix64_to_fix(r);
435 
436     // second column
437     r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
438     dest->gY = fix64_to_fix(r);
439 
440     // third column
441     r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
442     dest->gZ = fix64_to_fix(r);
443 }
444 
445 // rotate a yz delta. takes edi=dest vector, eax=dy, ebx=dz
446 // trashes eax,ebx,edx
g3_rotate_delta_yz(g3s_vector * dest,fix dy,fix dz)447 void g3_rotate_delta_yz(g3s_vector *dest, fix dy, fix dz) {
448     int64_t r;
449 
450     // first column
451     r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
452     dest->gX = fix64_to_fix(r);
453 
454     // second column
455     r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
456     dest->gY = fix64_to_fix(r);
457 
458     // third column
459     r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
460     dest->gZ = fix64_to_fix(r);
461 }
462 
463 // rotate a delta vector. takes edi=dest, eax,ebx,ecx=dx,dy,dz
464 // trashes all but ebp,edi
g3_rotate_delta_xyz(g3s_vector * dest,fix dx,fix dy,fix dz)465 void g3_rotate_delta_xyz(g3s_vector *dest, fix dx, fix dy, fix dz) {
466     do_rotate(dx, dy, dz, &dest->gX, &dest->gY, &dest->gZ);
467 }
468 
469 // rotate a delta vector. takes edi=dest, esi=src
470 // trashes all but ebp,edi
g3_rotate_delta_v(g3s_vector * dest,g3s_vector * src)471 void g3_rotate_delta_v(g3s_vector *dest, g3s_vector *src) {
472     do_rotate(src->gX, src->gY, src->gZ, &dest->gX, &dest->gY, &dest->gZ);
473 }
474 
475 // like add_delta, but creates and returns a new point
476 // takes esi=src, ebx=delta, returns edi=new point
477 // trashes eax,ebx
g3_copy_add_delta_v(g3s_phandle src,g3s_vector * delta)478 g3s_phandle g3_copy_add_delta_v(g3s_phandle src, g3s_vector *delta) {
479     g3s_point *point;
480 
481     getpnt(point);
482     point->gX = src->gX + delta->gX;
483     point->gY = src->gY + delta->gY;
484     point->gZ = src->gZ + delta->gZ;
485     point->p3_flags = 0;
486     code_point(point);
487     return (point);
488 }
489 
490 // adds a delta vector (created by rotate delta) to a point
491 // takes edi=point, esi=delta. clears projected bit, computes codes
492 // trashes eax,esi,bl
g3_add_delta_v(g3s_phandle p,g3s_vector * delta)493 void g3_add_delta_v(g3s_phandle p, g3s_vector *delta) {
494     p->gX += delta->gX;
495     p->gY += delta->gY;
496     p->gZ += delta->gZ;
497 
498     p->p3_flags &= ~PF_PROJECTED;
499     code_point(p);
500 }
501 
502 // add an x delta to a point. takes edi=point, eax=dx
503 // trashes eax,ebx,edx
g3_add_delta_x(g3s_phandle p,fix dx)504 void g3_add_delta_x(g3s_phandle p, fix dx) {
505     p->gX += fix_mul(vm1, dx);
506     p->gY += fix_mul(vm2, dx);
507     p->gZ += fix_mul(vm3, dx);
508     p->p3_flags &= ~PF_PROJECTED;
509 
510     code_point(p);
511 }
512 
513 // add a y delta to a point. takes edi=point, eax=dy
514 // trashes eax,ebx,edx
g3_add_delta_y(g3s_phandle p,fix dy)515 void g3_add_delta_y(g3s_phandle p, fix dy) {
516     p->gX += fix_mul(vm4, dy);
517     p->gY += fix_mul(vm5, dy);
518     p->gZ += fix_mul(vm6, dy);
519     p->p3_flags &= ~PF_PROJECTED;
520 
521     code_point(p);
522 }
523 
524 // add a z delta to a point. takes edi=point, eax=dz
525 // trashes eax,ebx,edx
g3_add_delta_z(g3s_phandle p,fix dz)526 void g3_add_delta_z(g3s_phandle p, fix dz) {
527     p->gX += fix_mul(vm7, dz);
528     p->gY += fix_mul(vm8, dz);
529     p->gZ += fix_mul(vm9, dz);
530     p->p3_flags &= ~PF_PROJECTED;
531 
532     code_point(p);
533 }
534 
535 // add an xy delta to a point. takes edi=point, eax=dx, ebx=dy
536 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xy(g3s_phandle p,fix dx,fix dy)537 void g3_add_delta_xy(g3s_phandle p, fix dx, fix dy) {
538     int64_t r;
539 
540     // first column
541     r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
542     p->gX += fix64_to_fix(r);
543 
544     // second column
545     r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
546     p->gY += fix64_to_fix(r);
547 
548     // third column
549     r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
550     p->gZ += fix64_to_fix(r);
551 
552     p->p3_flags &= ~PF_PROJECTED;
553     code_point(p);
554 }
555 
556 // add an xz delta to a point. takes edi=point, eax=dx, ebx=dz
557 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xz(g3s_phandle p,fix dx,fix dz)558 void g3_add_delta_xz(g3s_phandle p, fix dx, fix dz) {
559     int64_t r;
560 
561     // first column
562     r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
563     p->gX += fix64_to_fix(r);
564 
565     // second column
566     r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
567     p->gY += fix64_to_fix(r);
568 
569     // third column
570     r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
571     p->gZ += fix64_to_fix(r);
572 
573     p->p3_flags &= ~PF_PROJECTED;
574     code_point(p);
575 }
576 
577 // add an yz delta to a point. takes edi=point, eax=dy, ebx=dz
578 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_yz(g3s_phandle p,fix dy,fix dz)579 void g3_add_delta_yz(g3s_phandle p, fix dy, fix dz) {
580     int64_t r;
581 
582     // first column
583     r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
584     p->gX += fix64_to_fix(r);
585 
586     // second column
587     r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
588     p->gY += fix64_to_fix(r);
589 
590     // third column
591     r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
592     p->gZ += fix64_to_fix(r);
593 
594     p->p3_flags &= ~PF_PROJECTED;
595     code_point(p);
596 }
597 
598 // add an xyz delta to a point. takes edi=point, eax=dx, ebx=dy, ecx=dz
599 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xyz(g3s_phandle p,fix dx,fix dy,fix dz)600 void g3_add_delta_xyz(g3s_phandle p, fix dx, fix dy, fix dz) {
601     fix rx, ry, rz;
602 
603     do_rotate(dx, dy, dz, &rx, &ry, &rz);
604 
605     p->gX += rx;
606     p->gY += ry;
607     p->gZ += rz;
608 
609     p->p3_flags &= ~PF_PROJECTED;
610     code_point(p);
611 }
612 
613 // like add_delta, but creates and returns a new point in edi
614 // add an x delta to a point. takes esi=point, eax=dx
615 // trashes eax,ebx,edx
g3_copy_add_delta_x(g3s_phandle src,fix dx)616 g3s_phandle g3_copy_add_delta_x(g3s_phandle src, fix dx) {
617     g3s_point *point;
618 
619     getpnt(point);
620     point->gX = src->gX + fix_mul(dx, vm1);
621     point->gY = src->gY + fix_mul(dx, vm2);
622     point->gZ = src->gZ + fix_mul(dx, vm3);
623     point->p3_flags = 0;
624     code_point(point);
625     return (point);
626 }
627 
628 // like add_delta, but creates and returns a new point in edi
629 // add a y delta to a point. takes esi=point, eax=dy
630 // trashes eax,ebx,edx
g3_copy_add_delta_y(g3s_phandle src,fix dy)631 g3s_phandle g3_copy_add_delta_y(g3s_phandle src, fix dy) {
632     g3s_point *point;
633 
634     getpnt(point);
635     point->gX = src->gX + fix_mul(dy, vm4);
636     point->gY = src->gY + fix_mul(dy, vm5);
637     point->gZ = src->gZ + fix_mul(dy, vm6);
638     point->p3_flags = 0;
639     code_point(point);
640     return (point);
641 }
642 
643 // like add_delta, but creates and returns a new point in edi
644 // add a z delta to a point. takes esi=point, eax=dz
645 // trashes eax,ebx,edx
g3_copy_add_delta_z(g3s_phandle src,fix dz)646 g3s_phandle g3_copy_add_delta_z(g3s_phandle src, fix dz) {
647     g3s_point *point;
648 
649     getpnt(point);
650     point->gX = src->gX + fix_mul(dz, vm7);
651     point->gY = src->gY + fix_mul(dz, vm8);
652     point->gZ = src->gZ + fix_mul(dz, vm9);
653     point->p3_flags = 0;
654     code_point(point);
655     return (point);
656 }
657 
658 // like add_delta, but modifies an existing point in edi
659 // add an x delta to a point. takes esi=src point, edi=replace point, ax=dx
660 // trashes eax,ebx,edx
g3_replace_add_delta_x(g3s_phandle src,g3s_phandle dst,fix dx)661 g3s_phandle g3_replace_add_delta_x(g3s_phandle src, g3s_phandle dst, fix dx) {
662     dst->gX = src->gX + fix_mul(dx, vm1);
663     dst->gY = src->gY + fix_mul(dx, vm2);
664     dst->gZ = src->gZ + fix_mul(dx, vm3);
665     dst->p3_flags = 0;
666     code_point(dst);
667     return (dst);
668 }
669 
670 // like add_delta, but modifies an existing point in edi
671 // add a y delta to a point. takes esi=src point, edi=replace point, ax=dy
672 // trashes eax,ebx,edx
g3_replace_add_delta_y(g3s_phandle src,g3s_phandle dst,fix dy)673 g3s_phandle g3_replace_add_delta_y(g3s_phandle src, g3s_phandle dst, fix dy) {
674     dst->gX = src->gX + fix_mul(dy, vm4);
675     dst->gY = src->gY + fix_mul(dy, vm5);
676     dst->gZ = src->gZ + fix_mul(dy, vm6);
677     dst->p3_flags = 0;
678     code_point(dst);
679     return (dst);
680 }
681 
682 // like add_delta, but modifies an existing point in edi
683 // add a z delta to a point. takes esi=src point, edi=replace point, ax=dz
684 // trashes eax,ebx,edx
g3_replace_add_delta_z(g3s_phandle src,g3s_phandle dst,fix dz)685 g3s_phandle g3_replace_add_delta_z(g3s_phandle src, g3s_phandle dst, fix dz) {
686     dst->gX = src->gX + fix_mul(dz, vm7);
687     dst->gY = src->gY + fix_mul(dz, vm8);
688     dst->gZ = src->gZ + fix_mul(dz, vm9);
689     dst->p3_flags = 0;
690     code_point(dst);
691     return (dst);
692 }
693 
694 // like add_delta, but creates and returns a new point in edi
695 // add an xy delta to a point. takes edi=point, eax=dx, ebx=dy
696 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xy(g3s_phandle src,fix dx,fix dy)697 g3s_phandle g3_copy_add_delta_xy(g3s_phandle src, fix dx, fix dy) {
698     g3s_point *point;
699     int64_t r;
700 
701     getpnt(point);
702 
703     // first column
704     r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
705     point->gX = src->gX + fix64_to_fix(r);
706 
707     // second column
708     r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
709     point->gY = src->gY + fix64_to_fix(r);
710 
711     // third column
712     r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
713     point->gZ = src->gZ + fix64_to_fix(r);
714 
715     point->p3_flags = 0;
716     code_point(point);
717     return (point);
718 }
719 
720 // like add_delta, but creates and returns a new point in edi
721 // add an xz delta to a point. takes edi=point, eax=dx, ebx=dz
722 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xz(g3s_phandle src,fix dx,fix dz)723 g3s_phandle g3_copy_add_delta_xz(g3s_phandle src, fix dx, fix dz) {
724     g3s_point *point;
725     int64_t r;
726 
727     getpnt(point);
728 
729     // first column
730     r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
731     point->gX = src->gX + fix64_to_fix(r);
732 
733     // second column
734     r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
735     point->gY = src->gY + fix64_to_fix(r);
736 
737     // third column
738     r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
739     point->gZ = src->gZ + fix64_to_fix(r);
740 
741     point->p3_flags = 0;
742     code_point(point);
743     return (point);
744 }
745 
746 // like add_delta, but creates and returns a new point in edi
747 // add an yz delta to a point. takes edi=point, eax=dy, ebx=dz
748 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_yz(g3s_phandle src,fix dy,fix dz)749 g3s_phandle g3_copy_add_delta_yz(g3s_phandle src, fix dy, fix dz) {
750     g3s_point *point;
751     int64_t r;
752 
753     getpnt(point);
754 
755     // first column
756     r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
757     point->gX = src->gX + fix64_to_fix(r);
758 
759     // second column
760     r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
761     point->gY = src->gY + fix64_to_fix(r);
762 
763     // third column
764     r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
765     point->gZ = src->gZ + fix64_to_fix(r);
766 
767     point->p3_flags = 0;
768     code_point(point);
769     return (point);
770 }
771 
772 // like add_delta, but creates and returns a new point in edi
773 // add an xyz delta to a point. takes edi=point, eax=dx, ebx=dy, ecx=dz
774 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xyz(g3s_phandle src,fix dx,fix dy,fix dz)775 g3s_phandle g3_copy_add_delta_xyz(g3s_phandle src, fix dx, fix dy, fix dz) {
776     g3s_point *point;
777 
778     getpnt(point);
779     do_rotate(dx, dy, dz, &point->gX, &point->gY, &point->gZ);
780 
781     point->gX += src->gX;
782     point->gY += src->gY;
783     point->gZ += src->gZ;
784 
785     point->p3_flags = 0;
786     code_point(point);
787     return (point);
788 }
789