This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / 3d / interp.asm
1 ; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX\r
2 ; SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO\r
3 ; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A\r
4 ; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS\r
5 ; IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS\r
6 ; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE\r
7 ; FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE\r
8 ; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS\r
9 ; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  \r
10 ; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.\r
11 \r
12 \r
13 .386\r
14         option  oldstructs\r
15 \r
16         .nolist\r
17         include pstypes.inc\r
18         include psmacros.inc\r
19         include gr.inc\r
20         include 3d.inc\r
21         .list\r
22 \r
23         assume  cs:_TEXT, ds:_DATA\r
24 \r
25 _DATA   segment dword public USE32 'DATA'\r
26 \r
27 rcsid   db      "$Id: interp.asm,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"\r
28         align   4\r
29 \r
30 ;table with address for each opcode\r
31 opcode_table    dd      op_eof  ;0 = eof\r
32         dd      op_defpoints    ;1 = defpoints\r
33         dd      op_flatpoly     ;2 = flat-shaded polygon\r
34         dd      op_tmappoly     ;3 = texture-mapped polygon\r
35         dd      op_sortnorm     ;4 = sort by normal\r
36         dd      op_rodbm        ;5 = rod bitmap\r
37         dd      op_subcall      ;6 = call a subobject\r
38         dd      op_defp_start   ;7 = defpoints with start\r
39         dd      op_glow ;8 = glow value for next poly\r
40 n_opcodes = ($-opcode_table)/4\r
41 \r
42 bitmap_ptr      dd      ?\r
43 anim_angles     dd      ?       ;pointer to angle data\r
44 \r
45 morph_points    dd      ?       ;alternate points for morph\r
46 \r
47 ;light value for the next tmap\r
48 glow_num        dd      -1      ;-1 means off\r
49 glow_values     dd      ?       ;ptr to array of values\r
50 \r
51         public  _highest_texture_num\r
52 _highest_texture_num dw 0\r
53 \r
54 zero_angles     fixang  0,0,0   ;vms_angvec <0,0,0>     ;for if no angles specified\r
55 \r
56 rod_top_p       g3s_point <>\r
57 rod_bot_p       g3s_point <>\r
58 \r
59         public  g3d_interp_outline,_g3d_interp_outline\r
60 _g3d_interp_outline label       dword\r
61 g3d_interp_outline      dd      0\r
62 \r
63 morph_pointlist dd      ?,?,?\r
64 \r
65 morph_uvls      fix     3 dup (?,?,?)\r
66 \r
67 ;the light for the current model\r
68 model_light     fix     ?\r
69 \r
70 ;ptr to array of points\r
71 Interp_point_list       dd      ?\r
72 \r
73 MAX_POINTS_PER_POLY = 25\r
74 \r
75 point_list      dd      MAX_POINTS_PER_POLY dup (?)\r
76 \r
77 MAX_INTERP_COLORS = 100\r
78 \r
79 ;this is a table of mappings from RGB15 to palette colors\r
80 interp_color_table      dw      MAX_INTERP_COLORS dup (?,?)\r
81 \r
82 n_interp_colors dd      0\r
83 uninit_flag     dd      0\r
84 \r
85 \r
86 _DATA   ends\r
87 \r
88 \r
89 \r
90 _TEXT   segment dword public USE32 'CODE'\r
91 \r
92 ;get and jump to next opcode\r
93 next    macro\r
94         xor     ebx,ebx\r
95         mov     bx,[ebp]\r
96         ifndef  NDEBUG\r
97          cmp    ebx,n_opcodes\r
98          break_if       ge,'Invalid opcode'\r
99         endif\r
100         mov     ebx,opcode_table[ebx*4]\r
101         jmp     ebx\r
102         endm\r
103 \r
104 ;get and call the next opcode\r
105 call_next       macro   \r
106         xor     ebx,ebx\r
107         mov     bx,[ebp]\r
108         ifndef  NDEBUG\r
109          cmp    ebx,n_opcodes\r
110          break_if       ge,'Invalid opcode'\r
111         endif\r
112         mov     ebx,opcode_table[ebx*4]\r
113         call    ebx\r
114         endm\r
115 \r
116 ;give the interpreter an array of points to use\r
117 g3_set_interp_points:\r
118         mov     Interp_point_list,eax\r
119         ret\r
120 \r
121 ;interpreter to draw polygon model\r
122 ;takes esi=ptr to object, edi=ptr to array of bitmap pointers, \r
123 ;eax=ptr to anim angles, edx=light value, ebx=ptr to array of glow values\r
124 g3_draw_polygon_model:\r
125         pushm   eax,ebx,ecx,edx,esi,edi,ebp\r
126 \r
127         mov     ebp,esi ;ebp = interp ptr\r
128 \r
129         mov     bitmap_ptr,edi  ;save ptr to bitmap array\r
130         mov     anim_angles,eax\r
131         mov     model_light,edx\r
132         mov     glow_values,ebx\r
133 \r
134         mov     glow_num,-1\r
135 \r
136 ;;@@ mov depth,0\r
137 \r
138         call_next\r
139 \r
140         popm    eax,ebx,ecx,edx,esi,edi,ebp\r
141         ret\r
142 \r
143 ;handlers for opcodes\r
144 \r
145 ;end of a model or sub-rountine\r
146 op_eof: ret\r
147 \r
148 ;define a list of points\r
149 op_defpoints:   xor     ecx,ecx\r
150         mov     cx,2[ebp]       ;num points\r
151         mov     edi,Interp_point_list\r
152         lea     esi,4[ebp]\r
153 rotate_loop:    call    g3_rotate_point\r
154         add     edi,size g3s_point\r
155         add     esi,size vms_vector\r
156         dec     ecx\r
157         jnz     rotate_loop\r
158         mov     ebp,esi\r
159         next\r
160 \r
161 ;define a list of points, with starting point num specified\r
162 op_defp_start:  xor     ecx,ecx\r
163         xor     eax,eax\r
164         mov     ax,w 4[ebp]     ;starting point num\r
165         imulc   eax,size g3s_point      ;get ofs of point\r
166         add     eax,Interp_point_list\r
167         mov     edi,eax\r
168         mov     cx,2[ebp]       ;num points\r
169         lea     esi,8[ebp]\r
170         jmp     rotate_loop\r
171         next\r
172 \r
173 ;draw a flat-shaded polygon\r
174 op_flatpoly:    xor     ecx,ecx\r
175         mov     cx,2[ebp]       ;num verts\r
176         lea     esi,4[ebp]      ;point\r
177         lea     edi,16[ebp]     ;vector\r
178         call    g3_check_normal_facing\r
179         jng     flat_not_facing\r
180 \r
181 ;polygon is facing, so draw it\r
182 \r
183 ;here the glow parameter is used for the player's headlight\r
184         test    glow_num,-1     ;glow override?\r
185         js      no_glow2\r
186         mov     eax,glow_num\r
187         mov     esi,glow_values\r
188         mov     eax,[esi+eax*4]\r
189         mov     glow_num,-1\r
190         cmp     eax,-1  ;-1 means draw normal color\r
191         jne     not_normal_color\r
192 ;use the color specified, run through darkening table\r
193         xor     ebx,ebx\r
194         mov     eax,32  ;32 shades\r
195         imul    model_light\r
196         sar     eax,16\r
197         or      eax,eax\r
198         jns     no_sat1\r
199         xor     eax,eax\r
200 no_sat1:        cmp     eax,32\r
201         jl      no_sat2\r
202         mov     eax,32\r
203 no_sat2:        mov     bh,al   ;get lighting table\r
204         xor     eax,eax\r
205         mov     ax,28[ebp]                      ;get color index\r
206         mov     ax,interp_color_table[eax*4]\r
207         mov     bl,al\r
208         mov     al,gr_fade_table[ebx]\r
209         jmp     got_color_index\r
210 not_normal_color:       cmp     eax,-2  ;-2 means use white\r
211         jne     not_white\r
212         mov     eax,255 ;hack!\r
213         jmp     got_color_index\r
214 not_white:      cmp     eax,-3  ;-3 means don't draw polygon\r
215         je      flat_not_facing\r
216 no_glow2:\r
217 \r
218         xor     eax,eax\r
219         mov     ax,28[ebp]                      ;get color index\r
220         mov     ax,interp_color_table[eax*4]\r
221 got_color_index:        call    gr_setcolor_                    ;set it\r
222 \r
223         lea     esi,30[ebp]     ;point number list\r
224 \r
225         ;make list of point pointers\r
226 \r
227         ifndef  NDEBUG\r
228          cmp    ecx,MAX_POINTS_PER_POLY\r
229          break_if       ge,'Too many points in interp poly'\r
230         endif\r
231 \r
232         lea     edi,point_list\r
233         xor     ebx,ebx\r
234 copy_loop:      xor     eax,eax\r
235         mov     ax,w [esi+ebx*2]        ;get point number\r
236         imulc   eax,size g3s_point\r
237         add     eax,Interp_point_list\r
238         mov     [edi+ebx*4],eax\r
239         inc     ebx\r
240         cmp     ebx,ecx\r
241         jne     copy_loop\r
242         mov     esi,edi\r
243 \r
244         call    g3_draw_poly\r
245         xor     ecx,ecx\r
246         mov     cx,2[ebp]       ;restore count\r
247 \r
248         ifndef  NDEBUG\r
249         test    g3d_interp_outline,-1\r
250         jz      no_outline\r
251         pushm   ecx,esi\r
252         lea     esi,30[ebp]\r
253         call    draw_outline\r
254         popm    ecx,esi\r
255 no_outline:\r
256         endif   \r
257 \r
258 ;polygon is not facing (or we've plotted it). jump to next opcode\r
259 flat_not_facing:        and     ecx,0fffffffeh\r
260         inc     ecx     ;adjust for pad\r
261         lea     ebp,30[ebp+ecx*2]\r
262         next\r
263 \r
264 ;set the glow value for the next tmap\r
265 op_glow:        test    glow_values,-1\r
266         jz      skip_glow\r
267         xor     eax,eax\r
268         mov     ax,2[ebp]\r
269         mov     glow_num,eax\r
270 skip_glow:      add     ebp,4\r
271         next\r
272 \r
273 \r
274 ;draw a texture map\r
275 op_tmappoly:    xor     ecx,ecx\r
276         mov     cx,2[ebp]       ;num verts\r
277         lea     esi,4[ebp]      ;point\r
278         lea     edi,16[ebp]     ;normal\r
279         call    g3_check_normal_facing\r
280         jng     tmap_not_facing\r
281 \r
282 ;polygon is facing, so draw it\r
283 \r
284         xor     edx,edx\r
285         mov     dx,28[ebp]      ;get bitmap number\r
286         mov     eax,bitmap_ptr\r
287         mov     edx,[eax+edx*4]\r
288 \r
289         lea     esi,30[ebp]     ;point number list\r
290         mov     eax,ecx\r
291         and     eax,0fffffffeh\r
292         inc     eax\r
293         lea     ebx,30[ebp+eax*2]       ;get uvl list\r
294 \r
295 ;calculate light from surface normal\r
296         push    esi\r
297 \r
298         test    glow_num,-1     ;glow override?\r
299         js      no_glow\r
300 ;special glow lighting, which doesn't care about surface normal\r
301         mov     eax,glow_num\r
302         mov     esi,glow_values\r
303         mov     eax,[esi+eax*4]\r
304         mov     glow_num,-1\r
305         jmp     got_light_value\r
306 no_glow:\r
307         lea     esi,View_matrix.fvec\r
308         lea     edi,16[ebp]     ;normal\r
309         call    vm_vec_dotprod\r
310         neg     eax\r
311 ;scale light by model light\r
312         push    edx\r
313         mov     edx,eax\r
314         add     eax,eax\r
315         add     eax,edx ;eax *= 3\r
316         sar     eax,2   ;eax *= 3/4\r
317         add     eax,f1_0/4      ;eax = 1/4 + eax * 3/4\r
318         fixmul  model_light\r
319         pop     edx\r
320 ;now poke light into l values\r
321 got_light_value:        pushm   ecx,ebx\r
322 l_loop: mov     8[ebx],eax\r
323         add     ebx,12\r
324         dec     ecx\r
325         jnz     l_loop\r
326         popm    ecx,ebx\r
327         pop     esi\r
328 \r
329 ;now draw it\r
330         ;make list of point pointers\r
331 \r
332         ifndef  NDEBUG\r
333          cmp    ecx,MAX_POINTS_PER_POLY\r
334          break_if       ge,'Too many points in interp poly'\r
335         endif\r
336 \r
337         push    ebx\r
338         lea     edi,point_list\r
339         xor     ebx,ebx\r
340 copy_loop2:     xor     eax,eax\r
341         mov     ax,w [esi+ebx*2]        ;get point number\r
342         imulc   eax,size g3s_point\r
343         add     eax,Interp_point_list\r
344         mov     [edi+ebx*4],eax\r
345         inc     ebx\r
346         cmp     ebx,ecx\r
347         jne     copy_loop2\r
348         mov     esi,edi\r
349         pop     ebx\r
350 \r
351         call    g3_draw_tmap\r
352         xor     ecx,ecx\r
353         mov     cx,2[ebp]       ;restore count\r
354 \r
355         ifndef  NDEBUG\r
356         test    g3d_interp_outline,-1\r
357         jz      no_outline2\r
358         pushm   ecx,esi\r
359         lea     esi,30[ebp]\r
360         call    draw_outline\r
361         popm    ecx,esi\r
362 no_outline2:\r
363         endif   \r
364 \r
365 ;polygon is not facing (or we've plotted it). jump to next opcode\r
366 tmap_not_facing:        mov     ebx,ecx\r
367         and     ebx,0fffffffeh\r
368         inc     ebx     ;adjust for pad\r
369         lea     ebp,30[ebp+ebx*2]\r
370 \r
371         mov     eax,ecx\r
372         sal     ecx,1\r
373         add     ecx,eax\r
374         sal     ecx,2   ;ecx=ecx*12\r
375         add     ebp,ecx ;point past uvls\r
376 \r
377         next\r
378 \r
379 ;sort based on surface normal\r
380 op_sortnorm:    lea     esi,16[ebp]     ;point\r
381         lea     edi,4[ebp]      ;vector\r
382         call    g3_check_normal_facing\r
383         jng     sortnorm_not_facing\r
384 \r
385 ;is facing.  draw back then front\r
386 \r
387         push    ebp\r
388         xor     eax,eax\r
389         mov     ax,30[ebp]      ;get back offset\r
390         add     ebp,eax\r
391         call_next\r
392         mov     ebp,[esp]       ;get ebp\r
393         xor     eax,eax\r
394         mov     ax,28[ebp]      ;get front offset\r
395         add     ebp,eax\r
396         call_next\r
397         pop     ebp\r
398 \r
399         lea     ebp,32[ebp]\r
400         next\r
401 \r
402 ;is not facing.  draw front then back\r
403 \r
404 sortnorm_not_facing:\r
405         push    ebp\r
406         xor     eax,eax\r
407         mov     ax,28[ebp]      ;get back offset\r
408         add     ebp,eax\r
409         call_next\r
410         mov     ebp,[esp]       ;get ebp\r
411         xor     eax,eax\r
412         mov     ax,30[ebp]      ;get front offset\r
413         add     ebp,eax\r
414         call_next\r
415         pop     ebp\r
416 \r
417         lea     ebp,32[ebp]\r
418         next\r
419 \r
420 ;draw a rod bitmap \r
421 op_rodbm:       lea     esi,20[ebp]     ;bot point\r
422         lea     edi,rod_bot_p\r
423         call    g3_rotate_point\r
424 \r
425         lea     esi,4[ebp]      ;top point\r
426         lea     edi,rod_top_p\r
427         call    g3_rotate_point\r
428 \r
429         lea     esi,rod_bot_p   ;esi=bot, edi=top\r
430         mov     eax,16[ebp]     ;bot width\r
431         mov     edx,32[ebp]     ;top width\r
432 \r
433         xor     ebx,ebx\r
434         mov     bx,2[ebp]       ;get bitmap number\r
435         mov     ecx,bitmap_ptr\r
436         mov     ebx,[ecx+ebx*4]\r
437 \r
438         call    g3_draw_rod_tmap\r
439 \r
440         lea     ebp,36[ebp]\r
441         next\r
442 \r
443 \r
444 ;draw a subobject\r
445 op_subcall:     xor     eax,eax\r
446         mov     ax,2[ebp]       ;get object number\r
447 \r
448 ;get ptr to angles\r
449         mov     edi,anim_angles\r
450         or      edi,edi\r
451         jnz     angles_not_null\r
452 ;angles not specified.  Use zero angles\r
453         lea     edi,zero_angles\r
454         jmp     got_angles\r
455 angles_not_null:\r
456         imulc   eax,size vms_angvec\r
457         add     edi,eax\r
458 got_angles:\r
459         ;angles in edi\r
460 \r
461         lea     esi,4[ebp]      ;get position\r
462         call    g3_start_instance_angles\r
463 \r
464         push    ebp\r
465         xor     eax,eax\r
466         mov     ax,16[ebp]\r
467         add     ebp,eax ;offset of subobject\r
468         call_next               ;draw the subobject\r
469         pop     ebp\r
470 \r
471         call    g3_done_instance\r
472 \r
473         lea     ebp,20[ebp]\r
474         next\r
475 \r
476 ;takes ax, returns ax\r
477 find_color_index:       push    ebx\r
478 \r
479         ;first, see if color already in table\r
480 \r
481         xor     ebx,ebx ;counter\r
482 look_loop:      cmp     ebx,n_interp_colors\r
483         je      must_add_color\r
484         cmp     ax,interp_color_table+2[ebx*4]\r
485         je      found_color\r
486         inc     ebx\r
487         jmp     look_loop\r
488 \r
489 must_add_color: mov     interp_color_table+2[ebx*4],ax  ;save rgb15\r
490         call    gr_find_closest_color_15bpp_\r
491         mov     interp_color_table[ebx*4],ax            ;save pal entry\r
492         inc     n_interp_colors\r
493 \r
494 found_color:    mov     eax,ebx ;return index\r
495         pop     ebx\r
496         ret\r
497 \r
498 ;this remaps the 15bpp colors for the models into a new palette.  It should\r
499 ;be called whenever the palette changes\r
500 g3_remap_interp_colors:\r
501         pushm   eax,ebx\r
502 \r
503         xor     ebx,ebx ;index\r
504 remap_loop:     cmp     ebx,n_interp_colors\r
505         je      done_remap\r
506 \r
507         xor     eax,eax\r
508         mov     ax,interp_color_table+2[ebx*4]  ;get rgb15\r
509         call    gr_find_closest_color_15bpp_\r
510         mov     interp_color_table[ebx*4],ax            ;store pal entry \r
511 \r
512         inc     ebx\r
513         jmp     remap_loop\r
514 \r
515 done_remap:     popm    eax,ebx\r
516         ret\r
517 \r
518 \r
519 ;maps the colors back to RGB15\r
520 g3_uninit_polygon_model:\r
521         mov     uninit_flag,1\r
522 \r
523 ;initialize a polygon object\r
524 ;translate colors, scale UV values\r
525 ;takes esi=ptr to model\r
526 g3_init_polygon_model:\r
527         mov     _highest_texture_num,-1\r
528 \r
529         pushm   eax,ebx,ecx,edx,esi,edi\r
530         call    init_loop\r
531         popm    eax,ebx,ecx,edx,esi,edi\r
532 \r
533         mov     uninit_flag,0\r
534         ret\r
535 \r
536 \r
537 init_loop:      mov     ax,[esi]        ;get opcode\r
538         cmp     ax,0    ;eof\r
539         jne     not_eof\r
540         ret\r
541 not_eof:\r
542 \r
543 ;defpoints\r
544         cmp     ax,1    ;defpoints\r
545         jne     not_defpoints\r
546         xor     eax,eax\r
547         mov     ax,2[esi]       ;get count\r
548         sal     eax,1\r
549         add     ax,2[esi]       ;*3\r
550         lea     esi,4[esi+eax*4]\r
551         jmp     init_loop\r
552 not_defpoints:\r
553 \r
554 ;flat polygon\r
555         cmp     ax,2\r
556         jne     not_flatpoly\r
557         ifndef  NDEBUG\r
558         cmp     w 2[esi],3\r
559         break_if        l,'face must have 3 or more points'\r
560         endif\r
561         ; The following 3 lines replace the above\r
562         xor     eax, eax\r
563         mov     ax,28[esi]              ;get color\r
564         test    uninit_flag,-1\r
565         jz      not_uninit\r
566 ;unitialize!\r
567         mov     ax,interp_color_table+2[eax*4]\r
568         jmp     cont1\r
569 not_uninit:\r
570         call    find_color_index\r
571 cont1:  mov     28[esi],ax              ;store new color\r
572 \r
573         xor     ecx,ecx\r
574         mov     cx,2[esi]       ;get nverts\r
575         and     ecx,0fffffffeh\r
576         inc     ecx     ;adjust for pad\r
577         lea     esi,30[esi+ecx*2]\r
578         jmp     init_loop\r
579 not_flatpoly:\r
580 \r
581 ;tmap polygon\r
582         cmp     ax,3\r
583         jne     not_tmappoly\r
584         ifndef  NDEBUG\r
585         cmp     w 2[esi],3\r
586         break_if        l,'face must have 3 or more points'\r
587         endif\r
588         mov     ax,28[esi]      ;get bitmap number\r
589         cmp     ax,_highest_texture_num\r
590         jle     not_new\r
591         mov     _highest_texture_num,ax\r
592 not_new:        xor     ecx,ecx\r
593         mov     cx,2[esi]       ;get nverts\r
594         mov     ebx,ecx\r
595         and     ebx,0fffffffeh\r
596         inc     ebx     ;adjust for pad\r
597         lea     esi,30[esi+ebx*2]       ;point at uvls\r
598 \r
599         imul    ecx,12  ;size of uvls\r
600         add     esi,ecx ;skip them\r
601         jmp     init_loop\r
602 \r
603 ;;@@init_uv_loop:       mov     eax,[esi]       ;get u\r
604 ;;@@    imul    eax,64  ;times bitmap w\r
605 ;;@@    mov     [esi],eax\r
606 ;;@@    mov     eax,4[esi]      ;get v\r
607 ;;@@    imul    eax,64  ;times bitmap h\r
608 ;;@@    mov     4[esi],eax\r
609 ;;@@    add     esi,12  ;point at next\r
610 ;;@@    dec     ecx\r
611 ;;@@    jnz     init_uv_loop\r
612 ;;@@    jmp     init_loop\r
613 not_tmappoly:\r
614 \r
615 ;sort\r
616         cmp     ax,4    ;sortnorm\r
617         jne     not_sortnorm\r
618 \r
619         push    esi\r
620         xor     eax,eax\r
621         mov     ax,28[esi]      ;get front offset\r
622         add     esi,eax\r
623         call    init_loop\r
624         mov     esi,[esp]\r
625         xor     eax,eax\r
626         mov     ax,30[esi]      ;get front offset\r
627         add     esi,eax\r
628         call    init_loop\r
629         pop     esi\r
630         lea     esi,32[esi]\r
631 \r
632         jmp     init_loop\r
633 not_sortnorm:\r
634         cmp     ax,5\r
635         jne     not_rodbm\r
636 \r
637         add     esi,36\r
638         jmp     init_loop\r
639 \r
640 not_rodbm:\r
641         cmp     ax,6\r
642         jne     not_subcall\r
643 \r
644 \r
645         push    esi\r
646         xor     eax,eax\r
647         mov     ax,16[esi]      ;get subobj offset\r
648         add     esi,eax\r
649         call    init_loop\r
650         pop     esi\r
651 \r
652         add     esi,20\r
653         jmp     init_loop\r
654 not_subcall:\r
655         cmp     ax,7    ;defpoints\r
656         jne     not_defpoints_st\r
657         xor     eax,eax\r
658         mov     ax,2[esi]       ;get count\r
659         sal     eax,1\r
660         add     ax,2[esi]       ;*3\r
661         lea     esi,8[esi+eax*4]\r
662         jmp     init_loop\r
663 not_defpoints_st:\r
664         cmp     ax,8\r
665         jne     not_glow\r
666         add     esi,4\r
667         jmp     init_loop\r
668 not_glow:\r
669 \r
670         debug_brk       "Invalid opcode"\r
671 \r
672         jmp     init_loop\r
673 \r
674 \r
675 ;takes ecx=count, esi=ptr to point list\r
676 draw_outline:   pushm   eax,ebx,ecx,edx,esi,edi\r
677 \r
678         ;NO_INVERSE_TABLE xor   eax,eax\r
679         ;NO_INVERSE_TABLE mov   al,gr_inverse_table[7fffh]      ;white \r
680         mov     eax, 255        ; bright white\r
681         call    gr_setcolor_\r
682 \r
683         mov     ebx,esi\r
684 \r
685         xor     eax,eax\r
686         mov     ax,[ebx]        ;get first point\r
687         push    eax     ;save it\r
688 \r
689 outline_loop:   xor     esi,esi\r
690         xor     edi,edi\r
691         mov     si,[ebx]\r
692         dec     ecx\r
693         jz      done_loop\r
694         mov     di,2[ebx]\r
695         push    ebx\r
696 \r
697         imul    esi,size g3s_point\r
698         add     esi,Interp_point_list\r
699         imul    edi,size g3s_point\r
700         add     edi,Interp_point_list\r
701 \r
702         call    g3_draw_line\r
703         pop     ebx\r
704 \r
705         add     ebx,2\r
706         jmp     outline_loop\r
707 \r
708 done_loop:      pop     edi     ;get first point back\r
709 \r
710         imul    esi,size g3s_point\r
711         add     esi,Interp_point_list\r
712         imul    edi,size g3s_point\r
713         add     edi,Interp_point_list\r
714 \r
715         call    g3_draw_line\r
716 \r
717         popm    eax,ebx,ecx,edx,esi,edi\r
718         ret\r
719 \r
720 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
721 \r
722 ;Special code to draw morphing objects\r
723 \r
724 ;define a list of points\r
725 morph_defpoints:        xor     ecx,ecx\r
726         mov     cx,2[ebp]       ;num points\r
727         mov     edi,Interp_point_list\r
728         lea     esi,4[ebp]\r
729 morph_rotate_list:      lea     eax,[ecx*2+ecx] ;eax=npoint * 3\r
730         lea     esi,[esi+eax*4] ;point past points\r
731         push    esi\r
732         mov     esi,morph_points        ;get alternate points\r
733 morph_rotate_loop:      call    g3_rotate_point\r
734         add     edi,size g3s_point\r
735         add     esi,size vms_vector\r
736         dec     ecx\r
737         jnz     morph_rotate_loop\r
738         pop     esi     ;restore pointer\r
739         mov     ebp,esi\r
740         next\r
741 \r
742 ;define a list of points, with starting point num specified\r
743 morph_defp_start:       xor     ecx,ecx\r
744         xor     eax,eax\r
745         mov     ax,w 4[ebp]     ;starting point num\r
746         imulc   eax,size g3s_point      ;get ofs of point\r
747         add     eax,Interp_point_list\r
748         mov     edi,eax\r
749         mov     cx,2[ebp]       ;num points\r
750         lea     esi,8[ebp]\r
751         jmp     morph_rotate_list\r
752 \r
753 ;draw a flat-shaded polygon\r
754 morph_flatpoly: xor     ecx,ecx\r
755         mov     cx,2[ebp]       ;num verts\r
756         lea     esi,4[ebp]      ;point\r
757         lea     edi,16[ebp]     ;vector\r
758 \r
759 ;set color\r
760         xor     eax,eax\r
761         mov     ax,28[ebp]                      ;get color\r
762         mov     ax,interp_color_table[eax*4]\r
763         call    gr_setcolor_                    ;set it\r
764 \r
765 ;check and draw\r
766         lea     esi,30[ebp]     ;point number list\r
767 \r
768         xor     eax,eax\r
769         lodsw\r
770         imulc   eax,size g3s_point\r
771         add     eax,Interp_point_list\r
772         mov     morph_pointlist,eax\r
773         xor     eax,eax\r
774         lodsw\r
775         imulc   eax,size g3s_point\r
776         add     eax,Interp_point_list\r
777         mov     morph_pointlist+4,eax\r
778         xor     eax,eax\r
779         lodsw\r
780         imulc   eax,size g3s_point\r
781         add     eax,Interp_point_list\r
782         mov     morph_pointlist+8,eax\r
783 \r
784         cmp     ecx,3   ;3 points is good!\r
785         je      flat_got3\r
786         sub     ecx,2   ;tri count\r
787 \r
788 flat_tri_loop:  xor     edi,edi ;no normal, must compute\r
789         pushm   ecx,esi\r
790         mov     ecx,3   ;always draw triangle\r
791         lea     esi,morph_pointlist\r
792         call    g3_check_and_draw_poly\r
793         popm    ecx,esi\r
794 \r
795         mov     eax,morph_pointlist+8\r
796         mov     morph_pointlist+4,eax\r
797         xor     eax,eax\r
798         lodsw\r
799         imulc   eax,size g3s_point\r
800         add     eax,Interp_point_list\r
801         mov     morph_pointlist+8,eax\r
802 \r
803         dec     ecx\r
804         jnz     flat_tri_loop\r
805         jmp     flat_done_draw\r
806         \r
807 flat_got3:\r
808         lea     esi,morph_pointlist\r
809         xor     edi,edi ;no normal, must compute\r
810         call    g3_check_and_draw_poly\r
811 \r
812 flat_done_draw: xor     ecx,ecx\r
813         mov     cx,2[ebp]       ;restore count\r
814 \r
815         and     ecx,0fffffffeh\r
816         inc     ecx     ;adjust for pad\r
817         lea     ebp,30[ebp+ecx*2]\r
818         next\r
819 \r
820 ;draw a texture map\r
821 morph_tmappoly: xor     ecx,ecx\r
822         mov     cx,2[ebp]       ;num verts\r
823         lea     esi,4[ebp]      ;point\r
824         lea     edi,16[ebp]     ;normal\r
825 \r
826 ;get bitmap\r
827         xor     edx,edx\r
828         mov     dx,28[ebp]      ;get bitmap number\r
829         mov     eax,bitmap_ptr\r
830         mov     edx,[eax+edx*4]\r
831 \r
832         lea     esi,30[ebp]     ;point number list\r
833         mov     eax,ecx\r
834         and     eax,0fffffffeh\r
835         inc     eax\r
836         lea     ebx,30[ebp+eax*2]       ;get uvl list\r
837 ;calculate light from surface normal\r
838         push    esi\r
839         lea     esi,View_matrix.fvec\r
840         lea     edi,16[ebp]     ;normal\r
841         call    vm_vec_dotprod\r
842         neg     eax\r
843 ;scale light by model light\r
844         push    edx\r
845         mov     edx,eax\r
846         add     eax,eax\r
847         add     eax,edx ;eax *= 3\r
848         sar     eax,2   ;eax *= 3/4\r
849         add     eax,f1_0/4      ;eax = 1/4 + eax * 3/4\r
850         fixmul  model_light\r
851 \r
852         or      eax,eax\r
853         jge     not_zero\r
854         xor     eax,eax\r
855 not_zero:\r
856         pop     edx\r
857         pop     esi\r
858 \r
859 ;now eax=plane light value\r
860 \r
861         mov     morph_uvls+8,eax\r
862         mov     morph_uvls+20,eax\r
863         mov     morph_uvls+32,eax\r
864 \r
865         xor     eax,eax\r
866         lodsw\r
867         imulc   eax,size g3s_point\r
868         add     eax,Interp_point_list\r
869         mov     morph_pointlist,eax\r
870         xor     eax,eax\r
871         lodsw\r
872         imulc   eax,size g3s_point\r
873         add     eax,Interp_point_list\r
874         mov     morph_pointlist+4,eax\r
875         xor     eax,eax\r
876         lodsw\r
877         imulc   eax,size g3s_point\r
878         add     eax,Interp_point_list\r
879         mov     morph_pointlist+8,eax\r
880 \r
881         cmp     ecx,3   ;3 points is good!\r
882         jl      tmap_done_draw  ;something is bad, abort\r
883         je      tmap_got3\r
884         sub     ecx,2   ;tri count\r
885 \r
886         push    edx\r
887 \r
888         mov     edx,[ebx]\r
889         mov     morph_uvls,edx\r
890         mov     edx,4[ebx]\r
891         mov     morph_uvls+4,edx\r
892 \r
893         mov     edx,12[ebx]\r
894         mov     morph_uvls+12,edx\r
895         mov     edx,16[ebx]\r
896         mov     morph_uvls+16,edx\r
897 \r
898         mov     edx,24[ebx]\r
899         mov     morph_uvls+24,edx\r
900         mov     edx,28[ebx]\r
901         mov     morph_uvls+28,edx\r
902 \r
903         add     ebx,3*12\r
904 \r
905         pop     edx\r
906 \r
907 \r
908 tmap_tri_loop:  xor     edi,edi ;no normal, must compute\r
909         pushm   ebx,edx,ecx,esi\r
910         mov     ecx,3   ;always draw triangle\r
911         lea     esi,morph_pointlist\r
912         lea     ebx,morph_uvls\r
913         call    g3_check_and_draw_tmap\r
914         popm    ebx,edx,ecx,esi\r
915 \r
916         mov     eax,morph_pointlist+8\r
917         mov     morph_pointlist+4,eax\r
918         xor     eax,eax\r
919         lodsw\r
920         imulc   eax,size g3s_point\r
921         add     eax,Interp_point_list\r
922         mov     morph_pointlist+8,eax\r
923 \r
924         push    edx\r
925         mov     edx,morph_uvls+24\r
926         mov     morph_uvls+12,edx\r
927         mov     edx,morph_uvls+28\r
928         mov     morph_uvls+16,edx\r
929 \r
930         mov     edx,[ebx]\r
931         mov     morph_uvls+24,edx\r
932         mov     edx,4[ebx]\r
933         mov     morph_uvls+28,edx\r
934         add     ebx,12\r
935         pop     edx\r
936 \r
937         dec     ecx\r
938         jnz     tmap_tri_loop\r
939         jmp     tmap_done_draw\r
940         \r
941 tmap_got3:\r
942 ;poke in light values\r
943         pusha\r
944 tmap_l_loop:    mov     8[ebx],eax\r
945         add     ebx,12\r
946         dec     ecx\r
947         jnz     tmap_l_loop\r
948         popa\r
949 \r
950         lea     esi,morph_pointlist\r
951 \r
952         xor     edi,edi ;no normal\r
953         call    g3_check_and_draw_tmap\r
954 \r
955 tmap_done_draw: xor     ecx,ecx\r
956         mov     cx,2[ebp]       ;restore count\r
957 \r
958 ;jump to next opcode\r
959         mov     ebx,ecx\r
960         and     ebx,0fffffffeh\r
961         inc     ebx     ;adjust for pad\r
962         lea     ebp,30[ebp+ebx*2]\r
963 \r
964         mov     eax,ecx\r
965         sal     ecx,1\r
966         add     ecx,eax\r
967         sal     ecx,2   ;ecx=ecx*12\r
968         add     ebp,ecx ;point past uvls\r
969 \r
970         next\r
971 \r
972 \r
973 ;interpreter to draw polygon model\r
974 ;takes esi=ptr to object, edi=ptr to array of bitmap pointers, \r
975 ;eax=ptr to anim angles, ebx=alternate points, edx=light value\r
976 \r
977 g3_draw_morphing_model:\r
978         pushm   eax,ebx,ecx,edx,esi,edi,ebp\r
979 \r
980         mov     bitmap_ptr,edi  ;save ptr to bitmap array\r
981         mov     anim_angles,eax\r
982         mov     morph_points,ebx\r
983         mov     model_light,edx\r
984 \r
985         mov     ebp,esi ;ebp = interp ptr\r
986 \r
987         ;set alternate opcode pointers\r
988 \r
989         push    opcode_table[1*4]       ;defpoints\r
990         push    opcode_table[2*4]       ;flatpoly\r
991         push    opcode_table[3*4]       ;tmappoly\r
992         push    opcode_table[7*4]       ;defp_start\r
993 \r
994         mov     opcode_table[1*4],offset morph_defpoints\r
995         mov     opcode_table[2*4],offset morph_flatpoly\r
996         mov     opcode_table[3*4],offset morph_tmappoly\r
997         mov     opcode_table[7*4],offset morph_defp_start\r
998 \r
999         call_next\r
1000 \r
1001         pop     opcode_table[7*4]       ;defp_start\r
1002         pop     opcode_table[3*4]       ;tmappoly\r
1003         pop     opcode_table[2*4]       ;flatpoly\r
1004         pop     opcode_table[1*4]       ;defpoints\r
1005 \r
1006         popm    eax,ebx,ecx,edx,esi,edi,ebp\r
1007         ret\r
1008 \r
1009 _TEXT   ends\r
1010 \r
1011         end\r
1012 \r