Fermer2
GoldenCrystalLe 27/08/2003 à 14:43
J'avais besoin d'une routine de sessin de sprite spécifique pour mon je de zelda et j'ai programmé celle-là (une version pour ti 89 et une version pour ti92+/v200). J'aimerais avoir votre avis. | Assembly Source File | Created 26/08/2003; 23:34:07 .global sprite_draw_masked_89 .data | dessine un sprite avec du clipping | J'ai décidé de faire une version différente selon la machine car c'était le moyen d'avoir le code le plus rapide | étant donné les différences de l'affichage du jeu entre la ti89 et les TI92+ et V200 | void sprite_draw_masked(void *plane0, void *plane1, short x, short y, const unsigned short *sprite_data); sprite_draw_masked_89:      |illegal      movem.l %d0-%d7/%a0-%a6,-(%sp)      | lecture de x et de y      move.w 72(%sp),%d0 | je stocke la variable x dans d0      moveq.l #0,%d1 | la partie haute de d1 sera ansi vide      move.w 74(%sp),%d1 | et y dans d1      | Teste la visibilité.      | si le sprite est complètement hors de la zone visible, la routine se termine immédiatement      cmpi.w #-16,%d0 | test de x par la gauche      jble _sprt_msk_89_end      cmpi.w #160,%d0 | test de x par la droite      jbge _sprt_msk_89_end      cmpi.w #-16,%d1 | test de y par le haut      jble _sprt_msk_89_end      cmpi.w #100,%d1 | test de y par le bas      jbge _sprt_msk_89_end      | Tous les tests ont été passés, donc on peut continuer normalement      move.l 64(%sp),%a0 | Je stocke plane0 dans a0      move.l 68(%sp),%a1 | et plane1 dans a1      move.l 76(%sp),%a2 | Je stocke sprite_data dans a2      moveq.l #16,%d2 | J'initialise le compteur de la boucle dans d2 (je fais ça maintenant car c'est nécéssaire)      | Si y est négatif, je dois commencer à dessiner plus bas      tst.w %d1      jbge _sprt_msk_89_y_test_2 | je saute directement au deuxième test      add.w %d1,%d2 | Il faut garder en mémoire que d1 ne sera jamais plus petit que -15 donc d2 sera tjrs positif      neg.w %d1      lsl.w #1,%d1 | Multiplication par 2 puisque le sprite fait 2 octets par ligne      adda.l %d1,%a2 | J'augmente le pointeur du sprite (la hauteur du dessin a diminué)      moveq.l #0,%d1 | Je mets d1 (y) à 0 pour le calcul des addresses dans les plans      jbra _sprt_msk_89_calculate_addresses | Le test suivant n'est pas nécéssaire, daonc on le saute      | Si le sprite dépasse un peu en bas, je dois diminuer la hauteur du dessin _sprt_msk_89_y_test_2:      cmpi.w #85,%d1 | 85 + 16 = 101 et 101 > 100      jblt _sprt_msk_89_calculate_addresses      move.l %d1,%d3 | d3 était inutilisé jusqu'à maintenant (utilisation temporaire)      sub.w #84,%d3      sub.w %d3,%d2 | Je diminue le compteur      | Partie suivante: calcul du décalage par rapport aux adresses des plans _sprt_msk_89_calculate_addresses:      moveq.l #0,%d3      mulu #30,%d1 | d1 est obligatoirement positif, donc mulu convient très bien      move.l %d1,%d3      move.l %d0,%d1      lsr #3,%d1 | divise x par 8 pour obtenir l'adresse de l'octet qui contient le premier pixel du sprite      bclr.b #0,%d1 | S'assure d'obtenir une adresse paire (pour pouvoir utiliser des longs...)      add.w %d1,%d3      | Ajoute le décalage calculé dans d3 aux pointeurs plane0 et plane1      adda.l %d3,%a0      adda.l %d3,%a1      | Calcule les adresses des deux autres "plans" du sprite (foncé et masque) - on peut se passer de ça et faire autrement (utiliser 32(%a2) et 64(%a))      movea.l %a2,%a3      adda.l #32,%a3      movea.l %a3,%a4      adda.l #32,%a4      | Calcule le nombre de bits à décaler vers la gauche      move.w %d0,%d1 | Je dois toujours préserver d0, donc je le copie dans d1      and.w #0xF,%d1      neg.w %d1      addi.w #16,%d1 | Le calcul du nombre de décalages vers la gauche est ausi simple que ça :)      | Teste si le sprite dépasse vers la gauche      tst.w %d0      jbge _sprt_msk_89_x_test_2      move.l #0xFFFF,%d3 | Masque pour ne pas endommager les autres données placé dans d3      | Teste si le sprite dépasse vers la droite _sprt_msk_89_x_test_2:      cmpi.w #145,%d0      jblt _sprt_msk_89_drawnormal      move.l #0xFFFF0000,%d3 | Le masque est mis dans d3 _sprt_msk_89_out_of_screen:      moveq.l #0,%d5 | Efface d5 en entier      move.l %d5,%d6      move.l %d6,%d7      | Charge une ligne complète du sprite et la décale vers la gauche      | Puis lui applique le masque contenu dans d3      move.w (%a2)+,%d5      lsl.l %d1,%d5      and.l %d3,%d5      move.w (%a3)+,%d6      lsl.l %d1,%d6      and.l %d3,%d6      move.w (%a4)+,%d7      lsl.l %d1,%d7      and.l %d3,%d7      not.l %d7 | Inverse d7      | Traîtement du light plane      move.l (%a0),%d4      and.l %d7,%d4      or.l %d5,%d4      move.l %d4,(%a0)      adda.l #30,%a0      | Traîtement du dark plane      move.l (%a1),%d4      and.l %d7,%d4      or.l %d6,%d4      move.l %d4,(%a1)      adda.l #30,%a1      subq #1,%d2      bne _sprt_msk_89_out_of_screen      jbra _sprt_msk_89_end _sprt_msk_89_drawnormal:      moveq.l #0,%d5 | Efface d5 en entier      move.l %d5,%d6      move.l %d6,%d7      | Charge une ligne complète du sprite et la décale vers la gauche      move.w (%a2)+,%d5      lsl.l %d1,%d5      move.w (%a3)+,%d6      lsl.l %d1,%d6      move.w (%a4)+,%d7      lsl.l %d1,%d7      not.l %d7 | Inverse d7      | Traîtement du light plane      move.l (%a0),%d4      and.l %d7,%d4      or.l %d5,%d4      move.l %d4,(%a0)      adda.l #30,%a0      | Traîtement du dark plane      move.l (%a1),%d4      and.l %d7,%d4      or.l %d6,%d4      move.l %d4,(%a1)      adda.l #30,%a1      subq #1,%d2      bne _sprt_msk_89_drawnormal _sprt_msk_89_end:      movem.l (%sp)+,%d0-%d7/%a0-%a6      rts