Nous allons voir à présent la routine pour afficher des sprites
PRELIMINAIRE
DESCRIPTION DE LA ROUTINE


PRELIMINAIRE

L'affichage dans l'écran:

Il n'y a pas de grosse difficulté à programmer une routine d'affichage de sprite. Il suffit de copier les octets de l'image du sprite dans la mémoire écran sur la largeur puis sur la hauteur. Comme un sprite ne fait pas toujours la taille exacte d'un rectangle de part sa forme, il faut lui appliquer une transparence sur une couleur. Cette transparence est dans ce cas l'index de couleur 0 ou la couleur 0. Donc il suffit de sauter cette couleur. Ce choix de couleur n'est pas aléatoire. Il est très facile de faire un test de valeur 0 de façon rapide en assembleur.
Tout se passe très bien jusqu'au moment ou le sprite va sortir de l'écran. Nous allons nous retrouvez avec des octets non prévus sur des zones non connues ou dangereuses. Le paragraphe suivant traître de ce problème.

 

L'affichage dans et hors écran:

Que de problème si le sprite sort de l'écran !. Il est inconcevable d'utiliser une routine qui ne gère pas les sorties d'écran !.
Sous ce nom se cache un mot bien connu: le clipping. Il faut découper le sprite de façon qu'il puisse être afficher n'importe où même si il se trouve entièrement hors de l'écran.
La fonction que je vous livre permet de placer un sprite où vous voulez même en coordonnée 65000 si ça vous chante. Cette routine fonctionne exclusivement dans le mode 320x200x256c ou mode 0x13.
Pour cela, la routine va en premier lieu tester les coordonnées par rapport aux bord de l'écran et en recalculer la hauteur ainsi que la largeur. Si le sprite est hors écran, c'est fini.


DESCRIPTION DE LA ROUTINE

 

Le plan du buffer se trouve dans la page en cliquant ici.

Les zones utilisées sont données en rouge.

void affiche_sprite(byte *buf,word nu,short x,short y)
{

asm volatile("
pushw %%ds
aff_sprite:
movl %0,%%edi
aff_sprite1:
movw %2,%%ax /*x*/
movw %3,%%bx /*y*/
movw %%ax,
600006(%%edi)
movw %%bx,
600008(%%edi)
pushl %%edi
addl $580000,%%edi /*p sur def spr*/
xorl %%eax,%%eax
movw %1,%%ax
shll $3,%%eax
addl %%eax,%%edi
movw 4(%%edi),%%cx
movw 6(%%edi),%%dx

popl %%edi
push %%edi
addl $585000,%%edi /*tab adr spr*/
xorl %%eax,%%eax
movw %1,%%ax /*nu sprite*/
shll $2,%%eax
addl %%eax,%%edi
movl (%%edi),%%esi

popl %%edi
movw %%dx,
600014(%%edi)
movw %%cx,
600016(%%edi)
movw $0,
600010(%%edi)
movw $320,
600012(%%edi)
movw
600008(%%edi),%%ax
cmpw $0x0c8,%%ax
jns fin_aff_sprite
movw
600006(%%edi),%%bx
cmpw $0x140,%%bx
jns fin_aff_sprite
voir_sort_yhaut:
xorl %%eax,%%eax
xorl %%ebx,%%ebx
movw
600008(%%edi),%%ax
cmpw $0,%%ax
jns voir_sort_ybas
movw
600014(%%edi),%%bx
negw %%ax
subw %%ax,%%bx
cmpw $1,%%bx
js fin_aff_sprite
movw %%bx,
600014(%%edi)
cwde
movl %%eax,%%ebx
shll $8,%%eax
shll $6,%%ebx
addl %%ebx,%%eax
addl %%eax,%%esi
xorl %%eax,%%eax
movw %%ax,
600008(%%edi)
voir_sort_ybas:
xorl %%eax,%%eax
movw
600008(%%edi),%%ax
addw
600014(%%edi),%%ax
decw %%ax
cmp $0x0c7,%%ax
jle voir_sort_x_gauche
subw $0x0c7,%%ax
cmpw $1,%%ax
js fin_aff_sprite
subw %%ax,
600014(%%edi)
voir_sort_x_gauche:
xorl %%eax,%%eax
movw
600006(%%edi),%%ax
cmpw $0,%%ax
jns voir_sort_x_droite
movw
600016(%%edi),%%bx
negw %%ax
subw %%ax,%%bx
cmpw $1,%%bx
js fin_aff_sprite
addl %%eax,%%esi
movw %%ax,
600010(%%edi)
subw %%ax,
600016(%%edi)
xorl %%eax,%%eax
movw %%ax,
600006(%%edi)
voir_sort_x_droite:
movw
600006(%%edi),%%ax
addw
600016(%%edi),%%ax
cmpw $0x140,%%ax
js bon_pour_aff
subw $0x140,%%ax
subw %%ax,
600016(%%edi)
addw %%ax,
600010(%%edi)
bon_pour_aff:
movl %0,%%edi
xor %%eax,%%eax
movw
600008(%%edi),%%ax
movw %%ax,%%bx
shlw $8,%%ax
shlw $6,%%bx
addw %%bx,%%ax
addw
600006(%%edi),%%ax
pushl %%edi
movl %0,%%edi
addl $64000,%%edi
addl %%eax,%%edi

movw $320,%%bx
popl %%ecx
subw
600016(%%ecx),%%bx
movw
600014(%%ecx),%%dx
movl %%ecx,%%ebx
movw
600016(%%ebx),%%cx
subw %%cx,
600012(%%ebx)
boucle_putspry:
movw
600016(%%ebx),%%cx
pushl %%esi
boucle_putsprx:
movb (%%esi),%%al
cmpb $0,%%al
jz saut_ce_pixel
movb %%al,(%%edi)
saut_ce_pixel:
incl %%esi
incl %%edi
decw %%cx
jnz boucle_putsprx
popl %%esi
xorl %%eax,%%eax
movw
600012(%%ebx),%%ax
addl %%eax,%%edi
addl $320,%%esi
decw %%dx
jnz boucle_putspry
fin_aff_sprite:


fin_routine:
popw %%ds"
:
: "m" (buf), "m" (nu), "m" (x), "m" (y));

}

Les explications:

La première zone en marron référençant l'offset 580000 permet de prendre dans une copie de definition_sprite[] la largeur et hauteur.
La deuxième zone en marron référençant l'offset 585000 permet de prendre l'adresse pré calculée de l'image du sprite sur l'image PCX.
L'écran final d'offset
64000 recevra le sprite. Ce calcul de l'adresse est indiqué par les 3 trois lignes en bleu dans la fonction. La 1er récupère l'adresse du buffer, la 2éme additionne 64000 pour pointer sur l'écran de travail, et la 3ème donne l'adresse par addition de l'emplacement d'affichage du sprite.