CODING ★ LES VECTEURS SYSTEME DES CPC: EXEMPLE D'USAGE DES ROUTINES GRAPHIQUES ★

System - les Routines System - Exemple d'Usage des Routines Graphiques (SOS Programmeurs)

Le listing qui suit est assez complexe , si vous êtes vraiment débutant ,  il rique de vous plonger dans un abîme de perplexité ce qui est normal . Vous  pouvez vous contenter d'étudier l'appel  des  routines  système et ignorer le  reste . Sinon , une étude  approfondie  vous permettra d'éclaircir le mystère  des boucles , de la gestion des  pointeurs  , et constitue une bonne pratique  des connaissances dévoilées dans les cours d'assembleur de SOS5 et SOS6 .

     Les effets de ce programme  sont  des  plus spectaculaires pour un faible  encombrement en RAM (un peu moins  de  350  octets) , les spécialistes et les  débutants acharnés pourront vérifier qu'il suffit de modifier quelques octets  pour obtenir des dizaines  d'effets  différents  .  Quelques suggestions à ce  sujet seront faites à  la  fin  du  chapitre  .  Dans  sa version actuelle le  programme accomplit 2 actions essentielles :

     1A : Tracé  d'un  carré  au  centre  de  l'écran  entouré  par  18 carrés  concentriques à chaque fois d'une couleur différente .
     1B : Retraçage des mêmes carrés en  affichage  XOR qui efface la série de  carrés depuis l'intérieur et répétition du tout 21 fois .

     2  : La série de carrés  précédente  est  retracée 21 fois de l'extérieur  vers l'intérieur , toujours en  XOR  mais  avec  un décalage des couleurs qui  provoque un effet du genre 'hyper-espace' .

----------------
- FONCTIONNEMENT -
----------------

     Les 1ères lignes du programme ne  sont  qu'une  simple mise en œuvre des  routines système pour initialiser le  programme  puis cele devient rapidement  incompréhensible malgré les abondants  commentaires  .  Ne  paniquez pas , et  avant d'aborder le listing lisez ce qui suit .

     Il est question d'afficher un  carré  ,  de  le  répéter en augmentant sa taille à chaque fois (21 fois de  suite)  ,  puis de recommencer dans le sens  inverse c'est à dire en retraçant tout l'ensemble du plus grand carré vers le  plus petit et toujours 21 fois .

     Attaquons point par point .

     Pour pouvoir agrandir ou diminuer une  figure  ,  il est préférable de la  tracer par rapport à son centre afin  de disposer ce coordonnées négatives et  positives par rapport à ce  centre  .  Ceci  est  valable dans n'importe quel  langage de programmation et pour cela  l'origine  est mise en 320,200 qui est  le centre de l'écran .

     1 Il faut  une  routine  capable  d'agrandir  le  carré  c'est AUGCARRE .
     2 Une seconde pour le diminuer , ce sera DIMCARRE .

     Ensuite il faut une boucle de  répétition  pour agrandir le carré tout en  l'affichant puis une autre semblable pour le diminuer . On constate que l'une  ou l'autre de ces  opérations  demande  EXACTEMENT  les  mêmes instructions ,  seule la routine de  calcul  du  prochain  carré  sera (AUGCARRE ou DIMCARRE)  selon de cas . Il  serait  particulièrement  stupide  d'écrire 2 fois la même  boucle pour une différence si mineure ! Contrairement au BASIC , un programme  assembleur peut se modifier  lui  même  au  cours  de  son  déroulement . Par  exemple :

LD HL,AUGCARRE    ;Adresse de la routine à activer dans HL (ou autre rr) .
 LD (ROUTINE+1),HL ;Insérer l'adresse  de  la  routine  à  activer à l'adresse
 ROUTINE+1 . Le '+1' est vital  car  dans  cet exemple , l'assembleur donne au
 label ROUTINE la valeur de l'adresse ou figure l'octet #CD qui veut dire CALL
 et c'est l'OCTET SUIVANT qui contient l'adresse de la routine à activer .
             ;Ex : #CD #40 #9C = CALL 40000 (MSB , LSB inversés) .
 ;
 Début de boucle et routine
 ;
 ROUTINE CALL AUGCARRE
     On pourrait aussi écrire :
         LD HL,AUGCARRE
         LD (ROUTINE),HL
 ;
 Début de boucle et routine
 ;
         DB #CD   CALL défini comme octet .
 ROUTINE DW 0     ;2 Octets vides pour loger la routine à appeler .

Dans ce cas , le '+1' n'est  pas nécéssaire les 3 octets de l'instruction  étant divisés en 2 par DB et  DW  .  Du  point de vue de l'assembleur , c'est  stictement identique au 1er exemple , faites comme il vous plait mais ne vous  trompez pas sinon tout plante !  A  part  ça , le nombre d'auto modifications  dans un programme n'est limité que  par  votre résistance nerveuse à ce genre  d'exercice .

     Ce n'est pas tout ! Pour tracer un  carré ou toute autre figure , il faut  en connaître les coordonnées . PARACAR contient le point x,y du 1er sommet du  carré (pour MOVE) suivi des 4 point  x,y (pour 4 DRAW) chaque point demandant  2 octets (Valeur 16 bits) .

     Le programme est succeptible  d'être  appelé  à  plusieurs  reprises , la  table PARACAR ne doit donc subir  aucune  modification  , elle doit donc être  reproduite dans une seconde qui contiendra les nouvelles coordonnées fournies  par les routines de  calcul  .  La  double opération agrandissement/réduction  complique tout ! Pour la  seconde  opération  il  faudra partir du plus grand  vers le plus petit ,  donc  utiliser  une  troisième  table pour effectuer un  transfert provisoire . Soit :
 

Table à préserver        : PARACAR  (20 octets coordonnées figure du carré)
Table de transfert       : PARACAR1 (20 octets quelconques)
Table de calcul et tracé : PARACAR2 (20 octets quelconques)

 -----------------------------------
 - ALGORYTHME DE GESTION DES 3 TABLES -
 -----------------------------------

 ENTREE DU PROGRAMME : Copie  des  paramètre  d'origine dans table transfert ,  PARACAR va dans PARACAR1

+>DEBUT BOUCLE1 : Recopie de la table de transfert PARACAR1 vers PARACAR2 , à
! chaque tour ceci réinitialise les coordonnées du 1er carré à chaque tour
!
! +->DEBUT BOUCLE2 : On trace 19 carrés .
! !
! !  CORPS DE BOUCLE : PARACAR2  est  modifiée  à  chaque tour et contient en
! !  sortie de boucle les coordonnées du prochain carré à tracer .
! !
! +-!    carré à tracer .
!
+     Rectifier la position  du  carré  pour  retomber  sur  les coordonnées du  dernier tracé par DIMCARRE (Le plus grand) , implanter DIMCARRE dans le corps  de boucle et recopier PARACAR2 dans PARACAR1 .

     Lors du second passage par ce point , FLAG ordonera l'arrêt du programme.

 -------------------------

     Cette gestion d'un programme par tables multiples est essentielle à toute  (bonne) programmation graphique  .  Vous  retrouverez  toujours  des systèmes  similaires dans nos cours de graphisme et  parfois  pire ! Un jeu d'arcade de  40K assembleur se compose généralement de  20-25K  de datas images et sprites  et 10-15K pour les buffers temporaires  .  Le programme proprement dit occupe  ce qui reste ...

 ------------------------

;
 ;- Demonstration routines graphiques -
 ;
         ORG 40000
 nolist
 ;
         CALL #BC11        ;Determiner mode en cours
         LD (OLDMODE),A    ;Et stocker
 ;
         CALL #BB99        ;Idem pour PAPER
         LD (OLDPAPER),A
 ;
         CALL #BB93        ;Et pour PEN
         LD (OLDPEN),A
 ;
         LD A,1            ;Parametre mode écran
         CALL #BC0E        ;Fixer Mode 1
 ;
         LD DE,320         ;Placer l'origine au centre de l'ecran
         LD HL,200
         CALL #BBC9
 ;
         LD A,1            ;Mode d'affichage graphique en XOR
         CALL #BC59        ;N'a pas d'influence sur le texte
 ;
         XOR A             ;Mettre a 0 le flag interne utilise par le programme
         LD (FLAG),A
 ;
         LD HL,AUGCARRE    ;Initialiser l'adresse CALL du label ROUTINE
         LD (ROUTINE+1),HL ;Voir explications detailles dans le texte
 ;
         LD HL,PARACAR     ;Recopier les parametres d'origine du carre dans
         LD DE,PARACAR1    ;la table des parametres d'agrandissement .
         LD BC,20          ;5 Coordonnees x et 5 coordonnees y 16 bits
         LDIR              ;Copier
 ;
 RECOM   LD B,21
 NXTOPER PUSH BC           ;Preserver le nombre d'operations
         LD HL,PARACAR1    ;Copier encore les parametres , c'est necesaire pour
         LD DE,PARACAR2    ;Conserver une trace des donnees pour le second tour
         LD BC,20          ;5 Coordonnees x et 5 coordonnees y 16 bits
         LDIR
 ;
         LD B,19           ;Nombre de carres successifs
 ;
 BCLCAR1 PUSH BC           ;Preserver nombre de carres a dessiner
         LD A,(COLODRAW)   ;Stylo pour trace
         PUSH AF           ;Preserver
         CALL #BBDE        ;Activer GPEN A
         POP AF            ;Recuperer stylo
         INC A             ;Stylo suivant
         CP 4              ;Mais pas plus de 3 en mode 1
         JR C,PASTROP      ;Si < 3 on stocke pour le prochain tour
         LD A,1            ;Si on depasse 3 on revient a 1
 PASTROP LD (COLODRAW),A   ;Et on stocke
 ;
         LD IX,PARACAR2    ;DATAS du carre
         LD E,(IX+0)       ;Initialiser x
         LD D,(IX+1)
         LD L,(IX+2)       ;Puis y . Se souvenir qu'en adressage indirect
         LD H,(IX+3)       ;MSB et LSB sont inverses . (SOS 5)
         CALL #BBC0        ;MOVE
 ;
         LD B,4            ;4 traces a faire pour un carre
 UNCARRE INC IX            ;Pointer 4 octets plus loin dans la table
         INC IX            ;puis qu'on charge a chaque tour 2 * 16 bits
         INC IX
         INC IX
         LD E,(IX+0)       ;x pour DRAW
         LD D,(IX+1)
         LD L,(IX+2)       ;y pour DRAW
         LD H,(IX+3)
         PUSH BC           ;DRAW modifie les registres ! Presever compteur
         CALL #BBF6        ;DRAW
         POP BC            ;Recuperer compteur
         DJNZ UNCARRE      ;Continuer le carre
 ;
 ROUTINE CALL AUGCARRE     ;Calculer le carre suivant , l'adresse du CALL change
 ;                        ;au prochain tour en RECOM
         POP BC            ;Recuperer le nombre de carres a tracer
         DJNZ BCLCAR1      ;Et continuer tant qu'il reste des carres a tracer
 ;
         LD A,1            ;Remettre la couleur graphique a 1 comme au debut
         LD (COLODRAW),A
         POP BC            ;Et recommencer 21 fois .
         DJNZ NXTOPER
 ;
         LD A,(FLAG)       ;Ici on vient de repeter 21 fois l'affichage
         OR A              ;Le FLAG nous dit si il s'agit du 1er ou du second
         JR NZ,QUITTER     ;tour . Si c'est le second on quitte
         INC A             ;Si non on modifie le flag
         LD (FLAG),A       ;on le range
         INC A             ;on change la couleur
         LD (COLODRAW),A
 ;
         CALL DIMCARRE     ;On diminue le carre (sans l'afficher) car AUGCARRE
 ;                        ;etant en sortie de boucle,le carre est aggrandi une
 ;                        ;fois de trop pour etre repris au bon endroit
         LD HL,DIMCARRE    ;On change le programme pour lui faire diminuer
         LD (ROUTINE+1),HL ;le carre au lieu de l'augmenter .
         LD HL,PARACAR2    ;Ici PARACAR2 contient les dimensions maximales
         LD DE,PARACAR1    ;que l'on recopie dans la table de transfert
         LD BC,20
         LDIR
         JP RECOM          ;Et on effectue le second tour
 ;
         CALL #BB06
 ;
 QUITTER LD A,(OLDMODE)    ;Restaurer le mode écran sauve en entree
         CALL #BC0E
         LD A,(OLDPAPER)   ;Idem pour PAPER
         CALL #BB96
         LD A,(OLDPEN)     ;Idem pour PEN
         CALL #BB90
         XOR A             ;Restaurer le mode graphique normal
         JP #BC59          ;C'est fini .
 ;
 AUGCARRE LD IX,PARACAR2   ;Debut de la zone DATA a modifier
         PUSH BC
         LD B,10           ;10 * 16 bits
 NEXTAUG LD L,(IX+0)       ;Valeur x ou y dans HL
         LD H,(IX+1)
         LD DE,-10
         ;BIT 7,H           ;Tester si negatif
         JR NZ,NEGAT       ;Si oui on liasse DE a -10
         LD DE,10          ;Si non on passe en positif
 NEGAT   ADD HL,DE         ;Et on additionne DE a x ou y
         LD (IX+0),L       ;Avant de le ranger a nouveau dans la table
         LD (IX+1),H       ;qui sera utilisee comme coordonnees du carre
         INC IX            ;dans la boucle de trace
         INC IX
         DJNZ NEXTAUG
         POP BC
         RET
 ;
 DIMCARRE LD IX,PARACAR2   ;Exactement comme AUGCARRE , il suffit d'inverser
         PUSH BC           ;DE negatif DE positif pour obtenir une reduction
         LD B,10           ;du carre .
 NEXTDIM LD L,(IX+0)
         LD H,(IX+1)
         LD DE,10
         ;BIT 7,H
         JR NZ,NEGAT1
         LD DE,-10
 NEGAT1  ADD HL,DE
         LD (IX+0),L
         LD (IX+1),H
         INC IX
         INC IX
         DJNZ NEXTDIM
         POP BC
         RET
 ;
 OLDMODE  DB 0
 OLDPAPER DB 0
 OLDPEN   DB 0
 FLAG     DB 0
 ;
 COLODRAW DB 1
 PARACAR2 DW 00,00,00,00,00,00,00,00,00,00 ;Paramètres du carré en cours.
 PARACAR1 DW 00,00,00,00,00,00,00,00,00,00 ;Paramètres 1er carré tracé .
 PARACAR  DW -10,10,10,10,10,-10,-10,-10,-10,10 ;Paramètres initiaux carré .
 ;

--------------------------

     Si vous voulez vous amuser à modifier  ce  programme (Mais non il ne faut  pas être maso ...)

     Le plus simple : Changez les  valeurs  de PARACAR pour obtenir une figure  autre qu'un carré .
     Changez la valeur du compteur B  (LD  B,4)  avant la routine UNCARRE , le  nombre et la valeur des datas  pour  créer  d'autres figures . ATTENTION , il  faut allonger PARACAR2 et PARACAR1 dans  les  mêmes proportions que PARACAR .  Les valeurs de BC dans les 3 routines  LDIR doivent être augmentées de 4 pour  chaque côté supplémentaires .
     Le nombre de carrés (LD B,19)  successifs peut être augmenté sous réserve  de diminuer LD DE,10 , LD DE,-10 pour resserrer les carrés .
     Vous pouvez passer en mode 0 et pousser  à 16 couleurs (CP 4 dans BCLCAR1  devient CP 15) .
     Changer l'enchaînement des couleurs pour obtenir des effets différents .

     Si vous désirez aller plus loin  ,  sachez qu'hors de certaines limites ,  il  est  plus  simple  de  réécrire  complètement  un  programme  plutôt que
 s'acharner à modifier un listing donné .

 ----------------------------

     Dans ce genre de programme , les causes de disfonctionnement et plantages  les plus fréquentes sont :

     PUSH et POP . Il manque l'un ou  l'autre  .  L'un des 2 (Voire les 2) est  (sont) mal placés . PLANTAGE COMPLET .
     MSB est inversé avec LSB lors d'un LD r,(IX+d) ou la valeur de display de  IX est incorrecte . FIGURE INNATENDUE .
     Routine LDIR incorrecte (Mauvaise adresse  ou  mauvais compteur) . FIGURE  INCORRECTE ou PLANTAGE .
     Je vous laisse le soin de découvrir les autres , consolez vous en pensant  que malgré 3  ans  d'expérience  ,  cette  simple  (hum  ?)  routine m'a fait  l'offense de 11 plantages avant de fonctionner .

» SOURCE
SOS PROGRAMMEURS

★ ANNÉE: ???
★ AUTEUR: MICHEL MAIGROT

CPCrulez[Content Management System] v8.7-desktop/c
Page créée en 175 millisecondes et consultée 803 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.