home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Underground
/
UNDERGROUND.ISO
/
graphic
/
poly.asm
< prev
next >
Wrap
Assembly Source File
|
1995-07-28
|
15KB
|
484 lines
.286
w equ word ptr
b equ byte ptr
include texture.inc ;implement texture macros
setnewlinel macro ;use only ax and bx here !
local dylpos,dxlpos,dxlgreat,macro_finished
mov bx,4043h ;code for inc ax (in bh) and inc bx (in bl)
mov bp,left
mov ax,poly2d[bp+8] ;store destination coordinates
mov xl1,ax
mov ax,poly2d[bp+10d]
mov yl1,ax
mov ax,poly2d[bp] ;left x/y start in glob. var
mov xl0,ax
sub ax,xl1 ;make delta x
inc xl1 ;for the condition of truncation
neg ax ;xl1-xl0
jns dxlpos ;dxl negative ?
neg ax ;then obtain amount
mov bh,48h ;code for dec ax (dec xl0)
sub xl1,2 ;extension of destination coordinate to negative
dxlpos:
mov dxl,ax ;and store glob.
mov incflagl,ax ;store in increment flag
mov ax,poly2d[bp+2]
mov yl0,ax
sub ax,yl1 ;obtain |delta y|
inc yl1 ;for the condition of trunctation
neg ax
jns dylpos ;negative ?
neg ax ;then obtain amount
mov bl,4bh ;code for dec bx (dec yl1)
sub yl1,2 ;extension of destination coordinate to negative
dylpos:
mov dyl,ax ;and store glob.
cmp dxl,ax ;dx < dy
jae dxlgreat
neg incflagl ;then sign change for increment flag
dxlgreat:
mov cs:byte ptr incxl,bh ;perform self modification
mov cs:byte ptr incyl,bl
cmp texture,1 ;textures required ?
jne macro_finished ;no, then skip
txt_makevarl ;otherwise calculate texture variables
macro_finished:
mov ax,xl0 ;use register as control variable
mov bx,yl0
mov si,incflagl
endm
setnewliner macro ;use only cx and dx here !
local dyrpos,dxrpos,dxrgreat,macro_finished
mov cx,4142h ;code for inc cx (in ch) and inc dx (in cl)
mov bp,right
mov dx,poly2d[bp] ;get destination coordinates
mov xr1,dx
mov dx,poly2d[bp+2]
mov yr1,dx
mov dx,poly2d[bp+8] ;right x/y in glob. var
mov xr0,dx
sub dx,xr1 ;make |delta x|
inc xr1 ;for the condition of truncation
neg dx
jns dxrpos ;negative ?
neg dx ;then obtain amount
mov ch,49h ;code for dec cx
sub xr1,2 ;extension of destination coordinate to negative
dxrpos:
mov dxr,dx ;store in glob. var
mov incflagr,dx
mov dx,poly2d[bp+10d] ;make |delta y|
mov yr0,dx
sub dx,yr1
inc yr1 ;for the condition of truncation
neg dx
jns dyrpos ;negative ?
neg dx ;then obtain amount
mov cl,4ah ;code for dec dx
sub yr1,2 ;extension of destination coordinate to negative
dyrpos:
mov dyr,dx ;and store in glob. var
cmp dxr,dx ;dx < dy ?
jae dxrgreat
neg incflagr ;then sign change for increment flag
dxrgreat:
mov cs:byte ptr incxr,ch ;self modification
mov cs:byte ptr incyr,cl
cmp texture,1 ;textures needed ?
jne macro_finished ;no, then skip
txt_makevarr ;otherwise calculate texture variables
macro_finished:
mov cx,xr0 ;load register
mov dx,yr0
mov di,incflagr
endm
data segment public
extrn vpage:word ;current video page
extrn sf_shift ;flag for surface shift suppression
extrn glass:byte; ;flag for glass surfaces
;texture variables:
extrn texture:byte ;texture needed ?
extrn txt_data:dataptr ;array with pointer to graphic data
extrn txt_offs:dataptr ;array with offsets within the texture image
extrn txt_size:dataptr ;array with size specifications
d_x dd 0 ;relative x-coordinate
d_y dd 0 ;relative y-coordinate
D dd 0 ;main determinant
column1 dd 0 ;components of the main determinant
dd 0
column2 dd 0
dd 0
upper_row dw 0 ;which coordinates were used ?
lower_row dw 0
xl_3d dd 0 ;control values for 3d-coordinates when filling
yl_3d dd 0
zl_3d dd 0
xr_3d dd 0
yr_3d dd 0
zr_3d dd 0
inc_xl dd 0 ;values for addition to control values
inc_yl dd 0
inc_zl dd 0
inc_xr dd 0
inc_yr dd 0
inc_zr dd 0
;variables for fill algorithm
high_point dw 0 ;kept in dx during search
high_y dw 0 ;kept in bx during search
left dw 0 ;point of left side
right dw 0 ;point of right side
xl0 dw 0 ;control values for left start and end points
yl0 dw 0
xl1 dw 0
yl1 dw 0
xr0 dw 0 ;control values for right
yr0 dw 0
xr1 dw 0
yr1 dw 0
dxl dw 0 ;delta X / Y for both pages
dyl dw 0
dxr dw 0
dyr dw 0
incflagl dw 0 ;flags, when y has to be incremented
incflagr dw 0
data ends
code segment public
assume cs:code,ds:data
extrn polycol:word ;surface color
extrn polyn:word ;number of corners
extrn poly2d:word ;array with 2D-coordinates
extrn poly3d:word ;array with 3D-coordinates
extrn delta1,delta2:word ;plane vectors
extrn bline:near ;draws line
lambda1 dd 0 ;affine coordinates
lambda2 dd 0
inc_lambda1 dd 0 ;steps
inc_lambda2 dd 0
plane dw 0002h ;current plane to set
x0 dw 0 ;coordinates for line
y0 dw 0
x1 dw 0
zz dw 0 ;points still to be drawn
extrn txt_no:word ;number of texture to be drawn
public drawpol
;draws wireframe model of surface in poly2d
drawpol proc near
push es
pusha
xor si,si ;index to first entry
mov bp,polyn ;get number of corners
@nline:
mov ax,poly2d[si] ;get coordinates from table
mov bx,poly2d[si+2]
mov cx,poly2d[si+8]
mov dx,poly2d[si+10d]
push bp
push si
call bline ;draw line
pop si
pop bp
add si,8 ;next line
dec bp ;decrement number
jne @nline
popa
pop es
ret
drawpol endp
hline proc near ;draws horiz. line ax/bx -> cx/bx
pusha
push es
mov x0,ax ;store coordinates for later
mov y0,bx
mov x1,cx
sub cx,ax ;calculate number of pixels to be drawn
jne zzok
inc cx
zzok:
mov zz,cx
cmp glass,1 ;glass surface ?
jne Solid1
push ax ;yes, then GDC mode: OR
mov dx,3ceh
mov ax,1003h ;register 3: function select
out dx,ax
pop ax
Solid1:
mov dx,3c4h ;timing sequencer port
mov di,0a000h
mov es,di ;select VGA segment
mov di,ax ;calculate offset
shr di,2 ;(x div 4) + y*80
add di,vpage ;add current page
mov bx,y0
imul bx,80d
add di,bx ;now in di
cmp zz,4
jl no_middle ;<draw 4 points -> no blocks of 4
and ax,11b ;two lower bits are important
je middle ;if 0 set blocks of 4 immediately
no_middle:
mov bx,0f02h ;if no_shift, then use this mask
mov cx,zz ;set number of pixels in mask
cmp cx,20h ;beginning with 20h the 386 shifts back in !
jae no_shift
mov bx,0102h ;prepare mask
shl bh,cl ;number of pixels=number of bits to set
dec bh
and bh,0fh
no_shift:
mov cx,ax ;shift correctly depending on start plane
and cl,3
shl bh,cl
mov ax,bx ;and mask finished
sub zz,4 ;decrement pixels to be drawn
add zz,cx
start:
out dx,ax ;set calculated write mask
mov al,b polycol ;get color
mov ah,es:[di] ;load latches, only for glass solids
stosb ;set
middle:
cmp zz,4
jl close ;if no more blocks of 4 -> conclusion
mov ax,0f02h ;select all planes
out dx,ax ;(zz div 4) set blocks of 4
mov cx,zz
shr cx,2
mov al,b polycol
cmp glass,1 ;glass solid ?
jne solid
@lp:
mov ah,es:[di] ;load latches, only glass solids
stosb ;and write back
dec cx
jne @lp
jmp close
solid:
rep stosb ;draw middle part
close:
mov cx,x1 ;set remaining pixels
and cx,3h
dec zz
js hline_finished ;if nothing more there -> end
mov ax,0102h
shl ah,cl ;create mask
dec ah
out dx,ax
mov al,b polycol ;get color
mov ah,es:[di] ;load latches, only for glass solids
stosb ;and draw pixels
hline_finished:
mov dx,3ceh ;GDC mode back to MOVE
mov ax,0003h
out dx,ax
pop es
popa
ret
hline endp
txt_hline ;macro contains procedure "hline_texture"
public fillpol
fillpol proc near ;fills polygon in mode X
push bp
pusha
cmp texture,1 ;textures being used ?
jne fill ;no, then simply fill
txt_maindet ;otherwise calculate main determinant
Fill:
xor si,si ;search for highest point, select first entry
mov cx,polyn ;number of corners
sub cx,2
mov bx,0ffffh ;very high value, in any case lower
npoint:
mov ax,poly2d[si+2] ;get y
cmp ax,bx ;if previous minimum lower
ja no_min
mov bx,ax ;record new minimum
mov dx,si
no_min:
add si,8
dec cx ;next corner, if not 0ffffh
jns npoint
mov high_point,dx ;record in glob var
mov high_y,bx ;high point search concluded
or dx,dx ;left = 0 ?
jne dec_valid
mov bx,polyn ;yes: right to the other end
sub bx,2
shl bx,3
jmp lr_finished ;position
dec_valid:
mov bx,dx ;otherwise
sub bx,8
lr_finished:
mov left,dx ;record one beforehand in glob var
mov right,bx
; ax/bx : start coordinates left (xl0/yl0)
; cx/dx : start coordinates right (xr0/yr0)
; si : overflow flag left
; di : overflow flag right
; bp : pointer to current point
setnewlinel ;load line variables
setnewliner
loopl:
cmp ax,xl1
je new_linel ;if end reached -> set new line
cmp bx,yl1
je new_linel ;otherwise continue drawing
or si,si ;increment flag <= 0
jg flaglgreat
incyl: ;this place is being patched !
inc bx ;continue y
add si,dxl ;continue setting inc flag
txt_incl ;continue 3d coordinates also
cmp bx,yl1 ;destination reached ?
je new_linel ;then new line
jmp left_increased ;y has been increased left -> now right
flaglgreat:
sub si,dyl ;decrement inc flag
incxl: ;this place being patched !
inc ax ;continue x
jmp loopl
finished__:
jmp finished
new_linel:
mov bx,left ;prepare increase
cmp bx,right
je finished__ ;same, then finished
add bx,8 ;continue left
mov ax,polyn ;is left at the end of the list ?
shl ax,3
sub ax,8 ;end defined
cmp bx,ax ;compare
jb left_set
xor bx,bx ;if yes, then set to 0
left_set:
mov left,bx
setnewlinel ;reload variables
jmp loopl
finished_:
jmp finished
left_increased:
loopr:
cmp cx,xr1
je new_liner ;if end reached -> set new line
cmp dx,yr1
je new_liner ;otherwise continue drawing
or di,di ;increment flag <= 0
jg flagrgreat
incyr: ;this place being patched !
inc dx ;continue y
add di,dxr ;continue setting inc flag
txt_incr
cmp dx,yr1 ;destination reached ?
je new_liner ;then new line
jmp right_increased ;y was increased right -> now draw line
flagrgreat:
sub di,dyr ;decrement inc flag
incxr:
inc cx ;this place being patched !
jmp loopr
new_liner:
mov dx,right ;prepare decrease
cmp dx,left
je finished_ ;if same, then finished
sub dx,8 ;if previously at 0->set at other end
jns right_set
mov dx,polyn
sub dx,2
shl dx,3 ;positioned at end
right_set:
mov right,dx
setnewliner ;reload variables
jmp loopr
right_increased:
push ax
push cx
cmp cx,ax ;correct sequence ?
jae direct_ok ;then ok, otherwise:
cmp w sf_shift,0 ;suppress surface shift ?
je draw ;no, then draw anyway
pop cx
pop ax
jmp finished ;polygon will not be drawn
draw:
xchg ax,cx ;coordinates in correct sequence
direct_ok:
cmp texture,1 ;use textures ?
jne norm_fill ;no, then normal fill
call hline_texture ;draw horizontal texture line
pop cx
pop ax
jmp loopl ;and continue
norm_fill:
call hline ;draw horizontal line
pop cx
pop ax
jmp loopl ;and continue
finished:
popa
pop bp
ret
fillpol endp
code ends
end