[ST MAG 72] Les interruptions
GFA :: Programmation :: Graphismes
Page 1 sur 1
[ST MAG 72] Les interruptions
Vous croyez peut_être que l'Assembleur est le seul language capable de permettre la création de démos
comparables à celles des plus grands groupes ? Eh bien non ! Le but de cette série est de vous exposer
les techniques de programmation nécessaires pour arriver au même résultat en GfA Basic !
Après plusieurs mois de vacances, votre rubrique préférée est enfin de retour, bien que mon collègue
ait laché l'affaire. Pour (re)commencer, nous allons voir comment exécuter des routines sous interruption
en GfA, après quoi je répondrai aux principales questions qui ont fait craquer ma bal sur le 36 15 STMAG.
Je pense qu'il est inutile de rappeller ce qu'est une interrution, mais ça ne mange pas de pain de
le faire. Une interruption est une routine qui s'exécute à intervalles réguliers, et ce quelque soit ce que
le 68000 était en train de faire. La quasi-totalité des démos assembleur utilisent l'interruption VBL
(vecteur $70) qui n'est qu'un équivalent du VSYNC du GfA. Néanmoins, la différence entre notre VSYNC et une
interruption est que cette dernière peut très bien s'exécuter même si la tache principale est longue.
C'est ainsi qu'on peut réaliser des animations pendant un chargement.Nous allons tenter d'en faire autant en GfA.
Ah chouette alors
La Bee Forol Demo (excellente démo GfA que je vous conseille vivement de commander à la librairie demo)
est à ma connaissance la seule démo GfA avec un loader sous interruption. Ceci suggère que réaliser une
telle chose est loin d'être facile mais néanmoins possible.
Le GfA prétend être capable de gérer de telles interruptions grâce aux instructions EVERY et AFTER.
Malheureusement, en pratique ces instructions sont totalement inutiles. En effet, elles n'etablissent pas
de véritables interruptions, mais se contentent de tester un timer après chaque instruction exécutée et
faire un GOSUB de temps en temps. Les conséquences sont lourdes: un ralentissement intolérable, une
stabilité digne d'un grand père cocaïnomane et l'impossibilité d'exécuter autre chose que du GfA en même
temps. Il va donc falloir se débrouiller tout seuls une fois de plus ...
Alors...comment faire ? Réflechissons un peu: beaucoup de démos utilisent une routine sous
interruption VBL qui répond parfaitement à nos exigences. Je veux bien entendu parler des musiques.
Comment place-t-on une musique soundchip sous interruption en GfA ? Après l'avoir initialisée avec un CALL
ou RCALL, nous mettons l'adresse de la routine principale en $4D2 (généralement). En effet à partir de $4CE
se trouvent 8 mots longs qui forment la "VBL_queue". A chaque VBL, le système va regarder s'il trouve autre
chose que des zéro. Le cas échéant, il va appeller successivement les sous-programmes commençants à ces adresses.
Oui mais... On appelle une routine Assembleur et non du code GfA. Et alors ? Une fois compilé le GfA
donne bien naissance à du langage machine pur, non ? Pour retrouver l'adresse de début il suffit d'insérer
dans le code source des instructions générant des codes machine bien particuliers et de les rechercher.
Nous utiliseront pour ce faire le tilde (~) suivit d'une constante comprise entre 0 et 127. En effet, ceci
se traduit dans le code compilé par MOVEQ #constante,D0 soit en hexadécimal:$70+constante, ce qui est facile
à localiser.
Mais euh...comment marque-t-on la fin de la routine ? En assembleur, une routine placée en vblqueue
doit se terminer par un RTS. Nous devons donc trouver le moyen d'insérer cette instruction au milieu de notre
code GfA. Rien de plus simple. En effet, les procédures sont traduites comme de vrais sous programmes, donc
appelés par un JSR (équivalent du GOSUB en GfA) et limités par un RTS (le RETURNdu GfA).
Par conséquent il suffit de mettre la routine que l'on désire mettre sous interruption dans une
procédure et de mettre l'adresse du début de la procédure dans un vecteur libre de la vblqueue.
Ca se complique
Nous avons trouvé la technique, mais nous ne sommmes pas au bout de nos peines. Pour comprendre le
problème qu'il nous reste à surmonter il va falloir une fois de plus se réferer au code machine que le
compilateur génère.
Il faut en effet souligner que le fait que les pointeurs des variables sont rangés dans une grosse
table. L'adresse de celle-ci est stockée en permanence dans le registre A6 (les registres du 68000 sont
comparables aux variables de GfA). Or notre routine est susceptible de sedéclencher à n'importe quel moment
c'est à dire même si la tache principale modifie le contenu des registres, et à plus forte raison, A6.
Si la routine effectue des opérations sur les variables, une troupe de méchantes bombinettes apparaitra
sauvagement. Par conséquent la procédure ne devra jamais faire référence aux variables. Argh ! Comment survivre
sans variable ? Le seul moyen consiste à utiliser des adresses absolues en mémoire. Ainsi on peut remplacer
a%=78 par LONG{&H200}=78 et b%=ROR(a%,1) par LONG{&H204}=ROR(LONG{&H200},1).
Programmer de cette façon s'avère très pénible à la longue. De plus c'est une méthode très sale d'écrire
n'importe où dans la mémoire, mais c'est la seule solution à notre disposition. Je vous conseille la zone
comprise entre $200 et $3FF ainsi que celle comprise entre $40C et $41F. Rien ne vous empêche d'utiliser aussi
des vecteurs rarement utilisés, à part dans les protections, comme le vecteur trace ($24), le ILLEGAL ($10)...
Youpi, y a un listing !
Le programme que nous vous proposons n'est autre que le source du loader de la BEE FOROL DEMO, privé
des routines de chargement et d'affichage du texte. Des changements de palette sont mis sous interruption afin
de simuler l'affichage des chiffres (voir photo).
Chaque chiffre est l'objet d'une procédure spécifique, et l'adresse que nous mettons en vblqueue varie
afin de faire cycler les appels et par la suite les chiffres.
La boucle principale se résume à une boucle sans fin DO...LOOP que vous pouvez remplacer par n'importe
quoi y compris des opérations GEM ou des opérations disque.
Dernière minute: je viens de trouver le moyen d'utiliser librement les variables au sein des procédures
sous interruption. Il faut en fait restaurer puis sauvegarder (non il n'y a pas d'inversion) le contenu de tous
les registres au début et à la fin de la procédure. C'est ce qu'effectue l'instruction BMOVE avant et après les
transferts. Il faut donc inhiber l'exécution de la fin ou du début de la routine BMOVE en déclenchant une
interruption au bon moment, ce qui nous oblige à exécuter le BMOVE à des instants bien précis, en se
synchronisant sur le compteur vidéo, et en intégrant comme s'il s'agissait d'un fulscreen.
C'est déjà fini ?
Voilà, vous êtes maintenant en mesure de réaliser ce qui semblait jusqu'à présent être un privilège
réservé aux programmeurs en assembleur. Le mois prochain j'essayerai de vous expliquer la technique du BMOVE
interrompu, ainsi que le moyen de réaliser un veritable synscroll multidirectionnel sur STF. Et dans deux mois
vous aurez carrément droit à une routine de fulltracker en GfA.
En attendant je reste ouvert à toutes vos questions sur le recipiendaire 36 15 STMAG en bal SECTOR ONE
ou, pour les parisiens, sur mon graveleux rtc au 48701029(RTC-ONE) en bal JEDI.
______________________
Jedi / Sector One
- Code:
.
.Cyclage de couleur sous interruption en GfA
.Code par Jedi from Sector One (THK)
.Ce programme doit etre compile
.Vous pouvez essayer de creer le fichier counter.sct
.en mettant cote a cote toutes les couleurs puis en
.sauvegardant au format DOODLE (memoire ecran pure)
.mais le mieux serait de le telecharger sur le
.3615 STMAG ou sur RTC-ONE au 48 70 10 29
.A bientot dans notre Megademo
.
HIDEM
VSYNC
FOR a%=0 TO 15
SETCOLOR a%,0
NEXT a%
RESERVE 32768 ! Si on charge quelque chose faut mieux
. reduire la taille memoire sous it
BLOAD "counter.sct",XBIOS(2) ! Ce fichier est dispo
. en telechargement sur les meilleurs serveurs
a%=XBIOS(2)
start%=LONG{BASEPAGE+8} ! Adr du debut du prg
FOR t%=start% TO &H3FFFFF STEP 2 !4Mo maximum sur ST
IF CARD{t%}=&H7000 ! recherche du MOVEQ #0,D0
IF CARD{ADD(t%,2)}=&H7000
vga%=t%
t%=&H400000 ! si c'est bon on sort du FOR
ENDIF ! RTC-ONE est ouvert 24h/24
ENDIF ! au 48 70 10 29
NEXT t% ! tout pour le ST ...
LONG{&HFED00+&H1000}=vga% !un p'tit coin libre ?
FOR z%=1 TO 9 !Recherche des adresses des procedures
start%=vga%
FOR t%=start% TO &H3FFFFF STEP 2
IF CARD{t%}=ADD(&H7000,z%)
IF CARD{ADD(t%,2)}=ADD(&H7000,z%)
vga%=t%
t%=&H400000 ! adresse suivante
ENDIF
ENDIF ! Un p'tit salut a notre
NEXT t% ! nouveau codeur:MAGNUM
LONG{ADD(&HFED00+&H1000,SHL(z%,2))}=vga%
NEXT z%
super%=GEMDOS(&H20,L:0)
CARD{&HFED00+&H1028}=0
CARD{&HFED00+&H102A}=1
igrec%=0
BYTE{&HFFFFFC02}=&H12 ! bloque la souris
.
.Etat initial des couleurs
.
DPOKE &HFFFF825E,4
DPOKE &HFFFF8250,&H427
DPOKE &HFFFF8252,&H427
DPOKE &HFFFF8254,&H427
DPOKE &HFFFF8256,0
DPOKE &HFFFF8258,&H427
DPOKE &HFFFF825A,&H427
DPOKE &HFFFF825C,&H427
LPOKE &H4D2,LONG{&HFED00+&H1000} ! premiere procedure
~GEMDOS(&H20,L:super%)
.
.programme principal
.
DO
LOOP
.
PROCEDURE 0
~0
~0
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=0
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1004}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 1
~1
~1
CARD{&HFFFF8242}=0
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=0
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=0
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1008}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 2
~2
~2
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=0
CARD{&HFFFF824E}=&H427
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H100C}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 3
~3
~3
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1010}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 4
~4
~4
CARD{&HFFFF8242}=&H0
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1014}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 5
~5
~5
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H0
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1018}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 6
~6
~6
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H0
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H101C}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 7
~7
~7
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H0
CARD{&HFFFF8248}=&H0
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1020}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 8
~8
~8
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
LONG{&H4D2}=LONG{&HFED00+&H1014}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
PROCEDURE 9
~9
~9
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
IF CARD{&HFED00+&H1028}=4
CARD{&HFED00+&H1028}=0
IF CARD{&HFED00+&H102A}=0
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=0
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
ELSE IF CARD{&HFED00+&H102A}=1
CARD{&HFFFF8242}=0
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=0
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=0
ELSE IF CARD{&HFED00+&H102A}=2
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=0
CARD{&HFFFF824E}=&H427
ELSE IF CARD{&HFED00+&H102A}=3
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=0
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
ELSE IF CARD{&HFED00+&H102A}=4
CARD{&HFFFF8242}=&H0
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
ELSE IF CARD{&HFED00+&H102A}=5
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H0
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
ELSE IF CARD{&HFED00+&H102A}=6
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H0
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
ELSE IF CARD{&HFED00+&H102A}=7
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H0
CARD{&HFFFF8248}=&H0
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
ELSE IF CARD{&HFED00+&H102A}=8
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=&H427
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H0
ELSE IF CARD{&HFED00+&H102A}=9
CARD{&HFFFF8242}=&H427
CARD{&HFFFF8244}=&H427
CARD{&HFFFF8246}=&H427
CARD{&HFFFF8248}=&H427
CARD{&HFFFF824A}=0
CARD{&HFFFF824C}=&H427
CARD{&HFFFF824E}=&H427
ENDIF
LONG{&H4D2}=LONG{&HFED00+&H1000}
ELSE
CARD{&HFED00+&H1028}=SUCC(CARD{&HFED00+&H1028})
ENDIF
RETURN
.
.
tomchi- Messages : 52
Date d'inscription : 15/09/2018
Age : 49
GFA :: Programmation :: Graphismes
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum