CODINGAMSTRAD CPC 464 - CRÉER DE NOUVELLES INSTRUCTIONS

Nouvelles Instructions 007

EXEMPLES DE PROGRAMMES

4. DÉFILEMENT D'UNE LIGNE

Ce programme permettra d'effectuer des défilements (ou scrollings) de ligne vers la droite ou vers la gauche.

Il débute à l'adresse 43830, finit en 43902 (chiffre de vérification : 7424), est relogeable tel quel, et son format d'appel est le suivant :

CALL 43830, NL, S

NL est le numéro de la ligne concernée et S détermine le sens de défilement (0 provoquera un défilement vers la gauche et 1 un défilement vers la droite).

Attention, il est absolument nécessaire de lire l'Annexe III, concernant la mémoire écran, avant d'aborder l'étude de ce programme.

Pour ce programme, nous allons commencer par une description globale de la démarche adoptée. Nous nous aiderons pour cela de la figure ci-après, qui représente une partie de la carte mémoire de la ligne n°1 (cette ligne n'est bien sûr prise que comme exemple et le raisonnement reste le même quelle que soit la ligne choisie).

ligne choisie).

Remarques

1. Il va nous falloir deux compteurs de boucle : un compteur que nous appellerons compteur d'octets et qui nous servira pour décaler les 80 octets d'un même trait, et un autre que nous appellerons compteur général, et qui comptera le nombre de traits qui ont été décalés, de manière que le programme s'arrête lorsque les huit traits le sont.

2. En ce qui concerne les octets des extrémités gauches de chaque trait (49152, 51200, 53248, etc.), nous avons dit que nous commencerions par transférer (49153) dans 49152. Mais il faut savoir qu'alors le contenu initial de 49152 sera perdu, puisque remplacé.
Or nous devons conserver ce contenu pour pouvoir le transférer quand le trait aura été entièrement décalé, en 49231.

Il faudra donc veiller à la sauvegarde du contenu des huit octets de gauche.
Le défilement vers la droite s'obtiendra évidemment selon le même principe, mais inversé: (49230) dans 49231, (49229) dans 49230, etc. Cette fois, ce sont les contenus des octets des extrémités droites de chaque trait qui devront être sauvegardés.

Pratiquement, les décalages seront obtenus grâce à deux instructions qui constitueront véritablement le cceur du programme.

Transfert répétitif de bloc avec décrémentation

Cette instruction sera utilisée pour les défilements vers la droite. Voici sa description, qu'il convient de lire calmement, plusieurs fois, et en s'aidant de la figure ci-après.
Le contenu de l'emplacement mémoire dont l'adresse est dans HL est chargé dans l'emplacement mémoire dont l'adresse est dans DE. Puis HL, DE et BC sont tous trois décrémentés (on leur enlève 1). Si BC est différent de 0, l'instruction est exécutée de nouveau. Sinon, le programme continue normalement.
La description est un peu rébarbative, mais en fait le fonctionnement de cette instruction est très simple. Regardez la figure suivante.
Imaginons qu'au départ HL soit chargé avec 49230, DE avec 49231, et BC avec 79. Lorsque l'instruction est exécutée, le contenu de 49230 est chargé dans 49231. Les trois registres sont décrémentés. HL est maintenant chargé avec 49229 (on dit aussi pointé sur 49229) et DE est pointé sur 49230. Quant à BC, qui contient maintenant 78, il est différent de 0. L'instruction est donc exécutée de nouveau, et ainsi de suite.

Ainsi, HL et DE vont se déplacer ensemble tout au long du trait, jusqu'au moment où BC sera égal à 0, auquel cas le transfert sera terminé (le compteur d'octets évoqué plus haut sera donc constitué par BC et initialisé avec 79).
En prenant le cas du premier trait, par exemple, signalons qu'à la fin de l'instruction HL sera "sorti" de l'écran, puisqu'il se retrouvera pointé sur 49151 alors que DE le sera sur 49152 (vous comprenez sans doute maintenant pourquoi BC est chargé avec 79 au lieu de 80 : ce dernier transfert ne nous intéresse pas).
Pour information, il faut également signaler que l'emplacement source, c'est-à-dire celui dont le contenu est transféré, n'est pas affecté par le transfert en question (il serait en fait plus juste de parler de recopiage plutôt que de transfert).

L'instruction suivante permettra le défilement vers la gauche.

Transfert répétitif de bloc avec incrémentation

Le contenu de l'emplacement mémoire dont l'adresse est dans HL est chargé dans l'emplacement mémoire dont l'adresse est dans DE. Les registres HL et DE sont ensuite incrémentés (on leur ajoute 1), tandis que BC est décrémenté. Tant que BC n'est pas égal à 0, l'instruction est exécutée une nouvelle fois.
Pour transférer le premier trait, par exemple, HL et DE devront donc être respectivement pointés sur 49153 et 49152.

Une dernière chose enfin : puisque nous appellerons le programme en ne fournissant que le numéro de ligne, il devra se charger de calculer les adresses avec lesquelles HL devra être initialisé (le deuxième octet du premier trait de cette ligne pour un défilement vers la gauche, et l'avant-dernier octet de ce même trait pour un défilement vers la droite). Le deuxième octet peut être calculé grâce à la formule suivante :

49150 + (80 * NL)

où NL est le numéro de ligne. L'avant dernier octet, lui, est donné par :

49073 + (80 * NL)

Vous pouvez vérifier, si vous en avez envie, que ces formules sont valables quel que soit le numéro de ligne.

Si tout cela est bien compris, nous pouvons maintenant en venir au programme, dont voici le listing :

Ligne 1

Appel de la routine d'adresse &BD19. Cette routine s'appelle "Attendre le retour du rayon" ; elle permet de synchroniser un programme d'animation d'écran avec le balayage de l'écran par le rayon, ce qui évite des effets optiques désagréables. Cette routine est souvent indispensable pour les animations, mais il faut savoir qu'elle ralentit considérablement l'exécution des programmes (lorsque vous aurez entré le programme, essayez par exemple de remplacer les trois codes de la première ligne par trois zéros).

Lignes 2 et 3

Chargement de 8 dans B, puis sauvegarde par empilement. Il s'agit bien sûr de la valeur initiale du compteur général (notons que malgré le "PUSH BC", la valeur contenue dans C nous importe peu).
Il faut maintenant aborder le calcul de l'octet de départ, en fonction de la ligne. Si vous regardez les deux formules proposées dans le préambule, vous pouvez constater que, quel que soit le sens de défilement choisi, elles comportent une partie commune : 80 * NL. Nous allons donc commencer par cela :

Ligne 4

HL est chargé avec 80.

Lignes 5 et 6

Chargement du paramètre NL (numéro de ligne) dans DE.

Ligne 7

Appel de la routine d'adresse &BDDE, qui multiplie HL par DE et range le résulat dans HL. Ce dernier est donc maintenant chargé avec 80 * NL.
Il est temps maintenant de déterminer le sens de défilement.

Ligne 8

A est charge avec 1.

Lignes 9 et 10

Comparaison du paramètre S avec 1, puis saut relatif de 24 (en ligne 26) si non nul. Le branchement conditionnel est réalisé ici selon un processus déjà étudié dans le programme de dessin d'un quadrilatère (lignes 17 et 18). Seule la longueur du saut est différente. Pour résumer : si le défilement doit être vers la gauche, le saut se réalise. S'il doit être vers la droite, le programme continue en séquence. Voyons ce dernier cas :

Ligne 11

Il nous faut d'abord calculer l'adresse de l'avant-dernier octet du premier trait de la ligne concernée, grâce à la formule : 49150 + (80 * NL).

Rappelons que HL est toujours chargé avec 80 * NL. La ligne 11 charge maintenant DE avec 49150.

Ligne 12

HL est additionné à DE, et le résultat se retrouve dans HL, qui est maintenant pointé correctement pour le transfert du premier trait. Nous allons maintenant pointer DE.

Lignes 13 et 14

L'empilement de HL, suivi immédiatement du dépilement de DE, a pour résultat que les deux registres sont maintenant chargés de la même manière.

Ligne 15

Incrémentation de DE, qui est maintenant, lui aussi, pointé correctement pour le transfert. Sur l'exemple du préambule, HL et DE seraient respectivement pointés sur 49230 et 49231.

Ligne 16

Le compteur de transfert (ou compteur de trait) est chargé avec 79. Tout est prêt pour le transfert répétitif, mais n'oublions pas qu'il faut d'abord sauvegarder le contenu du dernier octet du trait.

Ligne 17

Réalisation de cette sauvegarde : le contenu de l'emplacement mémoire adressé par DE est chargé dans A. C'est donc dans ce registre A que nous pourrons, quand nous en aurons besoin, récupérer cette valeur.

Ligne 18

Transfert répétitif de bloc avec décrémentation. Cette instruction a été suffisamment été développée dans le préambule, et nous n'y reviendrons pas. Résumons simplement la situation lorsque ce transfert est terminé (là encore, nous prendrons l'exemple du premier trait de la figure du préambule) :
HL est chargé avec 49151, DE avec 49152, BC avec 0. Le premier trait est décalé d'une position vers la droite, et le contenu initial de 49231 est dans A.

Ligne 19

Le contenu de A est chargé dans l'emplacement mémoire adressé par DE. Cela se passe bien sûr de commentaire.
Le travail sur ce premier trait est donc terminé, restent les sept autres. Mais il s'agit de vérifier, avant de recommencer l'opération pour le trait suivant, si les huit traits n'ont pas déjà été décalés, auquel cas le programme serait terminé.

Ligne 20

Récupération, sur la pile, de la valeur actuelle du compteur général, qui se retrouve dans BC (rappelons que cette valeur tient sur un seul octet, qu'elle avait été chargée dans B avant empilement, et que la valeur éventuellement contenue dans C nous est indifférente).

Ligne 21

Une nouvelle instruction, une des plus puissantes du Z 80 : décrémentation de B et saut relatif si non nul (ici le saut éventuel est de + 1, en ligne 23).
A la huitième décrémentation de B, donc quand les huit traits auront été traités le saut ne se fera pas et le programme continuera en ligne 22, qui provoquera le retour au BASIC. Si ce n'est pas le cas, le programme saute à la ligne 23, pour traiter le trait suivant :

Ligne 23

La nouvelle valeur du compteur général est sauvegardée.

Ligne 24

Pour nous occuper du trait suivant, il nous faut d'abord pointer HL et DE respectivement sur l'avant-dernier et le dernier octets de ce trait.
On se rend compte qu'il est possible de pointer HL en ajoutant tout simplement 2127 à sa valeur actuelle (si par exemple nous venons de finir le premier trait, 49151 + 2127 = 51278). Cela est bien entendu valable quel que soit le numéro de trait.
Cette ligne 24 charge DE avec 2127.

Ligne 25

Saut relatif de -21, en ligne 12. Là, HL est additionné à DE, puis DE est chargé comme HL, puis DE est incrémenté, etc. La boucle est donc bouclée, et les huit traits successifs seront traités de la même manière.

Les lignes 26 à 40, s'occupant du défilement vers la gauche, sont l'exact pendant des lignes 11 à 25, vous pouvez donc les étudier seul. Rappelons simplement que HL doit être cette fois pointé sur le deuxième octet du trait concerné, et DE sur le premier. D'autre part, le transfert répétitif se fera avec incrémentation.

Ce programme fonctionne indifféremment dans les trois modes. Si vous fournissez un numéro de ligne erroné, il se contente en principe de ne pas fonctionner et ne se détruit pas.
En vous basant sur cet exemple, vous pouvez bien entendu concevoir d'autres programmes du même genre : défilement de plusieurs lignes, défilements inverses et simultanés, défilements verticaux, etc.
En voici un exemple d'utilisation :

100 MODE 1
110 LOCATE 1,12 : PRINT "VOICI UN DÉFILEMENT VERS LA DROITE..."
120 FOR l= 1 TO 300 : CALL 43830,12,1 : NEXT I
130 CLS : LOCATE 1,12 : PRINT "... EN VOICI UN VERS LA GAUCHE"
140 FOR I = 1 TO 300 : CALL 43830,12,0 : NEXT I
150 CLS : LOCATE 8, 12 : PRINT "ET ENFIN, LES 2 ENSEMBLES"
160 FOR I = 1 TO 14 : CALL 43830,12,0 : NEXT I : FOR I = 1 TO 14 : CALL 43830,12,1 : NEXT I : GOTO 160

★ ANNÉE: ???
★ AUTEUR: JEAN-CLAUDE DESPOINE

Page précédente : Nouvelles Instructions 006
Je participe au site:

» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop/c
Page créée en 536 millisecondes et consultée 1186 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.