ASMtrad CPC

Apprenez l'assembleur Z80

Couleurs - Gate Array - adressage.

A la demande de plusieurs personnes, je vais donc vous expliquer ici comment changer les couleurs de vos encres via le Gate Array.

Pourquoi ne pas passer simplement par des vecteurs système ?

La raison est simple: si vous coupez les interruptions ou si vous coupez le system en plaçant par exemple un EI:RET en #0038, vous ne pourrez plus utiliser les vecteurs system.
Il vous faudra donc utiliser la méthode hardware pour le faire (ce que font les vecteurs système mais le système lui rafraichit les couleurs sous interruption justement).

X.6.0.1 - Explications:

Pour changer les couleurs nous passerons donc par le Gate Array. Je vous remet ici le tableau correspondant à ce composant:

Gate array - selection d'une encre

Comment comprendre et utiliser ce schéma:

En haut, vous pouvez voir de représenté l'octet envoyé au Gate Array. Celui-ci consiste donc en 8 bits qui ont certaines fonctions.

Les bits 7 ; 6 et 5 donne le mode de fonctionnement.

Ici on évoque que deux choix: "Sélection du numéro d'encre" ou "Sélection de la couleur de l'encre courante".

Pour chaque mode de fonctionnement choisi, les bits 4 à 0 auront donc une fonction différente.

Voyons chacun de ces modes de fonctionnement en détail.

X.6.0.2 - Sélection de l'encre.

Sur cpc nous avons 16 encres + le border. (sur CPC+ c'est identique sinon qu'on ajoute 15 encres pour les sprites hard et que la sélection des couleurs+ se fait via l'ASIC et non pas le Gate Array (GA).)

Les encres sont donc numérotées de 0 à 15 et correspondent donc aux 16 encres utilisables en MODE 0(mode graphique).
Au passage, même si vous êtes en MODE 1, vous pouvez définir si vous le souhaitez 16 encres même si seulement 4 sont utiles. De même en MODE 2.

Pour chaque encre, nous pouvons choisir une couleur dans la palette des 26 couleurs du CPC.

Le mode de sélection de l'encre est donc très simple.
Il suffira d'envoyer au GA un octet ayant les bits 7 6 et 5 à 0 (ce qui signifie qu'on est en mode de sélection de l'encre), puis de donner le numéro de l'encre choisie dans les bits 3 à 0 (le bit 4 étant forcément à 0...
Mais il faudra le donner quand même). Nous avons donc 4 bits pour sélectionner l'encre ce qui nous donne 16 possibilités. Ca tombe bien c'est justement le nombre d'encre disponibles :)

Pour envoyer l'octet au GA nous utiliserons l'instruction OUT (C),r8
r8 correspondant à un registre 8bit sauf B.
En effet, B est utilisé par cette instruction pour désigner le périphérique adressé. Le GA est un périphérique.

La valeur à mettre dans B pour adresser le GA sera #7F (pour plus de détail, voir le chapitre "Adresser un périphérique (GA;CRTC...)").

Ainsi, pour envoyer notre octet %00000001 (et sélectionner l'encre 1), nous pourrons faire:

                            LD            B,#7F
                            LD            A,%00000001
                            OUT           (C),A

Mais il serait plus simple et plus rapide de faire ceci:

                            LD            BC,#7F01:OUT (C),C

Puisque C contiendrait donc 1...

De la on peut surtout se dire que l'octet qu'on envoie contient en fait simplement le numéro d'encre.
En partant sur ce principe on peut aussi écrire tout bêtement:

LD BC,#7F00+encre:OUT (C),C
Ou "encre" sera une valeur entre 0 et 15.

Pour le border, le bit 4 doit être mis à 1 et les bits 3 à 0 sont ignorés.
Aussi la valeur à envoyer pour le border sera donc simplement en décimal: 16

Voila pour la sélection.

Une fois l'encre sélectionnée, on pourra lui assigner une couleur.

X.6.0.3 - Sélection de la couleur de l'encre courante:

Ici les bits 7 ; 6 et 5 seront respectivement à %010 ce qui signifie donc qu'on est en mode de sélection de la couleur.

La couleur est appliquée à la dernière encre sélectionnée.
Il vous faut donc impérativement passer par la sélection de l'encre en premier lieu.

Pour la couleur on va faire simple: il n'y a aucune logique dans les numéro de couleur pour le GA...
Beaucoup se sont essayés à tenter de trouver la logique derrière tout ça mais personne n'y est jamais parvenu. Sans doute parce qu'il n'y en a pas...

Voici un joli tableau:

table des couleurs old

Occupez-vous seulement du tableau de gauche pour le moment.

Les couleurs y sont classées dans l'ordre du BASIC afin d'avoir un point de repère (le tableau de droit les donnent dans l'ordre du GA).

Ce qui nous intéresse dans ce tableau dans un premier temps c'est la colonne "GA".
En effet celle-ci nous donne les valeurs à ajouter à notre octet dont nous avons déjà mis les bits 7 ; 6 et 5 à %010.
Le premier chiffre est la valeur décimale tandis que celui immédiatement en dessous est la valeur hexadécimale.

Plus simple encore, la colonne "GA +64" vous donne carrement la valeur à envoyer avec les bits 7 ; 6 et 5 déjà mis à %010 !!! Le bit 6 valant 64, c'était quand même assez simple non ?

Pour sélectionner la couleur il suffira donc d'envoyer la valeur voulue.
Par exemple pour envoyer du rouge:

                            LD            A,76:LD B,#7F:OUT (C),A

Rien de plus simple !!!

X.6.0.4 - La totale:

Comme on place déjà #7F dans B lors de la sélection de l'encre, on n'aura pas besoin de le redonner lors de la sélection de la couleur. Ainsi on peut déjà simplifier:

                            LD            BC,#7F00                ;Sélection de l'encre 0
                            OUT           (C),C                   ;on envoie au GA
                            LD            A,76                    ;couleur rouge
                            OUT           (C),A                   ;sélection de la couleur

L'encre 0 est désormais en rouge.

Notez cependant que si le system n'a pas été exterminé via un DI ou un détournement du JP en #0038, celui-ci fera un refresh et vous aurez à peine le temps de voir la nouvelle couleur que vous avez donné.
En effet le system stocke en RAM les valeur données au encres sous basic et pendant une des interruptions se fera un joyeux plaisir de les remettre.

Enfin, on pourrait aussi utiliser une table pour envoyer toutes les couleurs.

ex:

                            LD            B,#7F                   ;pour sélection du GA
                            LD            A,16                    ;numéro d'encre de départ
                            LD            HL,table                ;HL pointera sur la table
            INK             OUT           (C),A                   ;on sélectionne l'encre
                            LD            E,(HL)                  ;on récupère la première couleur dans la table
                            OUT           (C),E                   ;on envoie la couleur
                            INC           HL                      ;on incrémente le pointeur de table
                            DEC           A                       ;on décrémente le numéro d'encre
                            JP            NC,INK                  ;temps que ca ne déborde pas on boucle
            ;ca débordera quand A=255 donc après avoir envoyé la couleur de l'encre 0
            table           DB            76,84,67,75 .....

La table devra contenir 16 valeurs bien entendu + le border.