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
★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser... |
CPCrulez[Content Management System] v8.73-desktop/c Page créée en 889 millisecondes et consultée 1535 foisL'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. |
|
|