J'ai développé il y a quelques temps des routines d'affichage de sprites en double buffering, et je viens de les mettre sur mon site. J'aimerais avoir si possible des avis, des conseils et des critiques constructives.
Inscription : 15 Août 2008, 13:00 Message(s) : 968 Localisation : Troyes, France
Salut , j'ai regardé vite fait et il y a quelques petites choses qui m'ont sauté aux yeux.Tout d'abord , ta routine a été testée sur une autre zone que #C000->#FFFF ?
Citer :
LD A,C DEC A CP 0 JP Z,SPREND0 LD C,A
un simple DEC C/jr z,xxxx fait aussi bien l'affaire et c'est nettement plus rapide.Je te recommande d'utiliser au max jr sur le CPC car contrairement à la doc il est plus rapide qu'un jp (à cause des temps de "pause" imposés au Z80 par le GA)
Par contre , ta routine avec maskage est pas top même si l'idée d'avoir une sélection est bonne car là ça doit être trèèèès lent.Le mieux étant d'avoir une routine par mode que tu branches directement en début de fonction.Pour le maskage , le top est évidemment d'avoir le masque et les pixels contigues en mémoire mais ça a l'inconvénient de prendre le double de place. Une méthode moins rapide mais plus légère que d'utiliser des conditionnelles (cp/jr/jp ce qui est très lent) est d'utiliser une table de masquage de 256 octets (1 par mode soit 768 octets au total)
_________________ "NOP" tel est le programme parfait ! court, rapide, lisible et sans bugs (connus)
Bonjour et merci beaucoup pour tes précieux conseils. J'ai commencé à optimiser le code comme tu me l'as dit. Tout à l'heure, je ferai des routines séparées pour le mode 0 et 1. (le mode 2 n'est pas nécessaire, je pense)
Par contre, je voulais savoir :
Citer :
Salut , j'ai regardé vite fait et il y a quelques petites choses qui m'ont sauté aux yeux.Tout d'abord , ta routine a été testée sur une autre zone que #C000->#FFFF ?
J'alterne la mémoire vidéo entre #4000 et #C000 (pour le double buffer) en m'assurant que l'utilisateur ait juste à rentrer dans chaque RSX une valeur comprise entre #C000 & #FFFF. J'ai fait quelque modifications sur le code pour l'optimiser là aussi. Je ne sais pas si c'est suffisant ?
Citer :
Une méthode moins rapide mais plus légère que d'utiliser des conditionnelles (cp/jr/jp ce qui est très lent) est d'utiliser une table de masquage de 256 octets (1 par mode soit 768 octets au total)
Existe t'il un exemple sur le web pour cette technique ?
_________________ Dj pour la musique, Poke pour la mémoire
Inscription : 15 Août 2008, 13:00 Message(s) : 968 Localisation : Troyes, France
Ce qui me choque pour ton changement de ligne c'est le :
Code :
LD A,H ADD #08 LD H,A ; Calcul de la prochaine ligne ecran. JR C,SPRERR1 ; Rectifier en cas de depassement.
Si ton écran est en #C000 , sur la dernière rasterline de ton caractère en cours ,tu vas avoir une adresse qui ressemble à ça 0b11111xxx donc en testant la carry ça fonctionne bien.Par contre avec un écran en #4000 , tu aura une valeur 0b01111xxx donc le resultat ensuite sera 0b10000xxx ce qui te fera sauter en page #8000 ! Une méthode pour palier à ça peut être de tester le groupe de bits correspondants à ta rasterline soit les bits 3,4,5, si il sont tous à 1 , tu les reset et tu changes de caractère, ce qui te fait une routine universelle.Sinon , quand tu est en page #4000 , tu peux te contenter de tester le bit 7 , ce qui te dira si tu as fait un dépassement et alors tu reset la rasterline.Si tu est vraiment interessé , il y encore une autre méthode qui te permet d'éviter tous ces tests mais elle demande de connaitre la coordonnée Y (réelle , c'est à dire 0 est en haut à gauche) pour effectuer un branchement.
Pour optimiser , ça peut sembler évident mais ça va mieux en le disant, il vaut mieux concentrer tes efforts sur la boucle intérieure (celle de la largeur pour toi) car c'est la plus répétée. Quand tu as juste une opération de transfert sans opération sur les octets , un ldir sera plus rapide qu'une boucle sur mesure. Après , il y a plein de méthodes pour optimiser mais vu que tes routines sont appelées du Basic , pas besoin d'en faire trop. Je te recommanderai d'éviter de charger des valeurs directement en mémoire (genre ld A,(#xxxx)) ou depuis les registres d'index (ld A,(IX/IY+z)).Par contre , si IX ou IY ne sert pas et que tu est à cours de registres , tu peux toujours utiliser IXL,IXH,IYL,IYH comme compteur , la pénalité n'est que de 1µs par rapport aux registres "réguliers".
DjPoke a écrit :
Existe t'il un exemple sur le web pour cette technique ?
A ma connaissance non , mais c'est une technique très simple. Dans un premier temps , il faut créer une table de masquage.Elle doit commencer à une adresse multiple de 256 octets.Tu vas de 0 à 255 et pour chaque valeur , tu testes les pixels.Si le pixel est vide ,tu mets tous ses bits à 0 , sinon à 1. Par exemple : 0b10001000 va te donner le masque 0b10101010. (en mode 0 j'entends, en mode 1 le principe est le même sauf que tu travailles avec 4 groupes de 2 bits) Ensuite , la boucle intérieure de ton code d'affichage, de tête, ressemble à ça
Code :
DE = données du sprite BC = adresse écran H = octet haut de l'adresse de la table IYL = largeur du sprite loop ld A,(DE) ;va chercher les pixels du sprite ld L,A ;stocke la valeur dans L pour pointer sur l'octet de masque ld A,(BC) ;récupère la valeur à l'écran and (HL) ;applique le masque or L ;ajoute les pixels ld (BC),A ;écrit le résultat à l'écran inc DE ;adresse suivant sur le sprite inc BC ;idem écran dec IYL ;boucle le nombre d'octets en largeur jr nz,loop
Ce système de table est utile car si tu comptes afficher tes sprites en mirroir , tu peux te créer une table qui génère le masquage et l'inversion de pixels en même temps.
J'ai trouvé ça dans mes archives , c'est un bout de code qui crée une table de maskage en mode 0 :
Code :
;create mask table - 256 bytes .create_mask_table
ld HL,mask_table
.create_mask_loop ld B,#FF ;left pixie ld A,L and %10101010 jr z,mask_noleft
ld A,%01010101 and B ld B,A .mask_noleft ;right pixie ld A,L and %01010101 jr z,mask_noright
ld A,%10101010 and B ld B,A .mask_noright
ld (HL),B inc L jr nz,create_mask_loop ret
Si tu as d'autres questions , n'hésites , c'est un plaisir d'aider quelqu'un qui veut faire quelque chose
_________________ "NOP" tel est le programme parfait ! court, rapide, lisible et sans bugs (connus)
Inscription : 28 Août 2008, 23:41 Message(s) : 258
Salut Si tu veux éviter de faire 2 routines différentes pour gérer l'affichage de tes sprites, il suffit de déplacer la page située habituellement entre C000 et FFFF en 4000 via le gate array (OUT &7F00,&C3). Pour remettre la page à sa place OUT &7F00,&C0
Utilisateur(s) parcourant ce forum : Aucun utilisateur inscrit et 48 invité(s)
Vous ne pouvez pas publier de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas insérer de pièces jointes dans ce forum