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
18 include psmacros.inc
\r
23 assume cs:_TEXT, ds:_DATA
\r
25 _DATA segment dword public USE32 'DATA'
\r
27 rcsid db "$Id: interp.asm,v 1.1.1.1 2001-01-19 03:29:58 bradleyb Exp $"
\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
43 anim_angles dd ? ;pointer to angle data
\r
45 morph_points dd ? ;alternate points for morph
\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
51 public _highest_texture_num
\r
52 _highest_texture_num dw 0
\r
54 zero_angles fixang 0,0,0 ;vms_angvec <0,0,0> ;for if no angles specified
\r
56 rod_top_p g3s_point <>
\r
57 rod_bot_p g3s_point <>
\r
59 public g3d_interp_outline,_g3d_interp_outline
\r
60 _g3d_interp_outline label dword
\r
61 g3d_interp_outline dd 0
\r
63 morph_pointlist dd ?,?,?
\r
65 morph_uvls fix 3 dup (?,?,?)
\r
67 ;the light for the current model
\r
70 ;ptr to array of points
\r
71 Interp_point_list dd ?
\r
73 MAX_POINTS_PER_POLY = 25
\r
75 point_list dd MAX_POINTS_PER_POLY dup (?)
\r
77 MAX_INTERP_COLORS = 100
\r
79 ;this is a table of mappings from RGB15 to palette colors
\r
80 interp_color_table dw MAX_INTERP_COLORS dup (?,?)
\r
82 n_interp_colors dd 0
\r
90 _TEXT segment dword public USE32 'CODE'
\r
92 ;get and jump to next opcode
\r
98 break_if ge,'Invalid opcode'
\r
100 mov ebx,opcode_table[ebx*4]
\r
104 ;get and call the next opcode
\r
110 break_if ge,'Invalid opcode'
\r
112 mov ebx,opcode_table[ebx*4]
\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
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
127 mov ebp,esi ;ebp = interp ptr
\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
140 popm eax,ebx,ecx,edx,esi,edi,ebp
\r
143 ;handlers for opcodes
\r
145 ;end of a model or sub-rountine
\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
153 rotate_loop: call g3_rotate_point
\r
154 add edi,size g3s_point
\r
155 add esi,size vms_vector
\r
161 ;define a list of points, with starting point num specified
\r
162 op_defp_start: xor ecx,ecx
\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
168 mov cx,2[ebp] ;num points
\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
181 ;polygon is facing, so draw it
\r
183 ;here the glow parameter is used for the player's headlight
\r
184 test glow_num,-1 ;glow override?
\r
187 mov esi,glow_values
\r
188 mov eax,[esi+eax*4]
\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
194 mov eax,32 ;32 shades
\r
200 no_sat1: cmp eax,32
\r
203 no_sat2: mov bh,al ;get lighting table
\r
205 mov ax,28[ebp] ;get color index
\r
206 mov ax,interp_color_table[eax*4]
\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
213 jmp got_color_index
\r
214 not_white: cmp eax,-3 ;-3 means don't draw polygon
\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
223 lea esi,30[ebp] ;point number list
\r
225 ;make list of point pointers
\r
228 cmp ecx,MAX_POINTS_PER_POLY
\r
229 break_if ge,'Too many points in interp poly'
\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
246 mov cx,2[ebp] ;restore count
\r
249 test g3d_interp_outline,-1
\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
264 ;set the glow value for the next tmap
\r
265 op_glow: test glow_values,-1
\r
270 skip_glow: add ebp,4
\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
282 ;polygon is facing, so draw it
\r
285 mov dx,28[ebp] ;get bitmap number
\r
287 mov edx,[eax+edx*4]
\r
289 lea esi,30[ebp] ;point number list
\r
293 lea ebx,30[ebp+eax*2] ;get uvl list
\r
295 ;calculate light from surface normal
\r
298 test glow_num,-1 ;glow override?
\r
300 ;special glow lighting, which doesn't care about surface normal
\r
302 mov esi,glow_values
\r
303 mov eax,[esi+eax*4]
\r
305 jmp got_light_value
\r
307 lea esi,View_matrix.fvec
\r
308 lea edi,16[ebp] ;normal
\r
309 call vm_vec_dotprod
\r
311 ;scale light by model light
\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
320 ;now poke light into l values
\r
321 got_light_value: pushm ecx,ebx
\r
322 l_loop: mov 8[ebx],eax
\r
330 ;make list of point pointers
\r
333 cmp ecx,MAX_POINTS_PER_POLY
\r
334 break_if ge,'Too many points in interp poly'
\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
353 mov cx,2[ebp] ;restore count
\r
356 test g3d_interp_outline,-1
\r
365 ;polygon is not facing (or we've plotted it). jump to next opcode
\r
366 tmap_not_facing: mov ebx,ecx
\r
368 inc ebx ;adjust for pad
\r
369 lea ebp,30[ebp+ebx*2]
\r
374 sal ecx,2 ;ecx=ecx*12
\r
375 add ebp,ecx ;point past uvls
\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
385 ;is facing. draw back then front
\r
389 mov ax,30[ebp] ;get back offset
\r
392 mov ebp,[esp] ;get ebp
\r
394 mov ax,28[ebp] ;get front offset
\r
402 ;is not facing. draw front then back
\r
404 sortnorm_not_facing:
\r
407 mov ax,28[ebp] ;get back offset
\r
410 mov ebp,[esp] ;get ebp
\r
412 mov ax,30[ebp] ;get front offset
\r
420 ;draw a rod bitmap
\r
421 op_rodbm: lea esi,20[ebp] ;bot point
\r
423 call g3_rotate_point
\r
425 lea esi,4[ebp] ;top point
\r
427 call g3_rotate_point
\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
434 mov bx,2[ebp] ;get bitmap number
\r
436 mov ebx,[ecx+ebx*4]
\r
438 call g3_draw_rod_tmap
\r
445 op_subcall: xor eax,eax
\r
446 mov ax,2[ebp] ;get object number
\r
449 mov edi,anim_angles
\r
451 jnz angles_not_null
\r
452 ;angles not specified. Use zero angles
\r
453 lea edi,zero_angles
\r
456 imulc eax,size vms_angvec
\r
461 lea esi,4[ebp] ;get position
\r
462 call g3_start_instance_angles
\r
467 add ebp,eax ;offset of subobject
\r
468 call_next ;draw the subobject
\r
471 call g3_done_instance
\r
476 ;takes ax, returns ax
\r
477 find_color_index: push ebx
\r
479 ;first, see if color already in table
\r
481 xor ebx,ebx ;counter
\r
482 look_loop: cmp ebx,n_interp_colors
\r
484 cmp ax,interp_color_table+2[ebx*4]
\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
494 found_color: mov eax,ebx ;return index
\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
504 remap_loop: cmp ebx,n_interp_colors
\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
515 done_remap: popm eax,ebx
\r
519 ;maps the colors back to RGB15
\r
520 g3_uninit_polygon_model:
\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
529 pushm eax,ebx,ecx,edx,esi,edi
\r
531 popm eax,ebx,ecx,edx,esi,edi
\r
537 init_loop: mov ax,[esi] ;get opcode
\r
544 cmp ax,1 ;defpoints
\r
547 mov ax,2[esi] ;get count
\r
550 lea esi,4[esi+eax*4]
\r
559 break_if l,'face must have 3 or more points'
\r
561 ; The following 3 lines replace the above
\r
563 mov ax,28[esi] ;get color
\r
564 test uninit_flag,-1
\r
567 mov ax,interp_color_table+2[eax*4]
\r
570 call find_color_index
\r
571 cont1: mov 28[esi],ax ;store new color
\r
574 mov cx,2[esi] ;get nverts
\r
576 inc ecx ;adjust for pad
\r
577 lea esi,30[esi+ecx*2]
\r
586 break_if l,'face must have 3 or more points'
\r
588 mov ax,28[esi] ;get bitmap number
\r
589 cmp ax,_highest_texture_num
\r
591 mov _highest_texture_num,ax
\r
592 not_new: xor ecx,ecx
\r
593 mov cx,2[esi] ;get nverts
\r
596 inc ebx ;adjust for pad
\r
597 lea esi,30[esi+ebx*2] ;point at uvls
\r
599 imul ecx,12 ;size of uvls
\r
600 add esi,ecx ;skip them
\r
603 ;;@@init_uv_loop: mov eax,[esi] ;get u
\r
604 ;;@@ imul eax,64 ;times bitmap w
\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
611 ;;@@ jnz init_uv_loop
\r
621 mov ax,28[esi] ;get front offset
\r
626 mov ax,30[esi] ;get front offset
\r
647 mov ax,16[esi] ;get subobj offset
\r
655 cmp ax,7 ;defpoints
\r
656 jne not_defpoints_st
\r
658 mov ax,2[esi] ;get count
\r
661 lea esi,8[esi+eax*4]
\r
670 debug_brk "Invalid opcode"
\r
675 ;takes ecx=count, esi=ptr to point list
\r
676 draw_outline: pushm eax,ebx,ecx,edx,esi,edi
\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
686 mov ax,[ebx] ;get first point
\r
689 outline_loop: xor esi,esi
\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
708 done_loop: pop edi ;get first point back
\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
717 popm eax,ebx,ecx,edx,esi,edi
\r
720 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
722 ;Special code to draw morphing objects
\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
729 morph_rotate_list: lea eax,[ecx*2+ecx] ;eax=npoint * 3
\r
730 lea esi,[esi+eax*4] ;point past points
\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
737 jnz morph_rotate_loop
\r
738 pop esi ;restore pointer
\r
742 ;define a list of points, with starting point num specified
\r
743 morph_defp_start: xor ecx,ecx
\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
749 mov cx,2[ebp] ;num points
\r
751 jmp morph_rotate_list
\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
761 mov ax,28[ebp] ;get color
\r
762 mov ax,interp_color_table[eax*4]
\r
763 call gr_setcolor_ ;set it
\r
766 lea esi,30[ebp] ;point number list
\r
770 imulc eax,size g3s_point
\r
771 add eax,Interp_point_list
\r
772 mov morph_pointlist,eax
\r
775 imulc eax,size g3s_point
\r
776 add eax,Interp_point_list
\r
777 mov morph_pointlist+4,eax
\r
780 imulc eax,size g3s_point
\r
781 add eax,Interp_point_list
\r
782 mov morph_pointlist+8,eax
\r
784 cmp ecx,3 ;3 points is good!
\r
786 sub ecx,2 ;tri count
\r
788 flat_tri_loop: xor edi,edi ;no normal, must compute
\r
790 mov ecx,3 ;always draw triangle
\r
791 lea esi,morph_pointlist
\r
792 call g3_check_and_draw_poly
\r
795 mov eax,morph_pointlist+8
\r
796 mov morph_pointlist+4,eax
\r
799 imulc eax,size g3s_point
\r
800 add eax,Interp_point_list
\r
801 mov morph_pointlist+8,eax
\r
808 lea esi,morph_pointlist
\r
809 xor edi,edi ;no normal, must compute
\r
810 call g3_check_and_draw_poly
\r
812 flat_done_draw: xor ecx,ecx
\r
813 mov cx,2[ebp] ;restore count
\r
816 inc ecx ;adjust for pad
\r
817 lea ebp,30[ebp+ecx*2]
\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
828 mov dx,28[ebp] ;get bitmap number
\r
830 mov edx,[eax+edx*4]
\r
832 lea esi,30[ebp] ;point number list
\r
836 lea ebx,30[ebp+eax*2] ;get uvl list
\r
837 ;calculate light from surface normal
\r
839 lea esi,View_matrix.fvec
\r
840 lea edi,16[ebp] ;normal
\r
841 call vm_vec_dotprod
\r
843 ;scale light by model light
\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
859 ;now eax=plane light value
\r
861 mov morph_uvls+8,eax
\r
862 mov morph_uvls+20,eax
\r
863 mov morph_uvls+32,eax
\r
867 imulc eax,size g3s_point
\r
868 add eax,Interp_point_list
\r
869 mov morph_pointlist,eax
\r
872 imulc eax,size g3s_point
\r
873 add eax,Interp_point_list
\r
874 mov morph_pointlist+4,eax
\r
877 imulc eax,size g3s_point
\r
878 add eax,Interp_point_list
\r
879 mov morph_pointlist+8,eax
\r
881 cmp ecx,3 ;3 points is good!
\r
882 jl tmap_done_draw ;something is bad, abort
\r
884 sub ecx,2 ;tri count
\r
891 mov morph_uvls+4,edx
\r
894 mov morph_uvls+12,edx
\r
896 mov morph_uvls+16,edx
\r
899 mov morph_uvls+24,edx
\r
901 mov morph_uvls+28,edx
\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
913 call g3_check_and_draw_tmap
\r
914 popm ebx,edx,ecx,esi
\r
916 mov eax,morph_pointlist+8
\r
917 mov morph_pointlist+4,eax
\r
920 imulc eax,size g3s_point
\r
921 add eax,Interp_point_list
\r
922 mov morph_pointlist+8,eax
\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
931 mov morph_uvls+24,edx
\r
933 mov morph_uvls+28,edx
\r
942 ;poke in light values
\r
944 tmap_l_loop: mov 8[ebx],eax
\r
950 lea esi,morph_pointlist
\r
952 xor edi,edi ;no normal
\r
953 call g3_check_and_draw_tmap
\r
955 tmap_done_draw: xor ecx,ecx
\r
956 mov cx,2[ebp] ;restore count
\r
958 ;jump to next opcode
\r
961 inc ebx ;adjust for pad
\r
962 lea ebp,30[ebp+ebx*2]
\r
967 sal ecx,2 ;ecx=ecx*12
\r
968 add ebp,ecx ;point past uvls
\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
977 g3_draw_morphing_model:
\r
978 pushm eax,ebx,ecx,edx,esi,edi,ebp
\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
985 mov ebp,esi ;ebp = interp ptr
\r
987 ;set alternate opcode pointers
\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
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
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
1006 popm eax,ebx,ecx,edx,esi,edi,ebp
\r