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