Revenir au plan du site
Pouvoir déclencher une interruption à la ligne sur Amstrad Plus ou d'une GX-4000.
C'est une des fonctionnalités les plus puissantes des modèles Plus, choisir à quelle ligne écran une interruption va se produire. Et les quelques limitations ne devraient pas vous gêner :
- L'interruption ne peut pas commencer à la ligne zéro car le paramètre zéro désactive la fonctionnalité.
- L'interruption ne peut pas dépasser la ligne 255 car le paramètre est sur 8 bits.
- Autre chose?
Oui, le déclenchement de l'interruption se fait selon un calcul de pseudos caractères dans le CPC un peu foireux, ce qui déclenche deux fois l'interruption quand on élargit un peu trop l'écran. Enfin, comme ce test est réalisé en fin de ligne, une interruption ligne 1 se passera à la fin de la ligne 1, soit quelque part, une interruption une ligne trop tard. Selon ce que vous voulez faire, vous pourrez vous retrouver avec deux lignes orphelines en haut de l'écran, comme dans le jeu Fluff ci dessous. Bouuuuuuuuuuh!
Ceci étant dit, si on modifiait le source de l'article précédent pour faire un dégradé dans le ciel? On cherche la couleur #F0E (RVB) dans la palette, c'est le #0FE (VRB) en encre 12 (la 13ème).
L'interruption à la demande se paramètre à
l'adresse #6800 de la page ASIC.
On va d'abord commencer à se synchroniser avec des HALT car c'est le plus simple. Assurez-vous d'avoir déjà téléchargé le
[fichier bitmap] suivant (pour avoir quelque chose à l'écran)
;*** RMR tags ***
MODE_0 equ 0
MODE_1 equ 1
MODE_2 equ 2
MODE_3 equ 3
CLEAR_INT equ %10000
ROM_OFF equ %1100
ROM_BOTH equ 0
ROM_UP equ %100
ROM_LOW equ %1000
INTRESET equ %10000
;*** RMR2 tags ***
ASICOFF equ 0
ROM0000 equ 0
ROM4000 equ %01000
ROM8000 equ %10000
ASICON equ %11000
ROM0 equ 0 : ROM1 equ 1 : ROM2 equ 2 : ROM3 equ 3 : ROM4 equ 4 : ROM5 equ 5 : ROM6 equ 6 : ROM7 equ 7
macro RMR tags
ld a,{tags}+%10000000
ld b,#7F
out (c),a
mend
macro RMR2 tags
ld a,{tags}+%10100000
ld b,#7F
out (c),a
mend
BUILDSNA
SNASET CPC_TYPE,4 ; indiquer un 6128 Plus dans le snapshot
BANKSET 0
ORG #38 : ei : ret ; interruption qui ne fait rien
ORG #100
RUN #100
RMR ROM_OFF|MODE_0 ; surtout pas les ROM!
call UnlockAsic
RMR2 ASICON
; et on recopie la palette dans l'ASIC
ld hl,palette
ld de,#6400
ld bc,32
ldir
ei ; activer les interruptions
; comme il n'est pas possible d'avoir une interruption juste avant la ligne zéro
; on va programmer notre encre du ciel tout en bas de l'écran, elle sera prête à l'avance.
rasterCiel
ld a,199 : ld (#6800),a : ld hl,#244 : HALT : ld (#6400+12*2),hl
ld a,50 : ld (#6800),a : ld hl,#7C7 : HALT : ld (#6400+12*2),hl
ld a,100 : ld (#6800),a : ld hl,#CF7 : HALT : ld (#6400+12*2),hl
jr rasterCiel
palette defw #112,#224,#432,#533,#435,#271,#454,#556,#5D1,#898,#9E5,#BD9,#0FE,#DEB,#EFC,#FFF
;------------------------------------------------------------------------- ^ -----------
UnlockAsic
ld bc,#BCFF
out (c),c
out (c),0
ld hl,%1001000011101010
.loop
out (c),c
ld a,h:rlca:ld h,l:ld l,a
srl c:res 3,c
and #88
or c
ld c,a
cp #4D
jr nz,.loop
ld a,#CD
out (c),a : out (c),a
ret
ORG #C000
incbin 'teepee.bin' ; notre binaire écran
|
Nous avons 3 rasters posés sur l'encre du ciel, c'est bien, mais on va aller plus loin!
L'idée va être d'enchainer plusieurs routines à des intervales plus réguliers pour faire un beau dégradé. On va supprimer les HALT et se mettre au niveau du saut d'interruption (à l'adresse #38).
Ainsi, pendant que les interruptions changent la valeur de l'encre du fond, on pourrait avoir un programme qui continue de faire autre chose. Par contre, si nous réalisons une vraie routine sous
interruption, elle DOIT faire une sauvegarde de tous les registres qu'elle va modifier, pour ne pas interférer avec le programme principal. Ici notre programme principal ne fera rien ce n'est pas
nécessaire, nous le ferons quand même pour rester un peu académiques ;)
Aussi, le code à l'adresse #38 devient un saut vers la routine en cours. On changera l'adresse à chaque interruption suivant le principe ci-dessous.
org #38
jp interruption_ligne_199 : vecteurInt=$-2
...
interruption_ligne_199
push af,hl ; sauvegarder AF et HL
; programmer l'interruption suivante et mettre la couleur
ld a,50 : ld (#6800),a : ld hl,#244 : ld (#6400+12*2),hl
ld hl,interruption_ligne_50 : ld (vecteurInt),hl ; changer l'adresse de saut de la prochaine interruption
pop hl,af
ei
ret
|
Maintenant que nous avons un modèles d'interruption, il est plus simple de créer une macro générique qui va nous servir pour chaque ligne.
macro creation_interruption_raster,ligneINT,INTsuivante,couleur
interruption_ligne_{ligneINT} ; créer le label avec le numéro
push af,hl
; programmer l'interruption suivante et mettre la couleur
ld a,{INTsuivante} : ld (#6800),a
ld hl,interruption_ligne_{INTsuivante} : ld (vecteurINT),hl
ld hl,{couleur} : ld (#6400+12*2),hl
pop hl,af
ei : ret
mend
|
Notre programme principal change un peu en #38 et à l'initialisation des interruptions. Ensuite on va dérouler notre macro en tant que sous-routines.
;*** RMR tags ***
MODE_0 equ 0
MODE_1 equ 1
MODE_2 equ 2
MODE_3 equ 3
CLEAR_INT equ %10000
ROM_OFF equ %1100
ROM_BOTH equ 0
ROM_UP equ %100
ROM_LOW equ %1000
INTRESET equ %10000
;*** RMR2 tags ***
ASICOFF equ 0
ROM0000 equ 0
ROM4000 equ %01000
ROM8000 equ %10000
ASICON equ %11000
ROM0 equ 0 : ROM1 equ 1 : ROM2 equ 2 : ROM3 equ 3 : ROM4 equ 4 : ROM5 equ 5 : ROM6 equ 6 : ROM7 equ 7
macro RMR tags
ld a,{tags}+%10000000
ld b,#7F
out (c),a
mend
macro RMR2 tags
ld a,{tags}+%10100000
ld b,#7F
out (c),a
mend
;----------------------------------------------------------------------
macro creation_interruption_raster,ligneINT,INTsuivante,couleur
interruption_ligne_{ligneINT} ; créer le label avec le numéro
push af,hl
; programmer l'interruption suivante et mettre la couleur
ld a,{INTsuivante} : ld (#6800),a
ld hl,interruption_ligne_{INTsuivante} : ld (vecteurINT),hl
ld hl,{couleur} : ld (#6400+12*2),hl
pop hl,af
ei : ret
mend
;----------------------------------------------------------------------
BUILDSNA
SNASET CPC_TYPE,4 ; indiquer un 6128 Plus dans le snapshot
BANKSET 0
ORG #38 : JP 0 : vecteurINT=$-2
ORG #100
RUN #100
RMR ROM_OFF|MODE_0 ; surtout pas les ROM!
call UnlockAsic
RMR2 ASICON
; et on recopie la palette dans l'ASIC
ld hl,palette
ld de,#6400
ld bc,32
ldir
ld hl,interruption_ligne_199 : ld (vecteurINT),hl : ld a,199 : ld (#6800),a ; initialiser la première INT
ei ; activer les interruptions
rasterCiel jr rasterCiel ; RIEN ^_^
palette defw #112,#224,#432,#533,#435,#271,#454,#556,#5D1,#898,#9E5,#BD9,#0FE,#DEB,#EFC,#FFF
;------------------------------------------------------------------------- ^ -----------
creation_interruption_raster 199, 10,#244
creation_interruption_raster 10, 20,#364
creation_interruption_raster 20, 30,#475
creation_interruption_raster 30, 40,#595
creation_interruption_raster 40, 50,#6B6
creation_interruption_raster 50,199,#7C7
UnlockAsic
ld bc,#BCFF
out (c),c
out (c),0
ld hl,%1001000011101010
.loop
out (c),c
ld a,h:rlca:ld h,l:ld l,a
srl c:res 3,c
and #88
or c
ld c,a
cp #4D
jr nz,.loop
ld a,#CD
out (c),a : out (c),a
ret
ORG #C000
incbin 'teepee.bin' ; notre binaire écran
|
Ça commence à prendre forme, nous avons une interruption toutes les 10 lignes et un joli dégradé. Par contre le changement d'encre se fait en plein milieu de la ligne.
On va ajouter une temporisation d'un peu plus de 20 NOPS pour que le changement se fasse en fin de ligne et ajouter des appels de macro pour compléter le dégradé.
En fait j'en profite aussi pour refaire le début du dégradé à partir d'un bleu nuit. Vous noterez que grâce à cette macro, le dégradé est très simple à modifier!
;*** RMR tags ***
MODE_0 equ 0
MODE_1 equ 1
MODE_2 equ 2
MODE_3 equ 3
CLEAR_INT equ %10000
ROM_OFF equ %1100
ROM_BOTH equ 0
ROM_UP equ %100
ROM_LOW equ %1000
INTRESET equ %10000
;*** RMR2 tags ***
ASICOFF equ 0
ROM0000 equ 0
ROM4000 equ %01000
ROM8000 equ %10000
ASICON equ %11000
ROM0 equ 0 : ROM1 equ 1 : ROM2 equ 2 : ROM3 equ 3 : ROM4 equ 4 : ROM5 equ 5 : ROM6 equ 6 : ROM7 equ 7
macro RMR tags
ld a,{tags}+%10000000
ld b,#7F
out (c),a
mend
macro RMR2 tags
ld a,{tags}+%10100000
ld b,#7F
out (c),a
mend
;----------------------------------------------------------------------
macro creation_interruption_raster,ligneINT,INTsuivante,couleur
interruption_ligne_{ligneINT} ; créer le label avec le numéro
push af,hl
; programmer l'interruption suivante et mettre la couleur
ld a,{INTsuivante} : ld (#6800),a
ld hl,interruption_ligne_{INTsuivante} : ld (vecteurINT),hl
ld a,6 : .tempo dec a : jr nz,.tempo ; attendre un peu pour changer la couleur
ld hl,{couleur} : ld (#6400+12*2),hl
pop hl,af
ei : ret
mend
;----------------------------------------------------------------------
BUILDSNA
SNASET CPC_TYPE,4 ; indiquer un 6128 Plus dans le snapshot
BANKSET 0
ORG #38 : JP 0 : vecteurINT=$-2
ORG #100
RUN #100
RMR ROM_OFF|MODE_0 ; surtout pas les ROM!
call UnlockAsic
RMR2 ASICON
; et on recopie la palette dans l'ASIC
ld hl,palette
ld de,#6400
ld bc,32
ldir
ld hl,interruption_ligne_199 : ld (vecteurINT),hl : ld a,199 : ld (#6800),a ; initialiser la première INT
ei ; activer les interruptions
rasterCiel jr rasterCiel ; RIEN ^_^
palette defw #112,#224,#432,#533,#435,#271,#454,#556,#5D1,#898,#9E5,#BD9,#0FE,#DEB,#EFC,#FFF
;------------------------------------------------------------------------- ^ -----------
creation_interruption_raster 199, 10,#014
creation_interruption_raster 10, 20,#124
creation_interruption_raster 20, 30,#134
creation_interruption_raster 30, 40,#234
creation_interruption_raster 40, 50,#244
creation_interruption_raster 50, 60,#364
creation_interruption_raster 60, 70,#475
creation_interruption_raster 70, 80,#595
creation_interruption_raster 80, 90,#6B6
creation_interruption_raster 90,100,#7C7
creation_interruption_raster 100,110,#8D7
creation_interruption_raster 110,120,#9D7
creation_interruption_raster 120,130,#AE7
creation_interruption_raster 130,140,#BE7
creation_interruption_raster 140,199,#CF7
UnlockAsic
ld bc,#BCFF
out (c),c
out (c),0
ld hl,%1001000011101010
.loop
out (c),c
ld a,h:rlca:ld h,l:ld l,a
srl c:res 3,c
and #88
or c
ld c,a
cp #4D
jr nz,.loop
ld a,#CD
out (c),a : out (c),a
ret
ORG #C000
incbin 'teepee.bin' ; notre binaire écran
|
Et voilà notre écran final (avec le 'Int highlight' pour bien voir ce qui se passe)