home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Interdit
/
pc-interdit.iso
/
graph
/
poly.asm
< prev
next >
Wrap
Assembly Source File
|
1994-10-17
|
16KB
|
485 lines
.286
w equ word ptr
b equ byte ptr
include texture.inc ;inclut les macros de texture
setnewlinel macro ;n'utiliser ici que ax et bx!
local dylpos,dxlpos,dxlgrand,macro_fini
mov bx,4043h ;code pour inc ax (en bh) et inc bx (en bl)
mov bp,gauche
mov ax,poly2d[bp+8] ;sauvegarde les coordonnées de destination
mov xl1,ax
mov ax,poly2d[bp+10d]
mov yl1,ax
mov ax,poly2d[bp] ;x,y début gauche dans var glob
mov xl0,ax
sub ax,xl1 ;forme delta x
inc xl1 ;pour la condition d'arrêt
neg ax ;xl1-xl0
jns dxlpos ;dxl négatif ?
neg ax ;alors valeur absolue
mov bh,48h ;code pour dec ax (dec xl0)
sub xl1,2 ;extension négative des coordonnées de destination
dxlpos:
mov dxl,ax ;sauvegarde glob.
mov incflagl,ax ;mémorise dans l'indicateur d'incrémentation
mov ax,poly2d[bp+2]
mov yl0,ax
sub ax,yl1 ;forme |delta y|
inc yl1 ;pour la condition d'arrêt
neg ax
jns dylpos ;négatif ?
neg ax ;alors valeur absolue
mov bl,4bh ;code pour dec bx (dec yl1)
sub yl1,2 ;extension négative des coordonnées de destination
dylpos:
mov dyl,ax ;sauvegarde glob.
cmp dxl,ax ;dx < dy
jae dxlgrand
neg incflagl ;changement de signe pour l'indicateur d'incrémentation
dxlgrand:
mov cs:byte ptr incxl,bh ;effectuer l'automodification
mov cs:byte ptr incyl,bl
cmp texture,1 ;besoin de texture ?
jne macro_fini ;non, on passe
txt_makevarl ;sinon calcule les variables de texture
macro_fini:
mov ax,xl0
mov bx,yl0
mov si,incflagl
endm
setnewliner macro ;n'utiliser ici que cx et dx!
local dyrpos,dxrpos,dxrgrand,macro_fini
mov cx,4142h ;code pour inc cx (en ch) et inc dx (en cl)
mov bp,droite
mov dx,poly2d[bp] ;lit les coordonnées de destination
mov xr1,dx
mov dx,poly2d[bp+2]
mov yr1,dx
mov dx,poly2d[bp+8] ;x,y à droite dans var glob.
mov xr0,dx
sub dx,xr1 ;forme |delta x|
inc xr1 ;pour la condition d'arrêt
neg dx
jns dxrpos ;négatif ?
neg dx ;opposé
mov ch,49h ;code pour dec cx
sub xr1,2 ;extension négative des coordonnées de destination
dxrpos:
mov dxr,dx ;sauvegarde en var glob
mov incflagr,dx
mov dx,poly2d[bp+10d] ;forme |delta y|
mov yr0,dx
sub dx,yr1
inc yr1 ;pour la condition d'arrêt
neg dx
jns dyrpos ;négatif ?
neg dx ;opposé
mov cl,4ah ;code pour dec dx
sub yr1,2 ;extension négative des coordonnnées de destination
dyrpos:
mov dyr,dx ;sauvegarde en var glob
cmp dxr,dx ;dx < dy ?
jae dxrgrand
neg incflagr ;alors changement de signe pour l'indicateur d'incrémentation
dxrgrand:
mov cs:byte ptr incxr,ch ;automodification
mov cs:byte ptr incyr,cl
cmp texture,1 ;besoin de texture ?
jne macro_fini ;non, on passe
txt_makevarr ;sinon calcule variables de texture
macro_fini:
mov cx,xr0 ;charge les registres
mov dx,yr0
mov di,incflagr
endm
data segment public
extrn vpage:word ;page d'écran courante
extrn su_cacher ;indicateur pour dessin des faces cachées
extrn verre:Byte; ;indicateur pour surfaces en verre
;variables de texture :
extrn Texture:Byte ;besoin de texture ?
extrn Txt_Data:DataPtr ;tableau de pointeurs sur données graphiques
extrn Txt_Offs:DataPtr ;tableau d'offsets à l'intérieur de l'image de texture
extrn Txt_Taille:DataPtr ;tableau avec indications de dimensions
d_x dd 0 ;abscisse relative
d_y dd 0 ;ordonnée relative
D dd 0 ;déterminant principal
Colonne1 dd 0 ;composants du déterminant principal
dd 0
Colonne2 dd 0
dd 0
ligne_sup dw 0 ;quelles sont les coordonnées utilisées ?
Ligne_inf dw 0
xl_3d dd 0 ;valeurs courantes des coordonnées 3d pendant le remplissage
yl_3d dd 0
zl_3d dd 0
xr_3d dd 0
yr_3d dd 0
zr_3d dd 0
inc_xl dd 0 ;valeurs à ajouter aux coordonnées courantes
inc_yl dd 0
inc_zl dd 0
inc_xr dd 0
inc_yr dd 0
inc_zr dd 0
;variables pour l'algorithme de remplissage
point_haut dw 0 ;maintenu en dx pendant la recherche
y_haut dw 0 ;maintenu en bx
gauche dw 0 ;point du côté gauche
droite dw 0 ;point du côté droit
xl0 dw 0 ;valeurs courantes des points de début et de fin à gauche
yl0 dw 0
xl1 dw 0
yl1 dw 0
xr0 dw 0 ;idem à droite
yr0 dw 0
xr1 dw 0
yr1 dw 0
dxl dw 0 ;Delta X, Y pour les deux côtés
dyl dw 0
dxr dw 0
dyr dw 0
incflagl dw 0 ;indicateurs pour savoir quand y doit être incrémenté
incflagr dw 0 ;sorte de "pente"
data ends
code segment public
assume cs:code,ds:data
extrn polycol:word ;couleur de surface
extrn polyn:word ;nombre de sommets
extrn poly2d:word ;tableau de coordonnées 2D
extrn poly3d:word ;tableau de coordonnées 3-D
extrn delta1,delta2:word ;vecteurs de plan
extrn bline:near ;dessine un segment
lambda1 dd 0 ;coordonnées affines
lambda2 dd 0
inc_lambda1 dd 0 ;pas d'incrémentation
inc_lambda2 dd 0
plane dw 0002h ;plan courant à fixer
x0 dw 0 ;coordonnées de segment
y0 dw 0
x1 dw 0
zz dw 0 ;points restant à tracer
extrn Txt_Nr:Word ;numéro de la texture à dessiner
public drawpol
;dessine un modèle en fil de fer des faces en Poly2d
drawpol proc near
push es
pusha
xor si,si ;indice sur première entrée
mov bp,polyn ;lit le nombre de sommets
@nline:
mov ax,poly2d[si] ;lit les coordonnées dans la table
mov bx,poly2d[si+2]
mov cx,poly2d[si+8]
mov dx,poly2d[si+10d]
push bp
push si
call bline ;dessine un segment
pop si
pop bp
add si,8 ;segment suivant
dec bp ;décrémente le nombre
jne @nline
popa
pop es
ret
drawpol endp
hline proc near ;trace un segment horizontal ax,bx -> cx,bx
pusha
push es
mov x0,ax ;sauve les coordonnées pour usage ultérieur
mov y0,bx
mov x1,cx
sub cx,ax ;calcule le nombre de points à dessiner
jne zzok
inc cx
zzok:
mov zz,cx
cmp verre,1 ;surface de verre ?
jne Solid1
push ax ;oui alors mode GDC : OR
mov dx,3ceh
mov ax,1003h ;registre 3: Function Select
out dx,ax
pop ax
Solid1:
mov dx,3c4h ;port du Timing Sequencer
mov di,0a000h
mov es,di ;sélectionne le segment VGA
mov di,ax ;calcule l'offset
shr di,2 ;(x div 4) + y*80
add di,vpage ;ajoute la page courante
mov bx,y0
imul bx,80d
add di,bx ;le tout dans di
cmp zz,4
jl no_moyen ;< 4 points à dessiner -> pas de groupe de 4
and ax,11b ;les deux bits inférieurs sont importants
je milieu ;si 0 fixe immédiatement des groupes de 4
no_moyen:
mov bx,0f02h ;si no_shift, utiliser ce masque
mov cx,zz ;fixe le nombre de points dans masque
cmp cx,20h ;à partir de 20h le 386 dérape au décalage !
jae no_shift
mov bx,0102h ;prépare le masque
shl bh,cl ;nombre de points = nombre de bits à mettre à 1
dec bh
and bh,0fh
no_shift:
mov cx,ax ;le bon décalage selon le plan de début
and cl,3
shl bh,cl
mov ax,bx ;le masque est fini
sub zz,4 ;décrémente le nombre de points à dessiner
add zz,cx
start:
out dx,ax ;installe le masque d'écriture calculé
mov al,b polycol ;lit la couleur
mov ah,es:[di] ;charge les bascules, uniqt objets en verre
stosb ;installe un octet
milieu:
cmp zz,4
jl termine ;plus de groupe de 4 -> terminus
mov ax,0f02h ;prend tous les plans
out dx,ax ;(zz div 4) calcule les groupes de 4
mov cx,zz
shr cx,2
mov al,b polycol
cmp verre,1 ;face en verre ?
jne Solid
@lp:
mov ah,es:[di] ;charge les bascules, uniqmt objets en verre
stosb ;et réécrit un octet
dec cx
jne @lp
jmp termine
Solid:
rep stosb ;dessine la partie du milieu
termine:
mov cx,x1 ;dessine les pixels restants
and cx,3h
dec zz
js hline_fini ;si plus rien -> c'est fini
mov ax,0102h
shl ah,cl ;crée le masque
dec ah
out dx,ax
mov al,b polycol ;lit la couleur
mov ah,es:[di] ;charge les bascules, uniqmt objets en verre
stosb ;et dessine les points
hline_fini:
mov dx,3ceh ;GDC Mode en position MOVE
mov ax,0003h
out dx,ax
pop es
popa
ret
hline endp
txt_hline ;macro contenant la procédure "hline_texture"
public fillpol
fillpol proc near ;remplit un polygone en mode X
push bp
pusha
cmp texture,1 ;utilise-t-on des textures?
jne Remplir ;non, remplissage simple
txt_Detprinc ;sinon calcule le déterminant principal
Remplir:
xor si,si ;recherche le point le plus haut, sél première entrée
mov cx,polyn ;nombre de sommets
sub cx,2
mov bx,0ffffh ;valeur extrême, interdite
npoint:
mov ax,poly2d[si+2] ;lit y
cmp ax,bx ;compare au minimum courant
ja no_min
mov bx,ax ;fixe un nouveau minimum
mov dx,si
no_min:
add si,8
dec cx ;sommet suivant, si pas 0ffffh
jns npoint
mov point_haut,dx ;sauve en variable globale
mov y_haut,bx ;recherche du point le plus haut achevée
or dx,dx ;gauche = 0 ?
jne dec_valid
mov bx,polyn ;oui : positionner à droite
sub bx,2
shl bx,3
jmp lr_fini ;à l'autre extrémité
dec_valid:
mov bx,dx ;sinon un de moins
sub bx,8
lr_fini:
mov gauche,dx ;sauve en variable globale
mov droite,bx
; ax,bx : coordonnées de départ gauche (xl0,yl0)
; cx/dx : coordonnées de départ droite (xr0,yr0)
; si : indicateur de débordement gauche
; di : indicateur de débordement droite
; bp : pointeur sur point courant
setnewlinel ;charges les variables des segments
setnewliner
boucleg:
cmp ax,xl1
je nouv_ligneg ;si fini -> nouveau segment
cmp bx,yl1
je nouv_ligneg ;sinon poursuite du dessin
or si,si ;indicateur d'incrémentation <= 0
jg flaglgrand
incyl: ;ce passage va être modifié !
inc bx ;y suivant
add si,dxl ;incrémente l'indicateur IncFlag
txt_incl ;coordonnées 3D suivantes
cmp bx,yl1 ;destination atteinte ?
je nouv_ligneg ;alors nouveau segment
jmp gauche_plus ;y augmenté à gauche -> maintenant à droite
flaglgrand:
sub si,dyl ;décrémente Incflag
incxl: ;ce passage va être modifié !
inc ax ;x suivant
jmp boucleg
fini__:
jmp fini
nouv_ligneg:
mov bx,gauche ;prépare l'augmentation
cmp bx,droite
je fini__ ;identique, alors fini
add bx,8 ;gauche suivant
mov ax,polyn ;gauche en fin de liste ?
shl ax,3
sub ax,8 ;détermine la fin
cmp bx,ax ;comparaison
jb fixer_gauche
xor bx,bx ;si oui, alors mise à 0
fixer_gauche:
mov gauche,bx
setnewlinel ;recharge les variables
jmp boucleg
fini_:
jmp fini
gauche_plus:
boucled:
cmp cx,xr1
je nouv_ligned ;si fin -> fixe un nouveau segment
cmp dx,yr1
je nouv_ligned ;sinon poursuit
or di,di ;indicateur d'incrémentation <= 0
jg flagrgrand
incyr: ;ce passage va être modifié !
inc dx ;y suivant
add di,dxr ;incrémente IncFlag
txt_incr
cmp dx,yr1 ;destination atteinte ?
je nouv_ligned ;alors nouveau segment
jmp droite_plus ;à droite y a été augmenté -> trace le segment horiz
flagrgrand:
sub di,dyr ;décrémente Incflag
incxr:
inc cx ;ce passage va être modifié!
jmp boucled
nouv_ligned:
mov dx,droite ;prépare la diminution
cmp dx,gauche
je fini_ ;si égal, alors fini
sub dx,8 ;si précédmt à 0 -> passe à l'autre extrémité
jns fixer_droite
mov dx,polyn
sub dx,2
shl dx,3 ;se positionne à l'extrémité
fixer_droite:
mov droite,dx
setnewliner ;recharge les variables
jmp boucled
droite_plus:
push ax
push cx
cmp cx,ax ;ordre correct ?
jae direct_ok ;alors ok, sinon:
cmp w su_cacher,0 ;dissimuler les faces cachées?
je dessiner ;non, alors on dessine quand même
pop cx
pop ax
jmp fini ;polygone non dessiné
dessiner:
xchg ax,cx ;coordonnées dans le bon ordre
direct_ok:
cmp texture,1 ;a-t-on une texture ?
jne remp_norm ;non, alors remplissage normal
call hline_texture ;dessine segment de texture horizontal
pop cx
pop ax
jmp boucleg ;et on continue
remp_norm:
call hline ;dessine segment horizontal
pop cx
pop ax
jmp boucleg ;et on continue
fini:
popa
pop bp
ret
fillpol endp
code ends
end