Canalblog
Editer l'article Suivre ce blog Administration + Créer mon blog
Publicité
Rétro Poke
27 avril 2019

Assembleur: Les Maxi-Caractères (Deuxième partie)

Hello,
Cet fois je vous livre le début de mon programme sur les maxi-caractères. Les explications sont trop volumineuses pour ne tenir que sur une seule la page. 
En premier lieu, j'ai déclaré les variables indispensables en début du programme pour une plus grande facilité d'adaptation avec d'autre mode d'écran.

Déclaration des variables et des valeurs par défauts:

; ########## - ########## - ########## - ########## - ########## - ########## - ########## - ##########
; ### Programmation AVRIL 2019 - Philippe Moulin
; ########## - ########## - ########## - ########## - ########## - ########## - ########## - ##########
; # Liste des Variables utilisees
CouleurCodee   EQU #A000 ; #A00F ; 16 Emplacements pour la table des couleurs codees MODE 0
Couleur        EQU #A010 ; #A017 ; 8 Emplacements pour nos couleurs (4 Encres et 4 Papiers)
Curseur        EQU #A018 ; #A019 ; 2 Emplacements pour les curseur (Colonne et Ligne)
Caractere      EQU #A02A ; #A031 ; 8 Emplacements pour le transfert des caracteres
Pile           EQU #A032 ; #A039 ; 8 Emplacements pour des variables provisoires
TableMaxiChr   EQU #A290 ; #A490 ; (368) Emplacement pour 23 matrices de 8x16

; ########## - ########## - ########## - ########## - ########## - ########## - ########## - ##########
; # Definition des variables par defaut et des couleurs codees de Mr SUGAR
ORG CouleurCodee
; # 00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F ; Numero du PEN en MODE 0
DB #00,#40,#04,#44,#10,#50,#14,#54,#01,#41,#05,#45,#11,#51,#15,#55 ; Couleur correspondante

ORG Couleur
DB #40, #04, #44, #10 ; 4 Emplacements pour les Encres> Defaut PEN 1, 2, 3, 4
DB #00, #00, #00, #00 ; 4 Emplacements pour les Papiers> Defaut PAPER 0, 0, 0, 0

ORG Curseur
DB 199, 0 ; (LIGNE, COLONE) par defaut en haut a gauche LOCATE 1, 1

ORG Caractere DS 8, #00 ; 8 emplacements Utilises par les RSX
ORG Pile DS 8, #00 ; 8 Emplacements Utilises par les RSX 

Variable: 'CouleurCodee' Il faut savoir que l' Amstrad fonctionne avec des couleurs codées. J'ai d'abord créé une table qui contient les codes qui remplaceront vos couleurs par la valeur des couleurs codées correspondante.
Par exemple, lorsque que l'on utilise la couleur 3 du MODE 0, il nous faudra remplacer la couleur 3 par la valeur située dans la table + 3 octets. Et si on regarde le code ci-dessus, la couleur 3 correspond à la valeur #44. Surprenant NON ?

On va prendre un exemple. L' Adresse écran du CPC commence à &C000. Pour allumer un pixel de couleur 3 en haut à gauche de l'écran après un MODE 0, faudrait'il faire un POKE &C000, &44 ?
Ben non, le pixel est de la bonne couleur mais il se trouve sur le deuxième emplacement de l'écran. Ouaaaaff c'est dans le compliqué tout ça! 
Explication:
L'écran de l'Amstrad est composé de 80 octets en largeur et comme 1 octet est constitué de 8BITs '0000 0000' 
Maintenant sachant qu' il faut 4 BITs pour obtenir une valeur de 0 à 15.
'0000' = 0
'0001' = 1
'0010' = 2
'0011' = 3
'0100' = 4
...
...
'1111' = 15
Soit 16 possibilités au total (Les 16 couleurs du MODE 0)
On peut en déduire que dans 8 BITs(1 OCTET) on peut stocker deux couleurs différentes.
Et le poids faible correspond à la droite d'un octet.
poids fort faible

Ma table des Couleurs codées est ajustée pour les valeurs correspondantes aux couleurs de la droite d'un octet.
Pour allumer le pixel de gauche, il faut multiplier la couleur codée par deux (&44*2)=&88

Un petit schéma est mieux parlant:
couleurcodee
NB: Puisque l'on a 80 octets par ligne et que l'on peut mettre deux couleurs par octet, on peut afficher (80 * 2) = 160 pixels sur chaque ligne en MODE 0 et avec 16 couleurs différentes pour chaque pixel.

Maintenant si on fait POKE &C000, (&44*2), on allumera bien le pixel de couleur 3 en haut à gauche de l'écran.

Pour afficher les deux points à la fois, un petit calcul s'impose:
(Début de table + Couleur de Gauche)*2 + (Début de table + Couleur de droite)
Pour la couleur 3 à gauche et la couleur 5 à droite cela donnera:
(#44 *2) + (#50) = #D8.
PS: J'utilise '#' en assembleur, mais en basic Amstrad, le signe hexadécimal est bien le '&'
Finalement un POKE &C000, &D8 affichera les deux pixels avec les bonnes couleurs ⚡ 

Difficile de faire mieux, mais si, il y a bien d'autres surprises qui nous attend... (L'adressage des lignes de l'écran 🙄) 

Passons maintenant à la variable suivante. 
Variable: 'Couleur' C'est à partir de cet emplacement que l'on stockera nos 4 encres et nos 4 papiers utilisées pour l'affichage des caractères. Par défaut, leurs valeurs sont initialisées avec des valeurs ajustées mais les RSX se chargeront de remplacer vos numéros de couleur par des valeurs ajustées. On n'a pas à s'occuper des calculs, l'ordinateur est la pour ça!
Comme exemple rapide, l'instruction '|ENCRE, 5, 4, 2, 3' inscrira les valeurs #50, #10, #04, #44 à partir de l'emplacement 'Couleur' et l'instruction '|PAPIER', 1, 0, 7, 0' inscrira les valeurs #40, #00, #54, #00 à l'emplacement 'Couleur + 4'

Variable: 'Curseur' L'emplacement de cette variable est réservé pour les coordonnées x et y de l'endroit ou démarrera l'affichage. Les valeurs par défauts sont ajustées pour démarrer du haut à gauche de l'écran et la commande 'ICURSEUR, x, y', s'occupera de calculer les coordonnées avant l'affichage des caractères.

Maintenant que l'on sait que L'affichage du CPC est composé de 80 octets en largeur, on doit savoir aussi qu'il comporte 200 lignes en hauteur et que l'adresse de départ commence à &C000.
On pourrait penser dans la logique humaine que l'adresse de l'octet en dessous de la première ligne est (&C000 + 80 octets).
👀 Et bien dada, cela correspond à l' emplacement de 8 lignes de 8 caractères en dessous. La logique me fait défaut ! 
Pour afficher un pixel en dessous de la première ligne, il faut ajouter &800 à l'adresse de départ.
Donc un POKE &C000 + &800, #88 allumera bien le pixel de gauche de  la ligne en dessous et un POKE &C000 + &800, #44 allumera le pixel de droite... Et pour allumer les deux pixels à la fois, rappelez vous qu'il faut additionner les deux valeurs. Un POKE &C000 + &800, &88 + &CC fera le boulot. Heureusement que l'Amstrad est assez rapide dans les calculs !

Variable: 'Caractere' Il s'agit d'un espace de stockage de 8 octets pour transférer les matrices de caractères de l'Amstrad avant manipulation.
Avant d'appeller la routine qui affichera le caractère dans différentes  couleurs, il faut transférer le caractère depuis la ROM ou la RAM de l' Amstrad vers un espace de stockage. Est cet variable pointe au début de cet espace de stockage. 

Variable: 'Pile' De même que pour les caractères de l'Amstrad, il nous faudra un espace plus grand pour les caractères de 8x16.
Cette espace de travail (Caractere + Pile) nous permettra de manipuler les BIT's des octets afin de retourner ou pivoter les caractères. Mais nous en reparlerons au moment de son utilisation.

Variable: 'TableMaxiCHR' C'est ici que la table de 23 caractères de 8*16 commencera. Vos matrice de 8*16 débuteront à cette adresse. Vous pouvez, indiquer une autre adresse afin de redéfinir bien plus que 23 caractères de 8*16, mais n'oubliez pas de réserver l'espace nécessaire avant modifications avec la commande 'MEMORY' du basic de l' Amstrad CPC.

Nous allons passez à la sous routine principale. Elle sera chargée d'afficher le caractère qui est stocké dans l'espace de travail désigné par la variable (Caractere).
Sous routine AfficheCarCHR
; ########## - ########## - ########## - ########## - ########## - ########## - ########## - ##########
; # SOUS ROUTINE (Utilisee pas les routines, elle n'est pas directement executable par le BASIC
; CE> Les variables 'CarCHR'=(8ou16) 'RotCou'=(170ou136) 'Zoom'=(Hauteur du zoom) doivent etre initialisees
; CS> Tous les registres sont detruits
AfficheCarCHR
       LD HL, (Curseur) ; 'H'= Col L=Lig
       LD D, 0          ; On transforme les coordonnees pour les adapter au vecteur qui renvoie l'adresse ecran
       LD E, H          ; 'DE' = Colonne
       LD H, 0          ; 'HL' = Ligne
       CALL #BC1D       ; Vecteur systeme (Adresse ecran)
       LD DE, Caractere ; On recupere l'adresse des octets a traiter dans 'DE' 
       LD IY, Couleur   ; 'IY' Pointe sur les couleurs a utiliser pour l'affichage 

; Variable 'CarCHR' represente le nombre de ligne (8 pour les caracteres et 16 pour les MaxiCHRs)
; Variable 'RotCou' Indiquera apres une rotation du registre 'C' si il faut changer de couleurs
CarCHR
       LD B, 16         ; 16 lignes pour les MaxiCHRs et 8 pour les caracteres
RotCou
       LD C, 136        ; Les couleurs tourneront a chaque BIT mis a 1
                        ; 'C' = (10001000) Apres l'instruction RRC 'C' = (01000100)
                        ; Et si le 'Carry' = 1 on changera de couleur

AFFCARCHR_NbLignes
   PUSH BC             

; Variable 'Zoom' represente la hauteur (Caractere Amstrad uniquement)
Zoom
       LD B, 2         ; Permet de zoomer les caracteres Amstrad en vertical

AFFCARCHR_ZOOM
   PUSH DE             ; DE contient l'adresse de l'octet a traiter
       LD A, (DE)      ; Et 'A' Contient l'octet
       LD C, A         ; 'C' aussi
       LD E, 4         ; En MODE 0 il faut 4 octets pour les 8 BITs par ligne

AFFCARCHR_QuatreOctetsParLigne
       LD A, (IY + 0)  ; 'A' contient la couleur de l'encre gauche et droite
       LD D, A         ; 'D' aussi
       SLA C           ; Pixel de gauche, Chaque bit est teste et si le BIT vaut 1
       JR C, AFFCARCHR_CouleurGauche ; On garde la couleur de l'encre
       LD D, (IY + 4)  ; Sinon 'D' contiendra la couleur du papier

AFFCARCHR_CouleurGauche ; La couleur de gauche est dans 'D' Soit l'encre soit le papier
       SLA C           ; On regarde si le bit droit est allume (=1)
       JR C, AFFCARCHR_CouleurDroite ; 'A' Contient toujours la couleur de l'encre
       LD A, (IY + 4)  ; Ou celui du papier si le pixel est OFF 

AFFCARCHR_CouleurDroite
       SLA D           ; On ajuste la couleur en multipliant par 2 (Pour la gauche seulement en MODE 0)
       ADD A, D        ; 'A' contient l'octet (point Gauche et droit)

AFFCARCHR_Effet        ; Reservation d'un emplacement pour ajouter un effet d'affichage
; OR (HL)=#B6 --- AND (HL)=#A6 --- XOR (HL)=#AE --- NOP=#00 ---> (POKE &A06D,xx)
       NOP
       LD (HL), A ; On affiche 2 pixels de l'octet
       INC HL          ; Suivant S.V.P.
       DEC E
       JR NZ,AFFCARCHR_QuatreOctetsParLigne

; Calcul l'emplacement pour descendre d'une ligne
; 'HL' sera incremente d'une ligne - 4 octets
       LD DE, #800-4   ; Quand Quasar nous donne la reponse! Merci
       ADD HL, DE      ; On descent d'une ligne
       JR NC, AFFCARCHR_LigneDeDessous
       LD DE,#C000+80  ; Mais si il y a debordement hors ecran
       ADD HL, DE      ; On corrige la cote

AFFCARCHR_LigneDeDessous
   POP DE
       DJNZ, AFFCARCHR_ZOOM ; Boucle du ZOOM
   POP BC
       RRC C          ; Tourne les couleurs suivant la valeur dans 'C'
       JR NC, AFFCARCHR_RotationCouleur ; 'C'= '10001000' pour les MaxiCHRs ; 'C'= '10101010' Pour les caracteres
       INC IY         ; En incrementant le pointeur des couleurs

AFFCARCHR_RotationCouleur
       INC DE DJNZ, AFFCARCHR_NbLignes ; On passe les 8 ou 16 lignes a afficher
       RET 
Je met beaucoup de commentaire dans mes programmes, cela évite de décrypter mes écrits, car je m'y perdrais vite moi aussi.
Cette sous routine est utilisée par les RSX, mais je préfère bien définir les CE>(Conditions d'Entrée) et (CS>Conditions de sortie) sur mes routines.
Les coordonnées des axes X et Y sont issues d'un système simplifié pour nous permettre de localiser facilement le curseur, mais il en va tout autrement pour calculer l'adresse de départ de l'octet concerné. J'aurais pu le faire à partir d'un calculs assez longs, mais un vecteur s'en occupe très proprement. Une fois l'adresse en mémoire, on utilisera des calculs pour nous déplacer par rapport à ce point.
Le vecteur système &BC1D fourni l'adresse d'écran par rapport aux coordonnées transmis dans les registres 'HL' pour les lignes (0 à 199) et 'DE' pour les colonnes (0 à 159). En retour, le registre 'HL' contient l'adresse d'écran et tous les autres registres sont HS.
Ensuite on fait pointer le registre 'DE' sur l'adresse de la matrice et le registre 'IY' sur l'adresse des couleurs à utiliser.

Comme ce programme permet de redéfinir des caractères en 8*16, il nous faudra une variable qui indique si on travail avec un caractère Amstrad de 8 lignes ou alors un caractères personnalisé de 16 lignes.
La variable 'RotCou' Rotation des couleurs servira à faire tourner les couleurs toutes les 2 lignes pour un caractère de 8 lignes ou bien toutes les 4 lignes pour un caractère de 16 lignes. On en reparlera plus bas, lors de sont utilisation.
Vient la variable 'Zoom', cette variable répétera le nombre de fois désiré l'affichage d'une ligne avec un décalage d'une ligne vers le bas pour donner un effet de Zoom.

Ensuite on charge dans le registre 'C' l'octet à traiter mais on passe par le registre 'A' car LD C, (DE) n'est pas possible avec le Z80.
Et on fait une boucle de 4 octets à afficher par ligne... On va afficher les 8 points de chaque ligne avec les couleurs demandées, mais comme on ne peut faire rentrer que deux points par octet, il nous faut bien 4 octets pour afficher les 8 points.
Le registre 'A' et 'D' contiendra la couleur codée de l'encre.

Pour le pixel de gauche (Poids fort) on fait tourner le registre 'C' qui contient l'octet de la ligne vers la gauche et si le 'Carry' (BIT de test) est à 1, alors on garde la couleur de l'encre du registre 'D' sinon on lui injectera la couleur du papier.

Pour le pixel de droite (Poids faible), on procède de la même manière, et si le 'Carry' est à 1, on gardera la couleur de l'encre du registre 'A' sinon on injectera la couleur du papier dans 'A'.
Il ne reste qu'à multiplier par deux la couleur de gauche du registre 'D' et à faire l'addition.

Ensuite, un octet spécial est réservé, car en ce moment, le registre 'A' contient la valeurs des deux pixels à afficher et on a la possibilité de combiner cette valeur avec l'octet situé sur l'écran.  
Je n'ai pas prévu de RSX permettant d'ajouter cet effet, car un simple poke peut le faire.
Donc voici un petit tableau avec les différentes possibilités. Le plus simple est de faire plusieurs essais mais je vous invite à vous renseigner sur la logique booléenne si vous n'avez pas d'aquis sur ce sujet.

logique boleenne
Par défaut, j'utilise l'opérateur 'NOT', ce qui s'affiche efface le dessous, certains jeu comme 'SORCERY+' utilise un XOR, en affichant la même chose deux fois sur la même position, ça l'efface. Très pratique pour les jeux sur fond uni!
Je ne vais pas m'attarder sur ce sujet, j'ai moi même encore beaucoup à apprendre.

Une fois les 8 points d'une ligne de la matrice affichés, on fait un petit calcul pour descendre d'une ligne.
Sachant que 'HL' pointe sur 4 octets plus loin, on l'additionne avec la valeur #800 - 4 octets. Cette recette je l'ai prise sur le site de QUAZAR. Elle est rapide et a le mérite d'être très simple surtout avec l'adressage d'écran de l'Amstrad.
Si on sort de l'écran, c'est que le registre 'HL' dépasse la valeur &FFFF, alors on rajoute à 'HL' l'adresse de départ de l'écran &C000 + 80 octets pour réajuster les lignes.
La commande d'après permet de répéter l'affichage mais une ligne en dessous. En affichant plusieurs lignes  identiques les une en dessous des autres, on obtient un zoom dans le sens vertical. 

Juste après l'affichage d'une ligne d'un caractère Amstrad ou d'un caractère de 8*16, on contrôle si on doit changer la couleur.
Le code 'RRC C' entraîne le report du BIT 0 du registre 'C' dans le 'CARRY' et effectue une rotation entière du registre 'C'.

L'image ci dessous est mieux parlante:
rotation

Et si le 'CARRY' vaut 1, alors on passe à la couleur suivant en incrémentant le registre 'IY' sinon on garde 'IY' sur sa position. 
Il ne reste plus qu'à répéter les opérations jusqu'à l'affichage complet du caractère. 

La prochaine partie concernera le principal du programme: Les RSX bien documentés eux aussi.

A bientôt sur RétroPoke.

 

Publicité
Publicité
Commentaires
Favoris

cheshirecats logo

amsnews logo

amsnews logo

amstradeu logo

cpcpower logo

crazi

acme logo

amstradfunlogo

amstradfunlogo

amstradMuseum

amstrad

 

 

 

me contacter

votre banniere ici

 


Publicité
Rétro Poke
Derniers commentaires
Archives
Visiteurs
Depuis la création 16 078
Publicité