Effectivement, en ne mettant que 199 lignes, mon petit bug disparait.
merci pour votre aide, j'ai atteint mon 1er objectif
La routine de Tatayoyode est rapide et compacte mais je ne peux pas réutiliser la fonction me donnant l'adresse de la ligne que j'ai principalement imaginé pour dessiner mon sprite.
Inscription : 28 Août 2008, 23:41 Message(s) : 258
Effectivement, le chapitre optimisation viendra après. Le coup du changement de ligne n'a pas forcément été évident pour chacun de nous la première fois
Par contre, tu devrais retirer ta sauvegarde de sp, y compris le "call fin", qui ne servent à rien. Car placé ainsi, cela dénote que tu ne maitrises pas encore bien la chose (si ta routine "init" avait été une sous sous routine, bouclage assuré via "fin").
Admettons que sp vaut &c000. Lorsque tu fais un "call init" tu mets sur la pile l'adresse de l'instruction suivant le "call init", soit l'adresse ou se trouve l'instruction "call EffaceEcran". Dans "init", le registre sp vaut alors &C000-2 et c'est ce que tu mets dans le ld sp dans "fin". Lorsque tu fais un ret dans init, le registre sp revient à &C000. Le "call fin" remet sp à &C000-2 et le ld sp,&C000-2 est donc inutile.
Inscription : 28 Août 2008, 23:41 Message(s) : 258
Citer :
Et vous comment auriez vous fait l'équivalent ?
Tout dépend si tu veux juste passer d'une ligne à l'autre ou calculer une adresse à partir de y, voire même de x (pour un sprite, je suppose que c'est ce que tu cherches)
Imagine que tu pré-calcules dans une table de 200x2 octets toutes les adresses de début de ligne (C000, C800, D000, D800, ...., C050, C850, ...) dans une table T. Il te suffit pour trouver l'adresse de la ligne de lire [T+(yx2)] Tu peux écrire ça en très peu de cycles. Pour connaitre l'adresse en fonction de x, il suffit de diviser x par 2 en mode 0, 4 en mode 1 et 8 en mode 2, et d'additionner le résultat à l'adresse de la ligne. Il ne te reste plus qu'à l'écrire
Une petite version personnelle, qui garde l'esprit de ton source. C'est normalement un peu plus rapide et plus court, que demande le peuple ?
On peut évidemment encore faire bien mieux, mais bon, le but, c'est plutôt de voir qu'il n'y a pas une seule solution à un problème en assembleur. J'ai viré tout ce qui touchait au SP, ça n'a aucun intérêt en fait dans ce type de routine. Le SP ne doit être sauvegardé que si tu fais des manipulations de la pile qui entreraient en conflit avec le système. Là, ce n'est pas le cas.
Bon, voici la bête .
ORG &8000 NOLIST ; pour Maxam
Ecran Equ &c000 ; definit l'adresse de l'ecran
;###### MAIN ###### Main call Init ; sauvegarde tout ce qui doit l'etre et initialise les parametres call EffaceEcran ret ; bye bye
;###### Init ###### Init
XOR A ; mode 0 JP &BC0E ; definition du mode
;###### EffaceEcran ###### ;###### colorie l'ecran en partant de la derniere ligne ######
; Ici, j'ai pas touche grand chose, il y a juste une petite amelioration ; en terme de vitesse. Le compteur de la boucle_EE_effC est divise par deux, ; car on efface toujours un nombre pair d'octets. ; Accessoirement, le premier octet efface est toujours pair, on peut donc se ; permettre de faire une incrementation de HL uniquement sur L (il ne debordera ; pas).
EffaceEcran ld b,&CC ; la valeur a donner aux pixels ld c,200 ; definit le nb de boucles (lignes)
Boucle_EE_effL ld d,40 ; definit le nb de boucles (colonnes) divise par deux ld a,c ; met dans a la ligne a chercher push bc ; sauvegarde bc push de ; sauvegarde de call Calc_AddrLigne ; cherche l'adresse de la ligne dans HL pop de ; recupere de pop bc ; recupere bc
Boucle_EE_effC
ld (hl),b ; ecrit les 2 pixels inc l ; position adressel ecran suivant ld (hl),b ; ecrit les 2 pixels inc hl ; position adresse ecran suivante
dec d ; decremente le nb de boucles (colonnes) JP NZ,Boucle_EE_effC ; tant qu'on est pas a 0 , on recommance dec c ; decremente le nb de boucles(lignes) JP NZ,Boucle_EE_effL ; tant qu'on est pas a 0 , on recommance ret
;###### Calc_AddrLigne ###### ;###### Calcule l'adresse memoire de la ligne ###### ;###### IN = a numero de ligne (en pixels) ###### ;###### OUT = HL adresse memoire de la ligne ######
; Alors, cette version du calcul est un peu amelioree (moins d'instructions ; pour arriver au meme resultat .
; L'idee de base, c'est de se dire qu'il ne faut pas faire de calculs specifiques ; pour le nombre de lignes (0 a 7), car cette information est par defaut presente dans la ; valeur transmise, c'est le reste de la division par 8 du nombre total de lignes. ; On fait donc un simple AND &7 pour avoir ce nombre.
; Ensuite, une petite amelioration au niveau de rajout de la valeur &800 en fonction ; du nombre de lignes. Au lieu de faire une boucle, on fait un calcul, en fait, une ; simple multiplication par 8.
calc_addrligne
DEC A
LD E,A AND &7 LD D,A ; on a dans D le nombre de lignes a (entre 0 et 7)
LD A,E SRL A SRL A SRL A ; division de A par 8 = nombre de ligne caracteres
LD HL,ecran AND A JR Z,no_50
LD BC,&0050 cal_501 ADD HL,BC DEC A JR NZ,cal_501
no_50 LD A,D ADD A,A ADD A,A ADD A,A ; on multiplie par 8 LD B,A LD C,&0 ADD HL,BC RET
La routine de Tatayoyode est rapide et compacte mais je ne peux pas réutiliser la fonction me donnant l'adresse de la ligne que j'ai principalement imaginé pour dessiner mon sprite. Et vous comment auriez vous fait l'équivalent ?
Salut, Comme le souligne Markerror, utiliser les vecteurs systèmes (&bc29 et &bc26) qui calculent "tout cuit", ne nous apprennent effectivement pas grand chose sur la structure de la mémoire écran du cpc. Je note cependant ta remarque qui comporte le mot "rapide" et forcément à un moment donné lorsque l'on veut aller plus loin, on y coupe pas ! Dans le cadre donc d'un calcul "rapide" d'une adresse écran à partir d'un numéro de ligne (y), l'option tables pré-calculées est, comme le dit Longshot, une solution redoutablement efficace... Alternativement donc au dernier post de Markerror, je te propose ce petit bout de code qui calcul tout ça... à étudier, à adapter et à compléter à ta sauce... :
Code :
org &8000 nolist
ld l,0 ; 1ere ligne (-1 = 0) call calc_addrligne_fast ; on lance le calcul ld (hl),&cc ; on affiche ret ; finito
;### calcul_addrligne_fast ;### in --> l=numero de ligne ;### out --> hl=adresse memoire de la ligne
calc_addrligne_fast ld h,&40 ; h=&40 et l=numero de ligne, sot si l=0, hl pointe en &4000 à savoir sur Table1 ld a,(hl) ; a=(hl) soit &00 inc h ; h=h+1 (cad h=&40+1 soit &41 et donc pointage sur Table2 en &4100) ld h,(hl) ; h=(hl) soit &c0 ld l,a ; l=a soit l=&00 ret ; on a donc en sortie hl=&c000
org &4000 ; table poids faibles adresses ecran en "y" assemblee en &40xx (h=&40 et xx=l=numero de ligne... ) Table1 db &00 ; ligne1_faible db &00 ; ligne2_faible db &00 ; ligne3_faible db &00 ; ligne4_faible db &00 ; ligne5_faible db &00 ; ligne6_faible db &00 ; ligne7_faible db &00 ; ligne8_faible db &50 ; ligne9_faible db &50 ; ligne10_faible ; ...etc... la table doit comprendre autant de db que tu as de lignes... tu peux d'ailleurs faire une routine qui genere cette table...
org &4100 ; table poids forts adresses ecran en "y" assemblee en &41xx (h=&40+1 soit &41 et xx=l=numero de ligne...) Table2 db &c0 ; ligne1_fort db &c8 ; ligne2_fort db &d0 ; ligne3_fort db &d8 ; ligne4_fort db &e0 ; ligne5_fort db &e8 ; ligne6_fort db &f0 ; ligne7_fort db &f8 ; ligne8_fort db &c0 ; ligne9_fort db &c8 ; ligne10_fort ; ...etc... la table doit comprendre autant de db que tu as de lignes... tu peux d'ailleurs faire une routine qui genere cette table...
Utilisateur(s) parcourant ce forum : Aucun utilisateur inscrit et 73 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