Revenir au plan du site
Se synchroniser avec les interruptions
Jusqu'à présent, nous n'avons pas utilisé les interruptions, et pour cause, elles n'étaient tout simplement pas activées dans nos programmes. Je ne prenais pas la peine de les désactiver non plus car la génération d'un snapshot s'occupe aussi de les désactiver par défaut. Ce n'est pas le cas lorsqu'on lance un programme depuis le système. Le système utilise les interruptions pour réaliser des tâches régulières, tout le temps.
En activant la 'mise en lumière' des interruptions avec l'émulateur ACE (
Misc. Options / Highlight Interrupts) on voit apparaitre des traits à intervalles réguliers.
Si le processeur Z80 démarre en mode d'interruption IM 0 (non utilisé sur CPC), le système se charge rapidement de forcer les interruptions dans le mode IM 1 (voir
[description des instructions de gestion des interruptions])
Dans ce mode, le Z80 saut donc à intervalles réguliers...
...à l'adresse #0038 !
Nous allons donc créer un petit programme qui exploite ce saut régulier. La partie principale du programme ne fera rien d'autre qu'être interrompue par ce qu'on appelle le code "sous interruption".
BUILDSNA : BANKSET 0
ORG #38
brk
ei ; activer à nouveau les interruptions
ret ; sortir de l'interruption
ORG #100
RUN #100
ei ; activer les interruptions
infini jr infini ; notre programme boucle à l'infini sur lui même
|
Ce programme n'est pas visuel mais vous verrez dans l'émulateur la fenêtre de débug s'ouvrir rapidement à l'adresse #38, bien que le programme exécute une boucle infinie à l'adresse #100.
Pour rendre ceci plus visuel, je vous propose d'utiliser plutôt les interruptions pour changer des couleurs. On pourrait choisir 1 couleur pour chacune des 6 zones où ont lieu les interruptions.
Arrive alors une première interrogation : Comment savoir dans quelle interruption on se trouve? Et comment attribuer une routine par différente interruption?
Je propose que l'on se serve de l'instruction HALT. Cette instruction attend la prochaine interruption. Si nous utilisons 6 HALT et que nous rebouclons, chaque HALT sera 'attribué' à une interruption.
BUILDSNA : BANKSET 0
ORG #38 : ei : ret ; ne rien faire, renvoyer la main de suite
ORG #100
RUN #100
ei ; activer les interruptions
ld bc,#7F00 : out (c),c ; sélectionner l'encre de fond
boucle_principale
halt : ld a,#54 : out (c),a ; noir
halt : ld a,#50 : out (c),a ; bleu marine
halt : ld a,#55 : out (c),a ; bleu vif
halt : ld a,#57 : out (c),a ; bleu dodger
halt : ld a,#53 : out (c),a ; bleu eau
halt : ld a,#4B : out (c),a ; blanc de Chine
jr boucle_principale
|
Et voilà, nous avons forcer une couleur par zone, sur la même encre! Bienvenue dans le monde des rasters et du multimode (oui, car on peut changer aussi le mode à la volée de la même façon)
Par contre, dans notre programme, nous avions demandé le noir en premier, nous n'avons résolu qu'une interrogation. Reste à savoir comment se synchroniser pour trouver la première de l'écran et autre interrogation, où se situe la première interruption de l'écran? La réponse se trouve dans quelque chose que nous avons vu précédemment : La VBL. Alors techniquement, la VBL n'est pas le début d'un nouvel écran mais c'est le début d'une nouvelle série d'interruptions. L'idée va être d'attendre les interruptions jusqu'à se trouver dans la VBL et décréter être dans la
dernière. Ainsi l'interruption suivante sera la première de l'écran visible, en haut.
BUILDSNA : BANKSET 0
ORG #38 : ei : ret ; ne rien faire, renvoyer la main de suite
ORG #100
RUN #100
ei ; activer les interruptions
ld b,#F5 ; port PPI pour tester la VBL
trouverLeHalt halt : in a,(c) : rra : jr nc,trouverLeHalt
ld bc,#7F00 : out (c),c ; sélectionner l'encre de fond
boucle_principale
halt : ld a,#54 : out (c),a ; noir
halt : ld a,#50 : out (c),a ; bleu marine
halt : ld a,#55 : out (c),a ; bleu vif
halt : ld a,#57 : out (c),a ; bleu dodger
halt : ld a,#53 : out (c),a ; bleu eau
halt : ld a,#4B : out (c),a ; blanc de Chine
jr boucle_principale
|
Voilà nos rasters synchronisés, vous pouvez ajouter une boucle d'attende avant le test de recherche du HALT d'origine, notre programme trouvera toujours ses petits :)
Allez, on va se faire plaisir, on remarque que la troisième interruption en partant du haut coupe à peu près l'écran à la moitié. On pourrait afficher un dessin en mode 0 dans la partie haute et un dessin en mode 1 dans la partie basse. Ou l'inverse, vous faites comme vous voulez.
Vous aurez besoin de
[ce fichier bitmap] pour voir les dessins à l'écran et assembler ce programme ;)
BUILDSNA : BANKSET 0
ORG #38 : ei : ret ; ne rien faire, renvoyer la main de suite
ORG #100
RUN #100
ei ; activer les interruptions
; charger la palette
ld hl,palette : ld bc,#7F00
setPalette out (c),c : inc b : outi : inc c : ld a,c : cp 16 : jr nz,setPalette
ld a,#54 : out (c),c : out (c),a ; border en Noir
ld b,#F5 ; port PPI pour tester la VBL
trouverLeHalt halt : in a,(c) : rra : jr nc,trouverLeHalt
ld bc,#7F00 : out (c),c ; sélectionner l'encre de fond
boucle_principale
halt ; première interruption en haut de l'écran
ld bc,#7F00+%10001100+%00 : out (c),c ; MODE 0
halt
halt ; milieu de l'écran
ld bc,#7F00+%10001100+%10 : out (c),c ; MODE 2
halt : ld a,#57 : out (c),a ; bleu dodger
halt : ld a,#53 : out (c),a ; bleu eau
halt ; hors zone visible, on remet le noir en fond
ld a,#54 : out (c),a
jr boucle_principale
palette defb #54,#5C,#44,#56,#46,#58,#5E,#40,#55,#4C,#57,#4E,#4A,#53,#5B,#4B
org #C000 : incbin 'metroBarjack.bin'
|
Et voici le résultat, une image en mode 0 sur la partie supérieure, on voit que l'image change en mode 2 un peu trop tôt (soit on adapte le dessin, soit on attend un peu avant de changer de mode, c'est au choix pour faire propre).
Dans la partie inférieure de l'image, on affiche en mode 2 (changement au 3ème HALT) et on continue de changer l'encre du fond, qui se passe en milieu de ligne, là encore, si on veut faire propre, on ajouter une temporisation pour le faire en fin de ligne et avoir notre changement 'à la ligne'.
J'espère que ce minuscule programme vous motivera à utiliser le multi-mode dans vos productions ;)