home *** CD-ROM | disk | FTP | other *** search
- ; common routines between 3d1.asm and 3d2.asm
-
- public poly_fill
- public clear_fill
- public initpages
- public flip_page
- public fakeline
- public set_clip_absolute
- public set_clip_offset
- public updvectors
-
- ; clears a block from active display page
- ;
- ; this routine works only if borders of xclip land on even nybbles
- ; eg minimum x is 32 - works fine. but if minimum x is 37, this
- ; routine will clear all the way to 32 just the same. for better clearing,
- ; call fill_block routine with lxupdate and lyupdate parameters on stack
- ;
- ; routine was originally written by matt prichard. routine was then modified
- ; to clear using dwords, and clear to integer borders.
- ;
- ; entry: lxupdate+0 = left x position of area to fill
- ; lxupdate+2 = top y position of area to fill
- ; lyupdate+0 = right x position of area to fill
- ; lyupdate+2 = bottom y position of area to fill
-
- align 4
-
- clear_fill:
-
- if useborders eq yes
-
- cmp use_clear,no
- je tf_exit ; don't use clear routine
-
- mov edi, current_page ; point to active vga page
- cld ; direction flag = forward
-
- out_8 sc_index, map_mask ; set up for plane select
- out_8 sc_data, all_planes ; write to all planes
-
- mov ax,lxupdate+0
- mov bx,lxupdate+2
- mov cx,lyupdate+0
- mov dx,lyupdate+2
-
- add ax,xcent ; center on screen
- add bx,xcent
- add cx,ycents1
- add dx,ycentp1
-
- and ax,0fff8h
- and bx,0fff8h
- add bx,7
-
- cmp ax,cliplt ; clip to inside borders
- jge s tf_noclip1
- mov ax,cliplt
- tf_noclip1:
- cmp bx,xmaxxcent
- jl s tf_noclip2
- mov bx,cliprt
- tf_noclip2:
- cmp cx,cliptp
- jge s tf_noclip3
- mov cx,cliptp
- tf_noclip3:
- cmp dx,ymaxycent
- jl s tf_noclip4
- mov dx,ymaxycent
- tf_noclip4:
- mov lxupdate+0,ax
- mov lxupdate+2,bx
- mov lyupdate+0,cx
- mov lyupdate+2,dx
-
- cmp ax,bx
- jg tf_exit ; nothing to do!
-
- cmp cx,dx
- jg tf_exit ; nothing to do!
-
- mov ax,cx
- mov bx,dx
-
- sub bx,ax ; get y width
- mov lyupdate+2,bx ; save in ypos2
-
- mov si,ax
- shl si,1
- movzx eax,w [si+fastimultable] ; mul y1 by bytes per line
- add edi,eax ; di = start of line y1
-
- mov dx,lxupdate ; dx = x1 (pixel position)
- shr dx,2 ; dx/4 = bytes into line
- movzx edx,dx
- add edi,edx ; di = addr of upper-left corner
-
- mov cx,lxupdate+2 ; cx = x2 (pixel position)
- sub cx,lxupdate
- shr cx,3 ; cx/4 = bytes into line
- inc cx
-
- ; di = addr of upper left block to fill
- ; cx = # of bands to fill in (width)
-
- mov dx,xactual/4 ; dx = di increment
- sub dx,cx ; = screen_width-# planes filled
- sub dx,cx
-
- movzx ecx,cx
- mov ebx,ecx ; bx = quick refill for cx
- mov si,lyupdate+2 ; si = # of lines to fill
- mov ax,background ; get fill color
- push ax ; make 32 bit
- shl eax,16
- pop ax
-
- shr ecx,1
- shr ebx,1
- jnc s tf_middle_loop2
-
- align 4
-
- tf_middle_loop1:
- stosw
- rep stosd ; fill in entire line
-
- mov ecx, ebx ; recharge cx (line width)
- add edi, edx ; point to start of next line
- loopx si, tf_middle_loop1 ; loop until all lines drawn
-
- ret
-
- align 4
-
- tf_middle_loop2:
- rep stosd ; fill in entire line, doubleword store
-
- mov ecx, ebx ; recharge cx (line width)
- add edi, edx ; point to start of next line
- loopx si, tf_middle_loop2 ; loop until all lines drawn
- tf_exit:
- endif
-
- ret ; exit
-
- ; fill starting at oney, from firstbyte to lastbyte
-
- align 4
-
- poly_fill:
- mov edi, current_page ; point to active vga page
-
- out_8 sc_index, map_mask ; set up for plane select
-
- mov ax,oney ; ax=y1
- cmp ax,ymins
- jge s pf_okmin
- xor ax,ax
- jmp s pf_missub
- align 4
- pf_okmin:
- cmp ax,ymaxs
- jge pf_outearly
- sub ax,ymins
- pf_missub:
- if usesteel eq yes
- cmp steel,no ; test to use steel texture
- je s pf_skipsteel
- mov bl,colq ; yes, save colour offset and 16 block
- mov steelc,bl
- and steelc,0f0h ; save base offset of 16 colour block
- shl bl,2 ; colour offset is *2 (small) *4 (large)
- add bl,al ; make steel always constant
- and bl,03fh ; colour indexer (so sides look different)
- mov steel ,bl
- pf_skipsteel:
- endif
-
- mov bp,ax ; indexer to line
- shl bp,1
- add ax, cliptp
-
- mov si,ax
- shl si,1
- movzx eax,w [si+fastimultable] ; mul y1 by bytes per line
-
- add edi,eax ; di = start of line y1
-
- pf_more_lines:
- push edi ; save right hand position
- mov ax, [firstbyte+bp]
- cmp ax,xmaxs ; check if fill done
- jge pf_done
-
- if usesteel eq yes
- mov bl,steel ; use steel texture?
- cmp bl,no
- je s pf_no_steel
- xor bh,bh
- mov dl,pf_updown[bx]
- add dl,steelc
- mov colq,dl
- inc bl
- and bl,03fh ; 16 colours, 32 positions for steel texture
- mov steel,bl
- pf_no_steel:
- endif
-
- mov bx,[lastbyte+bp]
- add ax,xcent
- add bx,xcent
-
- mov dx,ax ; dx = x1 (pixel position)
- shr dx,2 ; dx/4 = bytes into line
- movzx edx,dx
- add edi,edx ; di = addr of upper-left corner
-
- movzx ecx,bx ; cx = x2 (pixel position)
- shr cx,2 ; cx/4 = bytes into line
-
- cmp dx,cx ; start and end in same band?
- jg pf_exit ; skip if fakeline fails connection
- jne s pf_normal ; if not, check for l & r edges
- jmp pf_one_band_only ; if so, then special processing
- pf_done:
- pop eax
- pf_outearly:
- mov oney,1000 ; reset for next polygon call
- ret
- pf_normal:
- sub cx,dx ; cx = # bands -1
- mov si,ax ; si = plane#(x1)
- and si,plane_bits ; if left edge is aligned then
- jz s pf_l_plane_flush ; no special processing..
-
- ; draw "left edge" of 1-3 pixels...
-
- out_8 sc_data, left_clip_mask[si] ; set left edge plane mask
-
- mov al,colq ; get fill color
- mov [edi], al ; fill in left edge pixels
-
- inc edi ; point to middle (or right) block
- dec cx ; reset cx instead of jmp pf_right
-
- pf_l_plane_flush:
- inc cx ; add in left band to middle block
-
- ; di = addr of 1st middle pixel (band) to fill
- ; cx = # of bands to fill -1
-
- pf_right:
- mov si,bx ; get xpos2
- and si,plane_bits ; get plane values
- cmp si,0003 ; plane = 3?
- je s pf_r_edge_flush ; hey, add to middle
-
- ; draw "right edge" of 1-3 pixels...
-
- out_8 sc_data, right_clip_mask[si] ; right edge plane mask
-
- mov esi,edi ; get addr of left edge
- add esi,ecx ; add width-1 (bands)
- dec esi ; to point to top of right edge
-
- mov al,colq ; get fill color
-
- pf_right_loop:
- mov [esi], al ; fill in right edge pixels
-
- dec cx ; minus 1 for middle bands
- jz s pf_exit ; uh.. no middle bands...
-
- pf_r_edge_flush:
-
- ; di = addr of upper left block to fill
- ; cx = # of bands to fill in (width)
-
- out_8 sc_data, all_planes ; write to all planes
-
- mov dx, xactual/4 ; dx = di increment
- sub dx, cx ; = screen_width-# planes filled
-
- mov al, colq ; get fill color
- mov ah, al ; colour is in high and low for stosw
- push ax ; make colour 32 bit
- shl eax,16
- pop ax
-
- pf_middle_loop:
- shr cx,1 ; use doubleword transfer
- jnc s pf_ord
- stosb ; if cx odd, store byte first
- jcxz s pf_exit ; no words after stosb
- pf_ord:
- shr cx,1
- jnc s pf_dord
- stosw
- jcxz s pf_exit ; no doublewords after stosw
- pf_dord:
- rep stosd ; fill in entire line
- pf_exit:
- pop edi
- mov [firstbyte+bp],1000 ; reset table for next polygon
- mov [lastbyte+bp],-1000
- add bp,2
- add edi,xactual/4
- jmp pf_more_lines
-
- pf_one_band_only:
- cmp ax, cliplt
- jne s pf_nexit
- cmp bx,ax
- je s pf_exit
- pf_nexit:
- cmp ax, cliprt
- je s pf_exit
- mov si,ax ; get left clip mask, save x1
- and si,plane_bits ; mask out row #
- mov al,left_clip_mask[si] ; get left edge mask
- mov si,bx ; get right clip mask, save x2
- and si,plane_bits ; mask out row #
- and al,right_clip_mask[si] ; get right edge mask byte
-
- out_8 sc_data, al ; clip for left & right masks
-
- mov al, colq ; get fill color
-
- mov [edi], al ; fill in pixels
- jmp s pf_exit ; outa here, for this line
-
- ; small steel texture, make sure to set shl bl,*1* before skip_steel:
-
- ;pf_updown db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- ; db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
- ; db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
- ; db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
-
- ; large steel texture, make sure to set shl bl,*2* before skip_steel:
-
- pf_updown db 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
- db 10,10,11,11,12,12,13,13,14,14,15,15
- db 15,15,14,14,13,13,12,12,11,11,10,10
- db 9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0
-
- fastimultable label word
- i=0
- rept yactual
- dw i*(xactual/4)
- i=i+1
- endm
-
- resetupd: ; make old update equal current update
- if useborders eq yes
-
- mov ax,xupdate[0] ; and reset current update
- mov lxupdate[0],ax
- mov ax,xupdate[2]
- mov lxupdate[2],ax
- mov ax,yupdate[0]
- mov lyupdate[0],ax
- mov ax,yupdate[2]
- mov lyupdate[2],ax
- mov ax,xmaxs
- mov bx,xmins1
- mov cx,ymaxs
- mov dx,ymins1
- mov xupdate[0],ax
- mov xupdate[2],bx
- mov yupdate[0],cx
- mov yupdate[2],dx
-
- endif
-
- ret
-
- ; hey! where is my postcard! see readme.doc file and send me that postcard!
-
- initpages:
- pushw 0
- call set_display_page
-
- pushw 0
- call set_active_page
- pushw 0
- call clear_vga_screen
-
- pushw 1
- call set_active_page
- pushw 0
- call clear_vga_screen
-
- ret
-
- flip_page:
- call get_display_page
- xor ax,1
- push ax
- call set_display_page
-
- call get_active_page
- xor ax,1
- push ax
- call set_active_page
-
- ret
-
- ; draw a line in tables firstbyte,lastbyte
- ;
- ; line is not drawn on screen but is drawn in memory tables. to use,
- ; tables must be clear, (default is always clear), just draw
- ; line around screen, in any order, then call poly_fill. the polygon will
- ; be drawn and checked in memory, then poly_fill will plop it on the current
- ; page. poly_fill routine clears tables during plot so tables are ready for
- ; more lines and more polygons.
-
- align 4
-
- fakeline:
- mov ax,y1
- cmp y2,ax ; flip order of points if drawing up
- jg s okorder
- mov bx,x1
- xchg bx,x2
- xchg bx,x1
- xchg ax,y2
- xchg ax,y1
- okorder:
- mov ax,y1 ; set starting point for fill
- cmp ax,oney
- jge s nonewoney
- mov oney,ax
- nonewoney:
- if useborders eq yes
-
- cmp ax,yupdate+0 ; update borders for clearing routine
- jge s up_no1
- mov yupdate+0,ax
- up_no1:
- mov ax,y2
- cmp ax,yupdate+2
- jng s up_no2
- mov yupdate+2,ax
- up_no2:
- mov dx,xupdate+0
- mov cx,xupdate+2
- mov ax,x1
- mov bx,x2
-
- cmp ax,dx
- jge s up_no3
- dec ax
- mov xupdate+0,ax
- mov dx,ax
- inc ax
- up_no3:
- cmp bx,cx
- jle s up_no4
- inc bx
- mov xupdate+2,bx
- mov cx,bx
- dec bx
- up_no4:
- cmp bx,dx
- jge s up_no5
- dec bx
- mov xupdate+0,bx
- up_no5:
- cmp ax,cx
- jle s up_no6
- inc ax
- mov xupdate+2,ax
- up_no6:
- endif
-
- mov ax,x2 ; ax=x
- sub ax,x1
- mov bx,y2 ; bx=y
- sub bx,y1
- jle sliver
-
- mov rise,bx
- movsx ebx,bx
-
- shl eax,16
- cdq
- idiv ebx
- mov ebp,eax ; ebp = slope*65536 (allows decimals)
-
- mov ax,ymins
- cmp y1,ax ; check if above screen
- jge s li_abov1
- sub ax,y1 ; ax = abs(difference of ymin-y1)
- sub rise,ax ; dec counter
- jle li_out ; line totally off screen
-
- movsx eax,ax ; prepare for 32bit mul
- imul ebp
- shr eax,16 ; get top word
- add x1,ax ; set new x1,y1 pair
- mov ax,ymins
- mov y1,ax
- li_abov1:
- movsx edx,x1
- shl edx,16
- mov cx,rise
- mov ax,y1
- mov bx,ax ; bx pointer first/lastbyte table
- sub bx,ymins
- shl bx,1 ; bx now word
-
- add ax,cx ; will line go off bottom of screen?
- cmp ax,ymaxs
- jl s linep ; no...
- sub ax,ymaxs ; yes, truncate cx for early exit
- sub cx,ax
- jle s li_out ; right off screen
- linep:
- mov eax,edx
- movzx ecx,cx
-
- mov di,xmins
- mov si,xmaxs1
-
- align 4
- lineloop:
- shr edx,16 ; main line drawing loop!!!
-
- cmp dx,di
- jge s nou
- mov dx,di
- nou:
- cmp dx,si
- jle s noq
- mov dx,si
- noq:
- cmp dx,firstbyte[bx] ; fix first and lastbyte table
- jge s ci1
- mov firstbyte[bx],dx
- ci1:
- cmp dx,lastbyte[bx]
- jng s ci2
- mov lastbyte[bx],dx
- ci2:
- add eax,ebp
- mov edx,eax
- add bx,2
- loop s lineloop
- li_out:
- ret
- sliver:
- mov cx,x1
- mov ax,y1
- call checkin ; if off bottom of screen, never returns
- mov cx,x2
- mov ax,y1
- checkin: ; cx,ax=x,y...
- cmp ax,ymaxs
- jge s ci9q
- cmp ax,ymins ; clip to borders
- jl s ci6q
-
- cmp cx,xmins
- jge s nouq
- mov cx,xmins
- nouq:
- cmp cx,xmaxs
- jl s noqq
- mov cx,xmaxs1
- noqq:
- mov bx,ax ; bx pointer first/lastbyte table
- sub bx,ymins
- shl bx,1 ; bx now word
- cmp cx,firstbyte[bx] ; fix first and lastbyte table
- jg s ci1q
- mov firstbyte[bx],cx
- ci1q:
- cmp cx,lastbyte[bx]
- jng s ci6q
- mov lastbyte[bx],cx
- ci6q:
- ret
- ci9q:
- add esp,4 ; off bottom of screen, exit now!
- ret
-
- ; set new clipping parameters where center is in middle of points ax,bx cx,dx
- ; where points are absolutes! eg (10,10) (50,50) would be a small window in
- ; the top corner of the screen.
-
- set_clip_absolute:
-
- mov si,cx ; calc center based on points
- sub si,ax
- shr si,1
- add si,ax
-
- mov di,dx
- sub di,bx
- shr di,1
- add di,bx
-
- sub ax,si ; now make points offset from center
- sub cx,si
- sub bx,di
- sub dx,di
-
- ; set new clipping parameters. does all pre-calculation for variables and
- ; resets oney, firstbyte and lastbyte table. si,di is center of screen. ax,bx
- ; and cx,dx are topleft and botright points to clip to. clipping will include
- ; minimum clip variables but will exclude maximum clip variables. eg -160,-100
- ; +160,+100, with center 160,100 are valid clip parameters. points are offsets
- ; from center, not absolutes! this allows you to have the camera looking to the
- ; left or right of where the pilot/plane is moving without having to change
- ; the camera angle. note: this can only change slightly as distortion occures
- ; with too large an offset. make sure to assemble the original file with the
- ; maximum y size you will ever need so tables are set to correct size.
-
- set_clip_offset:
- mov bp,dx
- sub bp,bx
- cmp bp,ymax-ymin ; check input parameters with assembley restraints
- jg you_must_assemble_original_file_with_larger_clipping_to_achieve_this
-
- mov xmins,ax
- mov xmaxs,cx
- mov ymins,bx
- mov ymaxs,dx
- mov xcent,si
- mov ycent,di
-
- mov cliptp,di
- add cliptp,bx
-
- mov ycentp1,di
- inc ycentp1
-
- mov ycents1,di
- dec ycents1
-
- mov clipbt,di
- add clipbt,dx
- dec clipbt
-
- mov cliplt,si
- add cliplt,ax
-
- mov cliprt,si
- add cliprt,cx
- dec cliprt
-
- mov xmaxxcent,si
- add xmaxxcent,cx
-
- mov ymaxycent,di
- add ymaxycent,dx
-
- mov xmins1,ax
- dec xmins1
-
- mov xmaxs1,cx
- dec xmaxs1
-
- mov ymins1,bx
- dec ymins1
-
- movsx eax,ax
- movsx ebx,bx
- movsx ecx,cx
- movsx edx,dx
-
- mov xmit,eax
- mov xmat,ecx
- mov ymit,ebx
- mov ymat,edx
-
- sub xmit,tolerance
- add xmat,tolerance
- sub ymit,tolerance
- add ymat,tolerance
- you_must_assemble_original_file_with_larger_clipping_to_achieve_this:
- ret
-
- align 4
-
- ; update vector list based on traces_past
- ; i could have used a loop but shl ax,cl works faster
- ;
- ; what i am really doing is:
- ;
- ; for i = 1 to traces_past
- ; call updvectors
- ; next i
- ;
- ; but instead i am shifting and adding (if bit present) for a faster method
- ; you get the idea right?
- ;
- ; this way, the slower the machine, the faster we move the objects to
- ; maintaine a universal speed from 486dx66 machine to 386sx33 machine
-
- updvectors:
- mov bx, traces_past
- mov traces_past,0
-
- mov dx,1
- mov cl,0
- up_loop:
- shr bl,1
- jnc not_call
- call updvectors2
- not_call:
- shl dx,1 ; dx = 1,2,4,8..
- add cl,1 ; cx = 0,1,2,3,4,5,6...
- cmp bl,0 ; all bits clear?
- jne up_loop
-
- cmp wfollow,no ; check if camera has reached follow object
- je s nretest ; nothing to follow
- cmp eyeacount,0
- jne s nretest ; not reached yet
- mov si,wfollow ; looking at it, re-call newfollow
- mov di,oldspeed
- cmp di,0
- jne newfollow ; re-calculate in case its accelerating
-
- jmp just_look_at_it_now_instead_of_calculating
- nretest:
- ret
-
- align 4
-
- updvectors2: ; update vector list - shifted by cl
- ; and dec'ed by dx
- i=0
- rept maxobjects+1 ; generate unrolled update loop
- local nupang, nuploc, nuder, nuuder
-
- cmp acount+i*2,0
- je s nupang
- sub acount+i*2,dx
- jnc s nuder
- mov acount+i*2,0
- nuder:
- mov ax,vxadds+i*2 ; update angles
- shl ax,cl
- add ax,vxs+i*2
- mov vxs+i*2,ax
-
- mov ax,vyadds+i*2
- shl ax,cl
- add ax,vys+i*2
- mov vys+i*2,ax
-
- mov ax,vzadds+i*2
- shl ax,cl
- add ax,vzs+i*2
- mov vzs+i*2,ax
- nupang:
- cmp lcount+i*2,0
- je s nuploc
- sub lcount+i*2,dx
- jnc s nuuder
- mov lcount+i*2,0
- nuuder:
- mov eax,xadds+i*4 ; update position
- shl eax,cl
- add eax,xs+i*4
- mov xs+i*4,eax
-
- mov eax,yadds+i*4
- shl eax,cl
- add eax,ys+i*4
- mov ys+i*4,eax
-
- mov eax,zadds+i*4
- shl eax,cl
- add eax,zs+i*4
- mov zs+i*4,eax
- nuploc:
- i=i+1
- endm
-
- ret
-