home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Interdit
/
pc-interdit.iso
/
graph
/
sprites.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-10-17
|
11KB
|
248 lines
Unit Sprites;
Interface
Type SpriteTyp=Record {structure d'un bloc de données décrivant un sprite}
Adr:Pointer; {pointe sur les données graphiques }
dtx,dty:Word; {largeur et hauteur en pixels }
px,py, {position courante, facultatif *}
sx,sy:Integer; {vitesse courante, facultatif *}
End;
{* : facultatif veut dire que les routines GetSprite et PutSprite n'utilisent
pas ces variables qui ne servent qu'à faciliter une gestion par le programme
principal }
Procedure GetSprite(Ofs,dtx,dty:Word;var dSprite:SpriteTyp);
{lit un sprite de largeur dtx, de hauteur dty, à l'offset ofs de vscreen,
dSprite est l'enregistrement qui va mémoriser le sprite}
Procedure PutSprite(pg_ofs,x,y:Integer;sSprite:spritetyp);
{copie un sprite de la mémoire centrale (situation et taille dans sSprite)
vers la mémoire d'écran en page pg et coordonnées (x,y}
Implementation
Uses ModeXLib;
Var i:Word;
Procedure GetSprite;
Var ppp:Array[0..3] of Byte; {table avec le nombre de pixels à copier par plan }
Skip:word; {nombre d'octets à sauter}
Plane_Count:Word; {nombre de plans déjà copiés }
Begin
GetMem(dSprite.adr,dtx*dty); {alloue de la mémoire }
dSprite.dtx:=dtx; {prend note de la largeur et de la hauteur }
dSprite.dty:=dty; {dans l'enregistrement du sprite }
i:=dtx shr 2; {nombre de groupes de 4 octets}
ppp[0]:=i;ppp[1]:=i; {correspond au nombre minimum d'octets à copier }
ppp[2]:=i;ppp[3]:=i;
For i:=1 to dtx and 3 do {mémorise en ppp les pixels restants }
Inc(ppp[(i-1) and 3]); {ajoute les pixels en commençant par le plan de début}
Plane_Count:=4; {copie 4 plans }
asm
push ds
mov di,word ptr dSprite {charge d'abord un pointeur sur le bloc de données}
les di,[di] {es:di va pointer sur les données graphiques}
lea bx,ppp {bx référence le tableau ppp}
lds si,vscreen {charge un pointeur sur l'écran}
add Ofs,si {ajoute l'offset des données du sprite proprement dites}
@lcopy_plane: {boucle des plans}
mov si,ofs {si reçoit l'adresse de début des données du sprite }
mov dx,dty {le compteur d'ordonnées reçoit le nombre de lignes}
xor ah,ah {efface ah}
mov al,ss:[bx] {charge en al l'élément courant de ppp}
shl ax,2 {on déplace des groupes de 4 octets}
sub ax,320 {calcule la différence par rapport à 320}
neg ax {convertit ax-320 en 320-ax }
mov skip,ax {sauvegarde le résultat en Skip }
@lcopy_y: {boucle des lignes }
mov cl,ss:[bx] {tire la largeur du tableau ppp }
@lcopy_x: {boucle des pixels }
movsb {copie un octet }
add si,3 {point suivant dans le même plan }
dec cl {copie tous les points de la ligne }
jne @lcopy_x
add si,skip {passe à la ligne suivante }
dec dx {copie toutes les lignes }
jne @lcopy_y
inc bx {pointe sur l'élément suivant de ppp }
inc ofs {se positionne sur le nouveau début de plan }
dec plane_count {copie tous les plans }
jne @lcopy_plane
pop ds
End;
End;
Procedure PutSprite;
var plane_count, {nombre de plans déjà copiés }
masqueplan:Byte; {masque Write-Plane dans le registre 2 du TS }
Skip, {nombre d'octets à sauter }
ofs, {offset courant dans la mémoire d'écran }
plane, {numéro du plan courant }
Largeur, {largeur en octets à copier dans une ligne }
dty:Word; {hauteur }
source:Pointer; {pointe sur les données graphiques lorsque ds varie }
clip_lt, clip_rt:integer; {nombre de pixels restant à droite et à gauche }
clipact_lt, {nombre d'octets restants }
clipact_rt, {pour le plan courant }
clip_dn,clip_up:Word; {nombre de lignes restant en haut et en bas }
ppp:Array[0..3] of Byte; {nombre de pixels par plan }
cpp:Array[0..3] of Byte; {nombre d'octets restants par plan }
Begin
if (x > 319) or {pas de dessin }
(x+sSprite.dtx < 0) or {sprite en dehors de l'écran ?}
(y > 199) or
(y+sSprite.dty < 0) then exit;
clip_rt:=0; {normalement pas de clipping }
clip_lt:=0; {-> toutes les variables de clipping à 0 }
clip_dn:=0;
clip_up:=0;
clipact_rt:=0;
clipact_lt:=0;
with sSprite do begin
if y+dty > 200 then begin {premier cas de clipping : en bas}
clip_dn:=(y+dty-200); {nombre de lignes restantes }
dty:=200-y; {réduit la hauteur du sprite }
End;
if y<0 then begin {deuxième cas de clipping: en haut}
clip_up:=-y; {nombre de lignes restantes }
dty:=dty+y; {réduit la hauteur du spr }
y:=0; {ordonnée de départ nulle, au bord supérieur de l'écran }
End;
if x+dtx > 320 then begin {troisième cas de clipping : à droite }
clip_rt:=x+dtx-320; {pixels restants }
dtx:=320-x; {réduit la largeur }
End;
if x<0 then begin {quatrième cas de clipping : à gauche }
clip_lt:=-x; { nombre de pixels restants }
plane:=4-(clip_lt mod 4); {nouveau plan de début pour la colonne 0 }
plane:=plane and 3; {ramène à l'intervalle 0..3 }
ofs:=pg_ofs+80*y+((x+1) div 4) - 1; {Ofs sur groupe de 4 octets }
x:=0; {colonne de début }
End Else Begin {à droite pas de clipping?}
plane:=x mod 4; {alors calcul conventionnel du plan }
ofs:=pg_ofs+80*y+(x div 4); {et de l'offset }
End;
End;
Source:=sSprite.adr; {mémorise pointeur sur les données graphiques }
dty:=sSprite.dty; {et hauteur dans variables locales }
Largeur:=0; {initialise largeur et Skip }
Skip:=0;
i:=sSprite.dtx shr 2; {nombre de groupes de 4 octets complets}
ppp[0]:=i;ppp[1]:=i; {correspond au nombre minimum d'octets à copier }
ppp[2]:=i;ppp[3]:=i;
For i:=1 to sSprite.dtx and 3 do{mémorise en ppp les pixels restants }
Inc(ppp[(plane+i - 1) and 3]);{ajoute les pixels en commençant par le plan de début }
i:=(clip_lt+clip_rt) shr 2;
cpp[0]:=i;cpp[1]:=i; {valeurs par défaut du clipping}
cpp[2]:=i;cpp[3]:=i;
For i:=1 to clip_rt and 3 do {si clipping à droite }
Inc(cpp[i-1]); {enregistre le nombre dans les plans }
For i:=1 to clip_lt and 3 do {si clipping à gauche }
Inc(cpp[4-i]); {enregistre le nombre dans les plans }
asm
mov dx,3ceh {met le registre 5 du GDC (GDC Mode)}
mov ax,4005h {en mode Write 0 }
out dx,ax
push ds {sauve ds}
mov ax,0a000h {charge le segment de destination (VGA) }
mov es,ax
lds si,source {ds:si va pointer sur la source (données graphiques ) }
mov cx,plane {masque de plan de départ }
mov ax,1 {décale le bit 0 vers la gauche }
shl ax,cl
mov masqueplan,al {sauve le masque }
shl al,4 {le reporte dans le quartet supérieur }
or masqueplan,al
mov plane_count,4 {4 plans à copier }
@lplane: {boucle des plans }
mov cl,byte ptr plane {charge le plan courant }
mov di,cx {en di}
mov cl,byte ptr ppp[di] {charge le nombre ppp corrrespondant en cx }
mov byte ptr Largeur,cl {recalcule Skip }
mov ax,80 {forme la différence 80-largeur }
sub al,cl
mov byte ptr skip,al {et la reporte dans skip }
mov al,byte ptr cpp[di] {charge la largeur de clipping spécifique au plan }
cmp clip_lt,0 {si pas de clipping à gauche, voyons à droite }
je @adroite
{sauve en clip_act_lt clip. plan + spécif.}
mov clipact_lt,ax
sub Largeur,ax {réduit le nombre d'octets à copier }
jmp @clip_rdy {à droite pas de clipping}
@adroite: {si pas de clipping à gauche }
mov clipact_rt,ax {clipping pour tous les plans en clip_act}
@clip_rdy:
mov ax,Largeur {calcule la largeur totale en octets }
add ax,clipact_rt
add ax,clipact_lt
mul clip_up {multiplie par le nombre de lignes du clipping supérieur }
add si,ax {octets non représentés }
mov cx,Largeur {charge la largeur en cx }
or cl,cl {largeur 0, plan terminé }
je @planfini
mov di,ofs {offset de destination dans l'écran en di}
mov ah,masqueplan {réduit le masque de plan aux bits [0..3] }
and ah,0fh
mov al,02h {active le registre 2 du TS (Write Plane Mask)}
mov dx,3c4h
out dx,ax
mov bx,dty {initialise le compteur de lignes y }
@lcopy_y: {boucle des lignes y }
add si,clipact_lt {pointeur source au-delà clipping gauche }
add di,clipact_lt {idem pour le pointeur de destination }
@lcopy: {boucle des pixels }
lodsb {lit un octet }
or al,al {si 0, pas de traitement }
je @Valeur0
stosb {sinon copie }
@entry:
loop @lcopy {suite de la boucle }
add si,clipact_rt {après ligne complète, clipping droit }
dec bx {incrémente le compteur de lignes }
je @planfini {compteur de lignes = 0, plan suivant }
add di,skip {sinon passe en début de ligne suivante }
mov cx,Largeur {réinitialise le compteur de colonnes }
jmp @lcopy_y {retourne dans la boucle des lignes }
@valeur0: {couleur du sprite 0 }
inc di {saute l'octet de destination }
jmp @entry {retourne dans la boucle }
@planfini: {fin de la boucle des lignes }
mov ax,Largeur {calcul la largeur globale en octets }
add ax,clipact_rt
add ax,clipact_lt
mul clip_dn {multiplie par le nombre de lignes du clipping inf. }
add si,ax {octets non réprésentés }
rol masqueplan,1 {masque le plan suivant }
mov cl,masqueplan {a-t-on sélectionné le plan 0 ?}
and cx,1 {(bit 1 à 1), alors}
add ofs,cx {incrémente de 1 l'offset de destination (cx bit 1 !)}
inc plane {incrémente le numéro de plan (indice dans ppp) }
and plane,3 {réduit de 0 à 3 }
dec plane_count {déjà 4 plans copiés, on arrête }
jne @lplane
pop ds {restaure ds, ciao}
End; {asm}
End;
Begin
End.