Programmez vos ruptures facilement

Avant de commencer cet article, je tiens à remercier plus particulièrement CHANY/NPS, celui grâce à qui j’ai appris à maîtriser les Ruptures, simples au départ, puis ligne à ligne par la suite. La méthode que je vais vous expliquer provient de Duncan des 5KB, qui l’a, au départ, enseignée à Chany qui me l’a, par la suite, transmise. J’ai à mon tour, transmis cette technique à CMP, et je m’en vais vous l’expliquer aujourd’hui.

Pour être franc, ça fait déjà un moment que ça me trotte dans la tête, mais aujourd’hui grâce à une demande expresse de Plissken (le survivant), voyons cela de plus près.

La Rupture

Tout d’abord, qu’est ce qu’une rupture ? En voilà une bonne question mon Colonel ? La rupture est une technique permettant de changer l’adresse vidéo en cours de balayage et cela, plusieurs fois par ligne. Elle fut utilisée jadis, dans quelques jeux comme « Mission Genocide », « Axys » et d’autres, mais aussi par les grands noms du CPC comme Longshot par exemple. C’est en effet celui qui l’a démocratisé et pour cela je l’en remercie.

Maîtriser cette technique nécessite de bien connaître l’endroit où se déclenchent les interruptions. Pour cela, nous aurons besoin d’un tableau que j’ai très souvent utilisé et qui me sert encore. Comme je suis bon prince, je vous livre le fameux « schéma » qui guidera vos pas, jusqu’à l’élaboration de l’écran final.

Tableau des Ruptures tel que Chany me l’a transmis en 1993

Ce tableau schématise votre écran CPC et ses 39 lignes de texte, affichées verticalement. Un caractère texte s’inscrit dans un bloc de 8 lignes vidéos, ce qui signifie que quand on passe du bloc 1 au bloc 2, 8 lignes auront été affichées (dans une configuration normale, bien sur!). Vérifions quand même au cas où :

39 blocs de 8 lignes = 39*8 = 312 lignes totales affichées verticalement, c’est bien ça ! Hourra !

Ensuite, il ne vous aura pas échappé qu’il y a 5 lignes représentées en rouge sur le schéma . Celles ci symbolisent l’endroit exact où sont envoyées les interruptions, soit toutes les 52 lignes sur Cpc. Il y a 6 interruptions sur Cpc (6×52=312) alors pourquoi n’y a t’il pas 6 lignes rouges symbolisés ? Simplement car la dernière interruption arrive à la ligne 39, à la fin de la zone « non visible ».

Vérifions quand même si tout est bon. La première interruption se déclenche au 6ème bloc et demi. Comme 6.5*8 = 52, la 1ère interruption arrive bien à la 52ème ligne, la deuxième 52 lignes plus bas et ainsi de suite !

Pour finir, on aperçoit, pour les plus attentifs, deux zones situées, une tout en haut de l’écran et l’autre tout en bas de l’écran où est inscrit ‘NON VISIBLE ». Ces zones se situent simplement dans la partie non vue de l’écran, en gros sous le plastique du moniteur.

C’est simple pour le moment, non ?

Elaboration de ma première Rupture.

Pour la première rupture, nous allons essayer de créer 3 zones distinctes, appelées rupture 1rupture 2, et rupture 3. Souvenez vous d’une chose, le total des lignes affichées pour être à 50 Hz doit être de 312 lignes soit 39 caractères (ou blocs) de 8 lignes ! On va dire que :

  • Rupture 1 = 8 blocs de 8 lignes
  • Rupture 2 = 20 blocs de 8 lignes
  • Rupture 3 = ?

Calcul simple : Sachant que le total des blocs doit être égal à 39 nous avons donc :

8+20=28 blocs.

il reste donc 39-28=11 blocs à afficher pour être à 50hz.

Récapitulons :

  • Rupture 1 = 8 blocs
  • Rupture 2 = 20 blocs
  • Rupture 3 = 11 blocs

La trame est maintenant tracée. Mais comment ça marche pour la suite ?

Les registres du CRTC 6845

Avant de vous lancer à corps perdu dans l’élaboration d’une rupture, vous devez savoir au préalable que ceci ne sera possible qu’après modification de certains registres du CRTC. Oui, mais lesquels, et à quoi servent-ils ?

Dans l’exemple présent, nous aurons besoin de modifier les Registre 7 et 4, puis éventuellement les Registres 12 et 13. C’est tout ! Commençons par examiner de plus près ces fameux registres:

  • Le Registre 7 détermine l’envoi du signal VBL
  • Le Registre 4 détermine le nombre de caractères -1 à afficher en vertical
  • Les Registres 12 et 13 déterminent pour leur part les poids forts et faibles de l’adresse écran, l’OffseT quoi ! (Non, Plissken, pas celui de Futurs’)

Passons maintenant à l’élaboration de cette rupture tant attendue…. Un peu de code vous ferait-il du bien ? On commence ?

;   Ma première Rupture
; ---Ast/iMPACT Juillet 2017
;
        org #1000
;
        di ; on commence par couper les interruptions
        ld hl,#c9fb ; on empêche le système de nous embêter
        ld (#38),hl
        im 1 ; Nous sommes en Mode d'interruption 1 - Est-ce bien nécessaire de le préciser ?
;
main 
        ld b,#f5 ; Boucle attente VbL
vsync   in a,(c) ; dois-je expliquer tout le test ?
        rra
        jr nc,vsync
;
        ld b,4*8 ; attente de 32 lignes (4x8)
b1      fill 60,0 ; 60 Nops
        djnz b1
;
        ld bc,#bc07 ; Kill VBL
        ld a,#7f
        out (c),c
        inc b
        out (c),a
;
        ld bc,#bc04 ; Rupture 1
        ld a,8-1
        out (c),c
        inc b
        out (c),a
;
        ei
        halt
        ld b,5*8 +4 ; attente 44 lignes
b2      fill 60,0 ; 60 Nops
        djnz b2

        ld bc,#bc04 ; Rupture 2
        ld a,20-1
        inc b
        out (c),a
;
        ld b,20*8 ; attente 160 lignes
b3      fill 60,0 ; 60 Nops
        djnz b3
;
        ld bc,#bc04 ; Rupture 3
        ld a,11-1       
        out (c),c
        inc b
        out (c),a
;
        ld bc,#bc07 ; On repositionne la VBL
        ld a,11-4 
        out (c),c
        inc b
        out (c),a
;
        jp main 

Voici ce que vous devriez avoir sur votre CPC:

Maintenant, voyons pas à pas, les détails de cette routine juste après la VBL :

       ld b,4*8 ; attente 4 blocs de 8 lignes
b1     fill 60,0
       djnz b1

Pourquoi ? Cette partie permet de passer du bloc 1 au bloc 4 (Partie NON VISIBLE). TOUTES nos ruptures commenceront à partir de la ligne 4, soit à partir du moment où commence, l’écran visible. 

       ld bc,#bc07 ; Kill VBL
       ld a,#7f
       out (c),c
       inc b
       out (c),a

       ld bc,#bc04 ; Rupture 1
       ld a,8-1
       out (c),c
       inc b
       out (c),a

Kill Vbl : Pour éviter d’avoir la VBL visible à chaque changement d’écran, on provoque « volontairement » un overflow du Registre 7. Qu’est ce que cela signifie ? Nous lui mettons simplement une valeur qu’il ne pourra jamais atteindre (#7f). Donc pas de VBL durant le nouvel écran. Veuillez noter qu’il suffit simplement que la valeur du registre 7 soit supérieure à (R4+1). Dans le cas de notre exemple, on aurait pu mettre le registre 7 à 21 pour être certain que cette valeur ne soit jamais atteinte.

Nous lui mettons simplement une valeur qu’il ne pourra jamais atteindre (#7f). Donc pas de VBL durant le nouvel écran. Veuillez noter qu’il suffit simplement que la valeur du registre 7 soit supérieure à (R4+1). Dans le cas de notre exemple, on aurait pu mettre le registre 7 à 21 pour être certain que cette valeur ne soit jamais atteinte.

Rupture1 : Nous voulons afficher 8 blocs (de 8 lignes chacun). Le Registre 4 allant de 0 à X, nous enlevons 1 à la valeur que nous lui donnons, vu qu’il commence une valeur plus tôt (0).

       ei
       halt
       ld b,5*8 +4  ; attente 44 lignes
b2     fill 60,0    ; 60 Nops
       djnz b2

La Rupture a démarré à partir de la ligne 4 et continue jusqu’à la ligne 12 (4+8).
En cours de chemin, nous avons un Halt entre la ligne 6 et 7 puis il nous reste 5 blocs et demi pour aller au bloc 12 soit 5.5*8=44 lignes. On attends donc que 44 lignes se soient affichées avant de passer à la rupture 2.

       ld bc,#bc04 ; Rupture 2
       ld a,20-1
       inc b
       out (c),a

Une fois les 44 lignes affichées, on doit à nouveau modifier le registre 4. Je vous rappelle que nous sommes au bloc n°12 sur le schéma!
On voulait afficher 20 blocs pour la rupture 2, c’est chose faite ! Une fois affichées, nous serons au bloc 32.

      ld b,20*8 ; attente 160 lignes
b3    fill 60,0 ; 60 Nops
      djnz b3

On attend le temps nécessaire avant de passer au dernier écran, soit uen attente de 160 lignes (20*8). Ensuite, nous arrivons à la ligne 32 du schéma.

       ld bc,#bc04 ; Rupture 3
       ld a,11-1       
       out (c),c
       inc b
       out (c),a
;
       ld bc,#bc07 ; On repositionne la VBL
       ld a,11-4 
       out (c),c
       inc b
       out (c),a

Au dernier écran, on repositionne la VBL, parce qu’il faut au moins 1 VBL par trame vidéo.
Le calcul est fort simple. Nous nous trouvons au bloc 32. Pour aller au bloc 39, il faut 7 lignes, donc le registre 7 sera égal à 7.

Pour la rupture 3, nous avons vu que pour parcourir toute la trame, il faut aller jusqu’à la ligne 39 soit il reste 7 lignes + les 4 premières NON VISIBLES qu’on va ajouter à la fin.

Calcul : 7+4=11. Voilà donc, d’où vient la valeur 11 dans le registre 4. En mettant 11 dans le registre 4, nous nous retrouvons à la 4ème ligne et la boucle est bouclée.

Petit truc : vous aurez surement remarqué que je mets volontairement la valeur 11-4 pour le registre 7 ? Le -4, c’est juste un moyen mnémotechnique pour vous de calculer rapidement sa valeur. On prends la valeur du dernier registre 4 (11) et on soustrait les 4 lignes de la partie NON VISIBLE du haut.

Des questions sur les Ruptures ? C’est le moment avant d’attaquer les ruptures lignes à lignes.

La Rupture ligne à ligne.

La rupture ligne à ligne, qu’est ce que c’est ? Qu’est ce que cela permet ?
Au lieu de changer l’adresse écran (l’offset) tous les blocs de 8 lignes, nous avons la possibilité de la changer toutes les lignes, ce qui permet des effets connus et reconnus sur CPC, comme les plasmas, les rubbers, les rasters verticaux… etc… Le principe va être de réduire la taille des blocs, de façon a ce qu’ils fassent 1 ligne. Ceci est possible grâce au registre 9 du CRTC. Voyons quel est son rôle exact ?

Le registre 9 du CRTC donne le nombre de lignes de pixels affichées par bloc, la hauteur des blocs en quelque sorte. Ce registre varie de 0 à 31 sur Cpc. Sa valeur par défaut est de 7 soit 8 lignes (0 à 7, faites le compte)

Concernant, le nombre de lignes affichées par « bloc », quelques explications s’imposent. Chaque ligne de caractère (1 à 39 sur le schéma) est composée de Blocs (8) qui composent le nombre de lignes affichées, soit pour aller de la ligne 1 à la ligne 4 sur CPC, on affiche 4 lignes (registre 4-1) de 8 pixels (registre 9 -1). On ne peut pas faire plus clair. 

La première rupture ligne à ligne fut codée par Longshot (encore lui) dans la Amazing Demo. Regardez simplement la Supra Demo part !

Supra Demo part / Amazing Demo, par Longshot. Le scrolling avec le reflet, en bas de l’écran utilise la rupture ligne à ligne

Comment cela fonctionne si l’on veut modifier l’offset à chaque ligne ? Il suffit de mettre simplement les registres 9 et 4 à 0 !
Attention cependant, cette technique ne fonctionne pas du tout sur Crtc type 2 !!! En effet, le CRTC type 2, ne supporte pas d’avoir ces 2 registres à zéro, et vous aurez un bel écran noir en guise de récompense.
Une solution a néanmoins été trouvée. Encore suffisait-il d’y penser ; mettre R4 à 0 (compteur de ligne) et R9>0 (hauteur de lignes).

Il suffit pour s’en convaincre de regarder les démos « Tire au flan/Overlanders », « Yap!/Logon System »… Pour ces 2 démos, le registre 4 est à 0 et le registre 9 à 1. On pourrait appeler cela de la rupture 2 lignes à 2 lignes.

Tire au Flan de Shap, Madram et Beb / Overlanders

Nous allons reprendre la rupture précédente et se dire que nous voulons une rupture ligne à ligne sur la rupture 2!
Pour ce faire, rien de plus simple, il suffira de mettre les registres R4 et R9 à 0. Il faudra surtout ne pas oublier de remettre le R9 à sa bonne valeur, une fois la zone de ligne à ligne affichée, soit après avoir affiché les 160 lignes.

;
; Ma première Rupture ligne a ligne
; ---Ast/iMPACT Juillet 2017
;
        org #1000
;
        di ; on commence par couper les interruptions
        ld hl,#c9fb ; on empêche le système de nous embêter
        ld (#38),hl
        im 1 ; Nous sommes en Mode d'interruption 1 - Est-ce bien nécessaire de le préciser ?
;
main    ld b,#f5 ; Boucle attente VbL
vsync   in a,(c) ; dois-je expliquer tout le test ?
        rra
        jr nc,vsync
;
        ld b,4*8 ; attente de 32 lignes (4x8)
b1      fill 60,0 ; 60 Nops
        djnz b1
;
        ld bc,#bc07 ; Kill VBL
        ld a,#7f
        out (c),c
        inc b
        out (c),a
;
        ld bc,#bc04 ; Rupture 1
        ld a,8-1
        out (c),c
        inc b
        out (c),a
;
        ei
        halt
        ld b,5*8 +4 ; attente 44 lignes
b2      fill 60,0 ; 60 Nops
        djnz b2
;
; Début Rupture ligne a ligne -> r4=0 et r9=0
;
        ld bc,#bc04 ; Rupture 2
        ld a,0; ancienne valeur 20-1
        inc b
        out (c),a
;   
        ld bc,#bc09 ; Hauteur des lignes rupture 2       
        ld a,7-7
        out (c),c
        inc b
        out (c),a
;
        ld b,20*8 ; attente 160 lignes
b3      fill 60,0 ; 60 Nops
        djnz b3
;
; On revient à la normale -> r9=7
;
        ld bc,#bc04 ; Rupture 3
        ld a,11-1       
        out (c),c
        inc b
        out (c),a
;
        ld bc,#bc09 ; Hauteur des lignes Rupture 3 et 1       
        ld a,7      ; on remet la hauteur des lignes à 7 (soit 8 lignes affichées en hauteur)
        out (c),c
        inc b
        out (c),a
;
        ld bc,#bc07 ; On repositionne la VBL
        ld a,11-4 
        out (c),c
        inc b
        out (c),a
;
        jp main

Mais qu’est qui a changé au juste dans le code ? Découvrons le ensemble.

; Début Rupture ligne a ligne -> r4=0 et r9=0
;
       ld bc,#bc04 ; Rupture 2
       ld a,0; ancienne valeur 20-1
       inc b
       out (c),a
;   
       ld bc,#bc09 ; Hauteur des lignes rupture 2       
       ld a,7-7
       out (c),c
       inc b
       out (c),a

On met les registres 4 et 9 à 0 avant de début de la Rupture ligne à ligne.

;
; On revient à la normale -> r9=7
;
       ld bc,#bc04 ; Rupture 3
       ld a,11-1       
       out (c),c
       inc b
       out (c),a
;
       ld bc,#bc09 ; Hauteur des lignes Rupture 3 et 1       
       ld a,7      ; on remets la hauteur des lignes à 7 (soit 8 lignes affichées en hauteur)
       out (c),c
       inc b
       out (c),a

On remet le registre 9 à sa valeur d’origine, soit 7.

 Voilà le résultat :

Ah !!! Mince que se passe t’il ? Juste après le ‘8, nous avons un overflow du registre 9. Comment cela se manifeste t’il ? Nous avons 4 fois ‘1 affiché juste sous le ‘8.
En effet, il faut changer la valeur du registre 9 au moment où son compteur interne revient à zéro. Si ce n’est pas le cas, le registre 9 ira jusqu’à sa valeur maximum soit 31 (32 lignes).

Petit calcul :  32/8=4 lignes de caractères affichées ! Voilà le pourquoi du comment. Mais alors quelle serait la solution à tout ceci ?

;
; Ma première Rupture ligne a ligne corrigée
; ---Ast/iMPACT Juillet 2017
;
     org #1000
;
     di ; on commence par couper les interruptions
     ld hl,#c9fb ; on empêche le système de nous embêter
     ld (#38),hl
     im 1 ; Nous sommes en Mode d'interruption 1 - Est-ce bien nécessaire de le préciser ?
;
main ld b,#f5 ; Boucle attente VbL
vsync in a,(c) ; dois-je expliquer tout le test ?
        rra
        jr nc,vsync
;
        ld b,4*8 ; attente de 32 lignes (4x8)
b1    fill 60,0 ; 60 Nops
       djnz b1
;
       ld bc,#bc07 ; Kill VBL
       ld a,#7f
       out (c),c
       inc b
       out (c),a
;
       ld bc,#bc04 ; Rupture 1
       ld a,8-1
       out (c),c
       inc b
       out (c),a
;
       ei
       halt
       ld b,5*8 +4-2 ; attente 44 lignes -2 pour éviter l'overflow du registre 9
b2    fill 60,0 ; 60 Nops
       djnz b2
;
; Début Rupture ligne a ligne -> r4=0 et r9=0
;
       ld bc,#bc04 ; Rupture 2
       ld a,0; ancienne valeur 20-1
       inc b
       out (c),a
;   
       ld bc,#bc09 ; Hauteur des lignes rupture 2       
       ld a,7-7
       out (c),c
       inc b
       out (c),a
;
       ld b,20*8 ; attente 160 lignes
b3    fill 60,0 ; 60 Nops
       djnz b3
;
; On revient à la normale -> r9=7
;
       ld bc,#bc04 ; Rupture 3
       ld a,11-1       
       out (c),c
       inc b
       out (c),a
;
       ld bc,#bc09 ; Hauteur des lignes Rupture 3 et 1       
       Ld a,7      ; on remet la hauteur des lignes à 7 (soit 8 lignes affichées en verticale)
       out (c),c
       inc b
       out (c),a
;
       ld bc,#bc07 ; On repositionne la VBL
       ld a,11-4 
       out (c),c
       inc b
       out (c),a
;
       jp main 

Qu’est-ce qui change par rapport à la version précédente  ?

       ei
       halt
       ld b,5*8 +4-2 ; attente 44 lignes -2 pour éviter l'overflow du registre 9
b2    fill 60,0 ; 60 Nops
       djnz b2
;
; Début Rupture ligne a ligne -> r4=0 et r9=0
;

On enlève 2 lignes à la boucle d’attente avant de modifier la valeur des registres 4 et 9 à 0, ceci afin d’éviter ce fameux overflow ! A noter qu’il n’existe pas d’overflow du registre 9 sur CRTC 3 (CPC+).

Le résultat est sans appel! Voici notre belle rupture ligne à ligne. Elle commence cette fois-ci, bien après la ligne 8 et ce, sans aucun Overflow. La prochaine étape? La rupture verticale!

Pour discuter et posez vos questions, rendez vous sur le forum (d’ou est extrait cet article). Quelques liens en relation, toujours sur le forum: