Retourner au sommaire

Le CRTC

Cette série d'articles a été rédigée entre 1992 et 1995. À l'époque les connaissances CRTC de la scène (et les miennes) étaient plus empiriques que techniques, aussi certaines informations sont discutables du point de vue théorique. Cette rubrique peut donc être grandement améliorée ; toutefois, en l'état, elle pose déjà toutes les règles pratiques à connaître pour pouvoir coder tous les types d'overscans, de ruptures et de scrollings hard sur les différents CRTC.

Le CRTC : la midinette du CPC ! Nous allons donc ici parler du CRTC, le circuit sans lequel 99% des démos CPC n'auraient jamais été. C'est lui qui contrôle tous les signaux vidéos et gère les adresses de mémoire vidéo. Vous voulez faire de l'overscan ? des scrollings ? du page-flipping ? Eh bien c'est à lui qu'il faut s'adresser.

Plutôt que d'aborder le CRTC par une austère fiche technique, nous en découvrirons les fonctionnalités au fur et à mesure des techniques décrites. Pas à pas, nous allons apprendre à nous en servir pour faire de l'overscan1), de la rupture simple2), puis ligne-à-ligne3) et enfin verticale4). En outre, nous n'évoquerons ici les problèmes de compatibilité CRTC qu'au cas par cas en fonction des contraintes imposées par telle ou telle technique. Si vous voulez tous les détails sur les différents types de CRTC et leurs particularités, je vous invite à aller lire cet article, dans lequel vous trouverez également comment tester les CRTC logiciellement.

Vous le voyez, on a du pain sur la planche. Je tiens toutefois à vous avertir que les explications qui suivent nécessitent de votre part une parfaite maîtrise de l'assembleur et une excellente connaissance de l'architecture de la mémoire du CPC5).

L'overscan

Basé sur les articles publiés dans Quasar CPC numéro 3 et numéro 4, Perfectionnement à l'Assembleur et Concours6), par OffseT.

Comme le laisse deviner le titre de cette première section, nous allons donc parler ici de l'overscan. Pour ceux qui ne savent pas encore ce qu'est l'overscan7), eh bien il s'agit simplement de passer outre l'énorme bordure d'écran qui encercle normalement la zone affichable : faire disparaître purement et simplement le “border” ! D'ailleurs, si l'on traduit “overscan”, on s'aperçoit que ça veut dire “au-delà du bord”. Bref, reprenons nos élucubrations sur l'overscan.

La première chose que vous devez savoir, c'est comment s'adresse le CRTC, car nous allons avoir besoin de titiller quelques uns de ses registres. Je vous rassure tout de suite, c'est très simple. La procédure se fera en deux temps. D'abord il faut préciser au CRTC quel registre on veut modifier, et ensuite, il faut envoyer la sauce ! Ces deux opérations s'effectuent à l'aide de deux ports : &BC00 pour le registre, et &BD00 pour la sauce. Voici, en BASIC pour une fois, le schéma d'adressage du CRTC :

OUT &BC00,Registre
OUT &BD00,Valeur

Bon, maintenant, passons aux choses sérieuses.

Créer un écran overscan

Il ne faut opas confondre "overscan" et "par-delà les cimes" !

Positionnons l'écran

À gauche toute !

Il nous faut tout d'abord placer l'écran à gauche. Pour ce faire, nous n'allons pas le soulever pour le déplacer sur le bureau, mais nous servir du registre 2 du CRTC qui permet de choisir la position de la HBL. En standard, il est à 46, ce qui correspond à un écran centré. Nous, nous allons le mettre à 49, ce qui va placer l'écran complètement à gauche.

Comment ça, il n'est pas complètement à gauche ? No problem, si vous y tenez vraiment, mettez-le à 50. Mais attention, tous les types de CRTC ne l'acceptent pas ! Eh oui, il existe sur CPC plusieurs types de CRTC, ce qui conduit à divers problèmes de compatibilité… mais il s'agit d'un vaste sujet que nous n'approfondirons pas ici, pour plus de détail je vous invite à aller lire la rubrique traitant du test CRTC. Pour le cas qui nous intéresse, il faut en fait s'assurer que la somme des registres 2 et 3 soit inférieure à la valeur du registre 0 pour rester compatible avec les CRTC “type 2”… mais bon, je vous conseille donc de laisser le registre 2 à 49 pour le moment, ce qui est largement suffisant.

Aller plus hauuuutttt !

À présent, il nous faut placer l'écran en haut. C'est là qu'intervient le registre 7 qui agit sur la position de la VBL. En standard, sa valeur est de 30, et nous le mettrons à 34 (ou 35) pour positionner l'écran tout à fait en haut. Maintenant que l'écran est placé, il va nous falloir l'agrandir.

Étendons les limites de l'écran

Faites tout d'abord un BORDER 6 pour mieux visualiser l'écran et stigmatiser le border.

Mange de la soupe !

Maintenant, nous allons voir comment il faut s'y prendre pour augmenter la hauteur. Eh bien, le registre 6 est là pour ça ! Sa valeur standard étant de 25 (ce qui correspond ni plus ni moins aux 25 caractères de haut de l'écran standard), il nous faut le mettre à 35 pour avoir un écran en pleine hauteur. Et là, horreur malheur ! Ce qui est en haut se répète en bas ! Ne vous affolez pas, c'est normal !

Le mode overscan

Par défaut, le CRTC est programmé pour afficher un écran de &4000 octets (de &C000 à &FFFF). Mais lorsque l'on augmente la taille de l'écran, le nombre d'octets à afficher dépasse &4000… et que fait alors notre brave CRTC, il boucle ! La solution, vous vous en doutez, consiste à indiquer au CRTC qu'il n'a plus &4000 octets à afficher, mais &8000, on passe alors en “mode overscan” avec un buffer vidéo de 32Ko au lieu de 16Ko ! Pour ce faire, il faut utiliser le registre 12 qui sert également à choisir la page écran à afficher. Ce registre va en fait de paire avec le registre 13 qui permet de définir ce qu'on appelle l'offset et dont nous parlerons plus en détail un peu plus loin. Voici donc le schéma de ces deux registres :

Les registres 12 et 13 du CRTC6845 :

13 12 Adresse
0 0 &0000
0 1 &4000
1 0 &8000
1 1 &C000
11 10 Taille
0 0 16Ko
0 1 16Ko
1 0 16Ko
1 1 32Ko

On voit donc que ce sont les bits 2 et 3 du registre 12 (appelons-les les “overscan bits”) qui permettent de sélectionner le mode overscan. S'ils sont tous les deux à 1, la page écran fait 32Ko, dans tous les autres cas, elle en fait 16.

Courage, nous sommes bientôt à bon port !

Tout en largueur !

Bon, il ne nous reste plus qu'à l'élargir l'écran ! Il faut alors utiliser le registre 1 qui est à 40 en standard (comme 40 caractères “mode 1” de large), et le mettre à 46. Eh bien voilà, je crois que je n'ai rien omis de préciser concernant les notions générales sur l'overscan. Bidouillez, testez… et quand vous vous sentirez prêts, passez à la suite pour voir comment utiliser de tels écrans !

Gérer un écran overscan

Bon, nous avons vu la partie hardware de l'overscan, mais une fois que l'écran est retaillé et positionné, il faut le gérer…

Comme vous vous en êtes sûrement aperçus, la mise en place d'un écran overscan passe obligatoirement par un écrasement total ou partiel du système vu que nous n'avons pas deux pages de 16Ko consécutives totalement libres. Ok, Ok, le petit blond à lunettes a raison, “obligatoirement” est abusif, car si on fait de l'overscan avec des ruptures simples plutôt qu'en utilisant les overscan-bits, on peut ne pas toucher au système… mais nous verrons cela plus tard vu que l'utilisation de ruptures d'écran demande plus de prérequis que l'overscan de base.

Ceci est une lance overscan !

Dès lors, lorsque l'on veut faire des programmes avec un overscan via les overscan-bits, il faut soit reconfigurer les interruptions (passer en mode IM 2), soit déplacer la pile et, dans tous les cas, il faut se reprogrammer entièrement tous les vecteurs de gestion de l'affichage (&BC268), &BC299), etc.). Donc, il y a du boulot !

Je vais traiter ici deux gestions possibles de l'overscan, et, pour chacune d'entre-elles, vous expliquer comment doit se faire la reconfiguration du système.

Tout d'abord, envisageons le cas d'un écran de 32Ko logé de &C000 à &FFFF et de &0000 à &3FFF. Dans ce cas là, les avantages sont assez nombreux, surtout si on débute ; en effet, on n'écrase pas les vecteurs (la plupart d'entre-eux, notamment les &BB1B10), &BB06 et &BB1811), restent utilisables) ce qui facilite un peu la programmation, la pile reste intacte, l'Amsdos est toujours accessible, etc..

Mais, car il y a toujours un mais, du fait de la partie de l'écran logée de &0000 à &4000, les pauvres petites interruptions IM 1 en &38 se retrouvent au beau milieu de l'écran… gênant non ? Il y a donc deux solutions pour remédier à ce problème (j'en utilise parfois d'autres mais elles sont encore plus scabreuses) : soit on fait un DI et on en parle plus (mais là, on devra carrément se passer des interruptions, ce qui est souvent très embêtant !), soit on se met franchement en mode vectorisé (IM 2, c'est le mode d'interruption où l'on peut choisir l'adresse de l'interruption). Mais dans ce dernier cas, il y a un problème de compatibilité entre CPC et CPC+ (qui n'est pas insurmontable du tout) c'est pourquoi je vous invite tout de go à aller lire cet article qui vous expliquera tout cela en détail.

Ensuite, si on a un écran logé de &8000 à &FFFF (c'est la configuration que je préfère même si elle pose quelques problèmes pendant la programmation). Là, plus de système du tout ! Adieu les vecteurs, ciao l'Amsdos, bye bye la pile ! Vous le voyez, avant de pouvoir utiliser cette configuration, il faut bien maîtriser l'assembleur puisque l'on doit se refaire la gestion du clavier, du FDC (pas toujours en fait), etc..

Maintenant qu'on a fait un rapide tour d'horizon des problèmes que pose l'overscan 32Ko, on va pouvoir y aller ! Pour plus de simplicité commencez par travailler avec un écran logé à partir de &C000 et un DI.

L'organisation de la mémoire vidéo

Nous allons à présent afficher un sprite sur un écran overscan.

La plupart d'entre-vous ont déjà essayé et se sont écriés : “ça foire complètement !” Et pour cause, il faut, dès que l'on a reformaté l'écran en largeur, se refaire des &BC26 et des &BC29 adaptés car ceux du système sont prévus pour un écran de 80 octets de large… si on les utilise malgré tout, on obtient un affichage avec des lignes en décalé. Donc, nous allons voir comment il faut s'y prendre pour refaire les routines de calcul des lignes inférieures et supérieures.

Le tout pour s'y retrouver, c'est d'être O-R-G-A-N-I-S-É !

Mais comme je ne sais pas si vous connaissez bien la structure d'un écran (overscan ou standard), nous allons commencer par voir ça ensemble ! Étudions tout d'abord la configuration d'un écran standard (80 octets de large par 200 de haut) et voyons comment ça marche. Allumez votre CPC et faites un petit POKE &C000,&FF. Résultat des courses : un magnifique petit octet s'est affiché dans le coin en haut à gauche de votre écran ! Imaginons maintenant que nous voulions décaler cet octet vers la droite (qui a dit on fait RRA ?), eh bien il suffit d'incrémenter son adresse. D'où le fameux POKE &C001,&FF qui nous affiche un autre octet juste à droite du précédent. Bon, jusque là, c'est simple. Maintenant, si on continue à incrémenter l'adresse (allez, disons 78 fois de plus, au hasard), il va bien arriver un moment où on va se retrouver contre le bord droit de l'écran (dans le cas contraire, dites-vous qu'il doit peut-être y avoir un léger problème, si si !). Dès lors, si on ajoute encore un… ça nous donnera un POKE &C050,255 (&C050=&C000+80). Horreur ! L'octet se retrouve 8 lignes en dessous du premier que nous avions affiché. On peut renouveller l'opération et notre petit octet va continuer à divaguer de gauche à droite et à sauter de 8 lignes en 8 lignes, et ce, jusqu'en bas de l'écran. Si on continue alors à incrémenter l'adresse écran, le curseur réapparait en haut à gauche, mais cette fois-ci juste une ligne en dessous du &C000… etc.. Que du bonheur !

Si vous n'avez pas bien compris tout ça, tapez le programme suivant et vous verrez exactement ce qui se passe :

10 ' L'écran et ses octets...
20 FOR x=49152 TO 65535
30 ' 49152=&C000 et 65535=&FFFF
40 POKE x,255
50 NEXT
60 END

Bon, essayons maintenant de voir ce qu'il faut faire pour passer d'un seul coup d'un seul d'une ligne à celle du dessous. Il se trouve que l'écran fait &4000 octets de long (16384 si vous préférez la barbarie), or, lorsque l'on incrémente notre petite adresse (comme nous l'avons vu juste au dessus), il descend de 8 lignes en 8 lignes d'où le calcul savant du nombre qu'il faut ajouter à l'adresse pour descendre d'une ligne et d'une seule : x=&4000/8=&800. Donc, si vous faites un POKE en &C800, vous vous retrouverez à l'adresse située juste en dessous de &C000. Mais attention ! Ce calcul ne fonctionne que dans le cas où vous n'êtes pas déjà à une adresse correspondant à une ligne multiple de 8 !

En effet, dans le cas où vous êtes sur une ligne qui est multiple de 8, si vous ajoutez &800, vous sortez de l'écran et vous vous attaquez aux restarts du système… Pour obtenir une adresse correcte, il vous faudra ajouter &C000 (vous vous retrouvez ainsi de nouveau sur l'écran mais 8 lignes au dessus de l'adresse escomptée), puis enfin 80 (pour redescendre de 8 lignes). Oui, je sais, je ne suis pas très clair, mais c'est franchement pas évident à expliquer sans schéma ! Donc, pour plus de clarté, voici la routine du BC26 (pour un écran de 80 octets de large) :

;
; Calcul de la ligne inférieure
;
 
BC26 LD A,H      ; HL=adresse écran
     ADD A,8     ; On ajoute &800 à HL
     LD H,A
     RET NC      ; A-t-on débordé de l'écran ?
     LD BC,&C050 ; &C000+80
     ADD HL,BC
     RET

Oups, j'ai oublié de vous dire qu'il s'agit là d'un BC26 sur HL et qui modifie BC, de plus, il ne tourne que pour un écran logé en &C000 puisqu'il utilise la carry pour détecter le débordement. Libre à vous de le modifier selon vos besoins. Ensuite, pour l'adapter à n'importe quelle largeur d'écran, si vous avez suivi, cela ne devrait pas vous poser de problème ; il suffit de remplacer le +80 (&50) par la nouvelle largeur d'écran en octets (valeur du registre 1 du CRTC * 2).

Enfin, ce qu'il faut savoir, lorsque l'on passe en overscan, c'est qu'on ne gère pas un écran de 32Ko, mais 2 écrans de 16Ko consécutifs (généralement un en haut et un en bas, non, non, je ne blague pas !). Vous voyez donc logiquement qu'il vous faudra deux BC26 différents suivant que vous vouliez afficher un sprite sur une partie de l'écran ou sur l'autre. J'espère que c'est bien clair.

Je sais, cette section est un peu abstraite, mais si vous connaissez déjà un petit peu la gestion des sprites avec les vecteurs système, vous devriez être en mesure d'afficher de superbes pages overscan… je vous assure que ce chapitre contient tous les éléments nécessaires même si c'est un peu éparpillé !

Le CRTC est extrêmement riche de techniques, et après l'overscan primal, la rupture va encore nous ouvrir de nouveaux horizons !

La rupture simple

Basé sur l'article publié dans Quasar CPC numéro 7, Perfectionnement à l'Assembleur, par OffseT.

Découverte par Longshot à la fin des années 80, cette technique permet de changer l'adresse vidéo en cours de balayage. Elle est donc extrêmement pratique pour créer toutes sortes d'effets à base de scrollings ou de page-flipping, et est à la base de toutes les autres techniques vidéo hardware sur CPC.

C'est parti

Comme nous l'avons déjà vu plus haut, on adresse le CRTC via ses 18 registres. Dans le cas qui nous intéresse, nous aurons besoin de 8 d'entre eux seulement. Je vais tout d'abord commencer par faire les présentations ; vous connaissez normalement déjà la plupart de ces registres vu que nous en avons déjà parlé dans la section sur l'overscan mais un petit rappel ne fait jamais de mal.

Mais non, mais non, ça ne mord pas !

Registre 1 :

Largeur d'écran en caractères mode 1.
Valeur standard : 40
Bouclage sur 8 bits.

Registre 2 :

Position X de l'écran visible.
Valeur standard : 46
Bouclage sur 8 bits.

Registre 3 :

Longueur de synchronisation horizontale.
Valeur standard : 142 (128+14)
Bouclage sur 4 bits, le bit 7 permet de doubler la longueur de VBL sur certains CRTC, ceci sert notamment lors des tests CRTC.
En fait il n'a rien à voir avec la rupture simple mais pour des problèmes de compatibilité avec le CRTC 2, il faudra y toucher pour positionner notre écran en X (la problématique reste la même que pour l'overscan).

Registre 4 :

Alors là, on rentre dans le vif du sujet car c'est le registre qui permet les ruptures. Il permet de définir le nombre de lignes de caractères total à balayer avant de reboucler. En standard, il est à la valeur 38. Ce qui correspond à 39 (38+1) lignes de caractères balayées, soit un écran de 312 lignes de pixels (dont en pratique 25 sont visibles, voir le registre 6 ci-dessous).
Ce registre boucle sur 7 bits, il peut donc prendre des valeurs allant de 0 à 127.

Registre 6 :

Nombre de lignes de caractères visibles.
Valeur standard : 25
Bouclage sur 8 bits.

Registre 7 :

Position Y de l'écran… ou plus rigoureusement, position de la zone de VBL.
Bouclage sur 8 bits.
Par défaut ce registre vaut 30, ce qui nous positionne la VBL à 30 lignes après le début de l'écran, soit 5 lignes après la fin de l'écran visible et 4 lignes avant le début de celui-ci ! Vous n'avez pas compris ? Relisez la description des registres 4 et 6 ! Ceci étant, nous allons revenir dessus en détail plus bas.

Registres 12 et 13 :

Ils définissent l'adresse vidéo. Celle-ci se compose de 3 éléments :

  • de l'offset sur 10 bits, les 8 bits du registre 13 étant les bits de poids faible et les bits 0 et 1 du registre 12 étant les 2 bits de poids fort,
  • de l'adresse écran de base, les bits 4 et 5 du registre 12 définissant le doublet de poids fort de l'adresse écran (&0xxx, &4xxx, &8xxx ou &Cxxx),
  • du format de l'écran avec les bits 2 et 3 du registre 12. Si les deux sont à 1, on configure un écran de 32ko, sinon 16ko. Mais pour la rupture, seuls l'adresse écran et l'offset nous intéressent, ceci n'est utile qu'à l'overscan de base (sans rupture).

Pour plus de clarté, voici un schéma représentant ces registres :

Comment ça marche...

Hum ! Pour que vous compreniez bien comment fonctionne une rupture, il faut que vous sachiez que le CRTC dispose en fait de deux jeux de 18 registres. Il y a les registres à part entière qui sont ceux que nous pouvons adresser grâce au Z80 et des registres internes au fonctionnement du CRTC que nous appellerons les compteurs.

Voici maintenant, de façon simplifiée, comment ça se passe quand notre petit CRTC balaye l'écran.

On commence par le haut de l'écran. Le compteur 412) vient d'être remis à zéro. Le CRTC balaye la première ligne de caractères (8 lignes de pixels en standard), incrémente le compteur 4, le compare au registre 4, si c'est inférieur, on passe à la ligne suivante. Ainsi, notre CRTC continue gaiement à faire ses comptes jusqu'au moment fatidique où le compteur 4 et le registre 4 sont égaux. Le CRTC remet alors calmement son compteur 4 à zéro et lit l'adresse vidéo (le registre 12 et 13) afin d'en charger la valeur dans les compteurs 12 et 13… et reboucle.

Puisque je vous dis qu'il ne mord pas !

Et la rupture alors ?

Nous y venons. En fait une rupture c'est quoi ? Eh bien ça consiste tout simplement à changer l'adresse vidéo en cours de balayage, ce qui donne accès à quelques techniques hardware sans lesquelles le CPC serait relégué au rang d'Oric. En effet, à partir du moment où on peut changer l'adresse vidéo durant le balayage, on peut faire des scrollings hard, des flippings d'écran partiels, etc.. Mais en plus, tout un tas d'autres avantages viennent se rajouter (avec le registre 5 par exemple donc nous parlerons ci-après dans la section consacrée aux scrollings hard).

Revenons à notre adresse vidéo, comme vous l'aurez remarqué, le problème c'est que celle-ci n'est lue par le CRTC qu'au bouclage du registre 4.. Qu'à cela ne tienne, on va modifier la valeur du registre 4 et celle de l'offset pendant le balayage un peu comme on le fait avec les rasters ! Oui mais voilà : bug ! Soit on n'a plus de VBL du tout (dans le cas où le registre 7 est supérieur au registre 4), soit une vilaine zone noire de VBL vient se coller à chaque bouclage du registre 4 et donc, entre chacun des écrans ainsi créés (dans le cas où le regsitre 7 est inférieur ou égal au registre 4) ! Heureusement, papy Longshot est passé par là et il a trouvé la solution : trifouiller le registre 7 pendant la frame.

En effet, ce registre localise la zone de VBL sur l'écran et notre compère Longshot a eu la bonne idée de la mettre à 255 en haut de l'écran, il s'agit d'une valeur dite “overflow”, toujours supérieur à celle du registre 4 et qui a pour effet d'ordonner de faire la VBL… jamais ! Mais si on laissait ça comme ça, on aurait des problèmes car sans zone de synchro notre rupture ressemblerait plus à un bug qu'autre chose… d'où la suite, on remet ce registre à 0 tout à fait en bas, ce qui signifie : fais la VBL dès que le registre 4 vaut 0, c'est à dire tout de suite, dès le début de l'écran ! Résultat : notre écran est synchrone et la zone de synchro est allée se cacher sagement tout en haut de l'écran (si vous voulez voir cette zone de VBL, elle est en fait tout le temps présente, il vous suffit de tourner un peu le bouton “V-HOLD” à l'arrière de votre moniteur).

Argh !

Je vous assure ! Ça ne mord pas ! Il faut absolument que je vous parle de deux choses essentielles : la bufferisation des registres 12 et 13 et l'overflow du registre 4.

Tout d'abord, comme les registre 12 et 13 sont lus pendant le bouclage du compteur 4, vous comprendrez aisément que ceux-ci doivent impérativement avoir été chargés avec la nouvelle valeur avant ce bouclage (changement d'écran). C'est-à-dire que l'adresse vidéo de la rupture suivante doit être envoyées aux registres 12 et 13 pendant la rupture courante. Mais attention, pas trop vite non plus car sur CRTC 1 les registre 12 et 13 sont lus pendant que le compteur 4 vaut 0 (et non pas seulement quand il passe à zéro), donc il est pris en compte durant toute la première ligne de caractère de chaque rupture ce qui n'est généralement pas souhaitable ; il faut donc attendre un peu cette ligne soit terminée pour rester compatible avec ce CRTC.

Jusque là, ça n'est pas très compliqué mais par contre, pour le chargement du registre 4 se pose un problème. On ne peut pas le charger n'importe quand avant le bouclage car le CRTC ne comprendrait alors plus rien à son affaire. Il était en train de s'appliquer à compter pour arriver au bon résultat et voilà qu'un petit malin vient s'amuser à lui fausser ses calculs. Résultat : overflow dans le cas où la nouvelle valeur spécifiée est plus petite que la valeur courante du compteur 4 ou perte de toutes références (adieu les 50Hz) dans le cas où la valeur n'a pas encore été atteinte (puisque la rupture courante devient la rupture suivante !).

La solution, c'est donc de renouveller le registre 4 après que le bouclage ait eu lieu… Mais pas n'importe quel “après”. En effet, il faut faire attention à l'overflow. Il faut impérativement que lorsque vous chargez votre nouvelle valeur le compteur 4 ne l'ait pas déjà dépassée, car sinon celui-ci va refaire un tour complet sur 7 bits : c'est l'overflow.

Pour l'heure, les bases étant posées, voyez le petit prog' d'exemple qui est généreusement commenté. Pour information, sachez que les interruptions (qui nous servent de synchro via des HALT) ont lieu toutes les 6,5 lignes de caractères.

Listing : la rupture simple

Télécharger le listing assembleur au format Maxam 1.5

;
; Programme d'exemple de rupture simple
;   par OffseT 1994 pour Quasar CPC 7
;
;   Gestion de 3 ruptures classiques
;
 
	Org &8000
	Nolist
 
;
; Initialisations
;
 
	di		; On coupe les interruptions
	ld hl,(&38)	; On lit l'ancienne interruption
	ld (inter+1),hl	; et on la sauve.
	ld hl,&c9fb	; On remplace tout ça par
	ld (&38),hl	; du neuf (EI,RET)
	ei		; On remet les interruptions
 
; Formatage de l'écran
 
	ld bc,&bc00+3	; On met la valeur 8 dans
	out (c),c	; le registre 3 du CRTC
	ld bc,&bd00+8	; afin de rester compatible
	out (c),c	; avec les CRTC type 2
	ld bc,&bc00+2	; pour lesquels la valeur
	out (c),c	; 50 est autrement impossible
	ld bc,&bd00+50	; à mettre dans le registre 2
	out (c),c	; On met ensuite le registre 1
	ld bc,&bc00+1	; à la valeur 48 ce qui
	out (c),c	; nous fait un écran de
	ld bc,&bd00+48	; 96 octets de large,
	out (c),c	; un overscan complet quoi !
 
; Offset rupture 1
 
	ld bc,&bc00+12	; On initialise l'offset
	out (c),c	; qui sera celui de la
	ld bc,&bd00+&30	; première rupture avant le
	out (c),c	; programme principal afin
	ld bc,&bc00+13	; d'etre sur que tout marchera
	out (c),c	; sur tous les CRTC car certains
	ld bc,&bd00+0	; certains refusent de modifier
	out (c),c	; l'offset pendant la VBL
 
; Programme Principal
 
; Attente de la VBL
Prog	ld b,&f5	; On attend gentiment
Synchro	in a,(c)	; que le canon à électron
	rra		; entame sa remontée vers
	jr nc,synchro	; le haut de l'écran.
 
; Préparation des ruptures
 
	ld bc,&bc00+7	; On met le registre 7 en overflow
	out (c),c	; pour ne pas etre embeter par des
	ld bc,&bd00+255	; des zones de VBL intempestives au
	out (c),c	; milieu de nos ruptures.
 
	ld b,255	; Une petite boucle d'attente pour que
	djnz $		; les CRTC qui refusent de travailler
			; pendant la VBL ne soient pas genés.
 
; Gestion des ruptures
 
; Rupture 1
 
	ld bc,&bc00+4	; On met le registre 4 à 14
	out (c),c	; ce qui signifie que le
	ld bc,&bd00+14	; premier écran fera 15
	out (c),c	; lignes de haut.
 
; Offset rupture 2
 
	ld bc,&bc00+12	; On prépare le nouvel
	out (c),c	; offset pour la rupture
	ld bc,&bd00+&20	; 2 afin que celui-ci
	out (c),c	; soit pris en compte au
	ld bc,&bc00+13	; bouclage du compteur du
	out (c),c	; registre 4 de notre
	ld bc,&bd00+0	; brave petit CRTC
	out (c),c	; adoré...
 
; Rupture 2
 
	halt		; On attend que le premier
	halt		; écran ait été complètement
	halt		; balayé et que le compteur
	ld bc,&bc00+4	; du registre 4 ait bouclé
	out (c),c	; puis on charge la nouvelle
	ld bc,&bd00+12	; hauteur, 13 lignes de
	out (c),c	; caractères ici.
 
; Offset rupture 3
 
	ld bc,&bc00+12	; On prépare le nouvel
	out (c),c	; offset pour la rupture
	ld bc,&bd00+&10	; 3 afin que celui-ci
	out (c),c	; soit pris en compte au
	ld bc,&bc00+13	; bouclage du compteur du
	out (c),c	; registre 4 de notre
	ld bc,&bd00+0	; brave petit CRTC
	out (c),c	; adoré...
 
; Rupture 3
 
	halt		; On attend la fin de la
	halt		; rupture 2 et on commande
	ld bc,&bc00+4	; au CRTC la hauteur de
	out (c),c	; l'écran suivant, ici
	ld bc,&bd00+10	; c'est le dernier et il
	out (c),c	; fait 11 lignes.
 
; Offset rupture 1
 
	ld bc,&bc00+12	; On bufferise l'offset
	out (c),c	; de la première rupture
	ld bc,&bd00+&30	; qui sera pris en compte
	out (c),c	; après la VBL. On le fait
	ld bc,&bc00+13	; à l'avance car certains
	out (c),c	; CRTC un peu fainéants
	ld bc,&bd00+0	; refusent de travailler
	out (c),c	; pendant la VBL.
 
; Fin des ruptures
 
	ld bc,&bc00+7	; On remet le registre 7 à
	out (c),c	; 0 pour que le CRTC puisse
	ld bc,&bd00+0	; se remettre de ses émotions
	out (c),c	; sinon plus de synchro !
 
; Test clavier
; Barre espace
 
	ld bc,&f40e	; Rien à dire ici car
	out (c),c	; ce n'est pas le sujet !
	ld bc,&f6c0
	out (c),c
	xor a
	out (c),a
	ld bc,&f792
	out (c),c
	ld bc,&f645
	out (c),c
	ld b,&f4
	in a,(c)
	ld bc,&f782
	out (c),c
	ld bc,&f600
	out (c),c
	rla
	jp c,prog
 
;
; Réinitialisations
;
 
; Ecran en mode standard
 
	ld bc,&bc00+12	; On se remet l'offset
	out (c),c	; standard avec l'écran
	ld bc,&bd00+&30	; logé en &C000 pour ne
	out (c),c	; pas avoir de gribouillis
	ld bc,&bc00+13	; au retour au BASIC...
	out (c),c	; Puis on enchaine sur la
	ld bc,&bd00+0	; remise à l'état standard
	out (c),c	; de tous les autres
	ld bc,&bc00+4	; registre du CRTC.
	out (c),c	; Registre 4 à 38, dès la
	ld bc,&bd00+38	; prochaine VBL tout va
	out (c),c	; rentrer dans l'ordre.
	ld bc,&bc00+7	; Registre 7 à la valeur 30
	out (c),c	; pour recader l'écran en
	ld bc,&bd00+30	; hauteur.
	out (c),c	; Puis on remet l'écran
	ld bc,&bc00+2	; en place en largeur
	out (c),c	; avant de remettre le
	ld bc,&bd00+46	; registre 3 à 142 qui
	out (c),c	; nous avait servi à
	ld bc,&bc00+3	; faire suivre le CRTC
	out (c),c	; type 2 qui plante
	ld bc,&bd00+142	; autrement avec le
	out (c),c	; registre 2 à 50.
	ld bc,&bc00+1	; Et puis pour finir,
	out (c),c	; on se remet la bonne
	ld bc,&bd00+40	; largeur pour ne pas
	out (c),c	; perdre ce pauvre BASIC.
 
; Interruptions standard
 
	di		; On coupe tout !
Inter	ld hl,0		; On remet le vieux
	ld (&38),hl	; modèle et on
	ei		; remet en marche !
	ret		; Heu...
 
; Surtout, veillez bien à ce que la somme de la hauteur de
; tous les écrans soit égale à 39 (hauteur = registre 4 + 1).

Les scrollings hard

Basé sur l'article publié dans Quasar CPC numéro 8, Perfectionnement à l'Assembleur, par OffseT.

Scroooooolllllliiiiiiiinnnnnng ! Vous trouverez ici une application directe des ruptures classiques qui sont expliquées juste au dessus.

Le programme que je vous propose est en fait un des premiers programme de rupture que j'ai fait ; c'est pour vous dire s'il est simple ! Il n'y a qu'une seule rupture et, qui plus est, elle est au milieu de l'écran ! On ne peut pas faire plus simple… Sur le premier écran, il y a un scrolling hard vertical, et sur le second, un bête scrolling horizontal au word près.

Le scrolling horizontal

Là, c'est très simple ! Comme vous le savez si vous avez bien lu ce qui précède, lorsqu'on configure une rupture d'écran, on spécifie via les registres 12 et 13 du CRTC l'adresse vidéo de l'écran. Dans cette adresse vidéo, nous avons l'adresse écran de base (qui reste fixe ici) et l'offset (qui va être une variable). Le CRTC, lorsqu'il regarde ce qu'il doit afficher sur votre moniteur, se sert de l'offset pour repérer à quelle adresse il doit commencer la lecture de la mémoire écran ; l'adresse haut gauche de l'écran est ainsi celle correspondant à l'adresse écran de base à laquelle on ajoute le double de la valeur de l'offset, d'où la notion de word.

Vous voyez en effet que seules les adresses paires peuvent ainsi être atteintes ! D'où un scrolling offset se déplaçant obligatoirement de deux octets en deux octets. Le seul moyen d'avoir un scroll à l'octet (ou même moins !) est de recourir à la technique du page-flipping. On gère alors x scrollings (si possible sur la même page écran pour simplifier les choses et économiser de la mémoire) décalés les uns par rapport aux autres de 1 x-ième de word et on fait un page-flipping avec tout ça ! Les plus curieux d'entre-vous trouveront des exemples pratiques d'exploitation du page-flipping dans les articles sur les effets de plasma et les scroll-text.

Le scrolling vertical

C'est ici un peu plus compliqué même si la technique est tout aussi élémentaire. On peut ici utiliser le registre 5 du CRTC pour avoir un scrolling au pixel près (ce qui nous dispense de la technique du page-flipping). Le registre 5 contrôle le retard vidéo ; il peut prendre des valeurs allant de 0 à 15 qui provoquent un décalage vertical de l'écran de 0 à 15 pixels… mais également une modification de la vitesse de balayage de l'écran, ce que nous allons voir un peu plus loin.

Mais pour l'heure, le principe : on décrémente le registre 5 à chaque synchro, lorsqu'il boucle on le remet à 7, et on décale l'offset de la valeur du registre 1 (la largeur de l'écran visible), ce qui fait monter l'écran de 8 lignes ! Et ainsi de suite… On a alors en théorie un joli scroll vertical au pixel géré totalement en hard.

Oui mais voilà que nos deux écrans gesticulent dans tous les sens, ça clignote, c'est l'horreur ! Eh oui, il se trouve qu'il faut compenser la valeur prise par le registre 5 au niveau de l'écran suivant celui que l'on veut faire scroller ; et ce pour deux raisons : premièrement il faut rattrapper le décalage dû au retard vidéo, et deuxièmement il faut retomber sur une fréquence de balayage de 50Hz. Enfin, voyez le programme et vous comprendrez plus aisément.

Le mot de la fin

Quoi qu'il ne soit pas utile dans cet exemple, j'ai introduit dans le programme le registre 9 qui permet de spécifier au CRTC le nombre de lignes pixel de haut d'un caractère. En standard, sa valeur est à 7 soit un écran composé de caractères de 8 lignes de haut. Dans le chapitre suivant, je vous explique comment on utilise ce registre pour obtenir de la rupture ligne-à-ligne… mais si vous y regardez d'un peu plus près, je suis sûr que vous trouverez comme ça fonctionne sans même aller le lire !

Il ne vous reste plus qu'à éplucher le programme qui suit ; il vous donnera plein de renseignements utiles. Vous constaterez que tout ceci est en fait très simple, mais c'est une bonne base avant de se lancer dans des écrans plus complexes.

Allez ! Reste pas planté là ! Scrolle à la frame !

Listing : scrollings hard horizontal et vertical

ATTENTION: bien que le listing fonctionne visuellement, il est erronée, l'écran n'est pas à 50Hz. Une mise à jour corrigée devrait apparaître d'ici peu

la règle “Nbre ligne de l'écran=(Reg4+1)*(Reg9+1)+Reg5” n'est pas du tout respectée.

Télécharger le listing au format Maxam 1.5

;
; Scrollings multiples avec rupture d'écran
; par OffseT (Futurs') 25/12/93
; Adapté le 02/04/95 pour Quasar CPC 8
 
; Info ; Nbre ligne de l'écran=(Reg4+1)*(Reg9+1)+Reg5
 
; Registres utilisés ;
 
; Reg1=Largeur d'écran
; Reg2=Position X d'écran
;     =Position de la HBL
; Reg4=Nbre total de lignes de caractères
; Reg5=Retard vidéo
; Reg6=Hauteur d'écran
; Reg7=Position Y d'écran
;     =Position de la VBL
; Reg9=Nbre de lignes des caractères
 
	Org &4000
	Nolist
 
;
; Initialisations
;
 
; Interruptions
 
	di
	ld hl,(&38)
	ld (inter),hl
	ld hl,&c9fb
	ld (&38),hl
	ei
 
; Largeur de l'écran
; (Valeurs communes aux deux écrans)
 
	ld bc,&bc00+2
	out (c),c
	ld bc,&bd00+49
	out (c),c	; Reg2=49
 
	ld bc,&bc00+1
	out (c),c
	ld bc,&bd00+50	; Reg1=50
	out (c),c
 
;
; Prog. principal
;
 
Prog	ld b,&f5
Synchro	in a,(c)
	rra
	jp nc,synchro
 
; Format du premier écran
 
	ld bc,&bc00+4
	out (c),c
	ld bc,&bd00+19
	out (c),c	; Reg4=19
 
	ld bc,&bc00+9
	out (c),c
	ld bc,&bd00+7
	out (c),c	; Reg9=7
 
	ld bc,&bc00+5
	out (c),c
Retard1	ld bc,&bd00+7
	out (c),c	; Reg5=variable
 
	ld bc,&bc00+6
	out (c),c
	ld bc,&bd00+21	; Reg6=21
	out (c),c
 
	ld bc,&bc00+7
	out (c),c
	ld bc,&bd00+255	; Reg7 hors champ
	out (c),c
 
	ld bc,&bc0c
	out (c),c
Plot1	ld bc,&bd00+%00110000
	out (c),c	; Page=&C000 & Taille=16Ko
	ld bc,&bc0d
	out (c),c
Plot2	ld bc,&bd00+0
	out (c),c	; Offset=variable
 
	halt
	halt
 
; Format du deuxième écran
 
; On ne touche pas aux registres 4 et 9
; car c'est comme pour l'écran 1
 
	ld bc,&bc00+5
	out (c),c
Retard2	ld bc,&bd00
	out (c),c	; Reg5=variable
 
	ld bc,&bc0c
	out (c),c
Plot3	ld bc,&bd00+%00100000
	out (c),c	; Page=&8000 & Taille=16Ko
	ld bc,&bc0d
	out (c),c
Plot4	ld bc,&bd00+0
	out (c),c	; Offset=variable
 
	halt
	halt
	halt
 
; Fin du deuxième écran
 
	ld bc,&bc00+7	; On remet le Reg7
	out (c),c	; à une valeur
	ld bc,&bd00+19	; normale pour la
	out (c),c	; synchro VBL
 
	call reg5
	call offset2
 
	di		; Test clavier
	ld bc,&f40e
	out (c),c
	ld bc,&f6c0
	out (c),c
	xor a
	out (c),a
	ld bc,&f792
	out (c),c
	ld bc,&f645	; Ligne 5
	out (c),c
	ld b,&f4
	in a,(c)
	ld bc,&f782
	out (c),c
	ld bc,&f600
	out (c),c
	ei
	rla
	jp c,prog	; Test espace
 
;
; Exit, on remet tout en standard
;
 
	di
	ld bc,&bc04
	out (c),c
	ld bc,&bd00+38
	out (c),c	; Reg4=38
 
	ld bc,&bc09
	out (c),c
	ld bc,&bd00+7
	out (c),c	; Reg9=7
 
	ld bc,&bc05
	out (c),c
	ld bc,&bd00+0
	out (c),c	; Reg5=0
 
	ld bc,&bc0c
	out (c),c
	ld bc,&bd00+%00110000
	out (c),c	; Page=&C000
	ld bc,&bc0d
	out (c),c
	ld bc,&bd00+0
	out (c),c	; Offset=0
 
	ld bc,&bc06
	out (c),c
	ld bc,&bd00+25
	out (c),c	; Reg6=25
 
	ld bc,&bc07
	out (c),c
	ld bc,&bd00+30
	out (c),c	; Reg7=30
 
	ld bc,&bc02
	out (c),c
	ld bc,&bd00+46
	out (c),c	; Reg2=46
 
	ld bc,&bc01
	out (c),c
	ld bc,&bd00+40
	out (c),c	; Reg1=40
 
; Restitution des interruptions
 
	ld hl,(inter)
	ld (&38),hl
	ei
	ret
 
;
; Scrolling vertical
; Modif retard vidéo
; (écrans 1 et 2)
;
 
Reg5	ld a,(retard1+1)
	dec a
	ld c,a
	and %00000111
	ld (retard1+1),a
	cp c
	call nz,offset1
	ld a,(retard2+1)
	inc a
	and %00000111
	ld (retard2+1),a
	ret
 
;
; Scrolling vertical
; Modif. offset (écran 1)
;
 
Offset1	ld a,(plot1+1)
	ld h,a
	ld a,(plot2+1)
	ld l,a
	ld bc,50
	add hl,bc
	ld a,h
	and %00110011
	or %00110000
	ld (plot1+1),a
	ld a,l
	ld (plot2+1),a
	ret
 
;
; Scrolling horizontal
; Modif. offset (écran 2)
 
Offset2	ld a,(plot4+1)
	ld l,a
	ld a,(plot3+1)
	ld h,a
	inc hl
	ld a,h
	and %00100011
	ld (plot3+1),a
	ld a,l
	ld (plot4+1),a
	ret
 
;
; Data
;
 
Inter	dw &0000

La rupture ligne-à-ligne

Basé sur l'article publié dans Quasar CPC numéro 9, Perfectionnement à l'Assembleur, par OffseT.

Être sur la ligne de front n'est pas toujours de tout repos ! Ce coup-ci on passe aux choses sérieuses ! Je vais tenter de vous expliquer la technique de la rupture ligne-à-ligne qui est sans conteste celle qui a le meilleur rapport résultat / prise de tête. Mais ce ne sera pas une mince affaire puisque va se poser le problème qu'on a jusqu'alors pu éviter : la compatibilité CRTC.

Où ça marche ?

Alors là, je préviens tout de suite ceux qui ont un CRTC type 2 : vous pouvez aller vous jeter dans le fleuve le plus proche car votre CPC est 100% incompatible avec cette technique. Je sais, c'est dur, mais on n'y peut rien (merci Amstrad !). Vous pourrez au mieux avoir de la rupture “deux-lignes-à-deux-lignes” et même si ça peut être intéressant dans des cas particuliers, on perd beaucoup des avantages de la ligne-à-ligne.

Si vous avez un type 0, 1, 3 ou 4, pas de problème, ça marchera ! Mais attention, si ça marche sur votre CPC, cela ne veut pas dire que ça marchera sur celui de votre voisin… des adaptations CRTC seront nécessaires.

Comment ça marche ?

Le technique est extrêmement simple ! En fait, ce qu'on veut c'est avoir une rupture à chaque ligne pixel et non à chaque ligne caractère afin de pouvoir modifier l'offset quand bon nous semble. Ça y est, le petit blond à lunettes ricane car le registre 4 ne permet que des ruptures par lignes de caractères. Eh bien, qu'à cela ne tienne ! On va dire au CRTC que nos caractères font une ligne de haut !

Comme j'en ai déjà brièvement parlé dans la section précédente, nous allons utiliser le registre 9 qui donne le nombre de lignes d'un caractère. En standard, il est à 7 pour 8 lignes par caractère ; il nous faudra donc le mettre à 0 pour avoir des caractères d'une ligne de haut. Et puis pour avoir une rupture à chaque ligne, il nous faudra également mettre le registre 4 à 0 comme on l'aurait fait en rupture classique.

De plus, comme vous le constaterez, chacune de nos ruptures “ligne” sont identiques ; il ne sera donc pas nécessaire de renouveller les registres 4 et 9 durant notre rupture qui se fera toute seule ! Nous aurons juste à gérer l'offset ou des affichages au fur et à mesure de notre rupture “automatique”. C'est ce qui consitue le principal avantage de cette technique.

En revanche, nous avons un inconvénient en retour : comme nos caractères ne font qu'une seule ligne de haut, seul le bloc 0 est balayé. On n'a donc pas accès à toute la mémoire vidéo et le nombre de lignes différentes disponible est donc limité (à une vingtaine de lignes par écran de 16k si vous comptez), mais c'est largement suffisant pour nombre d'effets !

Voilà, côté théorique, comme vous le voyez, il n'y a aucune difficulté. Mais, va se poser à présent le douloureux problème de l'overflow…

Overflow de malheur !

Il ne faut pas se laisser abattre par l'overflow ! Eh oui, le registre 9 va nous poser problème lorsqu'on va le mettre à zéro. En effet, si notre CRTC était en train de balayer une ligne autre que la ligne numéro 0, on lui donne une borne inférieure à la valeur à laquelle il est déjà… comme je vous l'ai précédemment expliqué, on obtient alors un overflow !

Mettez-vous à la place du CRTC et vous allez mieux comprendre. Vous êtes en configuration standard et vous balayez un des caractères de 8 lignes. Vous commencez à balayer un nouveau caractère :

  • ligne 0,
    • on vérifie si on a fini en comparant au registre 9, il vaut 7,
    • on continue,
  • ligne 1,
    • 1=7 ?,
    • ok,
  • ligne 2,
    • 2=7 ?,
    • ok…

Tout se passerait pour le mieux si un petit malin ne se mettait pas à changer la valeur du registre 9 en cours de route ! Alors que vous balayiez la ligne 3, on vous met le registre 9 à 0.

  • ligne 3,
    • 3=0 ?,
    • ok,
  • ligne 4,
    • 4=0 ?,
    • ok…

Et on peut alors aller très très loin comme ça ! C'est l'overflow ! Heureusement, notre registre 9 boucle à 32 et l'overflow se traduira tout bêtement par la répétition (4 fois) de la première ligne de caractère de l'écran et non par un plantage CRTC… ouf !

La solution

Résoudre le problème de l'overflow est au final assez simple. Il suffit d'attendre la ligne précise à laquelle le CRTC est en train de balayer le bloc 0 pour mettre le registre 9 à 0. Ainsi, il n'y a pas d'overflow ! Oui, mais voilà, cette ligne n'est pas exactement au même endroit sur tous les CRTC par rapport aux interruptions qui nous servent de synchro. Cela implique donc qu'il faudra obligatoirement faire une adaptation CRTC en compensant ces décalages de synchro par des boucles de temporisation différentes d'un CRTC à l'autre.

Voici donc l'algorithme général à suivre pour faire de la rupture ligne-à-ligne.

  1. Attente de la VBL
  2. Tempo
  3. Reg7=255
  4. Rupture(s) classique(s) éventuelle(s)
  5. Attente du bloc 0
  6. Reg9=0 : Reg4=0
  7. Attente du nombre de lignes souhaité
  8. Reg9=7 : Reg4=valeur rupture
  9. Rupture(s) classique(s) éventuelle(s)
  10. Reg7=0
  11. Loop VBL

Je pense avoir été clair ! Je vous propose maintenant d'aborder le programme que je vais vous détailler afin d'aborder les problèmes d'adaptation CRTC.

Ceci étant, restez attentif aux bugs.

Le programme

Bon, au début du programme, vous avez les classiques initialisations. On met l'écran en overscan et on met EI:RET en interruption. Vient ensuite l'attente de la VBL qui est suivie par une boucle d'attente. Cette boucle est là uniquement pour une bête compatibilité CRTC. Elle est par exemple inutile pour les types 1 mais d'autres CRTC sont perdus en son absence.

On met ensuite le registre 7 à 255 pour préparer une rupture classique, puis le registre 4 à 6 pour la programmer à 7 lignes de caractères de haut. Un petit HALT nous amène à peu de choses près à la fin de notre rupture classique. Ici on va lancer notre rupture ligne-à-ligne ; il nous faut donc temporiser pour tomber sur le bloc 0. C'est le pourquoi de la boucle de 64 NOP en Loop1. La valeur 2 est correcte si vous avez un type 1. Si vous avez un type 3 c'est 3 qu'il vous faudra mettre. Il est à noter par ailleurs que le type 3 ne fait pas d'overflow car il fait un “reset block” lorque l'on modifie le registre 9.

Une fois que l'on est sûr d'être où il faut, on met les registres 9 et 4 à 0 pour lancer notre rupture ligne-à-ligne. On la laisse ensuite courir en attendant 4 HALT + 20 lignes de telle sorte de n'avoir plus qu'à faire une rupture classique de 4 lignes en bas de l'écran de notre petit CPC (je vous rappelle qu'au total on doit toujours avoir 312 lignes pour conserver un balayage à 50Hz). Mais attention, pour certains CRTC, il vous faudra là aussi temporiser en Loop2 pour que la reprise de la rupture classique se fasse sans problème.

Ensuite, il ne vous reste plus qu'à mettre le registre 7 à 0 pour que tout soit synchronisé correctement. Là encore, une petite temporisation de 8 lignes a été insérée. Elle n'est indispensable que pour le type 1. En effet, il se trouve que le CRTC 1 prend en compte les mises à jours des registres en direct tant qu'il est en train de balayer la première ligne de caractère (ce qui fait de lui le seul CRTC intéressant pour exploiter la RVMB… mais c'est un autre sujet) et il faut donc attendre la fin du premier caractère car sinon, sans se poser de question, il va nous balancer une VBL en plein milieu de notre rupture (quel farceur !). Alors, si vous voulez que votre programme soit compatible avec les types 1, attendez toujours que les 8 premières lignes d'une rupture classique aient été balayées avant de reprogrammer un registre (que ce soit le 7 ou même les registres d'offset) car sinon celui-ci sera pris en compte directement et non bufferisé.

Voilà, je crois que vous êtes maintenant en mesure de faire de la rupture ligne-à-ligne, à vos plasmas, rubber bars et autres aurores boréales !

Listing : rupture ligne-à-ligne

Télécharger le listing au format Maxam 1.5

; Exemple de rupture ligne-à-ligne
;     par OffseT le 25/08/95
;             pour
;      Quasar CPC numéro 9
 
	Org &8000	; On commence ici !
	Nolist		; ou à l'adresse
			; que vous voulez...
;
; Initialisations
;
	ld bc,&bc01	; On définit la
	out (c),c	; largeur de notre
	ld bc,&bd00+48	; écran en la fixant
	out (c),c	; à 48 words.
	ld bc,&bc02	; On positionne notre
	out (c),c	; écran pour qu'il
	ld bc,&bd00+50	; soit bien centré
	out (c),c	; sur le moniteur.
	di		; On coupe les inters
	ld hl,(&38)	; du système après
	ld (inter+1),hl	; les avoir sauvées en
	ld hl,&c9fb	; fin de programme par
	ld (&38),hl	; une auto-modif.
	ei		; Et hop là !
;
; Programme principal
;
Prog	ld b,&f5	; Attente de la synchro
Synchro	in a,(c)	; écran, classique quand
	rra		; on fait des ruptures
	jr nc,synchro	; ou des rasters.
 
	ld b,255	; Boucle d'attente pour
Loop	djnz loop	; la compatibilité CRTC
 
	ld bc,&bc07	; Mise en overflow du
	out (c),c	; registre 7 pour ne
	ld bc,&bdff	; pas avoir de VBL
	out (c),c	; entre nos ruptures
	ld bc,&bc04	; La première rupture
	out (c),c	; est classique et fait
	ld bc,&bd06	; 7 caractères de haut
	out (c),c	; Voilà...
 
	halt		; Attente de la fin de
	ld b,2		; la rupture. Puis
Loop1	ds 59		; positionnement précis
	djnz loop1	; avec une boucle à
			; adapter suivant
			; votre CRTC.
	ld bc,&bc04	; Nos écrans feront 1
	out (c),c	; ligne de caractère
	ld bc,&bd00	; de haut (reg4=0)
	out (c),c
	ld bc,&bc09	; Et nos caractères
	out (c),c	; feront 1 ligne pixel
	ld bc,&bd00	; de haut seulement !
	out (c),c	; C'est parti !
 
	halt		; On laisse se faire la
	halt		; rupture un petit brin
	halt		; de temps pour bien la
	halt		; voir...
 
	ld b,20		; Dernière petite attente
Loop2	ds 59		; pour tomber exactement
	djnz loop2	; où on veut...
 
	ld bc,&bc09	; STOP ! Plus de rupture
	out (c),c	; ligne-à-ligne ! On
	ld bc,&bd07	; reprogramme une rupture
	out (c),c	; classique...
	ld bc,&bc04	; Vu où on se trouve sur
	out (c),c	; l'écran, celle-ci doit
	ld bc,&bd03	; faire 4 lignes de haut
	out (c),c	; pour tourner à 50Hz...
 
	ds 64*8		; On attend que notre
			; rupture ait commencé
	ld bc,&bc07	; puis on met le registre
	out (c),c	; 7 à 0 pour envoyer
	ld bc,&bd00	; la VBL et synchroniser
	out (c),c	; le tout !
;
; Test clavier
;
	ld bc,&f40e	; On tripote un
	out (c),c	; petit peu le
	ld bc,&f6c0	; PPI pour se
	out (c),c	; faire un test
	xor a		; clavier de la
	out (c),a	; toutouche
	ld bc,&f792	; espace...
	out (c),c	; Pfiou ! Que
	ld bc,&f645	; c'est long...
	out (c),c	; Courage, la fin
	ld b,&f4	; est proche !
	in a,(c)	; On saisit l'état
	ld bc,&f782	; de la ligne 5
	out (c),c	; et on remet le
	ld bc,&f600	; PPI dans son état
	out (c),c	; normal.
	rla		; On teste ladite
	jp c,prog	; toutouche...
			; Et on boucle !
;
; Quit
;
	ld bc,&bc07	; On remet tous les
	out (c),c	; petits registres
	ld bc,&bd00+30	; du CRTC auxquels
	out (c),c	; on a touché à
	ld bc,&bc04	; leur état normal
	out (c),c	; pour que le CPC
	ld bc,&bd00+38	; n'ait pas le
	out (c),c	; mal de mer au
	ld bc,&bc01	; retour...
	out (c),c	; Que c'est laborieux !
	ld bc,&bd00+40	; Largeur standard...
	out (c),c	; OK !
	ld bc,&bc02	; Position standard
	out (c),c	; de l'écran...
	ld bc,&bd00+46	; OK !
	out (c),c	; Ouf !
 
	di		; On récupère les inters
Inter	ld hl,0		; du début et on revient
	ld (&38),hl	; au BASIC...
	ei		; Attention...
	ret		; Et voilà !

La rupture verticale

— À rédiger en exclusivité pour le Quasar Net !

Documentations externes

1) appelez-ça du fullscreen borderless si vous préférez
2) la fameuse technique découverte par Longshot qui permet de faire de gros scrollings hard à la frame
3) la technique de base qui permet de faire tous les effets à base de lignes comme les plasmas ou les rubber bars
4) exploitée pour la première fois dans la superbe S&KOH d'Overflow
5) même s'il y aura quelques rappels
6) Eh Targhan ! Ça ne te rappelle rien ?
7) est-ce encore possible ?
8) qui calcule l'adresse de la ligne suivante
9) qui calcule l'adresse de la ligne précédente
10) test clavier
11) attente d'une touche
12) comprendre “le compteur associé au registre 4”
 
assem/crtc.txt · Dernière modification: 2013/07/09 11:15 par krusty