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
19 include psmacros.inc
\r
24 assume cs:_TEXT, ds:_DATA
\r
26 _DATA segment dword public USE32 'DATA'
\r
28 rcsid db "$Id: interp.asm,v 1.2 2002-07-17 21:55:19 bradleyb Exp $"
\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
44 anim_angles dd ? ;pointer to angle data
\r
46 morph_points dd ? ;alternate points for morph
\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
52 public _highest_texture_num
\r
53 _highest_texture_num dw 0
\r
55 zero_angles fixang 0,0,0 ;vms_angvec <0,0,0> ;for if no angles specified
\r
57 rod_top_p g3s_point <>
\r
58 rod_bot_p g3s_point <>
\r
60 public g3d_interp_outline,_g3d_interp_outline
\r
61 _g3d_interp_outline label dword
\r
62 g3d_interp_outline dd 0
\r
64 morph_pointlist dd ?,?,?
\r
66 morph_uvls fix 3 dup (?,?,?)
\r
68 ;the light for the current model
\r
71 ;ptr to array of points
\r
72 Interp_point_list dd ?
\r
74 MAX_POINTS_PER_POLY = 25
\r
76 point_list dd MAX_POINTS_PER_POLY dup (?)
\r
78 MAX_INTERP_COLORS = 100
\r
80 ;this is a table of mappings from RGB15 to palette colors
\r
81 interp_color_table dw MAX_INTERP_COLORS dup (?,?)
\r
83 n_interp_colors dd 0
\r
91 _TEXT segment dword public USE32 'CODE'
\r
93 ;get and jump to next opcode
\r
99 break_if ge,'Invalid opcode'
\r
101 mov ebx,opcode_table[ebx*4]
\r
105 ;get and call the next opcode
\r
111 break_if ge,'Invalid opcode'
\r
113 mov ebx,opcode_table[ebx*4]
\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
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
128 mov ebp,esi ;ebp = interp ptr
\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
141 popm eax,ebx,ecx,edx,esi,edi,ebp
\r
144 ;handlers for opcodes
\r
146 ;end of a model or sub-rountine
\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
154 rotate_loop: call g3_rotate_point
\r
155 add edi,size g3s_point
\r
156 add esi,size vms_vector
\r
162 ;define a list of points, with starting point num specified
\r
163 op_defp_start: xor ecx,ecx
\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
169 mov cx,2[ebp] ;num points
\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
182 ;polygon is facing, so draw it
\r
184 ;here the glow parameter is used for the player's headlight
\r
185 test glow_num,-1 ;glow override?
\r
188 mov esi,glow_values
\r
189 mov eax,[esi+eax*4]
\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
195 mov eax,32 ;32 shades
\r
201 no_sat1: cmp eax,32
\r
204 no_sat2: mov bh,al ;get lighting table
\r
206 mov ax,28[ebp] ;get color index
\r
207 mov ax,interp_color_table[eax*4]
\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
214 jmp got_color_index
\r
215 not_white: cmp eax,-3 ;-3 means don't draw polygon
\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
224 lea esi,30[ebp] ;point number list
\r
226 ;make list of point pointers
\r
229 cmp ecx,MAX_POINTS_PER_POLY
\r
230 break_if ge,'Too many points in interp poly'
\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
247 mov cx,2[ebp] ;restore count
\r
250 test g3d_interp_outline,-1
\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
265 ;set the glow value for the next tmap
\r
266 op_glow: test glow_values,-1
\r
271 skip_glow: add ebp,4
\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
283 ;polygon is facing, so draw it
\r
286 mov dx,28[ebp] ;get bitmap number
\r
288 mov edx,[eax+edx*4]
\r
290 lea esi,30[ebp] ;point number list
\r
294 lea ebx,30[ebp+eax*2] ;get uvl list
\r
296 ;calculate light from surface normal
\r
299 test glow_num,-1 ;glow override?
\r
301 ;special glow lighting, which doesn't care about surface normal
\r
303 mov esi,glow_values
\r
304 mov eax,[esi+eax*4]
\r
306 jmp got_light_value
\r
308 lea esi,View_matrix.fvec
\r
309 lea edi,16[ebp] ;normal
\r
310 call vm_vec_dotprod
\r
312 ;scale light by model light
\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
321 ;now poke light into l values
\r
322 got_light_value: pushm ecx,ebx
\r
323 l_loop: mov 8[ebx],eax
\r
331 ;make list of point pointers
\r
334 cmp ecx,MAX_POINTS_PER_POLY
\r
335 break_if ge,'Too many points in interp poly'
\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
354 mov cx,2[ebp] ;restore count
\r
357 test g3d_interp_outline,-1
\r
366 ;polygon is not facing (or we've plotted it). jump to next opcode
\r
367 tmap_not_facing: mov ebx,ecx
\r
369 inc ebx ;adjust for pad
\r
370 lea ebp,30[ebp+ebx*2]
\r
375 sal ecx,2 ;ecx=ecx*12
\r
376 add ebp,ecx ;point past uvls
\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
386 ;is facing. draw back then front
\r
390 mov ax,30[ebp] ;get back offset
\r
393 mov ebp,[esp] ;get ebp
\r
395 mov ax,28[ebp] ;get front offset
\r
403 ;is not facing. draw front then back
\r
405 sortnorm_not_facing:
\r
408 mov ax,28[ebp] ;get back offset
\r
411 mov ebp,[esp] ;get ebp
\r
413 mov ax,30[ebp] ;get front offset
\r
421 ;draw a rod bitmap
\r
422 op_rodbm: lea esi,20[ebp] ;bot point
\r
424 call g3_rotate_point
\r
426 lea esi,4[ebp] ;top point
\r
428 call g3_rotate_point
\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
435 mov bx,2[ebp] ;get bitmap number
\r
437 mov ebx,[ecx+ebx*4]
\r
439 call g3_draw_rod_tmap
\r
446 op_subcall: xor eax,eax
\r
447 mov ax,2[ebp] ;get object number
\r
450 mov edi,anim_angles
\r
452 jnz angles_not_null
\r
453 ;angles not specified. Use zero angles
\r
454 lea edi,zero_angles
\r
457 imulc eax,size vms_angvec
\r
462 lea esi,4[ebp] ;get position
\r
463 call g3_start_instance_angles
\r
468 add ebp,eax ;offset of subobject
\r
469 call_next ;draw the subobject
\r
472 call g3_done_instance
\r
477 ;takes ax, returns ax
\r
478 find_color_index: push ebx
\r
480 ;first, see if color already in table
\r
482 xor ebx,ebx ;counter
\r
483 look_loop: cmp ebx,n_interp_colors
\r
485 cmp ax,interp_color_table+2[ebx*4]
\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
495 found_color: mov eax,ebx ;return index
\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
505 remap_loop: cmp ebx,n_interp_colors
\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
516 done_remap: popm eax,ebx
\r
520 ;maps the colors back to RGB15
\r
521 g3_uninit_polygon_model:
\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
530 pushm eax,ebx,ecx,edx,esi,edi
\r
532 popm eax,ebx,ecx,edx,esi,edi
\r
538 init_loop: mov ax,[esi] ;get opcode
\r
545 cmp ax,1 ;defpoints
\r
548 mov ax,2[esi] ;get count
\r
551 lea esi,4[esi+eax*4]
\r
560 break_if l,'face must have 3 or more points'
\r
562 ; The following 3 lines replace the above
\r
564 mov ax,28[esi] ;get color
\r
565 test uninit_flag,-1
\r
568 mov ax,interp_color_table+2[eax*4]
\r
571 call find_color_index
\r
572 cont1: mov 28[esi],ax ;store new color
\r
575 mov cx,2[esi] ;get nverts
\r
577 inc ecx ;adjust for pad
\r
578 lea esi,30[esi+ecx*2]
\r
587 break_if l,'face must have 3 or more points'
\r
589 mov ax,28[esi] ;get bitmap number
\r
590 cmp ax,_highest_texture_num
\r
592 mov _highest_texture_num,ax
\r
593 not_new: xor ecx,ecx
\r
594 mov cx,2[esi] ;get nverts
\r
597 inc ebx ;adjust for pad
\r
598 lea esi,30[esi+ebx*2] ;point at uvls
\r
600 imul ecx,12 ;size of uvls
\r
601 add esi,ecx ;skip them
\r
604 ;;@@init_uv_loop: mov eax,[esi] ;get u
\r
605 ;;@@ imul eax,64 ;times bitmap w
\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
612 ;;@@ jnz init_uv_loop
\r
622 mov ax,28[esi] ;get front offset
\r
627 mov ax,30[esi] ;get front offset
\r
648 mov ax,16[esi] ;get subobj offset
\r
656 cmp ax,7 ;defpoints
\r
657 jne not_defpoints_st
\r
659 mov ax,2[esi] ;get count
\r
662 lea esi,8[esi+eax*4]
\r
671 debug_brk "Invalid opcode"
\r
676 ;takes ecx=count, esi=ptr to point list
\r
677 draw_outline: pushm eax,ebx,ecx,edx,esi,edi
\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
687 mov ax,[ebx] ;get first point
\r
690 outline_loop: xor esi,esi
\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
709 done_loop: pop edi ;get first point back
\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
718 popm eax,ebx,ecx,edx,esi,edi
\r
721 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
723 ;Special code to draw morphing objects
\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
730 morph_rotate_list: lea eax,[ecx*2+ecx] ;eax=npoint * 3
\r
731 lea esi,[esi+eax*4] ;point past points
\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
738 jnz morph_rotate_loop
\r
739 pop esi ;restore pointer
\r
743 ;define a list of points, with starting point num specified
\r
744 morph_defp_start: xor ecx,ecx
\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
750 mov cx,2[ebp] ;num points
\r
752 jmp morph_rotate_list
\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
762 mov ax,28[ebp] ;get color
\r
763 mov ax,interp_color_table[eax*4]
\r
764 call gr_setcolor_ ;set it
\r
767 lea esi,30[ebp] ;point number list
\r
771 imulc eax,size g3s_point
\r
772 add eax,Interp_point_list
\r
773 mov morph_pointlist,eax
\r
776 imulc eax,size g3s_point
\r
777 add eax,Interp_point_list
\r
778 mov morph_pointlist+4,eax
\r
781 imulc eax,size g3s_point
\r
782 add eax,Interp_point_list
\r
783 mov morph_pointlist+8,eax
\r
785 cmp ecx,3 ;3 points is good!
\r
787 sub ecx,2 ;tri count
\r
789 flat_tri_loop: xor edi,edi ;no normal, must compute
\r
791 mov ecx,3 ;always draw triangle
\r
792 lea esi,morph_pointlist
\r
793 call g3_check_and_draw_poly
\r
796 mov eax,morph_pointlist+8
\r
797 mov morph_pointlist+4,eax
\r
800 imulc eax,size g3s_point
\r
801 add eax,Interp_point_list
\r
802 mov morph_pointlist+8,eax
\r
809 lea esi,morph_pointlist
\r
810 xor edi,edi ;no normal, must compute
\r
811 call g3_check_and_draw_poly
\r
813 flat_done_draw: xor ecx,ecx
\r
814 mov cx,2[ebp] ;restore count
\r
817 inc ecx ;adjust for pad
\r
818 lea ebp,30[ebp+ecx*2]
\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
829 mov dx,28[ebp] ;get bitmap number
\r
831 mov edx,[eax+edx*4]
\r
833 lea esi,30[ebp] ;point number list
\r
837 lea ebx,30[ebp+eax*2] ;get uvl list
\r
838 ;calculate light from surface normal
\r
840 lea esi,View_matrix.fvec
\r
841 lea edi,16[ebp] ;normal
\r
842 call vm_vec_dotprod
\r
844 ;scale light by model light
\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
860 ;now eax=plane light value
\r
862 mov morph_uvls+8,eax
\r
863 mov morph_uvls+20,eax
\r
864 mov morph_uvls+32,eax
\r
868 imulc eax,size g3s_point
\r
869 add eax,Interp_point_list
\r
870 mov morph_pointlist,eax
\r
873 imulc eax,size g3s_point
\r
874 add eax,Interp_point_list
\r
875 mov morph_pointlist+4,eax
\r
878 imulc eax,size g3s_point
\r
879 add eax,Interp_point_list
\r
880 mov morph_pointlist+8,eax
\r
882 cmp ecx,3 ;3 points is good!
\r
883 jl tmap_done_draw ;something is bad, abort
\r
885 sub ecx,2 ;tri count
\r
892 mov morph_uvls+4,edx
\r
895 mov morph_uvls+12,edx
\r
897 mov morph_uvls+16,edx
\r
900 mov morph_uvls+24,edx
\r
902 mov morph_uvls+28,edx
\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
914 call g3_check_and_draw_tmap
\r
915 popm ebx,edx,ecx,esi
\r
917 mov eax,morph_pointlist+8
\r
918 mov morph_pointlist+4,eax
\r
921 imulc eax,size g3s_point
\r
922 add eax,Interp_point_list
\r
923 mov morph_pointlist+8,eax
\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
932 mov morph_uvls+24,edx
\r
934 mov morph_uvls+28,edx
\r
943 ;poke in light values
\r
945 tmap_l_loop: mov 8[ebx],eax
\r
951 lea esi,morph_pointlist
\r
953 xor edi,edi ;no normal
\r
954 call g3_check_and_draw_tmap
\r
956 tmap_done_draw: xor ecx,ecx
\r
957 mov cx,2[ebp] ;restore count
\r
959 ;jump to next opcode
\r
962 inc ebx ;adjust for pad
\r
963 lea ebp,30[ebp+ebx*2]
\r
968 sal ecx,2 ;ecx=ecx*12
\r
969 add ebp,ecx ;point past uvls
\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
978 g3_draw_morphing_model:
\r
979 pushm eax,ebx,ecx,edx,esi,edi,ebp
\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
986 mov ebp,esi ;ebp = interp ptr
\r
988 ;set alternate opcode pointers
\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
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
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
1007 popm eax,ebx,ecx,edx,esi,edi,ebp
\r