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