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