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/interp.asm $
21 // $Revision: 1.19 $
22 // $Author: jaemz $
23 // $Date: 1994/10/13 20:51:43 $
24 //
25 // 3d object interpreter
26 //
27 // $Log: interp.asm $
28 // Revision 1.19  1994/10/13  20:51:43  jaemz
29 // Fixed lighting bug
30 //
31 // Revision 1.18  1994/09/20  13:34:36  jaemz
32 // Lighting
33 //
34 // Revision 1.14  1994/08/18  03:45:30  jaemz
35 // Added stereo to objects for real, reevals bsp tree
36 //
37 // Revision 1.13  1994/07/15  14:13:34  jaemz
38 // Added _view_position with an underscore to make it c readable
39 //
40 // Revision 1.12  1994/05/19  09:46:39  kevin
41 // g3_draw_tmap now uses watcom register parameter passing conventions.
42 //
43 // Revision 1.11  1994/02/08  20:46:17  kaboom
44 // Updated usage of gour_flag.
45 //
46 // Revision 1.10  1993/11/18  10:08:11  dc
47 // first set of debug setup for the interpreter
48 //
49 // Revision 1.9  1993/10/25  16:24:46  kaboom
50 // Changed call to polygon routine to use new calling convention.
51 //
52 // Revision 1.8  1993/10/02  09:27:49  kaboom
53 // Added vtext_tab.  Also updated texture map opcode to call the uv perspective
54 // mapper.
55 //
56 // Revision 1.7  1993/09/15  04:01:23  dc
57 // tmap interface, well, except there isnt a tmapper
58 //
59 // Revision 1.6  1993/08/10  22:54:13  dc
60 // add _3d.inc to includes
61 //
62 // Revision 1.5  1993/08/04  00:47:10  dc
63 // support for new interpreter opcodes
64 //
65 // Revision 1.4  1993/06/03  14:34:00  matt
66 // Removed int -> sfix conversion in defres_i & setshade
67 //
68 // Revision 1.3  1993/06/02  16:57:01  matt
69 // Gouraud polys handled differently: gouraud base now added at poly draw
70 // time, not point definition time.
71 //
72 // Revision 1.2  1993/05/27  18:11:46  matt
73 // Added getparms opcodes, and changed parameter passing scheme.
74 //
75 // Revision 1.1  1993/05/04  17:39:50  matt
76 // Initial revision
77 //
78 //
79 
80 #include "3d.h"
81 #include "GlobalV.h"
82 #include "lg.h"
83 //#include <String.h>
84 //#include <_stdarg.h>
85 #include <stdarg.h>
86 
87 // prototypes;
88 uchar *do_eof(uchar *);
89 uchar *do_jnorm(uchar *);
90 uchar *do_ldjnorm(uchar *);
91 uchar *do_ljnorm(uchar *);
92 uchar *do_lnres(uchar *);
93 uchar *do_multires(uchar *);
94 uchar *do_polyres(uchar *);
95 uchar *do_setcolor(uchar *);
96 uchar *do_sortnorm(uchar *);
97 uchar *do_debug(uchar *);
98 uchar *do_setshade(uchar *);
99 uchar *do_goursurf(uchar *);
100 uchar *do_x_rel(uchar *);
101 uchar *do_y_rel(uchar *);
102 uchar *do_z_rel(uchar *);
103 uchar *do_xy_rel(uchar *);
104 uchar *do_xz_rel(uchar *);
105 uchar *do_yz_rel(uchar *);
106 uchar *do_icall_p(uchar *);
107 uchar *do_icall_b(uchar *);
108 uchar *do_icall_h(uchar *);
109 uchar *do_sfcal(uchar *);
110 uchar *do_defres(uchar *);
111 uchar *do_defres_i(uchar *);
112 uchar *do_getparms(uchar *);
113 uchar *do_getparms_i(uchar *);
114 uchar *do_gour_p(uchar *);
115 uchar *do_gour_vc(uchar *);
116 uchar *do_getvcolor(uchar *);
117 uchar *do_getvscolor(uchar *);
118 uchar *do_rgbshades(uchar *);
119 uchar *do_draw_mode(uchar *);
120 uchar *do_getpcolor(uchar *);
121 uchar *do_getpscolor(uchar *);
122 uchar *do_scaleres(uchar *);
123 uchar *do_vpnt_p(uchar *);
124 uchar *do_vpnt_v(uchar *);
125 uchar *do_setuv(uchar *);
126 uchar *do_uvlist(uchar *);
127 uchar *do_tmap_op(uchar *);
128 uchar *do_dbg(uchar *);
129 
130 extern int check_and_draw_common(long c, int n_verts, g3s_phandle *p);
131 extern int draw_poly_common(long c, int n_verts, g3s_phandle *p);
132 extern void g3_light_obj(g3s_phandle norm, g3s_phandle pos);
133 
134 void interpreter_loop(uchar *object);
135 
136 void FlipVector(short n, g3s_vector *vec);
137 void FlipLong(long *lng);
138 void FlipShort(short *sh);
139 
140 // globals
141 extern char gour_flag; // gour flag for actual polygon drawer
142 
143 // clang-format off
144 #ifdef stereo_on
145   temp_vector      g3s_vector     <>
146   tmp_address      dd             ?
147 #endif
148 // clang-format on
149 
150 #define OP_EOF 0
151 #define OP_JNORM 1
152 
153 #define n_ops 40
154     void *opcode_table[n_ops] = {
155         do_eof,        do_jnorm,     do_lnres,     do_multires,   do_polyres,    do_setcolor, do_sortnorm,
156         do_debug,      do_setshade,  do_goursurf,  do_x_rel,      do_y_rel,      do_z_rel,    do_xy_rel,
157         do_xz_rel,     do_yz_rel,    do_icall_p,   do_icall_b,    do_icall_h,    0,           do_sfcal,
158         do_defres,     do_defres_i,  do_getparms,  do_getparms_i, do_gour_p,     do_gour_vc,  do_getvcolor,
159         do_getvscolor, do_rgbshades, do_draw_mode, do_getpcolor,  do_getpscolor, do_scaleres, do_vpnt_p,
160         do_vpnt_v,     do_setuv,     do_uvlist,    do_tmap_op,    do_dbg};
161 
162 #define N_RES_POINTS 1000
163 #define PARM_DATA_SIZE 4 * 100
164 
165 #define N_VCOLOR_ENTRIES 32
166 #define N_VPOINT_ENTRIES 32
167 #define N_VTEXT_ENTRIES 64
168 
169 // This determines when we no longer reevaluate
170 // the bsp tree.  It corresponds to the tan of
171 // 7.12 degrees, which empirically seems fine
172 // we might have to set it lower some day if
173 // you see polygons drop out in stereo
174 #define STEREO_DIST_LIM = 0x2000
175 
176 g3s_point *resbuf[N_RES_POINTS];
177 g3s_point *poly_buf[100];
178 
179 // clang-format off
180 uchar _vcolor_tab[N_VCOLOR_ENTRIES] = {
181     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
182     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
183 };
184 g3s_point *_vpoint_tab[N_VPOINT_ENTRIES] = {
185     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
187 };
188 grs_bitmap *_vtext_tab[N_VTEXT_ENTRIES] = {
189     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
190     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
193 };
194 // clang-format on
195 
196 // ptr to stack parms
197 va_list parm_ptr;
198 
199 // space for parms to objects
200 char parm_data[PARM_DATA_SIZE];
201 
202 char _itrp_gour_flg = 0;
203 char _itrp_wire_flg = 0;
204 char _itrp_check_flg = 0;
205 
206 // MLA not used, - uchar 	*struct_ptr;
207 
208 /*
209 // process the next opcode
210 next	macro	opsize
211         ifnb	<opsize>
212          add	ebp,opsize	// point at next opcode
213         endif
214         jmp	interpreter_loop
215         endm
216 
217 call_next	macro
218         call	interpreter_loop
219         endm
220 */
221 
222 // c callable context setting routines
223 // set virtual color eax to ebx
224 // inlined in 3d.h for now....
225 // g3_setvcolor:
226 //       add     eax, _vcolor_tab
227 //       mov     byte ptr [eax], bl
228 
229 // takes ptr to object in eax. trashes all but ebp
230 // this is bullshit, man, takes ptr to object on the freakin' stack!
g3_interpret_object(ubyte * object_ptr,...)231 void g3_interpret_object(ubyte *object_ptr, ...) {
232     int i, scale;
233 
234     // lighting stuff, params are on the stack
235     // so don't sweat it
236     // set fill type so 2d can light the thang
237     if ((_g3d_light_type & (LT_SPEC | LT_DIFF)) != 0) {
238         gr_set_fill_type(FILL_CLUT);
239         if (_g3d_light_type == LT_DIFF)
240             opcode_table[OP_JNORM] = &do_ldjnorm;
241         else
242             opcode_table[OP_JNORM] = &do_ljnorm;
243     }
244 
245 // clang-format off
246 #ifdef stereo_on
247   test    _g3d_stereo,1
248   jz      g3_interpret_object_raw
249   //       call normally if eyesep/distance is small enough (angular change is small)
250   //       transform 0,0,0 to get the z distance
251   mov     eax,_view_position.x
252   fixmul  view_matrix.m3
253   mov     ecx,eax
254 
255   mov     eax,_view_position.y
256   fixmul  view_matrix.m6
257   add     ecx,eax
258 
259   mov     eax,_view_position.z
260   fixmul  view_matrix.m9
261   add     ecx,eax
262   neg     ecx
263 
264   mov     eax,_g3d_eyesep_raw
265   fixmul  _matrix_scale.z
266   fixdiv  ecx
267 
268   cmp     eax,STEREO_DIST_LIM
269   jl      g3_interpret_object_raw
270 
271   mov     _g3d_stereo,0    // kill stereo
272   pop     eax     // grab real return address
273   mov     tmp_address,eax         // save it for later
274 
275   push    ret1    // fake out the poor thing so it jumps back here
276   jmp  g3_interpret_object_raw
277 
278   // shift view_position
279   ret1:
280   // save the current position
281   lea     edi,temp_vector
282   lea     esi,_view_position
283   movsd
284   movsd
285   movsd
286 
287   mov     eax,_g3d_eyesep_raw
288   mov     ebx,_matrix_scale.x
289   fixdiv  ebx     // make ebx the scaled down eyesep
290   mov     ebx,eax
291 
292   // get x slewed over (top row of current vector and scale)
293   mov     eax,view_matrix.m1
294   fixmul  ebx
295   add     _view_position.x,eax
296 
297   mov     eax,view_matrix.m4
298   fixmul  ebx
299   add     _view_position.y,eax
300 
301   mov     eax,view_matrix.m7
302   fixmul  ebx
303   add     _view_position.z,eax
304 
305   set_rt_canv             // install rt canvas
306   // this time when you call it, its still all set
307   call    g3_interpret_object_raw
308   mov     _g3d_stereo,1    // restore stereo
309   set_lt_canv             // restore left canvas
310 
311   // restore view position
312   lea     esi,temp_vector
313   lea     edi,_view_position
314   movsd
315   movsd
316   movsd
317 
318   // weeee, pretend we were here all along, but I suppose we
319   // could just jmp there
320   push    tmp_address
321 
322   ret
323 g3_interpret_object_raw:
324 #endif
325         // clang-format on
326 
327         va_start(parm_ptr, object_ptr); // get addr of stack parms
328 
329     // MLA- not used ever?
330     /*
331             mov	eax,16[esp]	// get angle
332             mov	struct_ptr,eax*/
333 
334     // mark res points as free
335     LG_memset(resbuf, 0, N_RES_POINTS * 4);
336 
337     // scale view vector for scale
338     FlipShort((short *)(object_ptr - 2));
339     scale = *(short *)(object_ptr - 2);
340     if (scale) {
341         if (scale > 0) {
342             _view_position.gX >>= scale;
343             _view_position.gY >>= scale;
344             _view_position.gZ >>= scale;
345         } else {
346             int temp;
347 
348             scale = -scale;
349 
350             temp = (((ulong)_view_position.gX) >> 16); // get high 16 bits
351             // FIXME: DG: I guess they meant &, not &&
352             // shamaz: Fixed that
353             if (((temp << scale) & 0xffff0000) != 0)
354                 return;                             // overflow
355             temp = (((ulong)_view_position.gY) >> 16); // get high 16 bits
356             if (((temp << scale) & 0xffff0000) != 0)
357                 return;                             // overflow
358             temp = (((ulong)_view_position.gZ) >> 16); // get high 16 bits
359             if (((temp << scale) & 0xffff0000) != 0)
360                 return; // overflow
361 
362             _view_position.gX <<= scale;
363             _view_position.gY <<= scale;
364             _view_position.gZ <<= scale;
365         }
366     }
367 
368     interpreter_loop(object_ptr);
369 
370     // free res points
371     for (i = N_RES_POINTS - 1; i >= 0; i--)
372         if (resbuf[i])
373             freepnt(resbuf[i]);
374 
375     // set lighting back to how it was
376     if ((_g3d_light_type & (LT_SPEC | LT_DIFF)) != 0) {
377         gr_set_fill_type(FILL_NORM);
378         opcode_table[OP_JNORM] = &do_jnorm;
379     }
380 
381 }
382 
383 // interpret the object
interpreter_loop(uchar * object)384 void interpreter_loop(uchar *object) {
385     do {
386         FlipShort((short *)object);
387         object = ((uchar * (*)(uchar *)) opcode_table[*(short *)object])(object);
388     } while (object);
389 }
390 
391 // opcodes.  [ebp] points at op on entry
do_debug(uchar * opcode)392 uchar *do_debug(uchar *opcode) { return 0; }
393 
do_eof(uchar * opcode)394 uchar *do_eof(uchar *opcode) // and return extra level
395 {
396     return 0;
397 }
398 
399 // jnorm lbl,px,py,pz,nx,ny,nz
400 // v=viewer coords-p
401 // if (n*v)<0 then branch to lbl
do_jnorm(uchar * opcode)402 uchar *do_jnorm(uchar *opcode) {
403     FlipShort((short *)(opcode + 2));
404     FlipVector(2, (g3s_vector *)(opcode + 4));
405 
406     if (g3_check_normal_facing((g3s_vector *)(opcode + 16), (g3s_vector *)(opcode + 4)))
407         return opcode + 28; // surface is visible. continue
408     else
409         return opcode + (*(short *)(opcode + 2)); // surface not visible
410 }
411 
412 // lnres pnt0,pnt1
do_lnres(uchar * opcode)413 uchar *do_lnres(uchar *opcode) {
414     FlipShort((short *)(opcode + 2));
415     FlipShort((short *)(opcode + 4));
416 
417     g3_draw_line(resbuf[*(unsigned short *)(opcode + 2)], resbuf[*(unsigned short *)(opcode + 4)]);
418     return opcode + 6;
419 }
420 
do_multires(uchar * opcode)421 uchar *do_multires(uchar *opcode) {
422     short count;
423 
424     FlipShort((short *)(opcode + 2));
425     FlipShort((short *)(opcode + 4));
426 
427     count = *(short *)(opcode + 2);
428     FlipVector(count, (g3s_vector *)(opcode + 6));
429 
430     g3_transform_list(count, (g3s_phandle *)(resbuf + (*(short *)(opcode + 4))), (g3s_vector *)(opcode + 6));
431     return opcode + 6 + (count * 12); // fixup: ebp = esi + ecx*12
432 }
433 
434 // this should do some cute matrix transform trick, not this ugly hack
435 
436 // that kid from the wrong side came over my house again, decapitated all my
437 // dolls
438 //  and if you bore me, you lose your soul to me       - "Gepetto", Belly,
439 //  _Star_
do_scaleres(uchar * opcode)440 uchar *do_scaleres(uchar *opcode) {
441     // MLA - this routine appears to be buggy and can't possibly work, so I'm not
442     // doing it yet.
443     DEBUG("%s Call Mark!", __FUNCTION__);
444 
445     /* 	int					count,scale;
446             long				temp_pnt[3];
447             g3s_phandle	temp_hand;
448 
449             count = * (unsigned short *) (opcode+2);
450             scale = * (unsigned short *) (opcode+4);
451             temp_hand = (g3s_phandle) (parm_data+(* (unsigned short *)
452        (opcode+6)));
453 
454             opcode += 8;
455             do
456              {
457              }
458             while (--count>0);
459 
460             return opcode;
461              */
462     /*
463            movzx	ecx,w 2[ebp]	// get count
464            movzx	eax,w 4[ebp]	// get scale factor
465            movzx	ebx,w 6[ebp]	// get dest start num
466            mov     eax,d parm_data [eax]
467            add     ebp,8
468    //	lea	esi,[ebp]	// get vector array start
469    do_sr_loop:
470            push    eax
471            push    ecx
472            push    ebx
473            mov     ecx, eax
474            mov     esi, OFFSET temp_pnt
475    // do better scaling here.....
476            imul    d [ebp]
477            shrd    eax,edx,16
478            mov     [esi],eax
479            mov     eax, ecx
480            imul    d 4[ebp]
481            shrd    eax,edx,16
482            mov     4[esi],eax
483            mov     eax, ecx
484            imul    d 8[ebp]
485            shrd    eax,edx,16
486            mov     8[esi],eax
487            call    g3_transform_point
488            pop     ebx
489            mov     resbuf[ebx*4],edi
490            inc     ebx
491            add     ebp,12
492            lea     esi,[ebp]
493            pop     ecx
494            pop     eax
495            dec     ecx
496            jnz     do_sr_loop
497            next
498     */
499     return 0;
500 }
501 
502 // these put the address of an old point in the interpreter respnt array
503 // note they will get freed when the interpreter punts
do_vpnt_p(uchar * opcode)504 uchar *do_vpnt_p(uchar *opcode) {
505     FlipShort((short *)(opcode + 2));
506     FlipShort((short *)(opcode + 4));
507 
508     resbuf[*(short *)(opcode + 4)] = (g3s_point *)(*(long *)(parm_data + (*(unsigned short *)(opcode + 2))));
509     return opcode + 6;
510 }
511 
do_vpnt_v(uchar * opcode)512 uchar *do_vpnt_v(uchar *opcode) {
513     FlipShort((short *)(opcode + 2));
514     FlipShort((short *)(opcode + 4));
515 
516     resbuf[*(short *)(opcode + 4)] = _vpoint_tab[(*(unsigned short *)(opcode + 2)) >> 2];
517     return opcode + 6;
518 }
519 
do_defres(uchar * opcode)520 uchar *do_defres(uchar *opcode) {
521     FlipShort((short *)(opcode + 2));
522     FlipVector(1, (g3s_vector *)(opcode + 4));
523 
524     resbuf[*(unsigned short *)(opcode + 2)] = g3_transform_point((g3s_vector *)(opcode + 4));
525     return opcode + 16;
526 }
527 
do_defres_i(uchar * opcode)528 uchar *do_defres_i(uchar *opcode) {
529     g3s_phandle temphand;
530 
531     FlipShort((short *)(opcode + 2));
532     FlipShort((short *)(opcode + 16));
533     FlipVector(1, (g3s_vector *)(opcode + 4));
534 
535     temphand = g3_transform_point((g3s_vector *)(opcode + 4));
536     resbuf[*(unsigned short *)(opcode + 2)] = temphand;
537 
538     temphand->i = *(short *)(opcode + 16);
539     temphand->p3_flags |= PF_I;
540 
541     return opcode + 18;
542 }
543 
544 // polyres cnt,pnt0,pnt1,...
do_polyres(uchar * opcode)545 uchar *do_polyres(uchar *opcode) {
546     int count, count2;
547 
548     FlipShort((short *)(opcode + 2));
549 
550     count2 = count = *(unsigned short *)(opcode + 2);
551     opcode += 4;
552     while (--count >= 0) {
553         FlipShort((short *)(opcode + (count << 1)));
554 
555         poly_buf[count] = resbuf[*(unsigned short *)(opcode + (count << 1))];
556     }
557 
558     opcode += count2 << 1;
559 
560     gour_flag = _itrp_gour_flg;
561     if ((_itrp_check_flg & 1) == 0)
562         draw_poly_common(gr_get_fcolor(), count2, poly_buf);
563     else
564         check_and_draw_common(gr_get_fcolor(), count2, poly_buf);
565 
566     return opcode;
567 }
568 
do_sortnorm(uchar * opcode)569 uchar *do_sortnorm(uchar *opcode) {
570     FlipVector(2, (g3s_vector *)(opcode + 2));
571     FlipShort((short *)(opcode + 26));
572     FlipShort((short *)(opcode + 28));
573 
574     if (g3_check_normal_facing((g3s_vector *)(opcode + 14), (g3s_vector *)(opcode + 2))) {
575         interpreter_loop(opcode + (*(short *)(opcode + 26)));
576         interpreter_loop(opcode + (*(short *)(opcode + 28)));
577     } else {
578         interpreter_loop(opcode + (*(short *)(opcode + 28)));
579         interpreter_loop(opcode + (*(short *)(opcode + 26)));
580     }
581 
582     return opcode + 30;
583 }
584 
do_goursurf(uchar * opcode)585 uchar *do_goursurf(uchar *opcode) {
586     FlipShort((short *)(opcode + 2));
587 
588     gouraud_base = (*(short *)(opcode + 2)) << 8;
589     _itrp_gour_flg = 2;
590     return opcode + 4;
591 }
592 
do_gour_p(uchar * opcode)593 uchar *do_gour_p(uchar *opcode) {
594     FlipShort((short *)(opcode + 2));
595 
596     gouraud_base = parm_data[(*(short *)(opcode + 2))] << 8;
597     _itrp_gour_flg = 2;
598     return opcode + 4;
599 }
600 
do_gour_vc(uchar * opcode)601 uchar *do_gour_vc(uchar *opcode) {
602 
603     FlipShort((short *)(opcode + 2));
604 
605     gouraud_base = ((long)_vcolor_tab[*(unsigned short *)(opcode + 2)]) << 8;
606     _itrp_gour_flg = 2;
607     return opcode + 4;
608 }
609 
do_draw_mode(uchar * opcode)610 uchar *do_draw_mode(uchar *opcode) {
611     short flags;
612 
613     FlipShort((short *)(opcode + 2));
614 
615     flags = *(short *)(opcode + 2);
616     _itrp_wire_flg = flags >> 8;
617     flags &= 0x00ff;
618     flags <<= 1;
619     _itrp_check_flg = flags >> 8;
620     flags &= 0x00ff;
621     flags <<= 2;
622     _itrp_gour_flg = flags - 1;
623     return opcode + 4;
624 }
625 
do_setshade(uchar * opcode)626 uchar *do_setshade(uchar *opcode) {
627     int i;
628     uchar *new_opcode;
629     g3s_phandle temphand;
630 
631     FlipShort((short *)(opcode + 2));
632 
633     i = *(unsigned short *)(opcode + 2); // get number of shades
634     new_opcode = opcode + 4 + (i << 2);
635 
636     while (--i >= 0) {
637         FlipShort((short *)(opcode + 4 + (i << 2)));
638         FlipShort((short *)(opcode + 6 + (i << 2)));
639 
640         temphand = resbuf[*(unsigned short *)(opcode + 4 + (i << 2))]; // get point handle
641         temphand->i = *(short *)(opcode + 6 + (i << 2));
642         temphand->p3_flags |= PF_I;
643     }
644 
645     return new_opcode;
646 }
647 
do_rgbshades(uchar * opcode)648 uchar *do_rgbshades(uchar *opcode) {
649     uchar *new_opcode;
650     int i;
651     g3s_phandle temphand;
652 
653     FlipShort((short *)(opcode + 2));
654 
655     i = *(unsigned short *)(opcode + 2); // get number of shades
656     new_opcode = opcode + 4;
657     while (--i >= 0) {
658         FlipShort((short *)new_opcode);
659         FlipLong((long *)(new_opcode + 2));
660 
661         temphand = resbuf[*(unsigned short *)new_opcode]; // get point handle
662         temphand->rgb = *(long *)(new_opcode + 2);
663         temphand->p3_flags |= PF_RGB;
664         new_opcode += 10;
665     }
666     return new_opcode;
667 }
668 
do_setuv(uchar * opcode)669 uchar *do_setuv(uchar *opcode) {
670     g3s_phandle temphand;
671 
672     FlipShort((short *)(opcode + 2));
673     FlipLong((long *)(opcode + 4));
674     FlipLong((long *)(opcode + 8));
675 
676     temphand = resbuf[*(unsigned short *)(opcode + 2)]; // get point handle
677     temphand->uv.u = (*(unsigned long *)(opcode + 4)) >> 8;
678     temphand->uv.v = (*(unsigned long *)(opcode + 8)) >> 8;
679     temphand->p3_flags |= PF_U | PF_V;
680 
681     return opcode + 12;
682 }
683 
do_uvlist(uchar * opcode)684 uchar *do_uvlist(uchar *opcode) {
685     int i;
686     g3s_phandle temphand;
687 
688     FlipShort((short *)(opcode + 2));
689 
690     i = *(unsigned short *)(opcode + 2); // get number of shades
691     opcode += 4;
692     while (--i >= 0) {
693         FlipShort((short *)opcode);
694         FlipLong((long *)(opcode + 2));
695         FlipLong((long *)(opcode + 6));
696 
697         temphand = resbuf[*(unsigned short *)opcode]; // get point handle
698         temphand->uv.u = (*(unsigned long *)(opcode + 2)) >> 8;
699         temphand->uv.v = (*(unsigned long *)(opcode + 6)) >> 8;
700         temphand->p3_flags |= PF_U | PF_V;
701         opcode += 10;
702     }
703 
704     return opcode;
705 }
706 
707 // should we be hacking _itrp_gour_flg?
do_setcolor(uchar * opcode)708 uchar *do_setcolor(uchar *opcode) {
709     FlipShort((short *)(opcode + 2));
710 
711     gr_set_fcolor(*(unsigned short *)(opcode + 2));
712     _itrp_gour_flg = 0;
713     return opcode + 4;
714 }
715 
do_getvcolor(uchar * opcode)716 uchar *do_getvcolor(uchar *opcode) {
717     FlipShort((short *)(opcode + 2));
718 
719     gr_set_fcolor(_vcolor_tab[*(unsigned short *)(opcode + 2)]);
720     _itrp_gour_flg = 0;
721     return opcode + 4;
722 }
723 
do_getpcolor(uchar * opcode)724 uchar *do_getpcolor(uchar *opcode) {
725     FlipShort((short *)(opcode + 2));
726 
727     gr_set_fcolor(*(unsigned short *)(parm_data + (*(unsigned short *)(opcode + 2))));
728     _itrp_gour_flg = 0;
729     return opcode + 4;
730 }
731 
do_getvscolor(uchar * opcode)732 uchar *do_getvscolor(uchar *opcode) {
733     short temp;
734 
735     FlipShort((short *)(opcode + 2));
736     FlipShort((short *)(opcode + 4));
737 
738     temp = (byte)_vcolor_tab[*(unsigned short *)(opcode + 2)];
739     temp |= (*(short *)(opcode + 4)) << 8;
740     gr_set_fcolor(gr_get_light_tab()[temp]);
741     return opcode + 6;
742 }
743 
do_getpscolor(uchar * opcode)744 uchar *do_getpscolor(uchar *opcode) {
745     short temp;
746 
747     FlipShort((short *)(opcode + 2));
748     FlipShort((short *)(opcode + 4));
749 
750     temp = (unsigned short)parm_data[*(unsigned short *)(opcode + 2)];
751     temp &= 0x00ff;
752     temp |= (*(short *)(opcode + 4)) << 8;
753     gr_set_fcolor(gr_get_light_tab()[temp]);
754     return opcode + 6;
755 }
756 
do_x_rel(uchar * opcode)757 uchar *do_x_rel(uchar *opcode) {
758     FlipShort((short *)(opcode + 2));
759     FlipShort((short *)(opcode + 4));
760     FlipLong((long *)(opcode + 6));
761 
762     resbuf[*(short *)(opcode + 2)] = g3_copy_add_delta_x(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6));
763     return opcode + 10;
764 }
765 
do_y_rel(uchar * opcode)766 uchar *do_y_rel(uchar *opcode) {
767     FlipShort((short *)(opcode + 2));
768     FlipShort((short *)(opcode + 4));
769     FlipLong((long *)(opcode + 6));
770 
771     resbuf[*(short *)(opcode + 2)] = g3_copy_add_delta_y(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6));
772     return opcode + 10;
773 }
774 
do_z_rel(uchar * opcode)775 uchar *do_z_rel(uchar *opcode) {
776     FlipShort((short *)(opcode + 2));
777     FlipShort((short *)(opcode + 4));
778     FlipLong((long *)(opcode + 6));
779 
780     resbuf[*(short *)(opcode + 2)] = g3_copy_add_delta_z(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6));
781     return opcode + 10;
782 }
783 
do_xy_rel(uchar * opcode)784 uchar *do_xy_rel(uchar *opcode) {
785     FlipShort((short *)(opcode + 2));
786     FlipShort((short *)(opcode + 4));
787     FlipLong((long *)(opcode + 6));
788     FlipLong((long *)(opcode + 10));
789 
790     resbuf[*(short *)(opcode + 2)] =
791         g3_copy_add_delta_xy(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6), *(fix *)(opcode + 10));
792     return opcode + 14;
793 }
794 
do_xz_rel(uchar * opcode)795 uchar *do_xz_rel(uchar *opcode) {
796     FlipShort((short *)(opcode + 2));
797     FlipShort((short *)(opcode + 4));
798     FlipLong((long *)(opcode + 6));
799     FlipLong((long *)(opcode + 10));
800 
801     resbuf[*(short *)(opcode + 2)] =
802         g3_copy_add_delta_xz(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6), *(fix *)(opcode + 10));
803     return opcode + 14;
804 }
805 
do_yz_rel(uchar * opcode)806 uchar *do_yz_rel(uchar *opcode) {
807     FlipShort((short *)(opcode + 2));
808     FlipShort((short *)(opcode + 4));
809     FlipLong((long *)(opcode + 6));
810     FlipLong((long *)(opcode + 10));
811 
812     resbuf[*(short *)(opcode + 2)] =
813         g3_copy_add_delta_yz(resbuf[*(short *)(opcode + 4)], *(fix *)(opcode + 6), *(fix *)(opcode + 10));
814     return opcode + 14;
815 }
816 
do_icall_p(uchar * opcode)817 uchar *do_icall_p(uchar *opcode) {
818     FlipVector(1, (g3s_vector *)(opcode + 6));
819     FlipShort((short *)(opcode + 18));
820     FlipLong((long *)(opcode + 2));
821 
822     g3_start_object_angles_x((g3s_vector *)(opcode + 6), *(fixang *)(parm_data + (*(unsigned short *)(opcode + 18))));
823     interpreter_loop((uchar *)(*(long *)(opcode + 2)));
824     g3_end_object();
825 
826     return opcode + 20;
827 }
828 
do_icall_h(uchar * opcode)829 uchar *do_icall_h(uchar *opcode) {
830     FlipVector(1, (g3s_vector *)(opcode + 6));
831     FlipShort((short *)(opcode + 18));
832     FlipLong((long *)(opcode + 2));
833 
834     g3_start_object_angles_y((g3s_vector *)(opcode + 6), *(fixang *)(parm_data + (*(unsigned short *)(opcode + 18))));
835     interpreter_loop((uchar *)(*(long *)(opcode + 2)));
836     g3_end_object();
837 
838     return opcode + 20;
839 }
840 
do_icall_b(uchar * opcode)841 uchar *do_icall_b(uchar *opcode) {
842     FlipVector(1, (g3s_vector *)(opcode + 6));
843     FlipShort((short *)(opcode + 18));
844     FlipLong((long *)(opcode + 2));
845 
846     g3_start_object_angles_z((g3s_vector *)(opcode + 6), *(fixang *)(parm_data + (*(unsigned short *)(opcode + 18))));
847     interpreter_loop((uchar *)(*(long *)(opcode + 2)));
848     g3_end_object();
849 
850     return opcode + 20;
851 }
852 
do_sfcal(uchar * opcode)853 uchar *do_sfcal(uchar *opcode) {
854     FlipShort((short *)(opcode + 2));
855 
856     interpreter_loop(opcode + (*(unsigned short *)(opcode + 2)));
857     return opcode + 4;
858 }
859 
860 // copy parms of stack. takes offset,count
do_getparms(uchar * opcode)861 uchar *do_getparms(uchar *opcode) {
862     long *src, *dest;
863     int count;
864 
865     FlipShort((short *)(opcode + 2));
866     FlipShort((short *)(opcode + 4));
867     FlipShort((short *)(opcode + 6));
868 
869     dest = (long *)(parm_data + (*(unsigned short *)(opcode + 2)));
870     src = (long *)(parm_ptr + (*(unsigned short *)(opcode + 4)));
871     count = *(unsigned short *)(opcode + 6);
872     while (count-- > 0)
873         *(dest++) = *(src)++;
874 
875     return opcode + 8;
876 }
877 
878 // copy parm block. ptr is on stack. takes dest_ofs,src_ptr_ofs,size
do_getparms_i(uchar * opcode)879 uchar *do_getparms_i(uchar *opcode) {
880     long *src, *dest;
881     int count;
882 
883     FlipShort((short *)(opcode + 2));
884     FlipShort((short *)(opcode + 4));
885     FlipShort((short *)(opcode + 6));
886 
887     dest = *(long **)(parm_data + (*(unsigned short *)(opcode + 2)));
888     src = (long *)(parm_ptr + (*(unsigned short *)(opcode + 4)));
889     count = *(unsigned short *)(opcode + 6);
890     while (count-- > 0)
891         *(dest++) = *(src)++;
892 
893     return opcode + 8;
894 }
895 
do_dbg(uchar * opcode)896 uchar *do_dbg(uchar *opcode) {
897 // clang-format off
898 #ifdef  _itrp_dbg
899   mov     ax, w 4[ebp]    // code
900   and     ax, _itrp_dbg_mask // mask in current debug mode
901   jz      dbg_end         // none currently on
902   cmp     ax, DBG_POLY_ID // itrp_pcode
903   jnz     dbg_nxt1
904   mov     ax, w 6[ebp]    // pgon_id
905   cmp     ax,_pgon_id_low
906   jl      pgon_skip
907   cmp     ax,_pgon_id_high
908   jle     dbg_end
909 pgon_skip:
910   movsx	eax,w 2[ebp]    // skip whatever
911   next	eax
912 dbg_nxt1:
913   cmp     ax, DBG_POLY_MAX
914   jnz     dbg_end
915   mov     ax, w 6[ebp]
916   mov     _pgon_max, ax
917 //        jmp     dbg_end
918 #endif
919                                                                       // clang-format on
920                                                                       return opcode +
921                                                                       8;
922 }
923 
924 extern void (*g3_tmap_func)();
925 extern int temp_poly(long c, int n, grs_vertex **vpl);
926 
do_tmap_op(uchar * opcode)927 uchar *do_tmap_op(uchar *opcode) {
928     int count, count2;
929     short temp;
930 
931     FlipShort((short *)(opcode + 2));
932     FlipShort((short *)(opcode + 4));
933 
934     count2 = count = *(unsigned short *)(opcode + 4);
935     count--;
936     do {
937         FlipShort((short *)(opcode + 6 + (count << 1)));
938         temp = *(short *)(opcode + 6 + (count << 1));
939 
940         poly_buf[count] = resbuf[temp];
941     } while (--count >= 0);
942 
943     ((int (*)(int, g3s_phandle *, grs_bitmap *)) * g3_tmap_func)(count2, poly_buf,
944                                                                  _vtext_tab[*(unsigned short *)(opcode + 2)]);
945 
946     return opcode + 6 + (count2 * 2);
947 }
948 
949 // routines to shade objects
950 // mostly replacements for jnorm
951 // ljnorm lbl,px,py,pz,nx,ny,nz
952 // v=viewer coords-p
953 // if (n*v)<0 then branch to lbl
954 // does lit version of jnorm, for flat lighting
do_ljnorm(uchar * opcode)955 uchar *do_ljnorm(uchar *opcode) {
956     FlipShort((short *)(opcode + 2));
957     FlipVector(2, (g3s_vector *)(opcode + 4));
958 
959     if (g3_check_normal_facing((g3s_vector *)(opcode + 16), (g3s_vector *)(opcode + 4))) {
960         g3_light_obj((g3s_phandle)(opcode + 4), (g3s_phandle)(opcode + 16));
961         return opcode + 28;
962     } else
963         return opcode + (*(short *)(opcode + 2)); // surface not visible
964 }
965 
966 // light diff not near norm
do_ldjnorm(uchar * opcode)967 uchar *do_ldjnorm(uchar *opcode) {
968     fix temp;
969 
970     FlipShort((short *)(opcode + 2));
971     FlipVector(2, (g3s_vector *)(opcode + 4));
972 
973     if (g3_check_normal_facing((g3s_vector *)(opcode + 16), (g3s_vector *)(opcode + 4))) {
974         temp = g3_vec_dotprod(&_g3d_light_vec, (g3s_vector *)(opcode + 4));
975         temp <<= 1;
976         if (temp < 0)
977             temp = 0;
978         temp += _g3d_amb_light;
979         temp >>= 4;
980         temp &= 0x0ffffff00;
981         temp += _g3d_light_tab;
982         gr_set_fill_parm(temp);
983 
984         return opcode + 28;
985     } else
986         return opcode + (*(short *)(opcode + 2)); // surface not visible
987 }
988 
989 // MLA - this routine doesn't appear to ever be called anywhere
990 /*
991 // check if a surface is facing the viewer and save the view vector and
992 // its dot product with everything.  Normalizes view vec and stuff
993 // takes esi=point on surface, edi=surface normal (can be unnormalized)
994 // trashes eax,ebx,ecx,edx. returns al=true & sign set, if facing
995 g3_light_check_normal_facing:
996         call g3_eval_view
997         mov     eax,_g3d_view_vec.x
998         imul    [edi].x
999         mov     ebx,eax
1000         mov     ecx,edx
1001 
1002         mov     eax,_g3d_view_vec.y
1003         imul    [edi].y
1004         add     ebx,eax
1005         adc     ecx,edx
1006 
1007         mov     eax,_g3d_view_vec.z
1008         imul    [edi].z
1009         add     eax,ebx
1010         adc     edx,ecx
1011 
1012         // now save this to ldotv
1013 
1014         sets    al      // al=true if facing
1015 
1016         ret
1017 */
1018 
FlipShort(short * sh)1019 void FlipShort(short *sh) {
1020     /*uchar temp;
1021     uchar *src = (uchar *) sh;
1022 
1023     temp = src[0];
1024     src[0] = src[1];
1025     src[1] = temp;*/
1026 }
1027 
FlipLong(long * lng)1028 void FlipLong(long *lng) {
1029     /*short *src = (short *) lng;
1030     short	temp;
1031 
1032     temp = src[0];
1033     src[0] = src[1];
1034     src[1] = temp;
1035 
1036     FlipShort(src);
1037     FlipShort(src+1);*/
1038 }
1039 
FlipVector(short n,g3s_vector * vec)1040 void FlipVector(short n, g3s_vector *vec) {
1041     /*int		i,j;
1042 
1043     for (i=0; i<n; i++, vec++)
1044             for (j=0; j<3; j++)
1045                     FlipLong((long *) &vec->xyz[j]);*/
1046 }
1047