Sponsors

FacebookTwitterGoogle Bookmarks

LE CLIPBOARD.DEVICE Le clipboard.device est une partie les plus mystérieuses de l’Amiga. Ceci est dû à la grande complexité de sa mise en œuvre. Ce device pas comme les autres permet aux programmes de s'échanger des données en faisant du Couper Copier Coller(Cut Copy Paste en anglais). Tout cela serait très simple si le clipboard.device n’imposait pas un format des données qu’on lui envoie. Ce format est le célèbre format IFF. Cela signifie que dans le clipboard.device, vous pourrez trouver aussi bien du texte que des images ou du son, à condition que ceux-ci soient placés sous un format IFF. Ceux qui connaissent bien le format IFF savent qu’il est possible de placer plusieurs types de données les uns à la suite des autres dans le clipboard, rendant la lecture très délicate à effectuer. C'est pourquoi notre exemple de démonstration ne s’occupe que du minimum, c’est-à-dire lire et écrire du texte dans le Clipboard. Si une image est présente dans le clipboard, je ne garantis absolument rien ! Quand on sait programmer un des device de l’Amiga, les autres ne posent plus beaucoup de problèmes. Le clipboard.device est loin d’être aussi compliqué que l’audio.device mais recèle tout de même quelques difficultés. La première difficulté consiste en la gestion d’un offset. On peut en fait, considérer le clipboard comme une bande magnétique.

Click image to download PDF

AMIGA NEWS TECH numero 12 (05-1990)

Document sans nom TRANSACTOR
LE 3D C (suite)
P. Amiable
Le blitter (3e partie) aies scroiiings»
Image intuition: aies gadgets de
Obriot
Initiation: la fonc
Application: le Clipboard.
D. Lorre
Initiation : le répmtm
mité k vr
: ht fia
DEVICE
wfim ous avons fêlé au champagne 5; le bouclage de ce vingt‘troisième j numéro de Commodore Revue 1 (bips !). Il a en effet ses deux ans. J I Nous avons trinqué une seconde fois en l'honneur de la PAO qui fait de plus en plus son entrée j 4 dans le magazine (AXT, jeux, PA, ?» news...). En troisième toast fut
porté au nouvel Amiga 3000, un quatrième à l'AAT, gui lui, célébrait son premier manniversaire... Enfin, l'AAT devrait I bientôt passer de 16 à 32 pages (et I donc la revue de 92 à 10S pages), pages dans lesquelles nous I glisserons des rubriques pratiques vidéo, graphisme, musique, 31), '¦*M$ sManimathm... Patiente: un peu, nous sommes sûrs que la prochaine formule vous plaira.
BUTTER 3e PARTIE
LES SCROLLINGS
Commençons par récapituler brièvement ce que nous savons déjà faire avec notre fameux blitter.
- nous savons transférer des données, ce qui nous a permis de placer une image dans un bitplane.
¦ nous savons transférer des données selon certaines conditions grâce à l'utilisation des Minterms pour, par exemple, éviter des recouvrements d'images.
- nous savons amputer une image à ses extrémités. Nous verrons plus loin que ceci est très utile.
- nous savons modifier une image en même temps que nous la copions grâce aux masques.
Mais les plus curieux d'entre-vous auront peut-être essayé en modifiant les listings que je vous ai déjà donnés de placer l’image à n'importe quelle position sur l’écran. Quelque chose me dit que vous n’y êtes pas arrivés !
LE PROBLEME
En effet, s’il est très simple de positionner une image sur l’écran dans le sens de la hauteur, il suffit de charger le registre BLTDPTH avec les valeurs appropriées pour pointer sur la ligne de son choix, il ne nous est pour l’instant pas possible de choisir la position horizontale de l’Image au point près. Tout simplement parce que le blitter travaille avec des mots et que BLTDPTH pointera dans le bitplane cible sur l’adresse d’un mot. Un mot contenant 16 bits allumant chacun un point, la position horizontale de l’image ne peut être pour l’instant choisie que tout les 16 points.
LA SOLUTION
Les plus attentifs auront remarqué que les registres BLTCON0 et BLTCON1 ont jusqu’à maintenant été chargés de cette façon.
Xxxx xxxx xxxx, BLTCON0 xxxx xxxx xxxx, BLTCON1 on constate alors que:
move.w % move.w %
- les bits xx de gauche (ceci seulement pour le premier mot de l’image) contiendront ce qu’il y a déjà dans la zone cible.
Si l’on suppose que l’exemple ci-dessus correspond à une image de 2 mots et d’une ligne, on s’aperçoit puisque chaque bit allume un point que l’image entière est déplacée de 2 points sur la droite.
On comprend ainsi qu’il est possible de cette manière de placer une image à n’importe quelle position horizontale et donc de réaliser des scrollings.
Mais attention au piège grossier ! Les bits de droite de chaque mot de donnée sont expulsés dans le mot de données d’adresse immédiatement supérieure. Pour scroller une image, il faut donc prévoir des zones "tampon”, ce qui explique que dans le listing d’exemple l'image soit agrandie d’un mot nul pour chaque ligne. (Les valeurs modulos sont bien sûr modifiées en conséquence).
Sachant tout cela vous n'aurez aucune difficulté pour comprendre le premier listing d'exemple. Le programme est constitué de deux boucles imbriquées : une boucle pour scroller l’image sur tous les "points” d'un mot, et une boucle pour la position initiale de l’image avant scrolling tous les 16 points.
Remarquez la ligne (1) : move.w $ 7fff,BLTAFWM(a0). Ainsi le premier point de chaque ligne de l’image sera masqué. Ceci afin d’éviter que chaque déplacement de l’image ne laisse subsister une petite barre verticale.
Remarquez également un nouveau moyen de s’accaparer le blitter : passer en mode superviseur. Comme en mode superviseur, l’Amiga n’est plus multi-tâches, seul notre programme accédera au blitter. En plus cela permet de ne pas être dérangé par les routines d'interruptions et de pouvoir tester le blanc vertical avec précision. On dit qu’on a le blanc vertical quand le rayon (raster) du tube cathodique de l’écran n’est pas visible. Il faut scroller l’image à ce moment afin d’éviter les saccades.
C’est-à-dire qu’à chaque fois les bits 12 à 15 étaient annulés dans les deux registres. Les quatre bits 12-15 de BLTCON0 concernent la source A Les quatre bits 12-15 de BLTCON1 concernent la source B. La source C n’est pas utilisable pour les scrollings horizontaux.
Les experts en binaire que vous êtes auront immédiatement compris que 4 bits permettent d’écrire toutes les valeurs de 0 à 15 (soit 16 valeurs).
A quoi servent ces 4 bits ?
A faire décaler par le blitter de la valeur décrite par ces 4 bits tous les bits de données d’une source. Cette opération est effectuée par le blitter en même temps que le transfert de données sans aucun ralentissement.
Un exemple pour bien comprendre : voilà une zone de données A constituée de 3 mots:
0001010111100100 1110000011010111 xxxxxxxxxxxxxxxx
Le registre BLTCON0 est chargé comme suit :
move.w %0010xxxxxxxxxxxx,BLTCON0
0010 en binaire vaut 2 en décimal, donc tous les bits seront décalés de 2 "crans” sur la droite et le résultat dans la cible sera:
XX00010101111001 0011100000110101 llxxxxxxxxxxxxxx
PLUS VITE !
Dans le listing modifiez 3 lignes comme suit :
(1) move.w $ 3fff,BLTAFWM(a0)
(2) cmp.w $ e000,d7
(3) add.w $ 2000,roll
pour obtenir un scrolling deux fois plus rapide.
Et enfin
( 1 ) move.w $ 0fff,BLTAFWM(a0)
(2) cmp.w $ c000,d7
(3) add.w $ 4000,roll
pour obtenir un scrolling quatre fois plus rapide.
TEST DE COLLISION
Cela peut se faire grâce au test du bit 13 de DMACON. C’est le bit appelé BZERO. Quand le blitter démarre BZERO est initialisé à 1. Quand le blitter travaille, il le fait suivant les combinaisons logiques définies par les Minterms. Tant que les Minterms empêchent le blitter de mettre un bit à 1 dans la zone cible, le bit BZERO reste à 1, dès que le blitter met un bit à 1 dans la zone cible le bit BZERO est annulé et le reste jusqu’à la fin du travail du blitter et cela quels que soient les résultats ultérieurs.
Il est maintenant possible d’examiner le 2e listing. Ce programme est déjà une petite animation faite au blitter !
- un écran à 3 plans de bits est ouvert
- puis une image appelée “cache” est installée dans le 2e plan de bits
- puis une image appelée “obstacle” est installée dans le 3e plan de bits.
Le but du programme est de scroller notre image maintenant familière dans le premier plan de bits en donnant l’impression de passer derrière le cache (cf. Article sur tes combinaisons logiques) et en s’arrêtant à la “rencontre" de l’obstacle.
On ne veut pas que l’image mobile chevauche l’obstacle même d’un seul point. Il faut donc tester avant chaque déplacement s’il y aura collision. Pour cela on effectue le déplacement à vide en BLOQUANT le CANAL DMA D (voir initialisation de rolH). Le blitter n’y voit que du feu et fait un transfert de données qui n'arrivera ... nulle part. Mais on pourra savoir s'il y aurait eu collision en testant BZERO. Regardez les Minterms de rolll BLTDPTH pointe sur l’image mobile, BLTBPTH pointe sur une zone équivalente en taille et en position à l’image dans le 36 plan de bits. Les Minterms disent : transfert pour AB. Tant que l’image n’est pas arrivée sur l’obstacle on n'a pas B donc le transfert ne peut se faire et BZERO reste à 1. Dès qu'on arrive sur l’obstacle, le transfert peut se faire (nulle part car DMA D est bloqué) et BZERO est annulé : la collision est détectée. Pour vérifier que tout se passe bien comme prévu, vous pouvez modifier dans le listing la position de l’obstacle. Mais pas trop à gauche tout de même sinon la collision serait détectée avant même de commencer...
SCROLLING VERTICAL
Afin d'être complet le listing 3 présente un scrolling vertical. Rien de mystérieux. Il suffit d’initialiser convenablement BLTDPTH à chaque déplacement. Une petite astuce pour paresseux Timage comporte une ligne de mots nuls en plus. Ainsi l’image efface d’elle-même en se déplaçant la traînée qu’elle laisserait sans cette ligne de mots nuls.
Je vous retrouve le mois prochain pour le remplissage de surfaces.
F. MAZUE
LISTING 1
Ce listing montre comment il est possible de programmer le blitter pour obtenir un scrolling horizontal.
* ** exec.libraiy ***
OldOpenLibrary = -408
CloseLibrary = -414
AllocMem = -198
FreeMem = -210
SuperState = -150
UserState = -156
* ** intuiüon.library ***
CloseScreen = -66
OpenScreen = -198
* ** CHIPS***
BLTSIZE =$ 58
BLTCPTH =$ 48
Fi
yinniüin tison
h
BLTBPTH =$ 4C BLTAPTH =$ 50 BLTDPTH =$ 54
BLTCMOD =$ 60 BLIBMOD =$ 62 BLTAMOD =$ 64 BLTDMOD =$ 66
BLTCON0 =$ 40 BLTCON1 =$ 42
BLTAFWM =$ 44 BLTALWM =$ 46
DMACON =$ 96 DMACONR = $ 02
début
move.l $ 04,a6
execbase
lea int_name,al jsr 01d0penLibrary(a6) move.l d0,int_base
intuiüon.library ouverte
move.l (fm_data-data),d0 move.l $ 10002,dl jsr AllocMem(a6) move.l d0,image
réservation de CHIP_RAM pour les données de l’image
move.l (fin_data-data) 2,d0
subq $ 01,d0
move.l image,a0
lea data,al
loop
transfert des données de l’image dans la mémoire précédemment réservée
move.w (al)+,(a0)+ dbra d0,loop
move.l int_base,a6 lea écran,a0 jsr OpenScreen(a6) move.l d0,canal_ecran
écran à un bitplane ouvert
bsr Blitter_Busy
move.l $ 04,a6 jsr SuperState(a6) move.l d0,pile_sys
passage en mode Superviseur sauvergarde de la pile système
lea $ dff000,a0
move.l $ 0000,offset
init_scroll
move.w %0000100111110000,roll ; initialisation du
; compteur ; de scrolling
scrolling
bsr vertical
; attente du blanc vertical
move.l image,BLTAPTH(a0) move.l canal_ecran,al move.l$ c0(al),al adda.1 (100*40), al
move.l offset,d0 add.l d0,al
; nombre de lignes par ; nombre d’octets par ligne
move.l al,BLTDPTH(a0)
; position de l’image ; avant décalage
move.w roll,BLTCON0(a0)
move.w %0000000000000000,BLTCONl(a0) move.w %1000000001000000,DMACON(a0) move.w $ 00,BLTAMOD(a0) move.w (20-10)*2,BLTDMOD(a0)
move.w $ 7fff,BLTAFWM(a0
move.w $ ffff,BLTALWM(a0) move.w (20164+10),BLTSIZE(a0
(1) ; le bit correspondant au ; point le plus à gauche ; est masqué ; aucun bit masqué
bsr BlitterJ3usy
move.w roll,d7 and.w $ 000,d7 cmp.w $ 000,d7
nprt oi llfp
add.w $ 1000,roll
; (2) ; tester si on a scrollé ; sur les 16 points
; (3) ; augmenter le décalage de 1
bra scrolling
suite
move.l offset,d0 cmp.l $ 14,d0 beq souris
add.l $ 02,d0 move.l d0,offset bra init_scroll
; 2 octets = 1 mot correspondant ; à 16 points
souris
Iea$ bfe001,a5 btst 6,(a5) bne souris
move.l $ 04,a6 move.1 pile_sys,d0 jsr UserState(a6)
; passage en mode User
move.l int_base,a6 move.l canal_ecran,a0 jsr CloseScreen(a6)
stop
move.l $ 04,a6
move.l image,al move.l (fin_data-data),d0 jsr FreeMem(a6)
move.l int_base,al jsr CloseLibrary(a6)
; ON FERME TOUT
rts
! ET ON S'EN VA
Blitter Busy
btst r4,DMACONR(a0) bne Blitter_Busy rts
vertical
cmp.b $ 0,$ df 006 bne vertical rts
; lecture de la ; position du raster
image
dc. 10
canal écran
dc. 10
int_base
dc. 10
int_name
dc. b 'intuition.library',0
even
roll
dc. w0
; compteur de scrolling
offset
dc. 10
pile_sys
dc. l 0
écran
dc. w 0
dc. w 0
dc. w 320
dc. w 200
dc. w 1 ; 1 bitplane
dc. b 0
dc. b 1
dc. w 2
dc. w 15
dc. l 0
dc. l titre_ecran
dc. l 0
dc. 10
titre_ecran
dc. b Mtter demo',0
even
data
dc. w
$ ffff, $ fff ,
$ fff, $ ffff, $ f£tf, $ ffff, $ ffff
$ fff, $ fff,
$ 0000
dc. w
$ ffff, $ ffff,
$ ff, $ ffff, $ ffff, $ f££f, $ ffff
$ fff , $ £fff,
$ 0000
dc. w
$ ffff, $ ffff,
$ fffi, $ ffff, $ ffff, $ ff£f, $ ffff
$ ffff, $ ££ff.
$ 0000
dc. w
$ ffif, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ffff, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ££f, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ fftf, $ ffff, $ £fff
$ 0000
dc. w
$ t££f, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ffff, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ üff
$ 0000, $ 0000, $ 0000
$ £fff, $ ffff, $ fffi
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ffff, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ fiif
$ 0000, $ 0000, $ 0000
$ ffff, $ fff£, m
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ffff, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ fff, $ ffff, $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ fff , $ ffff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ f f, $ f , $ ffff
$ 0000
dc. w $ £££, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ £fff, $ ff£f, $ f£ff
$ 0000
dc. w
$ ffff, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ f£ff, $ fff
$ 0000
dc. w
$ fffi, $ ffff, $ ffff
$ 0000, $ 0000, $ 0000
$ ffff, $ ffif, $ ffff
$ 0000
dc. w
$ fff, $ ffif,
$ ffff, $ fffi, $ ffff, $ ffff, $ ffff
$ ffff, $ ffff,
$ 0000
dc. w
$ ffff, $ ffff,
$ ifii, $ ffff, $ ffff, $ ffff, $ ffff
$ ffff, $ f££f.
$ 0000
dc. w
$ ffff, $ ffff,
$ ffff, $ ffff, $ ffff, $ ffff, $ ffff
$ fff , $ iff£,
$ 0000
fin_data
LISTING 2
BLTBPTH
= $ 4C
BLTAPTH
= $ 50
BLTDPTH
= $ 54
BLTCMOD
= $ 60
BLIBMOD
= $ 62
BLTAMOD
= $ 64
BLTDMOD
= $ 66
BLTCON0
= $ 40
BLTCON1
= $ 42
BLTAFWM
= $ 44
BLTALWM
= $ 46
DMACON
= $ 96
DMACONR
= $ 02
début
move.l $ 04,a6
;execbase
; intuiüon.library ouverte
lea int_name,al jsr 01d0penLibrary(a6) move.l d0,int_base
move.l (fin_data-data),d0 move.l $ 10002,dl jsr AllocMem(a6) move.l d0,image
move.l (fin_data-data) 2,d0
subq $ 01,d0
move.l image,a0
lea data,al
loop
move.w (al)+,(a0)+ dbra d0,loop
move.l (fin_cache-cache),d0 move.l $ 10002,dl jsr AhocMem(a6) move.l d0,imagel
move.l (fin_cache-cache) 2,d0 subq $ 01,d0 move.l imagel,a0 lea cache,al loopl
move.w (al)+,(a0)+ dbra d0,loopl
RESERVATION MEMOIRE ET TRANSFERT DES DONNEES
move.l (fin_obstacle-obstacle),d0 move.l $ 10002,dl jsr AllocMem(a6) move.l d0,image2
move.l (fin_obstacle-obstacle) 2,d0
subq $ 01,d0
move.l image2,a0
lea obstacle,al
loop2
move.w (al)+,(a0)+ dbra d0,loop2
move.l int_base,a6 lea écran,a0 jsr OpenScreen(a6) move.l d0,canal_ecran
; écran à trois bitplanes ouvert
; passage en mode Superviseur
move.l $ 04,a6 jsr SuperState(a6) move.l d0,pile_sys
lea $ dff000,a0
bsr Blitter_Busy
move.l imagel,BLTAPTH(a0) move.l canal_ecran,a3 move.l $ c4(a3),al adda.l (100*40),al
nombre de lignes par nombre d'octets par ligne approximativement au milieu de l'écran
adda.l 18,al
move.l a 1 ,BLTDPIH(a0) ; début de la cible
move.w %0000100100110000,BLTCON0(a0) move.w %0000000000000000, BLTCONl(a0) move.w %1000000001000000,DMACON(a0) move.w $ 00,BLTAMOD(a0)
move.w (20-1 )*2,BLTDMOD(a0) move.w $ ffff,BLTAFWM(a0 ; aucun bit masqué
move.w $ ffff,BLTALWM(a0) ; aucun bit masqué
move.w (20*64+1),BLTSIZE(a0)
bsr Blitter_Busy
* ** mise en place de l'obstacle ’**
move.l image2,BLTAFTH(a0) move.1 cand_ecran,a3 move.l $ c8(a3),al
adda.l (100*40),al ; nombre de lignes par
; nombre d'octets par ligne
adda.l 36,al ; sur la droite de l'écran
move.l a 1 ,BLTDPTH(a0)
move.w %0011100111110000,BLTCON0(a0)
; plus un décalage de trois points à droite que vous pouvez modifier comme bon vous semble afin de vérifier que le test de collision s'effectue correctement quelle que soit la position de l'obstacle
move.w %0000000000000000,BLTCONl(a0) move.w %1000000001000000,DMACON(a0) move.w $ 00,BLTAMOD(a0) move.w (20-2)*2,BLTDMOD(a0) move.w $ ffff,BLTAFWM(a0) ; aucun bit masqué
move.w $ ffff,BLTALWM(a0) ; aucun bit masqué
move.w (20*64+2), BLTSIZE(a0)
bsr Blitter_Busy
bsr tempo
afin d'avoir le temps d'observer la position de départ
; départ sur la gauche ; de l'écran
move.l $ 0000,offset
init_scroll
; initialisation des ; compteurs ; de scrolling
move.w %0000110100110000,roll
move.w %0000110011000000,rolll scrolling
.... test DE COLLISION'
move.l image,BLTAPTH(a0) move.l canal_ecran,a3 move.l $ c0(a3),al move.l $ c8(a3),a2 adda.l (100*40),al adda.l (100*40),a2
; nombre de lignes par ; nombre d'octets par ligne
move.l offset,d0 add.l d0,al add.l d0,a2
move.l al,BLTDPTH(a0) move.l a2,BLTBPTH(a0)
move.w rolll,BLTCON0(a0)
move.w %0000000000000000,BLTCONl(a0) move.w %1000000001000000,DMACON(a0) move.w $ 00,BLTAMOD(a0) move.w (20-10)*2,BLIBMOD(a0) move.w (20-10)*2,BLTDMOD(a0) move.w $ ffff,BLTAFWM(a0 ; aucun bit masqué move.w $ ffff,BLTALWM(a0) ; aucun bit masqué move.w (20*64+10),BLTSEE(a0)
bsr Blitter_Busy
move.w DMACONR(a0),d4 and.w $ 2000,d4 beq souris
; collision, il faut arrêter
* FIN TEST DE COLLISION
* *************************
bsr vertical
; attente du blanc vertical
move.l image,BLTAPTH(a0) move.l canal_ecran,a3 move.l $ c0(a3),al move.l $ c4(a3),a2 adda.l (100*40),a 1 adda.1 (100*40), a2
; nombre de lignes par ; nombre de mots
move.l offset,d0 add.l d0,al add.l d0,a2
move.l a 1 ,BETDPTH(a0) move.l a2,BLTBPTH(a0) move.w roll,BLTCON0(a0)
move.w %0000000000000000,BLTCONl(a0)
move.w %1000000001000000, DMACON(a0)
move.w $ 00,BLTAMOD(a0)
move.w (20-10)‘2,BLIBMOD(d0)
move.w (20-10)*2,BLTDMOD(a0)
move.w $ 7fff,BLTAFWM(a0) ; le point le plus à
; gauche est masqué move.w $ ffff,BLTALWM(a0) ; aucun bit masqué move.w (20*64+10), BLTSEE(a0)
bsr Blitter_Busy
move.w roll,d7 and.w $ f000,d7 cmp.w $ f000,d7
nprr i i tp
add.w $ 1000,roll add.w $ 1000,rolll bra scrolling
; scrolling complet sur un mot ?
; augmenter le decalage de 1 ; sur les deux compteurs
suite
move.l offset,d0 cmp.l $ 14,d0 beq souris add.l $ 02,d0 move.l d0,offset
; 2 octets = 1 mot
bra init_scroll
souris
lea $ bfe001,a5 btst 6,(a5) bne souris
move.l $ 04, a6 move.l pile_sys,d0 jsr UserState(a6)
move.l int_base,a6 move.l canal_ecran,a0 jsr CloseScreen(a6)
; passage en mode User
stop
move.l $ 04,a6
move.l image,al
move.l (fin_data-data),d0
jsrFreeMem(a6)
move.1 imagel.al move.l (fin_cache-cache),d0 jsr FreeMem(a6)
move.l image2,al
ON FERME TOUT
move.l (fm_obstacle-obstacle),d0
jsr FreeMem(a6)
move.l int_base,al jsr CloseLibrary(a6)
rts
Blitter_Busy
btst 14,DMACONR(a0) bne BlitterJ3usy rts
tempo
moveq $ 05,dl move.w $ ffff,d0 bouclejempo dbra d0,bouclejempo dbra dl,bouclejempo rts
vertical
cmp.b $ 0,$ dff006 bne vertical rts
; lecture de la ; position du raster
image
dc. 10
image 1
dc. 10
image2
dc. 10
canal_ecran
dc. 10
int_base
dc. 10
int_name
dc. b 'intuition.library',0 even
roll
dc. w0
; compteur de scrolling
; compteur de scrolling ; pour test de collision
rolll
dc. w0
offset
dc. 10
pile_sys
dc. 10
écran
dc. w 0
dc. w 0
dc. w 320
dc. w 200
dc. w 3
; 3 bitplanes
dc. b 0
dcb I
dc. w 2
dc. w 15
dc. l 0
dc. l titre écran
dc. 10
dc. 10
ütre_ecran
dcb blitter demo',0
even
data
cache
dc. w $ ffff, Sffff, Sffff, Sffff, $ ffff,
Sffff, Sffff, Sffff, Sffff, S0000
dc. w Sffff, * Sffff, $ ffff, Sffff,
Sffff, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sfffi, Sffff, Sffff, Sffff,
Sffff, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,$ 0000, Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,S0000,$ 0000,Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, S0000,$ 0000,$ 0000,Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, $ 0000, $ 0000, $ 0000, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,S0000,Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, $ 0000, $ 0000, $ 0000, Sffff, Sffff, Sffff, S0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,S0000,Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,$ 0000,Sffff,Sffff,Sffff,$ 0000
de. W Sffff, Sffff, Sffff, $ 0000, $ 0000, $ 0000, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,$ 0000,Sffff,Sffff,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, $ 0000, S0000, $ 0000, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,$ 0000,Sffff,Sffff,Sffff,S0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000, S0000, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, $ 0000,$ 0000,S0000,$ ffff,Sffif,Sffff,$ 0000
dc. w Sffff, Sffff, Sffff, Sffff, Sffff,
Sffff, Sffff, Sffff, Sffff, $ 0000
dc. w Sffff, Sffff, Sffff, Sffff, Sffff, Sffff, Sffff, Sffff, Sffff, S0000
dc. w Sffff, Sffff, Sffff, Sffff, Sffff,
Sffff, Sffff, Sffff, Sffff, S0000
fin_data
1
obstacle
dc. w $ 00ff
dc. w $ 00ff
dc. w $ ffff,$ 0000
dc. w S00n
dc. w Sim,$ 0000
dc. w $ 00iî
dcw Sffff,$ 0000
dc. w $ 00ff
dc. w Sffff,$ 0000
dc. w S00n
dc. w Sffff,$ 0000
dc. w S00ff
dc. w Sffff,S0000
dc. w S00if
dc. w Sffff,$ 0000
dc. w S00n
dc. w Sffff, $ 0000
dc. w S00ff
dc. w Sffff,$ 0000
GC.W $ 00ff
dc. w Sffff,$ 0000
dc. w S00ff
dc. w Sfffi,$ 0000
dc. w $ 00ff
dc. w Sffff,$ 0000
dc. w S00ff
dc. w Sffff,$ 0000
cc. w S00a
dc. w Sffff,$ 0000
dc. w S00ü
dc. w Sffff,$ 0000
dc. w $ 00ff
dc. w Sffff,$ 0000
dc. w $ 00ff
dc. w $ ffff,$ 0000
dc. w$ 00ff
dc. w Sffff,$ 0000
dc. w $ 00ff
dc. w Sffff,$ 0000
dcw Sffff,$ 0000
fin cache , . ,
| fin_obstacle
Ce listing montre comment il est possible de programmer le blitter pour obtenir un scroüing vertical.
* ** execiibraty ***
OldOpenLibrary = -408 CloseLibrary = -414
AllocMem = -198
FreeMem = -210
SuperSiate =-150
UserState = -156
* ** intuitiomlibrary ***
CloseScreen = -66
QpenScreen = -198
*” CHIPS*"
BLTSIZE =$ 58
BLTCPIH =$ 48
BLTBPTH =$ 4C
BLTAPTH =$ 50
BLTDPTH =$ 54
BLTCMOD =$ 60
BLT3MOD =$ 62
BLTAMOD =$ 64
BLTDMOD =$ 66
3LTCON0 =$ 40
BLTCON1 =$ 42
BLTAFWM =$ 44
BLTALWM =$ 46
DMACON =$ 96
DMACONR =$ 02
début
;execbase
; intuitiomlibrary ouverte
; réservation de CHD?_RAM ; pour les données de l'image
; transfert des données ; de l'image dans la mémoire ; précédemment réservée
move.1 $ 04,a6
lea int_name,al jsr 01d0penlibrary(a6) move.1 d0,int_base
move.l (fin_daia-data),d0 move.1 d0, longueur move.l $ 10002,dl jsrAllocMem(a6) move.1 d0,image
move.l (fin_data-data) 2,d0 move.l image,a0
lea data,al loop
move.w(al)+,(a0)+
dbrad0,loop
move.1 int_base,a6 lea écran,a0
jsr OpenScreen(a6) ; écran à un biiplane ouvert
move.1 d0,canal_ecrcm
bsr Blitter_Busy
move.i$ 04,a6 '' :.....”
jsr SuperState(a6) ; passage en mode Superviseur
move.1 d0,pile_sys ; sauvegarde de la pile système
lea $ àff000,a0
H
TfMS»ST®B
IBHC3H HBHB
; ' Yfi"; O
int_base
dc. 10
int_nctme
dc. b 'intuition.library',0
longueur
dc. 10
offset
dc. 10
pile_sys
dc. 10
écran
dc. w 0
dc. w 0
dc. w 320
dc. w 200
dc. w 1
dc. b 0
dc. b 1
dc. w 2
dc. w 15
dc. l 0
dc. l titre_ecran
dc. 10
dc. 10
titre_ecran
dc. b 'blitter demo',1
; 1 bitplane
data
dc. w
dc. wl
dc. w]
dc. w;
dc. w
dc. w
dc. w
dc. w
dc. w
dc. w
dc. w $ ffff,$ ffff,$ ffff
dc. w
dc. w
dc. w
dc. w
dc. w
dc. w $ ffff,$ £fff,$ ffff
dc. w $ ffff,$ fffi,$ ffif
dc. w$ ffi, $ tffi,
dc. w $ ffff, $ ffff,
dc. w$ ffif, ÎB,
fin data
move.l $ 0000,offset init_sCToll
bsr vertical
move.l image,BLTAPTH(a0)
move.l canal_ecran,al move.l $ c0(al),al adda.l (10*40),a
; nombre de lignes par ; nombre d'octets par ligne
move.l offset,d0 add.l d0,al
adda.l 10,al
; centre de l'écran approximatif
move.l al,BLTDPTH(a0)
move.w %0000100111110000,BLTCON0(a0) move.w %0000000000000000,BLTCONl(a0) move.w %1000000001000000,DMACON(a0) move.w $ 00,BLTAMOD(a0) move.w (20-9)*2,BLTDMOD(a0)
move.w $ ffff,BLTAFWM(a0 ; aucun bit masqué move.w $ ffff,BLTALWM(a0) ; aucun bit masqué move.w (21*64+9), BLTSIZE(a0)
bsr Blitter_Busy
move.l offset,d0 cmp.l 160*40,d0 beq souris add.l 40,d0 move.l d0,offset bra init_scroll
; scrolling sur 150 lignes ; 40 octets = plus 1 ligne
souris
Iea$ bfe001,a5 btst 6,(a5) bne souris
move.l $ 04,a6 move.l pile_sys,d0 jsr UserState(a6)
; passage en mode User
move.l int_base,a6 move.l canal_ecrcm,a0 jsr CloseScreen(a6)
stop
move.l $ 04,a6
move.l image,al
move.l (fin_data-data),d0
;
jsr FreeMem(a6)
move.l int_base,al jsr CloseLibrary(a6)
! ON FERME TOUT
rts
! ET ON S'EN VA
Blitter Busy
btst 14,DMACONR(a0) bne Blitter_Busy rts
vertical
cmp.b $ 0,$ dff006 bne vertical rts
; lecture de la ; position du raster
image
dc. 10
canal_ecran
dc. 10
IBBE3B BBBD
imM
IMAGE INTUITION INITIATION
LES GADGETS DE CHAINE
Cette fois nous allons voir le dernier type de gadget d’intuition : les gadgets de chaîne. Ils permettent de saisir une chaîne de caractères ou un entier sans passer par la lecture du clavier.
Ils consistent en une zone de saisie dans laquelle il faut cliquer pour pouvoir rentrer les données. Nous avons déjà vu que dans le champ type de la structure gadget 4 correspond à un gadget de chaîne (voir Commodore Revue 18). Il faut ensuite placer dans le champ spécial info un pointeur sur une structure Stringlnfo.
Voici comme d’habitude la structure C
Struct Stringlnfo IUBYTE 'Butter; UBYTE 'UndoBuffer; SHORT BufferPos; SHORT McrxChars; SHORT DispPos
'pointeur sur la chaîne '
'pointeur sur chaîne de sauvegarde * 'position caractère dans le buffer '
'nombre majdmun de caractères *
'position du premier caractère aff *
* les variables suivantes sont mises à jour par intuition *
UTILISATION DU GADGET DE CHAINE
L’activation du gadget est effectuée par cliquage dans le container du gadget. La fin de saisie est réalisée soit par l’appui sur la touche return soit par cliquage hors du container du gadget.
Le gadget de chaîne permet la saisie d’une chaîne bien plus longue que la place occupée à l’écran : les touches curseurs permettent de se déplacer à l’intérieur de la chaîne.
Les touches DEL et backspace permettent respectivement d’effacer le caractère sous le cuseur, le caractère à gauche du curseur.
L’appui simultané sur Amiga-droite et Q annule la dernière modification.
L’appui simultané sur Amiga-droite et X efface le tampon d’entrée.
D. OBRIOT
PROGRAMME DE DEMONSTRATION DES GADGETS
SHORT Undopos; de*
‘position caractère dans le tampon sauvegar-
'longueur de la chaîne actuelle * 'nombre de caractères visibles dans le contai-
SHORT Numchars;
SHORT DispCount; ner*
SHORT Cleft.Ctop; 'offset du coin haut gauche du container * struct Loyer'layerPtr; 'pointeur sur rasport '
LONG Longlnt; ‘valeur entière si gadget entier '
struct KeyMap 'AltKeyMap 'pointeur sur une carte de décodage clavier '
I
les variables de cette structure n’appellent pas de commentaire particulier
Quelques petites précisions :
le champ activation de la structure gadget comporte quelques bits ayant une signification pour les gadgets de chaîne
&h0200 la chaîne sera centrée dans le container du gadget
&h0400 la chaîne sera justifiée à droite
&h0800 le gadget représente un entier long
&h1000 le gadget possède une structure AltKeyMap personnelle
Voilà pour les données générales, le programme de ce mois-ci définit un gadget de chaîne, et affiche la chaîne lors du cliquage sur le gadget. Trois routines sont définies :
- stringinfo qui initialise la structure C et les deux tampons de saisie (buffer) et un dobuffer, le calcul des premières lignes permet de déterminer la longueur exacte occupée dans la mémoire (on aligne un dobuffer% pour ne pas avoir d’adresse impaire car le 68000 en a horreur). La boucle en fin de procédure sert à initialiser le buffer par la chaîne c$ en la terminant par un zéro (en C les chaînes se terminent par un zéro qui sert de délimiteur).
- litstringinfo qui permet de récupérer la chaîne saisie par l’intermédiaire du gadget
- et enfin liberestringinfo qui libère la mémoire occupée par le gadget
H
' ouverture écran et fenêtre
OPENS 1,0,0,640,250,4,&H8000 TITLES 1,"TEST DES GADGETS INTUITION'' üag%= 1+2+8+4+4096+65536
idcmp%=&H10+&H8+&H20+&H40+&H200+&H40000+&H80000
!... ouINACTtVEWINDOW
OPENW1,10,10,600,200,idcmp%,flag%
TITLEW 1,"FENETRE DES GADGETS"
’ définition du gadget
stringinfo(41,1,1, "essai initialisation” ,stringinfo%)
gadget(100,100,150,20,0,&H402,4,0,0,1,stringinfo%,gadget 1 %)
BOX 95,95,250,115 Itrace un carré pour délimiter le gadget ~RefreshGadgets(gadgetl%,WlNDOW( 1 ),0)
' demande traitement des événements intuition
ON MESSAGE GOSUB mess
' attente d'un événement
DO
SLEEP
LOOP UNTL MOUSEK=2 liberestringinfo(41 ,stringinfo%)
' fin du programme
PROCEDURE gadget(x&,y&,largeur&,hauteur&,flag&,acti&,type&, image%,imageselect%,gadgetid&,spedalinfo%,VARgadget%) gadget%=MALLOC(44,&H4)
IF gadget%=0 THEN PRINT "plus de mémoire "
END
ENDIF
LONG(gadget%+0)=0 ! Pointeur sur gadget suivant
INT|gadget%+4j=x& ! X
INT|gadget%+6j=y& ! Y
lNTjgadget%+8)=largeur& ! Largeur
INT|gadget%+101=hauteur& INT(gadget%+12]=flag& CARDlgadget%+14)=acti& CARD|gadget%+16)=type& LONG(gadget%+ 18)=image%
! Hauteur Iflags I Activation ! Gadgettype ! GadgetRender
inana hhhd
LONG|gadget%+22|=imageselect%! Selectrender LONG(gadget%+261=0 ! Intuitext
LONG(gadget%+30)=0 ! MutualExclude
LONG(gadget%+34)=specialinfo% ! Speciallnfo
CARD|gadget%+38)=gadgetid& ! Gadgetid
LONG|gadget%+40)=0 ! Userdata
fenetre%=WlNDOW(l) pos%=-l
pos%=AddGadget(fenetre%,gadget%,pos%)
' longueur gadget 44 RETURN
PROCEDURE mess IF MENU(1)=32 THEN LOCATE 1,1
PRINT "le gadget vient d'etre clique"
PRINT "contenu : litstringinfo(stringinfo%,c$ )
PRINT c$ ;"
ENDIF
RETURN
PROCEDURE stringinfo(longueur%,pospremier%,curseur%,c$ ,VAR- stringinio%)
bytebuf%=SUB(ADD(longueur%,2),(longueur% MOD 2))
byte%=36+MUL(bytebuf%,2)
stringinfo%=MALLOC(byte%,&Hl)
IF stringinfo%=0 THEN PRINT "plus de mémoire"
END
ENDF
buffer%=stringinfo%+38
undobuffer%=buffer%+bytebuf%
LONG(stringinfo%l=buf er% ! Buffer LONG(stringinfo%+41=undobuffer% ! Tampon de saisie lNT|stringinfo%+81=curseur% ! Position curseur M(stringinfo%+ 101=longueur% ! Longueur maximum INT|stringinfo%+121=pospremier% ! Position du premier INT stringinfo%+141=0 ! Position dans le tampon
INT(stringinfo%+161=0 ! Longueur actuelle
lNT|stringinfo%+18)=0 ! Nombre caractères visibles
INT(stringinfo%+20|=0 ! Coin haut gauche du container
INTistringinfo%+22)=0 !
LONG(stringinfo%+24!=0 ! Rasport du gadget
LONG(stringinfo%+281=0 ! Valeur entière du gadget
LONG(stringinfo%+32j=0 ! Structure keymap
FOR i=0 TO longueur%-l BYTE|buffer%+il=ASC(MŒ)$ (c$ ,i+1,1))
NEXTi
BYTE|buffer%+i)=0
RETURN
PROCEDURE litstringinfo(stringinfo%,VAR c$ ) c$ =""
FOR i=0 TO INTistringinfo%+161-1 c$ =c$ +CHR$ (BYTE!stringinfo%+38+i))
NEXTi
RETURN
PROCEDURE liberestringinfo(longueur%,stringinio%) bytebuf%=SUB(ADD(longueur%,4),(longueur% MOD 4)) byte%=36+MUL(bytebuf%,2)
- -MFREE(stringinfo%,byte%)
RETURN
SCHEMAS LANGAGE "C11 DU N° 22
Ü r At
V
INITIATION
LA FONCTION INKEYS
Quand on débute avec un langage de programmation tel que le GFABasic, la gestion du clavier pose souvent des problèmes. Parmi ceux-ci on peut citer la façon de lire les touches de fonction et aussi comment lire une touche sans qu’elle soit affichée (frappe sans écho). Je vous propose ce mois-ci une série de programmes qui utilisent la fonction INKEYS, qui permet de résoudre ces problèmes.
La fonction INKEYS est une fonction d’un grand intérêt qui se situe entre les fonctions de très haut niveau comme INPUT et celles de très bas niveau (niveau quasiment hardware, lecture des scan-codes). Au niveau des touches, la fonction INKEYS reconnaît les touches du clavier selon la key- map utilisée. Il ne sera donc pas besoin d'effectuer une quelconque conversion. INKEYS offre aussi l’avantage de lire une touche à la fois sans avoir besoin d’une validation par RETURN>. Une autre particularité de INKEYS est que cette fonction n’est pas bloquante comme INPUT. Si aucune touche n'est pressée, INKEYS renvoie une chaîne vide. Les touches ne sont pas affichées non plus, ce qui peut permettre d’effectuer un traitement avant affichage tel que le passage en majuscules et également de n’afficher que les caractères valides (par exemple si on demande un chiffre, notre routine pourra n’afficher aucune lettre pouvant être tapée par l’utilisateur). Et le dernier avantage de INKEYS est la reconnaissance des touches curseurs, des touches de fonction et de la touche HELP.
Pour vous familiariser en douceur avec cette fonction, examinez le premier programme. Dans la boucle DO...LOOP, la variable a$ prend à chaque fois la valeur de INKEYS puis est affichée. On aurait pu écrire PRINT INKEYS mais alors on n'aurait pas pu tester la fin du programme. Le code CHR$ (27) est celui de la touche Esc>. Si vous essayez toutes les touches du clavier avec ce programme vous constaterez que les touches curseur fonctionnent réellement, que la touche BackSpace revient bien d’un caractère vers la gauche mais sans effacer le caractère et que la touche RETURN> ne fait que revenir au début de la ligne. Tout cela est normal car les codes qui vous sont retournés sont bruts. Un caractère BackSpace ne peut pas être lu avec INPUT mais INKEY$ le reconnait. C’est l’instruction PRINT a$ ; qui fait ainsi revenir le curseur d'un caractère vers la gauche alors que quand INPUT reçoit un BackSpace du clavier, elle envoit à l’écran un BackSpace, un espace (pour effacer le caractère) et un deuxième BackSpace (pour revenir à la bonne position). C’est ainsi que les touches peuvent être filtrées, quand la touche RETURN> est reconnue par INPUT, un CTRL>-J (line-feed ou saut de ligne) est envoyé à la suite pour que le curseur descende d’une ligne. Vous pouvez aussi remarquer que l’appui de CTRL>-L efface l’écran.
A propos du curseur, celui-ci brille par son absence. Un deuxième problème est que l’on est obligé d’activer la fenêtre avant de commencer à taper au clavier. Ces deux problèmes sont réglés par le programme numéro 2 qui ouvre une fenêtre avec le flag ACTIVATE($ 1000) positionné. La procédure curon est la même que celle du numéro 21 (je vous avais dit qu’on en reverrait des codes ANSI...).
Maintenant, il serait temps de passer aux touches de fonction. Le programme numéro 3 vous permet de comprendre comment INKEY$ s'y prend pour les récupérer.C’est ici que l’on peut découvrir une ruse de sioux qui a fait date dans les annales de la programmation (d'accord, j’exagère un peu ...). Lorsqu'une touche de fonction ou du curseur est pressée, la fonction INKEY$ renvoie dans a$ une chaîne de caractères d'une longueur comprise entre 2 et 4. Si vous ne me croyez pas ce programme est là pour le prouver. En ce qui concerne la manière de quitter le programme, j’ai changé le test pour reconnaître la pression des deux boutons de la souris simultanément. La longueur de a$ est affichée en inverse vidéo à chaque fois (c’est joli, l'inverse vidéo). Le test IF ll>0 permet d’éviter que des 0 ne remplissent pas l’écran en permanence car a$ change de valeur plusieurs fois par seconde et est le plus souvent vide.
Comme nous sommes maintenant persuadés que nos touches de fonctions sont codées sur plusieurs caractères, le programme numéro 4 nous permet de savoir à quoi elles ressemblent. Toutes les touches sont ici affichées dans leur valeur hexadécimale.
Ceux qui sont observateurs remarqueront que les touches de fonctions, les touches de curseur et la touche HELP commencent toutes par le caractère
CSI (Contrai Sequence Introducer, 9B en hexadécimal) qui devrait commencer à être connu de la plupart d’entre vous. Quant à ceux qui en plus d’être observateurs, ont une table de conversion ASCII en hexadécimal et réciproquement, ils auront pu remarquer que la plupart des codes affichés auraient pu être imprimés, à l’exception toutefois du CSI. Ces judicieuses remarques sont d'ailleurs confirmées par la documentation officielle de Commodore. Le programme numéro 5 se contente donc de tester uniquement le caractère CSI pour afficher ensuite la séquence CSI correspondant aux touches de fonction. Le test sur longueur permet d’ignorer les chaînes vides (qui, hélas,sont toujours à l’affût).
Et pour finir en beauté, nous allons identifier chacune des touches de fonction en affichant son nom à l’écran (programme numéro 6). Les touches curseur sont identifiées au moyen d'un SELECT...CASE. Les touches de fonction sont calculées, ce qui nous permet d'économiser un peu de place. Vous avez sans doute remarqué que l’instruction SELECT...CASE vous permet d’écrire une petite sous-routine pour chaque touche de fonction, et donc de les utiliser dans vos futurs programmes.
Programme numéro 1
' Exemple de lecture du clavier avec INKEY$
PRINT "Activez la fenêtre pour pouvoir commencer"
PRINT "ESC pour arrêter"
keyl
PROCEDURE keyl DO
a$ =INKEY$
PRINT a$ ;
LOOP UNTIL a$ =CHR$ (27)
RETURN
Programme numéro 2
' Exemple de lecture du clavier avec 1NKEY$ csi$ =CHR$ (&H9B)
OPENW 0,0,11,639,199,0,&H1007 PRINT "ESC pour arrêter" curon keyl
PROCEDURE keyl DO
a$ =INKEY$
PRINT a$ ;
LOOP UNTIL a$ =CHR$ (27)
RETURN
PROCEDURE curon PRINT csi$ ;" p"
RETURN
Programme numéro 3
’ Exemple de lecture du clavier avec INKEY$ csi$ =CHR$ (&H9B)
OPENW 0,0,11,639,199,0.&H1007
PRINT "Les deux boutons de la souris pour arrêter"
curon
keyl
PROCEDURE keyl DO
a$ =INKEY$
ll=LEN(a$ )
IF 1I>0 PRINT a$ '; inverse PRINT 11; normal ENDIF
LOOP UNTIL MOUSEK=3 RETURN
PROCEDURE curon PRINT csi$ ;" p";
RETURN
!???? HHHB
PROCEDURE inverse PRINT csi$ ;"7m"; RETURN
PROCEDURE normal PRINT csi$ ;''0m"; RETURN
Programme numéro 4
' Exemple de lecture du clavier avec INKEY$
OPENW 0,0,11,639,199,0.&H1007
PRINT "Les deux boutons de la souris pour arrêter"
keyl
PROCEDURE keyl DO
a$ =INKEY$
ll=LEN(a$ )
IF 1I>0
FOR il= 1TO 11 c$ =MID$ (a$ ,il, 1)
PRINT HEX$ (ASC(c$ ),2)';
NEXTil
PRINT
ENDIF
LOOP UNTL MOUSEK=3 RETTURN
Programme numéro 5
' Exemple de lecture du clavier avec INKEYS csi$ =CHR$ (&H9B)
OPENW 0,0,11,639,199,0.&H1007
PRINT "Les deux boutons de la souris pour arrêter"
keyl
PROCEDURE keyl DO
a$ =INKEYS ll=LEN(a$ )
FLEFT$ (a$ ,l)=csi$
c$ =MID$ (a$ ,2,ll-l)
PRINT " CSI>";c$ '
ELSE F 1I>0 PRINT a$ ';
ENDIF
LOOP UNTL M0USEK=3 RETURN
Programme numéro 6
’ Exemple de lecture du clavier avec INKEYS csi$ =CHR$ (&H9B)
OPENW 0,0,11,639,199,0.&H1007
PRINT "Les deux boutons de la souris pour arrêter"
keyl
PROCEDURE keyl DO
a$ =INKEY$
ll=LEN(a$ )
FLEET$ (a$ ,l)=csi$
c$ =MD$ (a$ ,2,ll-l)
nbVALfcS)
F nl>10 AND nl 20 k$ =" SHFT>+ F"+STR$ (nl-9)+">"
ENDF
F nl>0 AND nl 10 k$ =" F"+STR$ (nl+1)+">"
ENDF SELECT c$
CASE ”0~" k$ =" Fl>"
CASE"?-"
k$ ="HELP"
CASE "A"
k$ =" Curseur haut>"
CASE "B"
k$ =" Curseur bas>"
CASE "C"
k$ =" Cuiseur droite>"
CASE "D"
k$ =" Curseur gauche>"
CASE "S"
k$ =" SHFT>+ Cuiseur bas>"
CASE "T"
k$ =" SHFT>+ Curseur haub"
CASE " @"
k$ =" SHFT>+ Curseur droite>"
CASE "A"
k$ =" SHFT>+ Cureeur gauche>"
ENDSELECT PRINT k$ '
ELSE F 1I>0 PRINT aS’;
ENDF
LOOP UNTIL M0USEK=3 RETURN
APPLICATION
LE CLIPBOARD.DEVICE
Le clipboard.device est une partie les plus mystérieuses de l’Amiga. Ceci est dû à la grande complexité de sa mise en œuvre. Ce device pas comme les autres permet aux programmes de s'échanger des données en faisant du Couper Copier Coller(Cut Copy Paste en anglais). Tout cela serait très simple si le clipboard.device n’imposait pas un format des données qu’on lui envoie.
Ce format est le célèbre format IFF. Cela signifie que dans le clipboard.device, vous pourrez trouver aussi bien du texte que des images ou du son, à condition que ceux-ci soient placés sous un format IFF. Ceux qui connaissent bien le format IFF savent qu’il est possible de placer plusieurs types de données les uns à la suite des autres dans le clipboard, rendant la lecture très délicate à effectuer. C'est pourquoi notre exemple de démonstration ne s’occupe que du minimum, c’est-à-dire lire et écrire du texte dans le Clipboard. Si une image est présente dans le clipboard, je ne garantis absolument rien !
Quand on sait programmer un des device de l’Amiga, les autres ne posent plus beaucoup de problèmes. Le clipboard.device est loin d’être aussi compliqué que l’audio.device mais recèle tout de même quelques difficultés.
La première difficulté consiste en la gestion d’un offset. On peut en fait, considérer le clipboard comme une bande magnétique. Il est possible avant
I7Ô
toute lecture ou écriture de se positionner ailleurs qu’au début. En lecture, cela permet de ne pas lire entièrement les données d'une image si c'est un texte que l’on recherche et qu’il est situé après elle. Comprendre cela demande une connaissance minimale de TIFF. Un format IFF est repéré par quatre lettres qui sont FORM, CAT (‘C’.’A’.’T’,’ ') ou LIST. Les quatres octets suivants et qui seront représentés par donnent la taille des données qui suivent. On peut donc lire les 12 ou 20 premiers octets du clipboard et rechercher du texte. Il est possible de trouver directement du texte (FORM FTXT, ce que le programme ci-dessous suppose). Il est également possible de ne trouver, que des données images (FORM ILBM) dans ce cas il y a échec en lecture. Une troisième possibilité est de rencontrer une image suivie d’un texte (CAT ILBMFTXT- FORM ILBM ). Dans ce cas, on doit ignorer le FORM ILBM en se positionnant à sa fin. Le déplacement est calculé avec la taille inscrite après FORM et effectué en utilisant l’offset.
Une autre difficulté tient dans l'obligation d’envoyer un nombre pair de caractères. Si vous désirez mettre 3 caractères dans le clipboard, il vous faudra ajouter un octet nul en tant que pad-byte. Par contre, la taille indiquée après CHRS ne doit pas tenir compte de cet octet tandis que la taille de la FORM doit en tenir compte.
Voilà, vous pouvez considérer ce programme comme une introduction à la programmation du clipboard.device. Les opérations Copier et Coller sont présentes. Elles sont très rustiques mais cela vous permettra de mieux comprendre leur fonctionnement. Cet exemple permettra peut-être à devoir le jour. A bientôt.
IQBC3B BBBB
-
init ! Initialisation du menu et ouverture du clipboard.device ONMENU GOSUB evenemenu
DO
SLEEP
LOOP
PROCEDURE init
DIM titre$ ( 100) ! Tableau des titres de menu
i%=0
DO
*
READ titre$ (i%)
EXIT IF titre$ (i%)="*" INCi%
LOOP
titre$ (i%)=",,
OPENW 0,0,11,640,199,&H8,&H1007 ! Ouverture de la fenêtre
i*
MENU titre$ ()
MENU KEY 1,ASC("0") ! Raccourds clavier
MENU KEY 4,ASC("C")
MENU KEY 5,ASC("P")
cmd_invalid&=0 ! Commandes d'entrée sortie standards cmd_reset&=l
cmd_read&=2
cmd_write&=3
cmd_update&=4
cmd_clear&=5
cmd_stop&=6
cmd_start&=7
cmd_flush&=8
cmd_nonstd&=9
cbd_post8f=cmd_nonstd&+0 ! Commandes spédales du clipboard
cbd_currentreadid&=cmd_nonstd&+1
cbd_currentwriteid&=cmd_nonstd&+2
header$ ="FORMXXXXFTXTCHRSXXXX''+CHR$ (0) ! En-tête de formatIFF-FTXT header%=V:header$
head%=MALLOC(20,&H10001) ! Header lu dans un paste IF head%=0
END
ENDIF
nul$ =CHR$ (0) ! Pad-byte
nul%=V:nul$
nt_messagel=5 ! Type message clipsize%=52 ! Taille de la structure IOClipReq clipname$ ="clipboard.device" +CHR$ (0) clipname%=V:clipname$
clipport%=CreatePort(0,0) ! Initialisation du clipboard.device
clipio%=@createextio2(clipport%,clipsize%)
erTor%=OpenDevice(clipname%,unit%,clipio%,0) IF error%
- DeletePort(clipport%)
@deleteextio(clipio%)
ENDIF
' Données de menu
DATA Projet,Quitter ,
DATA Edition,Couper ,Copier ,
DATA*
RETURN
PROCEDURE cleanit
~CloseDevice clipio%)
IF clipport% ~DeletePort(clipport%)
ENDIF
IF clipio%
@deleteextio(clipio%)
ENDIF
Ifhead%
- MFREE(head%,20)
ENDIF
IF tampon%
~MFREE(tampon%,tailletampon%)
ENDIF
CLOSEW 0
RETURN
' Gestion des appels au menu
PROCEDURE evenemenu SELECT MENU(0)
CASE 1 ! Quitter cleanit
END
CASE 4 ! Couper (Copy)
PRINT "Entrez le texte à placer dans le clipboard : "
INPUT "",montexte$
PRINT"
montexte$ =montexte$ +CHR$ (0)
montexte%=V:montexte$
couper(montexte%,LEN(montexte$ )-1 )
CASE 51 Coller (Paste)
IF tampon%
~MFREE(tampon%,tailletampon%)
ENDIF
coller
txt$ =CHAR(tampon%)
PRINT txt$
ENDSELECT
• RETURN
' Interfaçage de la structure IOClipReq en GFABasic
I G *3 I
PROCEDURE clipstrud(clipreq%)
ABSOLUTE ln_typel,cüpreq%+8 ABSOLUTE ln_pril,clipreq%+9 ABSOLUTE ln_name%,clipreq%+10 ABSOLUTE mn_replyport%,tclipreq%+14 ABSOLUTE mn_length&,clipreq%+18 ABSOLUTE io_device%,clipreq%+20 ABSOLUTE io_unit%,clipreq%+24 ABSOLUTE io_command&,clipreq%+28 ABSOLUTE io_flagsl,clipreq%+30 ABSOLUTE io_errorl,clipreq%+31 ABSOLUTE io_actucd%,clipreq%+32 ABSOLUTE io_length%,clipreq%+36 ABSOLUTE io_data%,clipreq%+40 ABSOLUTE io_offset%,clipreq%+44 ABSOLUTE io_clipid%,clipreq%+48 RETURN
PROCEDURE couperftexte%,taille%) clipstrucKclipio%) io_clipid%=0 io_offeet%=0
ctaüle%=tcrille%+12 ! Dcrille% : taille des données envoyées 1F ODD(taille%) ! Compter le pad-byte si la taille est impaire INC daille%
ENDIF
LONG header%+4}=daille%
LONG i header%+16)=taille%
io_command&=cmd_write&
io_data%=header%
io_length%=20
~DoIO(clipio%)
io_command&=cmd_write&
io_data%=texte%
io_length%=taille%
~DoIO(clipio%)
IF ODD(taille%) ! Ajouter le pad-byte ? Io_command&=cmd_write& io_data%=nul% io_length%-l ~DoIO(clipio%)
ENDIF
io_command&=cmd_update& ! Finir l'envoi au clipboard ~DoIO(clipio%)
RETURN
PROCEDURE coller clipstrud(clipio%)
io_command&=cmd_read& ! Lire le header
io_clipid%=0
io_offset%=0
io_data%=head%
io_length%=20
~DoIO(clipio%)
taüle%=LONG(head%+41
daille%=LONGlhead%+16)
IF taille%=0
ALERT 0,"Pas de texte !'',0,',Ok",a% cleanit END ENDIF
tampon%=MALLOC(taille%,&H10001) ! Allouer la mémoire du tampon de texte IF tampon%=0
ALERT 0,"Le tampon de texte est vide !'',0,"Ok'',a% cleanit END ENDIF
tailletampon%=taille% io_data%=tampon% ! Lire le tampon io_length%=taille%
~DoIO(clipio%)
ADD io_offset%,daille% ! La lecture après la fin des données a pour
io_length%=l ! Effet de refermer le clipboard.
Io_data%=0
~DoIO(clipio%)
RETURN
' Fonctions de remplacement pour CreateExtIO et DeleteExtIO FUNCTION createextio2(port%,size%)
IF port%=0 RETURN0 ENDIF
ioreq%=MALLOC(size%,&H10001)
IF ioreq%=0 RETURN 0 ENDIF
BYTE(ioreq%+8)=nt_messagel WORD(ioreq+ 18j=size%
LONGIioreq%+14}=port%
RETURN ioreq%
ENDFUNC
PROCEDURE deleteextio(ioext%)
BYTEIioext%+8}=-l LONG(ioext%+141=-1 LONG(ioext%+201=-1 ~MFREE(ioext%,WORD(ioext%+181)
RETURN
!???? HHHB
INITIATION
Dans le précédent article, nous avons commencé à remplir notre disquette en créant les répertoires s, I, devs, c et system. Nous y avons placé les fichiers les plus importants qui sont leDisk-Validator et la Startup-Sequence ainsi que certaines commandes telles que SetMap, Copy et Assign. A titre d'exemple nous avons lancé l’AmigaBASIC à partir de la Startup-Sequence.
C’est ici que les chemins se séparent suivant l’usage que vous comptez avoir de cette disquette. Ce qui fait tout le charme de l’AmigaDOS, et aussi sa complexité, c’est qu’il ne vous faut a priori rien de plus. Examinez donc le cas du répertoire FONT S:, encore vide à l’heure où nous mettons sous presse. Si votre disquette est destinée à héberger un traitement de textes ou un programme de titrage, il y a de fortes chances pour que vous deviez le créer et le remplir, avec vos fontes favorites. En ce qui concerne un programme de musique, les chances sont moins grandes pour qu’il ait besoin de fontes pour fonctionner (mais on ne sait jamais ...). Ce qui est vrai pour les fontes est également vrai pour les bibliothèques de fonctions (répertoire LIBS:), les handlers (répertoire L:), les pilotes de périphériques (DEVS:). C’est ici que la méthode que je vous ai proposée pour créer une disquette boot montre ses limites.
Il existe pourtant une deuxième manière de créer une disquette de boot, beaucoup moins fine mais sûrement plus rapide et très connue. C’est celle qui consiste à copier une disquette Workbenchet ensuite à la débarrasser de tout ce qui ne sert pas jusqu’à ce qu’on ait libéré assez de place pour qu’on puisse mettre les programmes que l’on veut. En général passent à la casserole tous les drivers d’imprimantes sauf celui que vous utiliserez, les fichiers keymaps autres que le f et beaucoup de commandes du répertoire C:. Vous allez donc me demander pourquoi je vous ai expliqué une manière de créer une disquette Boot alors qu’il en existe une autre plus rapide. Je vous répondrai que la deuxième méthode ne vous apprendra jamais à bien utiliser l’AmigaDOS, et c’est le sujet de cet article. Savoir quoi enlever ne vous dit pas à quoi servent les fichiers qui doivent rester. Je pense que le fait de taper quelques lettres sous clavier américain vous a fait comprendre à quoi servait la commande SetMap plus vite que si on vous avait dit de ne pas enlever cette commande de ia disquette Workbench. Continuons donc.
A chaque fois que vous avez utilisé notre disquette Boot, !'écran est apparu en 60 colonnes et non pas en 80 colonnes comme avec un Workbench normal. Ceci vient du fait que nous n’avons pas de fichier DEVS:system- configuration sur notre disquette. Celui-ci est créé par le programme Preferences que nous ne possédons pas non plus. Il nous faut donc placer ce fichier dans le répertoire DEVS:. La solution la plus courte consiste à copier le fichier system-configuration d’une disquette Workbench standard. Une autre solution envisageable est de booter sur notre disquette, puis de lancer Preferences à partir d'une autre disquette, de choisir ses options (notamment l’imprimante et l’écran en 80 colonnes) et enfin créer le fichier system-configuration en cliquant sur Save. La taille de ce fichier n’est pas très importante, c’est pourquoi on peut se permettre d’en avoir un exemplaire sur chacune de ses disquettes.
Maintenant que vous allez remplir votre disquette, il faut que vous décidiez quels sont les fichiers que vous désirez avoir et ceux dont vous n’avez pas besoin. Je ne peux pas en décider à votre place mais je peux vous donner ce sujet.
LE REPERTOIRE C
Dans le répertoire C:, il est judicieux de toujours avoir les commandes Cd, Assign et soit Dir, soit List. Ces commandes vous permettront de naviguer entre les disquettes et d’appeler des programmes d'autres disquettes. Quant aux autres réputées indispensables, vous pouvez vous passer du plus grand nombre, simplement en sachant que souvent une commande peut en remplacer une autre. Voici une petite liste explicative :
Delete: elle peut être remplacée par Dir. En effet, en mode interactif avec Dir INTER, il existe une option DEL qui supprime les fichiers. Cette option est très rustique et n’offre pas tous les avantages de Delete, mais elle marche. Type : la commande Copy nom du fichier> TO *
fait la même chose que Type. On peut aussi faire Join nom du fichier> AS *
ou utiliser l'option t de la commande Dir INTER. Dans tous les cas on perd les options d'affichage en hexadécimal et la numérotation. Il ne faut pas oublier que l’on peut toujours visualiser un fichier avec Ed, Edit ou le programme More (pour ne citer qu’eux).
Copy : la commande Join remplace Copy de la façon suivante :
Join source> AS destination>
On peut aussi faire :
Type source> TO destination>
Avec Type un octet pourra être ajouté à la fin du nouveau fichier, celui-ci ne devrait pas être gênant.
Ed : Il est possible d’éditer un fichier avec la commande Copy en faisant : Copy * To nom du fichier>
et en tapant un CTRL>- à la fin de la saisie. Une autre méthode consiste à entrer les lignes une à une avec la commande Echo :
Echo > fichtest “Ceci est un fichier”
Echo » fichtest “Créé avec la commande Echo”
Echo » fichtest “et la double redirection” ou en utilisant Echo et Join :
Echo > Iig1 “Ceci est un fichier”
Echo > Iig3 “et avec Join"
Echo > Iig2 “créé avec Echo”
Join Iig1 Iig2 Iig3 AS monfich
Cette dernière méthode est utile si le fichier que vous voulez créer contient beaucoup de lignes qui se répètent. Mais si vous avez des fichiers à créer, le mieux est quand même de mettre un véritable éditeur de textes comme Ed sur votre disquette.
MakeDir : la commande Copy peut créer des répertoires (j’en avais parlé dans un autre article). Pour créer un répertoire vide vous pouvez toujours copier le répertoire Empty du Workbench si vous en avez un sur votre disquette.
Run : une variante originale à la commande Run qui est souvent utile consiste à lancer la commande d’un autre CLI que l’on aura créé avec NewCLI ou NewShell. On peut considérer comme un inconvénient le fait d’avoir deux fenêtres CLI à gérer à la fois. Dans ce cas, il faut savoir qu’une même fenêtre peut accepter plusieurs CLI qui alternent après chaque commande. La syntaxe pour les obtenir est :
NewCLI *
on peut évidemment utiliser NewShell à la place de NewCLI.
Cd : Cette commande est quasi-indispensable dans le sens où c’est la seule qui nous permette de changer de répertoire. Pour ce qui est de connaître le répertoire en cours, la commande Prompt, sous Shell permet de l’afficher :
Prompt “%S"
le prompt des Shell issus d’un Workbench standard affiche le chemin courant.
Nous avons donc examiné le cas des commandes les plus utilisées du répertoire C:. Vous voyez que même si votre manque de place est critique, vous pourrez dans la majeure partie des cas vous contenter de peu de commandes à condition que vous les choisissiez bien. Il en résultera un peu moins de confort d’utilisation, ce qui était prévisible. Nous allons maintenant examiner les fichiers dont vous aurez besoin pour utiliser telle ou telle partie de l’AmigaDOS, tout en donnant une nouvelle fois la preuve de sa modularité. Commençons donc par le Workbench.
Le Workbench se lance par la commande du répertoire C: qui se nomme LoadWB. Il vous faut donc la copier dans le répertoire c de votre disquette boot si vous en avez besoin. Si vous ne désirez pas conserver de CLI ouvert, il faudra utiliser la commande EndCLI. La commande LoadWB et la commande EndCLI peuvent être placées dans la Startup-Sequence, pour être lancées dès le démarrage. Il faut savoir qu’après EndCLI, vous n’aurez plus aucun moyen d’utiliser l’AmigaDOS, à moins que le Workbench soit présent et que vous disposiez d’une icône Shell ou CLI et au minimum du fichier CLI dans le tiroir System. D’où le proverbe : ”On a toujours besoin d’un plus petit CLI que soi chez soi”. Le mois prochain, nos occupations nous mèneront à l'installation du Workbench sur la disquette Monboot:.
[54j
IHBC3B BBBP
IMIGRI
1
APPLICATION
Les fichiers scripts occupent une place très importante dans l’AmigaDOS. A l’avenir, cette place va continuer à augmenter régulièrement. L’unité logique S: désigne l'endroit où sont placés les fichiers scripts du système. Lorsque vous en créez un, c’est toujours une bonne idée de le placer à cet endroit, surtout s'il a été conçu pour être utilisé par plus d'une seule personne ou sur plus d’une seule disquette. Un utilisateur averti (et vous en êtes un maintenant) aura toujours l’idée d'aller regarder dans S: si des fichiers scripts sont placés pour pouvoir les modifier à sa guise.
Les fichiers scripts sont de plusieurs types. Tout d’abord, ils servent pendant l’initialisation du système : Startup-Sequence, Startupll et autres. Ils servent aussi à l’installation d'un nouveau logiciel: Install, Install-HD, ou autres. Leur troisième utilisation est la configuration du système pour qu'ils reconnaissent un logiciel : Start-ARexx est un bon exemple. Ils peuvent avoir été générés automatiquement par la commande List- LFORMAT (voir les exemples dans les deux précédents numéros). Les autres sont le plus souvent des groupes de commandes destinés à vous faciliter une opération que vous devez souvent refaire, on peut citer la copie d'un répertoire, renommer un ensemble de fichiers, ou bien même des opérations plus compliquées faisant appel aux variables d’environnement (comme le fichier PCD de la disquette Workbenchj. Il nous reste deux fichiers particuliers qui sont Shell-Startup et CLI-Startup qui sont exécutés à chaque ouverture d’une fenêtre CLI ou Shell. On peut même créer des fichiers scripts qui effacent l’écran, proposent un jeu (devinez un nombre ...), ou fassent parler l’Amiga (vous alliez dire qu’il ne leur manquait plus que la parole).
Pour utiliser au maximum les possibilités des fichiers scripts, il faut connaître un certain nombre de commandes clefs. La première d'entre elles est la commande If. Cette commande permet entre autres de tester le code de retour des commandes précédentes (et énormément de commandes renvoient un code), de tester l’existence d’un fichier et aussi de tester les variables d’environnement. Voici un fichier script qui permet de vérifier si de la mémoire chip est en quantité suffisante (ici 100000) pour lancer un programme (MonProg) :
avait > ENV:mchip CnlP IF SmchipGT 100000VAL Run MonProg Else
Echo "Mémoire Chip insuffisante pour lancer MonProg"
Endil
On peut développer ce fichier script de manière à ce qu’il fonctionne quel que soit le programme demandé et pour une taille de mémoire définie par l’utilisateur. Nous faisons ici appel aux paramètres :
.KEY Programme A,TailleMem N A crvctil > ENVmchip CHIP 1F $ mchip GT TadlleMem> VAL Run Programme>
Else
Echo "Mémoire Chip insuffisante pour lancer Programme>"
Endlf
Il est également indispensable de savoir utiliser la commande Echo dans un fichier script. Quand je dis savoir utiliser Echo, je pense aux paramètres NOLINE, FIRST et LEN qui sont royalement ignorés de 99 % des utilisateurs . L’intérêt de l’option NOLINEest évident dans un fichier script :
Echo "Mémoire CHIP disponible : " NOLINE AvailCHIP
Les paramètres FIRST et LEN servent notamment avec les noms de fichiers et les paramètres des fichiers scripts. Voici une variante de notre fichier précédent qui lançait un programme si la mémoire chip était suffisante. Nous pouvons maintenant tester la chip, la fast ou la mémoire totale :
.KEY Programme A,TailleMem N A Echo > ENV:typemem TailleMem> FIRST 1 LEN 1 IF Stypemem EQ "C" avail > ENV:mem CHIP Else
If Stypemem EQ "F" avcril > ENV:mem FAST Else
If îtypemem EQ "T" avail > ENV:mem TOTAL Endif Endif Endif
Echo > ENV:memtaille TailleMem> FIRST 2 IF $ mem GT îmemtaiile VAL Run Progiamme>
Else
Echo "Mémoire insuffisante pour foncer Programme>"
Endif
Si ce fichier est appelé memrun et protégé avec l’option +s, on pourra essayer :
memrnn list T5C ~
Lancera la commande list si 5000 octets sont disponibles en mémoire
memrun list C12000
idem si on possède 12000 octets de mémoire chip.
Nous allons maintenant écrire une variante du fichier script Srenque nous allons améliorer en plusieurs étapes :
.KEY Source A,Destination A
.BRAI
.KET )
List > RAM:aze Source] LFORMAT "Rename %S%S as%S%S|Desünationr Exécuté ram:aze
Donnez à ce fichier le nom xren et protégez-le avec Protect xren+s. Si vous avez un répertoire contenant les fichiers t1 ,t2,t3 et t4, la commande : xren t? .old
les renommera tl.old, t2.old, t3.old et t4.old. Jusqu’ici rien de mieux que sren. Ce qu’il nous faudrait, c’est une commande :
xren t? D?
Qui renomme les fichiers en d1, d2, d3 et d4. Chose que ne fait pas sren. On peut y arriver très facilement avec Edit. Edit est l’éditeur que tout le monde déteste, dont personne ne sait se servir mais qui a des possibilités extraordinaires pour qui se donne la peine de l’utiliser. Il a notamment la possibilité d’effectuer ses commandes à partir d’un fichier, ce qui est très utile pour bidouiller les fichiers créés avec la commande LFORMAT:
.KEY Source A,Destination A
.BRAI
.KET]
List > RAMraze (Source) ? LFORMAT "Rename %S%S as %S%S"
Echo > T:ed-temp ”GE la s Isource) as Idestination)"
Echo » T:ed-temp ”Q"
Edit RAM:aze WTTH T:ed-temp VER NIL:
Exécuté ramraze
La commande GE de Edit s’intitule Global Exchange. Nous nous contentons en fait, de remplacer les caractères spécifiés dans source par les caractères spécifiés dans destination. Ce fichier est loin d’être parfait mais il offre une bonne alternative à sren (il ne fait pas la même chose en fait). J’espère qu’il vous sera utile.
Une fonction que tous les programmeurs connaissent bien est la fonction CASE. Suivant les langages on l’appelle aussi switch ou encore SELECT. Il s’agit du test à choix multiples dont l’ancêtre est le ON...GOSUB du Basic. Il est possible de simuler ceci avec les commandes If et Skip :
Lab Début
Echo "1: Commande List"
Echo "2: Commande Info”
Echo "3: Commande Status"
Lab Saisie
Echo "Entrez votre choix : " NOLINE SetEnv > ML: choix ?
If Schoix EQ 1 Skip Choixl Endif
IF Schoix EQ 2 SkipChoix2 Endif
If Schoix EQ 3 SkipChoix3 Endif
Skip ChoixAutre Lab Reprise
Ask "Une autre commande (Y=Oui N=Non) ?"
IfWARN Skip BACK Saisie Else
Echo "Au revoir"
Endif
Quit
Lab Choixl Echo "Choix numéro I"
List
Skip BACK Reprise LabChoix2 Echo "Choix numéro D"
Info
Skip BACK Reprise Lab Choix3 Echo "Choix numéro III"
Status
Lab ChoixAutre Echo “le ne sais compter que jusqu’à trois !"
Skip BACK Début
Ce genre de fichier peut être très utile si des débutants en AmigaDOS veulent utiliser votre machine. Cela permet de limiter la casse au maximum et de les aider un peu le temps qu’ils se familiarisent un peu plus avec le CLI.
(TOUJOURS AUSSI) FACILE
Chers lecteurs et lectrices, Bonjour I! Comme promis le mois dernier, nous allons continuer notre exploration de l'univers 3D, avec à la clef ce mois-ci un petit programme qui vous permettra d’afficher un objet à l’écran suivant un angle de vision de votre choix et à l’aide d’une projection simple.
Nous verrons comment ouvrir un écran et tracer droites et points sur cet écran. Comment écrire un fichier de points et de droites représentant un objet et pouvoir le relire ensuite. La projection dimé- trique qui nous servira pour l’affichage de notre objet sur l’écran sera décrite avec d'autres projections le mois prochain. Je vous fournis néanmoins la fonction qui transforme notre objet 3D en objet écran afin d’avoir un programme complet pour ce mois-ci.
Bien commençons donc sans plus attendre.
OUVERTURE DES BIBLIOTHEQUES “INTUITION” ET “GRAPHICS”
Pour créer un écran, nous allons nous servir de la bibliothèque "Intuition”. De même pour tracer les droites et afficher les points, nous aurons recours au module "Graphics”. Mais pour utiliser ces différentes fonctions il faut d’abord ouvrir ces 2 bibliothèques. On utilise pour ce faire, la fonction OpenLibraryO. On passe à cette fonction deux paramètres : le nom de la bibliothèque (char*) et le numéro de version (long). Elle renvoie un pointeur sur une structure associée à la bibliothèque que l’on veut ouvrir.
On aura à définir le numéro de version (0L) et à déclarer les pointeurs de structures en global, soit :
define INTUITIONJ3EV 0L
defineGFX_REV0L
et
struct IntuitionBase ‘IntuitionBase = NULL ; ‘pointeur surintuition*
struct GfxBase ‘GfxBase = NULL ; 'pointeur sur Graphics*
A partir de là, on peut écrire une fonction initO qui ouvrira les deux bibliothèques à l’aide d’OpenLibraryO void initO I
IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library'',INTUriION_REV); if (IntuitionBase == NULL)
I
printf("je ne trouve plus Intuition, où est-il ? n"); exit(FALSE);
1
GfxBase = (struct GfxBase *)OpenLibraiy("graphics.library",GFX. REV); if (GfxBase == NULL)
1
printff Mais où est donc passé le module graphies ? n"); exit(FALSE);
)
OUVERTURE DE L’ECRAN
Maintenant que les bibliothèques sont ouvertes, nous allons pouvoir créer un écran. La création d’un écran s’effectue simplement en deux étapes.
Primo : on initialise une structure NewScreen qui va définir les caractéristiques de notre écran.
Secundo: on appelle la fonction OpenScreen (NewScreen) qui renvoie un pointeur sur la structure Screen représentant l’écran qui a été ouvert.
Nous allons regarder quelles informations il nous faut communiquer à la structure NewScreen.
D’abord la position du coin haut et gauche de l’écran (LeftEdge TopEdge). Il est vivement recommandé d’initialiser LeftEdge à 0. Ensuite la largeur (320,640) et la hauteur de l’écran (200,256,400,512) (Width.Height). Il faudra faire attention à positionner les valeurs nécessaires dans le champ ViewModes pour certaines résolutions (voir ci-dessous).
Le nombre de plans graphiques (Depth) donne le nombre de couleurs utilisables simultanément (1=2 couleurs, 2=4 couleurs, 3=8 couleurs, 4=16 couleurs et 5=32 couleurs).
Les champs DetailPen et BlockPen représentent respectivement la couleur du texte de la barre de menu et du fond de cette barre.
ViewMode représente le type d’écran si on le met à NULL on a un écran basse résolution. Si on met HIRES on a un écran haute résolution et avec INTERLACED on passe en mode entrelacé (HIRES + INTERLACED = 640 x 400 ou 640 x 512 en PAL).
Le type d’écran vaut CUSTOMSCREEN dans le cas qui nous intéresse.
Le champ Font pointe sur la police de caractère utilisée. S’il vaut NULL on a par défaut la police TOPAZ.
Le champ DefaultTitle contient le titre de l’écran qui apparaît dans la barre de menu.
Le champ Gadgets contient la liste des gadgets “système” liés à l’écran (passage arrière avant, barre de déplacement, etc.).
Enfin le champ CustomBitmap pointe sur une structure “Bitmap” spéciale créé par le programmeur.
Dans notre petit programme nous allons créer un écran basse résolution 320x200, avec 32 couleurs. La barre de menu non apparente (couleur = 0) sans titre et sans gadgets, bref tout ce qu’il y a de plus simple.
Après avoir initialisé cette structure il suffit d’appeler la fonction OpenScreen (& NewScreen).
On déclare en global un pointeur sur une structure Screen qui va nous servir à récupérer le résultat de OpenScreenO. Struct Screen ‘écran = NULL;
On déclare de la même façon OpenScreenO pour éviter quelques grognements du compilateur, struct Screen * OpenScreenO; et c’est fini !
On écrit notre fonction ouvrecranO très facilement. La voici, void ouvrecranO
struct NewScreen nouvecran ; nouvecran.LeftEdge = 0; nouvecran.TopEdge = 0; nouvecran.Width = 320; nouvecran.Height = 200; nouvecran.Depth = 5; nouvecran.DetailPen = 0; nouvecran.BlockPen = 0; nouvecran.ViewModes = NULL; nouvecran.Type = CUSTOMSCREEN; nouvecran.Font = NULL;
nouvecran.DefaultTiltle = NULL; nouvecran.Gadgets = NULL; nouvecran.CustomBitMap = NULL;
écran = OpenScreen(fknouvecran); if(ecran == NULL)
(
printfC Lecran ne veut pas apparaitre n"); exit(FALSE);
)
rp = &(ecran->RastPort);
La dernière ligne du programme nécessite une petite explication ; rp est un pointeur sur le RastPort de l’écran. Ce pointeur est nécessaire pour effectuer toutes les opérations de traçage.
On déclare donc en global ce pointeur struct RastPort ‘rp;
et comme indiqué dans la fonction ouvrecranO on récupère l’adresse de l’écran : rp=&(ecran->RastPort);.
LE CHARGEMENT DES POINTS ET LIGNES
Bien, maintenant voyons comment créer un fichier (ou plutôt deux) pour représenter un objet. Dans un esprit de simplification et de réduction du source, j’ai décidé de représenter un objet sous forme de deux fichiers textes, 1 pour les points, 1 pour les lignes.
Ces fichiers sont organisés comme suit :
Pour le fichier “point.dat” en coordonnées homogènes lre ligne; nombre de points ex : 5 2e ligne: coordonnée en X ex : 10.0 3e ligne: coordonnée en Y ex : 10.0 P 1( 10.0,10.0,10.0,1.0)
4e ligne: coordonnée en Z ex : 10.0 5e ligne: coordonnée en W ex: 1.0 idem pour les quatre autres points.
Pour le fichier on indique les numéros des points extrémités et origines L0(premier point P0, extrémité P3)
lre ligne: nombre de lignes ex : 8
2e ligne: origine de L0 0 L0(P0,P3)
3e ligne: extrémité de L0 3
idem pour les sept autres lignes.
Maintenant que nous avons défini la représentation de nos fichiers, il est très simple d’écrire une fonction permettant de lire ces fichiers. Je vous propose ci-après deux fonctions charge points et charge lignes qui permettent de lire les fichiers point.dat et ligne.dat et, à partir des données lues, d’inltialiser les tableaux de points et de droites. La méthode est bien simple. On ouvre le fichier, on lit la première ligne qui représente le nombre de points (ou lignes) à lire et ensuite on a deux boucles “for” imbriquées qui initialisent les tableaux.
On déclarera en global les tableaux de lignes et de points en coordonnées homogènes 3D comme expliqué le mois dernier double pointH3D[100][4]; *cent points*
SHORT ‘ligneEj 10012]; * 100 lignes*
tant qu’on y est on déclare le tableau de point écran.
SHORT PointEj 10012];
Ainsi que deux entrées int nbrligne, nbrpoint qui recevront respectivement le nombre de lignes et de points de l’objet.
A partir de là on écrit nos deux fonctions.
Bon je suis gentil ! Voici le code source II
void chargepointsQ
FILE *fich,*fopen(); int i,j;
char tab[ 100];
fich = fopenfpoint.dat","r");
ifffich == NULL)

puts("problème d'ouverture du fichier point.dat n"); exit(FALSE);
)
else
(
fgets(tab, 100, fich); nbrpoint = atoi(tab);
puts("Chargement de la structure POINT en cours ... n"); for(i=0;i nbrpoint;i++)
I
for(]=0;j 4;j++)
(
fgetsftcrb, 100, fich); pointH3D[i][j] = atof(tab);
1
fclose(fich);
void chargelignesO
FILE *fich,*fopen(); int i,j;
char tab[100];
fich = fopen("ligne.dat","r");
ifffich == NULL)
I
putsC'problème d'ouverture du fichier ligne.dat n"); exit(FALSE);
)
else
I
fgets(tab, 100,fich); nbrligne = atoi(tab);
putsC'Chargement de la structure LIGNE en cours ... n"); for(i=0;i nbrligne;i++)
I
for(j=0;j 2;j++)
I
fgets(tab, 100,fich); ligneEjilj] = &pointE[atoi(tab)][0];
fcloseffich);
LA TRANSFORMATION DE L’OBJET POUR AFFICHAGE
Voici maintenant la fonction transformeO qui permet de transformer notre objet 3D en objet écran à l’aide d’une projection dimétrique. Par manque de place cette fonction sera décrite le mois prochain. En attendant voici le source en C.
void transformeO
int i;
for(i=0;i nbrpoint;i++)
IHBC3B OE3HD
IhigrM
(
pointE[i][l] = 150 -(int)(pointH3D[i][0]*sin(teta)*cos(alpha)+ pointH3D[i][l]*sin(teta)*sin(alpha)+pointH3D[i][2]‘cos(teta));
pointE[i][0] = 300 - (int)(-pointH3D[i][0]*sin(alpha)+ pointH3D[i][ 1 ]*cos(alpha));
)
1
Maintenant que nous avons la projection dimétrique qui nous permet de transformer nos points 3D en points écran, il nous reste à voir comment afficher notre objet en coordonnées écran.
Les deux instructions qui vont nous permettre de tracer à l’écran les lignes représentant le contenu de l’objet sont Move et Draw.
La fonction MoveO positionne le RastPort (que l’on peut assimiler à la pointe d’un crayon) aux coordonnées XE, YE spécifiées en paramètres.
Move(struct RastPort*, short, short);
Ainsi dans notre programme, si l’on considère la ligne Li[P0,P1] pour se positionner sur le point origine de la ligne on tapera Move(rp,ligneE[i] [0] [0],ligne E[i] [0] [i]);
La fonction DrawO trace une droite de la position courante du RastPort jusqu’aux coordonnées XE2, YE2 spécifiées en paramètres.
Drcrw(struct RastPort*,short,short):
Si l’on reprend notre ligne Li[P0,P1] on tracera le segment de droite en tapant
Draw(ip,ligneE[i] [1] [0],ligneE[i] [1] [1]);
A partir de là, la fonction affiche(short) qui affiche l’objet est très simple : la voici
void affiche(couleur)
SHORT couleur;
(
inti;
SetApen(rp,couleur); for(i=0;i nbrligne;i++)
I
Move(rp,ligneE[i] [0] [0],ligneE[i] [0] [1]);
Draw(rp,ligneE[i] [1] [0],ligneE[i] [1] [1]);
Le paramètre couleur est utilisé par la fonction SetApen(struct RastPort *, short) qui détermine quel registre de couleur sera utilisé par le RastPort pour le tracé (couleur du crayon).
LE RESTE
Que reste-t-il à faire désormais ?
Et bien plus grand chose à vrai dire.
1 - Déclarer quelques "include” utiles
En voici la liste
include stdio.h> * fonctions d'entrées sorties standard* include math.h> * fonctions mathématiques de base * include intuition intuition.h> * include pour Intuition * include intuition intuitionbase.h> * Base pour intuition 7 ffinclude exec types.h>
2 - Ecrire un programme principal dont l’utilité est d’appeler dans un ordre logique les différentes fonctions que l’on a décrites précédemment
On déclarera en global les deux angles teta et alpha de la projection.
Double alpha = 0, teta = 0; mcrinO
char ‘test = CIAAPRA ; char tab[ 100];
void chargepointsO, chargelignesO, initQ, ouvrecran(),referme();
chargepointsQ;
chargelignesO;
printfC'Valeur de teta: "); * entrer la valeur en radians *
gets(tab);
teta = atof(tab);
printfC'Valeur de alpha: ''); * entrer la valeur en radians *
gets(tab);
alpha = atof(tab);
init();
ouvrecranO; transformeO; affiche(l); * couleur 17
while(!(*test & 0x40)-64)); * test du bouton de la souris * refermeO;
NB: CIAAPRA est défini comme : define CIAAPRA 0xbfe001
Il s’agit de l’adresse physique d’un registre machine : le Port A du CIA A.
C’est barbare, mais c’est très court II
3 Enfin avant de terminer le programme on aura pris soin de refermer l’écran et les bibliothèques.
Voici la fonction qui fait cela
void refermeO I
CloseScreen(ecran);
CloseLibrary(IntuitionBase);
CloseLibrary(GfxBase);
Eh bien c’est fini il ne vous reste plus qu’à taper ce petit programme et à créer un objet de votre choix sous forme de fichiers.
CONCLUSION
Comme il ne me reste que très peu de place je me contenterai de vous souhaiter une excellente lecture en vous retrouvant dans un mois pour la description des différentes projections possibles et autres transformations amusantes.
Herr Doktor Von GlutenStimmellimDorf
LES LIBRAIRIES MATHEMATIQUES
APPLICATION
Sans doute savez-vous que les nombres peuvent être stockés et manipulés sous différentes formes par l'ordinateur, La forme courante (integer = entier) concerne les nombres entiers uniquement ; elle permet un traitement rapide et nécessite 4 octets (un mot long). L’autre forme (float = flottant) concerne tout type de nombre ; elle permet un traitement presque aussi rapide et nécessite également 4 octets (merci ô dieu Commodore...). De quoi s’agite-t- il ? Dans un premier temps, des libraries”mathffp.library” et “mathtrans. Libra- ry”. Dans ce qui suit, nous considérerons qu’elles sont déjà ouvertes (voir plus loin l’ouverture).
Passons en revue ses différentes routines précisées par leurs offsets (hexa puis décimal) et les paramètres entre parenthèses : Transformations et tests divers :
- $ 1E -30 SPFix(D0) : permet de convertir le nombre flt(flottant ) contenu dans D0 en nombre entier contenu dans D0. Sice nombre est décimal, seule sa valeur absolue sera gardée. Le registre D1 est aussi modifié.
- $ 24 -36 SPFlt(D0) : permet de convertir l’entier contenu dans D0 en nombre fit contenu dans D0. Le registre D1 est aussi modifié.
- $ 2A -42 SPCmp(Dl,D0) : permet de comparer 2 nombres fit, Les flags sont fixés d’après le résultat de l’opération D0- D1 soit : Z si D0=D1 ; NC si D0>D1 ; C si D0 D1. Le registre D0 est modifié dans tous les cas.
- $ 30 -48 SPTst(Dl) : permet de tester le signe de D1. Le flag Nest mis si D1 0 . Les registres D0 et D1 sont modifiés.
- $ 36 -54 SPAbs(D0) : remplace le contenu de D0 par sa valeur absolue.
- $ 3C -60 SPNeg(D0) : remplace le contenu de D0 par son opposé. Les opérations courantes:
Le résultat est toujours mis dans D0. Les autres registres ne sont pas modifiés.
- $ 42 -66 SPAdd(Dl,D0):calculeD0 + D1
- $ 48 -72 SPSub(Dl,D0): calcule D0-D1
- $ 4E -78 SPMul(Dl,D0): calcule D0xDl
- $ 54 -84 SPDiv(Dl,D0) : divise D0 par Dl.
Attention au GURU si D 1=0 !
ATTENTION : Dans toutes les routines, les registres D0 et D1 contenant des nombres fit doivent être manipulés comme des mots longs (4 octets).
Exemple : calcul de: 30,1 x 15,28
spfix = -30 spflt = -36 spmul = -78 spdiv = -84 début:
move.l 4,a6;exec base
move.l ffpname,al;nom de la lib. à ouvrir
moveq 0,d0
jsr -408(a6);OpenLib = ouverture de la librairie beq tin; si ouverture ratée... move.l d0,ffpbase
move.l Ifpbase,a6;adresse de base de la librairie move.l 100,d0
jsr spflt(a6); conversion en fit dans D0 move.l d0,d2; mis de côté move.l 3010,d0
jsr spflt(a6); conversion en fit dans D0 move.l d2,dl; récupère 100 en lit dans Dl jsr spdiv(a6); calcule 3010 100 soit 30,10 en fit dans D0 move.l d0,d3; mis de côté
move.l 1528,d0 jsr spflt(a6)
move.l d2,dl;récupère 100 en fit dans Dl
jsr spdiv(a6);calcule 1528 100 soit 15,28 en fit dans D0
move.l d3,dl;récupère 30,1 en fit
jsr spmul(a6);calcule 30,1 x 15,28 soft 459,928 en fit dans D0
jsr spfix(a6);pour voir le résultat (en mode trace)
fin:
move.l ffpbase.al move.l 4,a6
jsr -414(a6);CloseLib = fermeture de la librairie
rts
even
ffpbase: dc.l 0
ffpname: dc.b "mathffp.library",0
Le résultat peut être ensuite exploité sous sa forme fit ou converti en entier par : jsr spfix(a6), qui donnera D0=459 car seule la partie entière est conservée. Notez que si vous tracez cette routine, votre traceur visualisant très probablement le contenu des registres en hexadécimal, vous verrez que D0 contient 1CB (= 459 en décimal).
Ouf ! Vous suivez toujours ? Passons alors à des calculs plus complexes :
MATHTRANS.LIBRARY
Elle contient les routines de calculs trigonométriques (circulaires et hyperboliques). Le principe reste le même : le résultat est mis dans le registre DO qui est donc toujours modifié; le registre D1 est aussi modifié. Tous les angles sont en radians: pi radians => 180°.
- $ 1E -30 SPAtan(D0) : arc-tangente
- $ 24 -36 SPSm(D0): sinus
- $ 2A -42 SPCos(D0) : cosinus
- $ 30 -48 SPTan(D0) : tangente
- $ 36 -54 SPSincos(dl,d0):sin(D0)efcos(D0)
- $ 3C -60 SPSinh(D0) : sinus hyperbolique
- $ 42 -66 SPCosh(D0) : cosinus hyperbolique
- $ 48 -72 SPTanh(D0j : tangente hyperbolique
- $ 4E -78 SPExp(D0) : e exposant D0 avec e=2.718...
- $ 54 -84 SPLog(D0) : logarithme népérien de D0 ( log à base e )
- $ 5A -90 SPPow(Dl,D0):D0 exposant Dl
- $ 60 -96 SPSqrt(D0) : racine carrée de D0
- $ 66 -102 SPTieee(D0) : met un nombre fit au format double précision
- $ 6C -108 SPFieee(D0): met un nombre double précision auformat fit
- $ 72 -114 SPAsin(D0) : arc-sinus
- $ 78 -120 SPAcos(D0) : arc-cosinus
- $ 7E -126 SPLogl0(D0) : logarithme à base 10 de D0
REM: Pour la routine SPSinCos, DO doit être chargé avec l’angle en radians et D1 doit pointer sur un tampon de 4 octets dans lequel la routine rangera la valeur du cosinus ainsi calculée. DO contiendra la valeur du sinus.
Well ! Après cette liste fastidieuse à taper pour moi et à lire pour vous je vous laisse le temps de digérer ces informations. Le mois prochain : applications aux tracés de courbes polaires sous intuition et animations de sprites sous IRQ ( c’est chooooli ! ).
Un dernier mot: les petits fûtés que vous êtes auront bien sûr compris que le répertoire LIBS: de la disquette ou du disque dur à partir duquel vous avez lancé le système DOIT contenir les dites librairies mathématiques.
D. GENOT
NDLR : Cet article aborde un sujet peu souvent étudié sur l'Amiga, ce qui est dommage car il y a là matière à avoir les moyens de faire des animations magnifiques et de plus en lemps réel. Aussi, si ce sujet vous intéresse, n’hésitez pas : écrivez à votre Commodore Revue préférée pour nous en faire part.
APPRENEZ-LUI LE CANIVEAU!!!
Laissons tomber - provisoirement - ia graphics.library et permettez-moi une petite parenthèse pour aborder un problème qui, apparemment, vous tient à cœur : programmer “proprement”.
Ça veut dire quoi, “proprement”? Tout simplement ceci : respectez sinon les gugusses qui se sont emm... pendant des années pour pondre un ordinateur fabuleux (n’ayons pas peur des mots), au moins cet ordinateur lui-même. En d'autres termes, évitez la programmation sauvage qui consiste à implanter son programme en mémoire, sans soucis de ce qui peut déjà s'y trouver. N'oubliez pas que l'Amiga est une machine multi-tâches, ce qui implique que l’on se conforme à quelques régies, succintes certes, mais indispensables.
Premièrement, et sans doute le plus important, ne logez jamais vos programmes à une adresse absolue ! Finis les ORG préhistoriques de l’antédiluvien K-Seka. De nos jours, un programme est chargé n’importe où en mémoire, selon la place disponible. Si vous forcez une adresse de chargement, rien ne dit que vous n’irez pas écraser une tâche ou des données importantes !
Et que ceux qui prétendent que c’est le seul moyen d’avoir des données en Chip-Ram me laissent me marrer deux minutes,.. Au moins deux moyens permettent d’y parvenir. Le premier, plutôt soft et pro, consiste à réserver la mémoire grâce à la fonction AllocMem(), à charger les données adéquates depuis le disque, et à restituer cette mémoire avec FreeMemO lors de la sortie du programme. Le second, plus facile à mettre en œuvre, consiste à forcer l’assemblage du programme et ou des données en Chip-Ram. Devpac II connaît les pseudo-directives SECTION CODEJ3, SECTION DATA_C et section BSS_C, tandis que K-Seka admet, tout du moins dans sa dernière version, une option d’assemblage appropriée.
Deuxièmement, et à partir de maintenant, je m’adresserai plus particulièrement aux programmeurs de démos en tous genres, lorsque l’on détourne un vecteur quelconque, il convient de le remettre en place. Dans le même ordre d’idée, tous les registres hardware importants, au même titre que les toilettes, doivent être laissés dans l’état où on les a trouvés en entrant. Ils ne sont pourtant pas nombreux : DMACON et INTENA, Quant au Copper, il est réinitialisé tous les 1 50e de seconde par le système (registre COPxLCH et COPxLCL), on peut donc, à la rigueur, ne pas s’en occuper.
Troisièmement, les interruptions. Ben oui, il arrive souvent, pour ne pas dire tout le temps, que l’on ai besoin de s’installer une routine d’interruption propre (n’est-pas, m’sieur SoundTracker ?). Le moyen le plus couramment utilisé est le suivant : on place en $ 6c l’adresse de notre propre routine, et le tour est joué. Ben oui, mais non: si on ne rétablit pas ce vecteur en quittant, l’Amiga se trouvera fort embêté lorsque la bise sera venue...
Quatrièmement, le multi-tâches. Là encore, on s’en passe quasiment tout le temps. Il existe plusieurs manières de le désactiver, depuis l’appel à Forbid() - suivi de l’inévitable PemnitQ - au passage en mode superviseur - par SuperState, trap x, etc.
Tout ça pour introduire les deux routines suivantes, baptisées, de manière fort judicieuse d’ailleurs, Sauve et Restaure. Un simple appel à ces routines respectivement en début et fin de votre propre programme, résoudra tous les problèmes évoqués plus haut. On en reparle tout de suite après lesdites routines.
Sauve: move.l $ 6c.w,01dIRQ ; Sauve le vecteur IRQ
lea $ dff000,a5 ; CustomBase dans a5
move.w $ 002(a5),OldDMA ; Sauve DMACON
move.w $ 01c(a5),OldINT ; Sauve INTENA
move.w $ 7fff,$ 096(a5) ; "Vide" DMACON
move.w
$ 7fff,$ 09c(a5)
; "Vide" INTENA
move.l
$ 4.w,a6
; ExecBase dans a6
jsr
- 150(a6)
; Appel de SuperStateO
Restaure:
move.l
rts
d0, SysStack
; Sauve USP
move.l
£
Ü
CD
'o
QH
a
o
; Remet le vecteur IRQ
lea
$ dff00,a5
; CustomBase dans a5
move.w
OldDMA(pc),d0
; Ancien DMACON dans d0
or.w
$ 8000, d0
; Bit 15 mis à 1
move.w
d0,$ 096(a5)
; Le rétablit
move.w
OldINT(pc),d0
; Ancien INTENA dans d0
or.w
$ 8000,d0
; Bit 15 mis à 1
move.w
d0,$ 09a(a5)
; Le rétablit
move.l
$ 4.w,a6
; ExecBase dans a6
move.l
SysStack(pc),d0
; USP dans d0
jsr
rts
- 156(a6)
; Appel de UserStateO
OldIRQ :
dc. l
0
OldDMA :
dc. w
0
OldINT :
dc. w
0
SysStack :
dc. w
0
Voyons d’abord Sauve : comme expliqué en long, en large, en travers et plus haut, cette routine sauvegarde quelque part en mémoire les valeurs des registres hardware les plus importants pour le système. Premièrement, le vecteur IRQ (vecteur d’interruption de niveau 3, celle exécutée à chaque VBL) que l’on trouve à l’adresse $ 6c) est copié en OldIRQ. Même si vous n’utilisez pas d’interruption, ou d’une autre manière, deux précautions valent toujours mieux qu’une. Viennent ensuite les registres DMACON et INTENA qui contrôlent respectivement les canaux DMA à activer (Copper, Blitter, sprites...) et les interruptions à autoriser parmi les 6 niveaux que connaît le 68000 (rappel : en fait, 8 niveaux sont à distinguer, mais le niveau 0 correspond à l’état “pas d’interruption” et le niveau 7, dit “non masquable”, n’est pas utilisé dans l’Amiga), Une fois sauvegardés, ces deux registres sont “vidés”, c’est-à-dire que tous les canaux DMA sont bloqués et toutes les interruptions interdites. Seul le 68000 continue à fonctionner. Heureusement d’ailleurs, sinon on ne pourrait pas appeler la fonction Exec SuperSta- te(), qui a pour but de le commuter en mode superviseur (ce qui a pour effet de bloquer le multi-tâches). A partir de là, plus rien ne viendra dis- turber le bon fonctionnement de votre programme.
IBBEÜB HBHEI
Imigr bt , :,-.zzz.::=zrt--.
INITIATION
Restaure : remet tout dans l'état initial. L’ancien vecteur IRQ est remis à sa place en $ 6c, ainsi que les anciens DMACON et INTENA, en ayant bien entendu pris soin de positionner le bit SET CLR (le bit 15, quoi) à un avant - d’où l’utilité des or.w $ 8000,d0.
Une remarque au passage : Sauve ayant interdit tout canal DMA et toute interruption, vous devrez, dans votre programme, initialiser ces registres d’après vos propres besoins.
Après ces deux routines, il ne vous reste plus qu’à gérer vous-même l’utilisation de la mémoire. De manière aussi propre, j’espère...
Voilà, on se retrouve incessapeu sous ment - si fin certain commandant de ma connaissance ne m’a pas mis aux arrêts de rigueur d’ici là - pour continuer notre visite de la graphics.library. Repos !
Max
H
1
Exemple de programmation du blitter pour obtenir un scrolling horizontal avec test de collision.
Hrough underline;">zrt--.
INITIATION
Restaure : remet tout dans l'état initial. L’ancien vecteur IRQ est remis à sa place en $ 6c, ainsi que les anciens DMACON et INTENA, en ayant bien entendu pris soin de positionner le bit SET CLR (le bit 15, quoi) à un avant - d’où l’utilité des or.w $ 8000,d0.
Une remarque au passage : Sauve ayant interdit tout canal DMA et toute interruption, vous devrez, dans votre programme, initialiser ces registres d’après vos propres besoins.
Après ces deux routines, il ne vous reste plus qu’à gérer vous-même l’utilisation de la mémoire. De manière aussi propre, j’espère...
Voilà, on se retrouve incessapeu sous ment - si fin certain commandant de ma connaissance ne m’a pas mis aux arrêts de rigueur d’ici là - pour continuer notre visite de la graphics.library. Repos !
Max
H
1
Exemple de programmation du blitter pour obtenir un scrolling horizontal avec test de collision.

Click image to download PDF

AMIGA NEWS TECH numero 12 (05-1990)

Merci pour votre aide à l'agrandissement d'Amigaland.com !


Thanks for you help to extend Amigaland.com !
frdanlenfideelhuitjanoplptroruessvtr

Connexion

Pub+

55.3% 
9.9% 
3.6% 
3.5% 
3% 
2.4% 
2.1% 
1.3% 
1% 
0.8% 

Today: 32
Yesterday: 122
This Week: 318
Last Week: 732
This Month: 2244
Last Month: 2867
Total: 77632

Information cookies

Cookies are short reports that are sent and stored on the hard drive of the user's computer through your browser when it connects to a web. Cookies can be used to collect and store user data while connected to provide you the requested services and sometimes tend not to keep. Cookies can be themselves or others.

There are several types of cookies:

  • Technical cookies that facilitate user navigation and use of the various options or services offered by the web as identify the session, allow access to certain areas, facilitate orders, purchases, filling out forms, registration, security, facilitating functionalities (videos, social networks, etc..).
  • Customization cookies that allow users to access services according to their preferences (language, browser, configuration, etc..).
  • Analytical cookies which allow anonymous analysis of the behavior of web users and allow to measure user activity and develop navigation profiles in order to improve the websites.

So when you access our website, in compliance with Article 22 of Law 34/2002 of the Information Society Services, in the analytical cookies treatment, we have requested your consent to their use. All of this is to improve our services. We use Google Analytics to collect anonymous statistical information such as the number of visitors to our site. Cookies added by Google Analytics are governed by the privacy policies of Google Analytics. If you want you can disable cookies from Google Analytics.

However, please note that you can enable or disable cookies by following the instructions of your browser.

Visitors

Visite depuis
03-10-2004
Visite depuis
23-02-2014