home *** CD-ROM | disk | FTP | other *** search
- ; 3d vector routines - full sorting method (slower)
- ;
- ; - objects can pass through one another and still be sorted correctly
- ; - sort_list and draw vect must be called seperatly
- ; - maxsurfs and maxpoints must be large - set to TOTAL points/surfs on screen
- ;
- ; to use
- ;
- ; call look_at_it ; make camera look at selected object
- ; call setsincose ; set rotation multipliers for eye
- ; call makeobjs ; plot all objects in sides table
- ; call set_makeorder ; reset sort order
- ; call sort_list ; sort all sides/points/bitmaps
- ; call drawvect ; draw vectors/bitmaps/points/lines
- ; call instant_mouse ; plot mouse on screen
- ; call flip_page ; flip video pages
- ; call clear_fill ; clear video memory (last screen)
- ; call resetupd ; reset borders
- ; call updvectors ; move objects around, rotate them
-
- .386p
-
- code32 segment para public use32
- assume cs:code32, ds:code32
-
- ; define externals
-
- extrn objbase:dword ; object lists and bitmap lists are
- extrn bitbase:dword ; external! set to 0 if none
- extrn bitx:dword ; x and y sizes for 3d conversion
- extrn bity:dword
-
- include pmode.inc ; protected mode externals
- include xmouse.inc ; xmode mouse externals
- include xmode.inc ; xmode externals by matt pritchard
-
- include macros.inc
- include equ.inc
-
- ; include vars2.inc ; vars goes at end so indexing can be near
- include math.inc ; rotate, cos,sin,arctan...
- include xscale.inc
- include poly.inc ; common ploygon stuff
- align 4
- include sin.inc ; sin/cosin table
- include arctan.inc ; inverse tan
-
- public move_si
- public newfollow
- public resetupd
- public makeobjs
- public make1obj
- public look_at_it
- public calc_angles
- public get_displacement
- public put_object
- public set_angle
- public set_shape
- public set_object_on
- public set_object_off
- public dv_middle
- public set_makeorder
- public drawvect
- public sort_list
-
- align 4
-
- abort_all:
- add esp,2+2 ; abort from loadpoints and make1obj
- ret ; returning now from makeobjs call
-
- align 4
-
- loadpoints:
- mov bl,userotate[esi]
-
- shl si,1
- mov di,whatshape[esi] ; get shape, bp = z distance
- shl di,2 ; four resolutions
- mov eax,zad
- cmp eax, smalla ; check if too far to see detail anyway
- jl s viewhi
- inc di ; use resolution b
- cmp eax, smallb
- jl s viewhi
- inc di ; use resolution c
- cmp eax, smallc
- jl s viewhi
- inc di ; use resolution d
- viewhi:
- shl di,2
- mov edi,objbase[di]
- mov ax,[edi]
- mov numpoints,ax
-
- mov si,pointindex ; set xp,yp,zp pointer
-
- shl ax,1
- add pointindex,ax ; pointindex = word indexer to last point
-
- cmp pointindex,maxpoints*2 ; test for overflow in points tables
- jge s abort_all
-
- mov ax,[edi+2]
- mov numsides,ax
-
- add ax,showing
- cmp ax,maxsurfaces-1 ; check for overflow in "sides" tables
- je s abort_all
-
- add edi,4 ; skip start data
- mov lindex,si ; set last index to points (this one)
-
- cmp bl,0 ; check userotate command
- jne s np13 ; use different loop if no rotation
- np12:
- movsx ebx,w [edi] ; x
- movsx ecx,w [edi+2] ; y
- movsx ebp,w [edi+4] ; z
-
- push edi si
- call rotate ; rotate
- add ebp,zad
-
- cmp ebp,ztruncate
- jge s ntrunct
- mov ebp,ztruncate
- ntrunct:
- add ebx,xad
- add ecx,yad
- call make3d
- pop si edi
- mov [xp+si],bx
- mov [yp+si],cx
- mov [zp+si],bp
- add si,2 ; inc xp indexer
- add edi,6 ; inc input pointer
- dec numpoints
- jne s np12
-
- ret ; edi exits with pointer to sides
- np13:
- movsx ebx,w [edi] ; x
- movsx ecx,w [edi+2] ; y
- movsx ebp,w [edi+4] ; z
-
- push edi si
-
- call erotate ; rotation matrix already set up!
-
- add ebp,zad
-
- cmp ebp,ztruncate
- jge s ntrunct2
- mov ebp,ztruncate
- ntrunct2:
- add ebx,xad
- add ecx,yad
- call make3d
- pop si edi
- mov [xp+si],bx
- mov [yp+si],cx
- mov [zp+si],bp
- add si,2 ; inc xp indexer
- add edi,6
- dec numpoints
- jne s np13
-
- ret
-
- align 4
-
- ; handle loading of bitmap from object list
- ;
- ; eg dw 32,8,5,50,60 ;command is 32,point 8, bitmap 5, x&y scaling of 50,60
-
- ld_special:
- lodsw ; get from si, first is point
- shl ax,1
- add ax,lindex ; add to include offset in list
- stosw ; put in sides table
-
- mov dx,bp ; save indexer
- mov bp,ax ; get point indexers
- mov ax,[zp+bp]
- mov zeds[ebx],ax ; set zed for sort.
- mov bp,dx
-
- movsw ; get bitmap type
- movsw ; get x then y scaling
- movsw
-
- cmp zad,64000 ; bitmaps farther than 65536 screw up
- jge skipit ; you can't see them anyway. prevent overflow
- jmp ln2
-
- align 4
-
- loadsides:
- mov esi,edi ; edi = pointer to side object data
- mov edi,offsides ; get ready for lodsw and stosw
- mov ebp,edi ; ebp = offset to first point in side
- movzx ebx,showing ; bx = word indexer for surfaces
- shl bx,1
- ld_lp:
- lodsw ; get command word
-
- mov commands[ebx],ax
-
- test ax,32 ; if bitmap, do special load
- jnz ld_special
-
- lodsw ; get colour, high byte is other side
-
- mov surfcolors[ebx],ax ; save colour
-
- mov cx,lindex ; quick add for loop
-
- lodsw ; get from si, first is unconditinal
- shl ax,1
- add ax,cx ; add to include offset in list
- stosw ; put in di
- mov dx,ax
- ld_loop:
- lodsw ; get from si
- shl ax,1
- add ax,cx
- stosw ; put in di
-
- cmp ax,dx ; check all after first point
- jne s ld_loop
-
- push ebp
- push esi
- push ebx
-
- mov edi,ebp ; adjust bp into appropriate indexer
-
- mov bp,dx ; get point indexers
- mov dx,[zp+bp] ; get at least one z value, should be max
- mov zeds[ebx],dx ; but any will do.
-
- test commands[ebx],2+16+64 ; check for always visable or command
- jnz its_line
-
- mov bx,[edi+4]
-
- mov dx,[xp+bp] ; first point
- mov ax,[yp+bp]
- mov esq,ax ; memory
-
- mov bp,[edi+2]
- mov si,[xp+bp] ; second point
- mov ax,[yp+bp]
- mov dsq,ax ; memory
-
- mov bp,bx
- mov di,[xp+bp] ; third point
- mov bp,[yp+bp]
-
- call checkfront ; check if side is visable using p1,2,3
-
- pop ebx
- pop esi ; return object data pointer
- pop ebp ; return where we are in sides list
-
- cmp ecx,0+1 ; +1 makes small objects look better
- jle ln2 ; cx>-1 if side visible, skip if not
-
- test commands[ebx],4 ; test to use other colour
- jz s skipit ; miss this side...
-
- mov ax,surfcolors[ebx] ; get new colour
- xchg ah,al ; flip to other colour
- mov surfcolors[ebx],ax ; save colour
- mov ax,commands[ebx] ; use new steel texture bit
- mov cx,ax
- shr ax,3
- and ax,1
- and cx,255-1
- or cx,ax
- mov commands[ebx],cx
- ln2:
- inc showing ; another side added...
-
- add bx,2
- add ebp,maxpolys*2 ; bump ebp to next block
- skipit:
- mov edi,ebp ; set di for next stosw
-
- dec numsides ; count for next side
- jne ld_lp
-
- mov offsides,edi ; save for next call
-
- ret
- its_line:
- pop ebx esi ebp
- jmp s ln2
-
- align 4
-
- ; make object esi - routine assumes object is already ON! note: esi, not si!
-
- make1obj:
- push esi
- shl si,2 ; si = dword
-
- mov ebx,xs[esi] ; displacement
- sub ebx,eyex
- mov ecx,ys[esi]
- sub ecx,eyey
- mov ebp,zs[esi]
- sub ebp,eyez
-
- shr ebx,8 ; account for decimal places
- test ebx,00800000h
- jz s pm_1
- or ebx, 0ff000000h
- pm_1:
- shr ecx,8
- test ecx,00800000h
- jz s pm_2
- or ecx, 0ff000000h
- pm_2:
- shr ebp,8
- test ebp,00800000h
- jz s pm_3
- or ebp, 0ff000000h
- pm_3:
- cmp ebx,-maxz ; check if within visible space
- jl s noa2 ; if object miles away, don't bother
- cmp ebx,maxz
- jg s noa2
-
- cmp ebp,-maxz
- jl s noa2
- cmp ebp,maxz
- jg s noa2
-
- cmp ecx,-maxz
- jl s noa2
- cmp ecx,maxz
- jng s mo_misout
-
- align 4
- noa2:
- pop esi
- ret
-
- mo_misout:
- call zsolve ; figure out camera displacement
- cmp esi,minz ; check if behind camera, miminum dist.
- jl s noa2
-
- call xsolve
- mov xad,edi ; store 3d offsets
- call make3dx ; now make object farther in 3d (cheat)
-
- cmp edi,xmit ; tolerance is max object size/ratio
- jl s noa2
- cmp edi,xmat
- jge s noa2
-
- call ysolve
- mov yad,ecx
- call make3dy
-
- pop esi ; pop original object number
-
- mov zad,ebp
-
- test userotate[esi],32+64 ; check if bitmap or point
- jnz s mo_special
-
- cmp ecx,ymit
- jl s noa
- cmp ecx,ymat
- jge s noa
-
- cmp userotate[esi],0
- jne s mk_skipc ; skip if anything other than full rotations
-
- shl si,1 ; si = word
- call compound ; full rotation object, calc. matrix
- shr si,1
- mk_skipc:
- call loadpoints ; load points and rotate, exit di=sides
- jmp loadsides ; now load sides, starting at di
-
- align 4
- noa:
- ret
-
- align 4
-
- ; if userotate = 32 then draw bitmap at location x,y,z
-
- mo_special:
- cmp pointindex,(maxpoints-1)*2 ; check if there is room in table
- jge s noa
- cmp showing,maxsurfaces-1
- jge s noa
-
- test userotate[esi],64 ; is point or bitmap?
- jnz mo_ispoint
-
- cmp ecx,ymit ; test if bitmap visible
- jl s noa
- cmp ecx,ymat
- jge s noa
-
- cmp ebp,65535 ; far bitmaps screw up, abort
- jge s noa
-
- mov di,pointindex
- mov [xp+di],bx ; set location of bitmap
- mov [yp+di],cx
- mov [zp+di],bp
-
- mov edi,offsides
-
- movzx ebx,showing
- shl bx,1
- mov zeds[ebx],bp ; set z sort indexer
-
- inc showing ; one more surface...
- mov commands[ebx],32 ; set command for bitmap
-
- shl esi,1 ; si = word
-
- mov ax,pointindex
- add pointindex,2
- stosw
- mov ax,whatshape[esi]
- stosw
- mov ax,vxs[esi] ; set x and y scales (stretching)
- stosw
- mov ax,vys[esi]
- stosw
- mov offsides,edi ; update for next object/bitmap
- noa4:
- ret
-
- align 4
-
- mo_ispoint:
- cmp bx,xmins ; draw single point/bullet
- jl s noa8
- cmp bx,xmaxs
- jge s noa8
- cmp cx,ymins
- jl s noa8
- cmp cx,ymaxs ; ymaxs1 if larger pixel
- jge s noa8
-
- mov di,pointindex
- mov [xp+di],bx ; set location of point/bitmap
- mov [yp+di],cx
- mov [zp+di],bp
-
- mov edi,offsides
-
- movzx ebx,showing
- shl bx,1
- mov zeds[ebx],bp ; set z sort indexer
-
- inc showing ; one more surface...
-
- mov commands[ebx],64 ; set this command as point
- mov surfcolors[ebx],bulletcolour ; only for variable colours
-
- mov ax,pointindex
- add pointindex,2
-
- stosw
- stosw
- mov offsides,edi
- noa8:
- ret
-
- align 4
-
- ; draw vectors from sides list.
- ; number of "sides" is "showing"
-
- drawvect:
- cmp showing,0 ; no sides visible?
- je s noa8
-
- mov whichside,0 ; start at side 0
- movzx ebp,order[0] ; indexer to sides
- dv_loop2:
- test commands[ebp],16+32+64 ; test if line, point or bitmap
- jnz dv_testit ; yes, do faster line routine
-
- shl bp,mult
- mov dx,[sides+bp] ; first point is end flag
- dv_loop1:
- mov si,[sides+bp] ; get point, shl 1 not needed, pre-shl'ed
- mov ax,[xp+si]
- mov bx,[yp+si]
- mov x1,ax
- mov y1,bx
-
- mov si,[sides+bp+2] ; get next point
-
- cmp si,dx ; test if last = first, therefore done
- pushf
-
- mov ax,[xp+si]
- mov bx,[yp+si]
-
- mov x2,ax
- mov y2,bx
-
- push bp dx
- call fakeline ; draw next line
- pop dx bp
-
- add bp,2 ; bump to next pointer now
- popf ; was this point equal to the first point?
- jne s dv_loop1 ; no, draw more lines
-
- movzx esi,whichside ; set colour for this side
- mov si,order[esi]
- mov ax,surfcolors[esi]
- mov colq,al
-
- mov bx,commands[esi] ; use register which we can access low byte
- and bl,1 ; strip steel command bit
- sub bl,1
- mov steel,bl
-
- call poly_fill
-
- dv_return:
- add whichside,2 ; bump bp to next block of points
- movzx ebp,whichside
- mov bp,order[ebp] ; get sort order
- dec showing ; count for all sides
- jne dv_loop2
- dv_none:
- ret
-
- align 4
- dv_testit:
- mov ax,commands[ebp] ; perform command, return to dv_return
- test ax,16
- jnz dv_doline
- test ax,64
- jnz dv_dopoint
-
- ; draw bitmap at location x,y,z if userotate = 32 or command = 32
-
- shl bp,mult
- push bp
-
- movzx ebx,[sides+4+bp]
- movzx ecx,[sides+6+bp]
-
- mov si,[sides+2+bp]
- shl si,2 ; si = dword
- add ebx,bitx[si]
- add ecx,bity[si] ; ebx,ecx = top corner of bitmap in 3d
-
- mov eax,bitbase[si]
- mov bitmap,eax
-
- mov si,[sides+0+bp]
- mov bp,[zp+si]
-
- call make3d ; ebx,ecx = difference from center
-
- pop bp
-
- mov si,[sides+0+bp] ; get point
- mov ax,[xp+si]
- mov bp,[yp+si]
-
- sub ax,bx ; bx = x width/2 ax, bp = top corner
- sub bp,cx ; cx = y height/2
-
- if useborders eq yes
-
- cmp bp,yupdate+0
- jge s up_no12
- mov yupdate+0,bp
- up_no12:
- cmp ax,xupdate+0
- jge s up_no32
- mov xupdate+0,ax
- up_no32:
- mov di,ax
- mov dx,bp
-
- endif
-
- add ax,xcent
- add bp,ycent
- mov destx,ax
- mov desty,bp
-
- shl bx,1
- shl cx,1
-
- mov destwidth,bx
- mov destheight,cx
-
- if useborders eq yes
- add di,bx
- add dx,cx
-
- cmp dx,yupdate+2
- jng s up_no42
- mov yupdate+2,dx
- up_no42:
- cmp di,xupdate+2
- jng s up_no22
- mov xupdate+2,di
- up_no22:
- endif
-
- call xscale2
- noa7:
- jmp dv_return
-
- align 4
-
- dv_dopoint:
- mov dx,surfcolors[ebp] ; get colour of point
-
- shl bp,mult
- mov si,[sides+bp] ; get point x,y
- mov bx,[xp+si]
- mov cx,[yp+si]
-
- cmp bx,xmins ; check if on screen
- jl s noa7
- cmp bx,xmaxs
- jge s noa7
- cmp cx,ymins
- jl s noa7
- cmp cx,ymaxs ; ymaxs1 if larger pixel
- jge s noa7
-
- mov edi, current_page ; point to active vga page
-
- if useborders eq yes
-
- cmp cx,yupdate+0
- jge s up_no16
- mov yupdate+0,cx
- up_no16:
- cmp bx,xupdate+0
- jge s up_no36
- mov xupdate+0,bx
- up_no36:
- cmp cx,yupdate+2
- jng s up_no46
- mov yupdate+2,cx
- up_no46:
- cmp bx,xupdate+2
- jng s up_no26
- mov xupdate+2,bx
- up_no26:
- endif
-
- add bx,xcent
- add cx,ycent
-
- mov bp,dx ; save colour
-
- mov si,cx
- shl si,1
- mov ax,[si+fastimultable] ; get offset to start of line
-
- mov cx, bx ; copy to extract plane # from
- shr bx, 2 ; x offset (bytes) = xpos/4
- add bx, ax ; offset = width*ypos + xpos/4
-
- mov ax, map_mask_plane1 ; map mask & plane select register
- and cl, plane_bits ; get plane bits
- shl ah, cl ; get plane select value
- out_16 sc_index, ax ; select plane
-
- movzx ebx,bx
- mov ax,bp ; re-get colour
- mov [edi+ebx],al ; draw pixel, low is top, high is bottom
- ; add edi,xactual/4
- ; mov [edi+ebx],ah ; draw larger bullet/pixel (high byte)
-
- ; if drawing larger pixel, change above code to this!
- ; cmp cx,ymaxs1
- ; jge s noa7
-
- jmp dv_return
-
- align 4
-
- ; clipped line, only callable from draw_vect!
- ; similar routine to fakeline but faster, more accurate and draws directly
- ; to screen (current_page).
- ;
- ; this routine will always return to dv_return but you could replace those with
- ; ret's and make this routine callable from places other than draw_vect.
- ; if you do this, make sure you re-direct the draw_vect routine to
- ; call dv_doline, jmp dv_return. for now, set showing=1 and load dx,cx,ax,bx
- ; with x1,y1,x2,y2 and call dv_middle. thats if you really need a clipped line
- ; draw routine.
-
- dv_doline:
- shl bp,mult
- mov si,[sides+bp] ; get first point
- mov dx,[xp+si]
- mov cx,[yp+si]
-
- mov si,[sides+bp+2] ; second point
- mov ax,[xp+si]
- mov bx,[yp+si]
- dv_middle:
- cmp bx,cx ; flip order of points if drawing up
- jg s r_okorder
- xchg bx,cx
- xchg ax,dx
- r_okorder:
- mov x1,dx
- mov y1,cx
- mov x2,ax
- mov y2,bx
-
- if useborders eq yes
-
- cmp cx,yupdate+0 ; update borders for clearing routine
- jg s r_up_no1
- mov yupdate+0,cx
- r_up_no1:
- cmp bx,yupdate+2
- jng s r_up_no2
- mov yupdate+2,bx
- r_up_no2:
- mov bx,ax
- mov ax,dx
- mov dx,xupdate+0
- mov cx,xupdate+2
-
- cmp ax,dx
- jge s r_up_no3
- dec ax
- mov xupdate+0,ax
- mov dx,ax
- inc ax
- r_up_no3:
- cmp bx,cx
- jle s r_up_no4
- inc bx
- mov xupdate+2,bx
- mov cx,bx
- dec bx
- r_up_no4:
- cmp bx,dx
- jge s r_up_no5
- dec bx
- mov xupdate+0,bx
- r_up_no5:
- cmp ax,cx
- jle s r_up_no6
- inc ax
- mov xupdate+2,ax
- r_up_no6:
- mov ax,x2 ; ax=x
- sub ax,x1
- mov bx,y2 ; bx=y
- sub bx,y1
-
- elseif not useborders eq yes
-
- sub ax,dx
- sub bx,cx
-
- endif
-
- movzx esi,whichside ; set colour for this line
- mov si,order[esi]
- mov dx,surfcolors[esi]
- mov colq,dl
-
- mov dx,ymaxs
- cmp y1,dx
- jge dv_return
-
- mov rise,bx
- movsx ebx,bx
- cmp ebx,0
- jne s r_nsliver
-
- mov bx, y1
- cmp bx, ymins ; draw sliver, avoid divide by zero
- jl dv_return
- cmp bx, dx ; dx = ymax
- jge dv_return
-
- add bx,ycent
- mov si,bx
- shl si,1
- movzx eax,[si+fastimultable] ; get offset to start of line
- mov edi, current_page
- add edi, eax ; edi = starting y location
-
- mov rise,1
-
- mov dx, x1 ; from here...
- mov si, x2 ; ..to here
-
- cmp si,xmins
- jge s u_nou3
- mov si,xmins
- u_nou3:
- cmp si,xmaxs
- jl s u_noq3
- mov si,xmaxs1
- u_noq3:
- jmp r_splint ; re-enter draw later in code
-
- align 4
- r_nsliver:
- 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 r_li_abov1
- sub ax,y1 ; ax = abs(difference of ymin-y1)
- sub rise,ax ; dec counter
- jle dv_return ; 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
-
- r_li_abov1:
- mov bx,y1 ; bx distance from top of screen
- add bx,ycent
- mov si, bx ; calculate screen address
- shl si,1
- movzx eax,[si+fastimultable] ; get offset to start of line
- mov edi, current_page
- add edi,eax ; edi = starting y location
-
- movsx edx,x1
- shl edx,16
- mov cx,rise
- mov ax,y1
- add ax,cx ; will line go off bottom of screen?
- cmp ax,ymaxs
- jl s r_linep ; no...
- sub ax,ymaxs ; yes, truncate cx for early exit
- sub rise,ax
- jle dv_return
- r_linep:
- mov eax,edx
- movzx ecx,cx
-
- mov esi,edx
- shr esi,16
-
- cmp si,xmins
- jge s r_nou
- mov si,xmins
- r_nou:
- cmp si,xmaxs
- jl s r_noq
- mov si,xmaxs1
- r_noq:
- align 4
-
- r_lineloop:
- add eax,ebp ; main line drawing loop!!! (for lines)
- mov edx,eax
- shr edx,16
- r_splint:
- cmp dx,xmins
- jge s u_nou
- mov dx,xmins
- cmp dx,si
- je r_mis
- u_nou:
- cmp dx,xmaxs
- jl s u_noq
- mov dx,xmaxs1
- cmp dx,si
- je r_mis
- u_noq:
- push dx edi ebp eax ; save for next line
- cmp dx,si
- jle s r_no_switch
- xchg dx,si
- r_no_switch:
-
- add dx,xcent
- add si,xcent
-
- mov ax,dx
- mov bx,si
- mov x2,si
-
- 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?
- je rf_one_band_only ; if so, then special processing
-
- sub cx,dx ; cx = # bands -1
- mov si,ax ; si = plane#(x1)
- and si,plane_bits ; if left edge is aligned then
- jz s rf_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 s rf_right
-
- rf_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
-
- rf_right:
- mov si,bx ; get xpos2
- and si,plane_bits ; get plane values
- cmp si,0003 ; plane = 3?
- je s rf_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
-
- rf_right_loop:
- mov [esi], al ; fill in right edge pixels
-
- dec cx ; minus 1 for middle bands
- jz s rf_exit ; uh.. no middle bands...
-
- rf_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
-
- rf_middle_loop:
- shr cx,1 ; use doubleword transfer
- jnc s rf_ord
- stosb ; if cx odd, store byte first
- jcxz s rf_exit ; no words after stosb
- rf_ord:
- shr cx,1
- jnc rf_dord
- stosw
- jcxz s rf_exit ; no doublewords after stosw
- rf_dord:
- rep stosd ; fill in entire line
-
- jmp s rf_exit ; outa here, for this line
-
- rf_one_band_only:
- 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
- rf_exit:
- pop eax ebp edi si ; pop screen left address
- r_mis:
- add edi, xactual/4
- dec rise
- jg r_lineloop
-
- jmp dv_return ; re-enter draw_vect
-
- ; bubble sort for sides
-
- ; sort is not perfect since many sides can use the same point.
- ; if this point is the first point in the list and therefore zeds[] uses
- ; the same point for sort, the routine may mess up when plotting at some
- ; acute angles. if you ever notice this, you are way too picky. you
- ; could fix this by adjusting the load_sides routine to search for the
- ; closest z point.
-
- align 4
-
- minusd equ offset zeds - offset order
-
- sort_list:
- movzx esi,showing
- cmp si,1 ; if only one surface, exit
- jle qke
-
- shl si,1 ; si = word
- add esi,o order
-
- align 4
- nextcx:
- sub esi,2 ; point to last word in order[] table
-
- mov ebp,esi ; set order pointer
- mov bx,w [esi] ; get order[si]
-
- mov edi,esi
- add edi,minusd
- mov cx,w [edi] ; get zeds[si]
-
- align 4
- nextdx:
- sub edi,2
- sub ebp,2
-
- cmp cx,w [edi] ; zeds is point from side, should be max z
- jle s donothing
- xchg cx,w [edi] ; don't flip entire side, just indexers to it
- xchg bx,w [ebp]
- donothing:
- cmp ebp,o order ; check bp = 0
- jne s nextdx
-
- mov [esi + minusd],cx
- mov [esi],bx
-
- cmp esi,o order + 2
- jne s nextcx
- qke:
- ret
-
- align 4
-
- set_makeorder:
- movzx ecx,showing
- jcxz s non2_do
- dec ecx
- jcxz s non2_do
- shl ecx,1
- mov esi,ecx
- add esi,offset order
- ordrloop:
- mov [esi],cx
- sub esi,2
- dec cx
- loop ordrloop
- non2_do:
- mov [order],0 ; fill last
-
- mov offsides, offset sides ; clear table indexers for next call
- mov pointindex,0
-
- ret
-
- align 4
-
- look_at_it: ; force camera to look at object wherelook
-
- mov si,wherelook
- cmp si,no
- je s noat ; get out, no object to look at (-1=flag)
-
- mov edi,maxobjects
- movzx esi,si
- call calc_angles
- mov eyeay,bx
- mov eyeax,ax
- noat:
- ret
-
- ; calculate angles between objects esi and edi. angles are from point of view
- ; of di.
-
- calc_angles:
- shl si,2 ; si = dword
- shl di,2
- call get_displacement
- calc_middle:
- shr ebx,8 ; account for decimal places
- test ebx,00800000h
- jz s pm_7
- or ebx, 0ff000000h
- pm_7:
- shr ecx,8
- test ecx,00800000h
- jz s pm_8
- or ecx, 0ff000000h
- pm_8:
- shr ebp,8
- test ebp,00800000h
- jz s pm_9
- or ebp, 0ff000000h
- pm_9:
- cmp ebx,-maxz ; check if within visible space
- jl noaq ; object miles away, don't bother
- cmp ebx,maxz ; could divide by some high number
- jg noaq ; and try again. shr not good because
- ; ecx,ebx,ebp must be sign extended
- cmp ebp,-maxz
- jl noaq
- cmp ebp,maxz
- jg noaq
-
- cmp ecx,-maxz
- jl noaq
- cmp ecx,maxz
- jg noaq
-
- push ecx ebx ebp
-
- mov ecx,ebx ; first get z,x plane, (y angle)
- mov eax,ebp
-
- cmp eax,16384 ; if object miles away, shr and re-check
- jle s lk_oktab1
- shr eax,3
- shr ecx,3
- jmp s lk_oktab4 ; re-check to test if in space
- align 4
- lk_oktab1:
- cmp ecx,16384 ; if object miles away, shr and re-check
- jle s lk_oktab2
- shr eax,3
- shr ecx,3
- jmp s lk_oktab4 ; re-check to test if in space
- align 4
- lk_oktab2:
- cmp eax,-16384 ; if object miles away, shr and re-check
- jge s lk_oktab3
- shr eax,3
- shr ecx,3
- jmp s lk_oktab4 ; re-check to test if in space
- align 4
- lk_oktab3:
- cmp ecx,-16384 ; if object miles away, shr and re-check
- jge s lk_oktab4
- shr eax,3
- shr ecx,3
- jmp s lk_oktab4 ; re-check to test if in space
- align 4
- lk_oktab4:
- cmp eax,0
- je lk_right_above ; check arctan(cx/0)
-
- call arctan
- lk_resume:
- mov dsq,ax ; save y angle
- call cosign ; set up 32bit sin/cos multipliers
- mov vycos,eax
- mov ax,dsq
- call sign
-
- pop ebp ebx ; now compute sqr(z^2+x^2) through y rotation
-
- imul ebx ; use angle from calculation above
- shrd eax,edx,14
- mov edi,eax
- mov eax,vycos
- imul ebp
- shrd eax,edx,14
- add eax,edi ; di = new z = run
-
- pop ecx ; cx = rise
-
- cmp eax,16384 ; if object miles away, shr and re-check
- jle s lk_oktap1
- shr eax,3
- shr ecx,3
- jmp s lk_oktap4 ; re-check to test if in space
- align 4
- lk_oktap1:
- cmp ecx,16384 ; if object miles away, shr and re-check
- jle s lk_oktap2
- shr eax,3
- shr ecx,3
- jmp s lk_oktap4 ; re-check to test if in space
- align 4
- lk_oktap2:
- cmp eax,-16384 ; if object miles away, shr and re-check
- jge s lk_oktap3
- shr eax,3
- shr ecx,3
- jmp s lk_oktap4 ; re-check to test if in space
- align 4
- lk_oktap3:
- cmp ecx,-16384 ; if object miles away, shr and re-check
- jge s lk_oktap4
- shr eax,3
- shr ecx,3
- jmp s lk_oktap4 ; re-check to test if in space
- align 4
- lk_oktap4:
- cmp eax,0
- je s noaq
-
- call arctan ; get ax=arctan(y/sqr(z^2+x^2))
-
- mov bx,dsq ; bx = y angle , ax = x angle
- noaq:
- ret
-
- align 4
-
- lk_right_above:
- mov ax,vys[esi] ; camera directly above object, use old y
- jmp lk_resume
-
- align 4
-
- get_displacement:
- mov ebx,xs[esi] ; get displacement of esi to edi
- sub ebx,xs[edi]
- mov ecx,ys[esi]
- sub ecx,ys[edi]
- mov ebp,zs[esi]
- sub ebp,zs[edi]
- ret
-
- align 4
-
- ; new follow, si = object for new follow, di = time to get there.
-
- newfollow:
- mov wfollow,si ; save in case object is accelerating
- mov oldspeed,di
- mov wherelook,no ; disable look_at_si routine
-
- shl si,1
- movzx esi,si
- mov ax,lcount[esi]
- cmp ax,di ; if di>lcount, shorten to lcount
- ja s nx
- mov di,ax
- nx:
- movzx edi,di
-
- shl si,1 ; si = dword
-
- mov eax,xadds[esi] ; figure out where object will be di*frames
- imul edi
- add eax,xs[esi]
- mov ebx,eax
-
- mov eax,yadds[esi]
- imul edi
- add eax,ys[esi]
- mov ecx,eax
-
- mov eax,zadds[esi]
- imul edi
- add eax,zs[esi]
- mov ebp,eax
-
- mov di,oldspeed
- mov ax,eyelcount
- cmp ax,di ; if di>lcount, shorten to lcount
- ja s tx
- mov di,ax
- tx:
- movzx edi,di
-
- mov eax,eyexadds
- imul edi ; figure out where camera will be di*frames
- add eax,eyex
- sub ebx,eax ; get displacement to eye
-
- mov eax,eyeyadds
- imul edi
- add eax,eyey
- sub ecx,eax
-
- mov eax,eyezadds
- imul edi
- add eax,eyez
- sub ebp,eax
-
- call calc_middle ; jump in middle of angle computation
-
- mov di,bx
-
- sub ax,eyeax ; get difference from where we are now
- sub di,eyeay
-
- add ax,followtol ; check if already looking at it
- cmp ax,followtol*2
- ja s calcit
-
- add di,followtol
- cmp di,followtol*2
- jb just_look_at_it_now_instead_of_calculating
- sub di,followtol
- calcit:
- sub ax,followtol
-
- mov si,oldspeed ; ax=x angle, di=y angle, si=# frames
- cwd
- push dx ; save sign extend
- idiv si ; x/time
- pop dx
- cmp ax,0
- jne s n0
- shl dx,1
- mov ax,dx
- inc ax ; ax = 1 or ax = -1
- n0:
- mov eyevxadds,ax
-
- mov ax,di
- cwd
- push dx
- idiv si ; y/time
- pop dx
- cmp ax,0 ; check if zero slope, must have some...
- jne s n1
- shl dx,1 ; dx = fffe (-2) or 0
- mov ax,dx
- inc ax ; ax = 1 or ax = -1
- n1:
- mov eyevyadds,ax
-
- mov eyeacount,si
- shr oldspeed,1 ; if need to try again, time/2
- noau:
- ret
-
- just_look_at_it_now_instead_of_calculating:
- mov ax,wfollow
- mov wherelook,ax ; already looking at object, now follow it
- mov wfollow,no
- ret
-
- ; move object si from wherever it is now to ebx,ecx,ebp in di frames
- ; move is 32 bit, make sure high words of registers are set!
- ; time to get there is 16 bit. (if you need more, think! 65535 frames at
- ; 1/30 frames a sec is 36 minutes!)
-
- move_si:
-
- movzx esi,si
- shl si,2 ; si = dword
- sub ebx,xs[esi]
- sub ecx,ys[esi]
- sub ebp,zs[esi]
-
- movzx edi,di
-
- mov eax,ebx ; 32 bit moves
-
- cdq
- idiv edi
- mov xadds[esi],eax
-
- mov eax,ecx
- cdq
- idiv edi
- mov yadds[esi],eax
-
- mov eax,ebp
- cdq
- idiv edi
- mov zadds[esi],eax
-
- shr si,1 ; si = word
-
- mov lcount[esi],di
- shr si,1 ; restore original si
-
- ret
-
- put_object:
- movzx esi,si
- shl si,2
- mov xs[esi],ebx
- mov ys[esi],ecx
- mov zs[esi],ebp
- shr si,2
- ret
-
- set_angle:
- movzx esi,si
- shl si,1
- mov vxs[esi],bx
- mov vys[esi],cx
- mov vzs[esi],bp
- shr si,1
- ret
- set_shape:
- movzx esi,si
- shl si,1
- mov whatshape[esi],ax
- shr si,1
- ret
-
- set_object_on:
- movzx esi,si
- mov onoff[esi],1
- ret
-
- set_object_off:
- movzx esi,si
- mov onoff[esi],0
- ret
-
- align 4
-
- include vars2.inc ; vars goes at end so indexing can be near
-
- makeobjs: ; make all objects, unrolled loop
- i=0
-
- rept maxobjects
- local itsoff
-
- test onoff+i,255 ; check on/off
- jz s itsoff
-
- mov esi,i
- call make1obj
- itsoff:
-
- i=i+1
- endm
-
- ret ; put no code here! make1obj may abort!
-
- code32 ends
- end