Sponsors

FacebookTwitterGoogle Bookmarks

OURS Bienvenue dans l'Ours de Vamiga NewsTech ! Àïïtîga NewsTech est vendit disque mois et uniquement sw afeoimemern par Commodore Revue SARL 5. Rue h la Fidélité, 75010 Paris, 42,46,92.90. RecPchef : Stéphane Schreiber* Oui collaboré î Pascal Amiable, Bruno Baiüuei. Jérôme Etienne, Loïc Par, Olivier Garrigues, François Ciueugnon, Denis Jarril, Thomas ?.nndxpurg, Pierre Ehibppe Launay. S François Lionel, Max, Philippe Riviiîllori, Stéphane Schreiber, Lucien Turskï-Mareom PAO : Stéphane Schreiber, Support orthographique ; Christine (et) Robert. Répondeur téléphonique : Valérie (modèle uareoï.* Piqueuse de dopes î Aime avec l’aide de Pop t. *s Encouragements : la voisine d’en face qui n'a pas de rideaux à la fenêtre de sa salle de bain,*. Spécial thanks to ; Yvounet, GaëÜounetie, ïüod ineiie. S Bïbounet, Strïng, Poumt, Sined, Idéfix, Roger 7ahel. Flastojge : CohrWafr 5, rue de la Fidélité, 75(W Paris. 47,70,87,87 (désolé, j’avais pas la place pour le kmo). ; impression : MO Mont rouge. 9, rue Au hcr, 92120 Montr(mge, 46,562?,69 (désolé, j‘avais pas de logoj. ¦ Abonnements : MCM Anî, 16, Quai Jean-Baptiste Clément, 94140Alforivith, 43J8MJ.ll Ce numéro 29 de 1" Amiga NewsTech est dédié à uhjs ceux qui ont contribué, directement on indirectement, a mon épanouissement culturel ces cinquante dm nicres années, ainsi qu’à rinvemenr du treizième mois. Ce numéro 2 de Tamiga Newsïech n'est pus dédié à tons ceux qui ne >e sont pas abonné, ni â ceux qui ne connaissent même pas TANT* ;;; Ce numéro 29 de P Amiga NewsTech auraitpu eue dédié à tous mes amis, cens qui j’aime et qui me le rendent bien. Mais il ne Lest pas. LE C AMSI Nous débutons ici une nouvelle série à l’intérieur de la série... Au menu, les spécifications de la norme ANSI pour le langage C, avec comme plat de résistance les fonctions de la bibliothèque standard. !?! A NSI est l’abréviation de American National Standards Institute, ce qui signifie en français et à peu de choses près, Institut National Américain de Standardisation (INAS). Mais bon, ANSI, c’est tout de même plus simple. Le but de ce vénérable établissement est tout simplement et comme son nom l’indique, de fournir au bon peuple américain des standards pour tout ce qu’il est possible de standardiser. Et Dieu sait que rien qu’en informatique, ces gens-là ont bien du boulot... On ne reviendra pas particulièrement sur le rôle et l’utilité d’un standard, qu’il s’agisse de machines à laver ou de contrôleurs de disques optiques réinscriptibles à triple faisceau laser orthogonalement entrelacé. Les travaux informatiques de l’ANSI sont mondialement connus, ne serait-ce que concernant les codes de contrôles des consoles d’ordinateurs, codes auxquels l’Amiga a d’ailleurs totalement adhéré. Ainsi, un fichier texte ASCII contenant quelques codes ANSI de mise en valeur (gras, italique, etc.) sera visualisé exactement de la même manière sur un Amiga que sur un PC équipé du driver ANSI.SYS. Sauf que ce sera plus joli sur l’Amiga, paske bon, quand même, hein, faut pas déconner.

Click image to download PDF

AMIGA NEWS TECH numero 29 (01-1992)

Document sans nom TE UNIQUEMENT PA R ABONNEMENT ExecBase : Le C ANSI 2 Denis Jarril AMOS : La nouvelle extension musicale 4 François Lionet Arexx : Travail pratique (III) 6 François Gueugnon Pascal : Présentations 8 Olivier Garrigues GFA Basic : Le timer.device 10 Pierre Philippe Launay Algos : Les listes chaînées 12 Lucien Turski et Bruno Bailluet Hardware : La voix de Paula 14 Philippe Rivaiilon Transactor : Les Plasmas 16 Thomas Landspurg ToolBox : Les créateurs d’images 18 Herr Doktor von Glupa Demos : Le RollerText 20 Jérôme Etienne Utilitaire : BigCLI 24 Max Routinettes : GetDir 27 Tonton François Lionet SubWay : Les Bobs 28 Herr Doktor von Glupa 45 F EDITO Ce numéro de Vamiga NewsTech est exceptionnel à plus d’un titre. Exceptionnel, parce chaque numéro d’Amiga NewsTech est déjà exceptionnel en lui-même, c’est pas à vous que je vais l’apprendre. Exceptionnel, parce qu’il marque la première de plusieurs nouvelles rubriques : Pascal, GFA, Algos... Bon, vous connaissez le refrain : vous pouvez toujours nous faire part de vos remarques et suggestions sur ces rubriques. Et soyez sans pitié, si telle ou telle vous semble superflue, dites-le nous franchement, on la virera ! Bien sûr; vous avez également le droit de complimenter. Exceptionnel, parce qu’il marque l’arrivée de six nouveaux venus dans notre grande équipe rédactionnelle : Bruno Bailluet, Olivier Garrigues, Thomas Landspurg, Pierre Philippe Launay, Philippe Rivaillon et Lucien Turski- Marcon. Bienvenue à eux ! Exceptionnel, parce qu’il est le premier numéro d’une nouvelle année qui s’annonce très riche. Vous en saurez plus le moment venu, je ne veux pas gâcher la surprise. Exceptionnel, parce que grâce au groupe Poltergeist et notamment à son coder Enzo, la disquette d’accompagnement est maintenant parée d’une Antlntro superbe ! Exceptionnel, enfin, parce que bon, j’ai décidé qu’il serait exceptionnel. Non mais, c’est qui le chef, ici ? Bonne année ! Stéphane Schreiber OURS Bienvenue dans l'Ours de Vamiga NewsTech ! Àïïtîga NewsTech est vendit disque mois et uniquement sw afeoimemern par Commodore Revue SARL 5. Rue h la Fidélité, 75010 Paris, 42,46,92.90. RecPchef : Stéphane Schreiber* Oui collaboré î Pascal Amiable, Bruno Baiüuei. Jérôme Etienne, Loïc Par, Olivier Garrigues, François Ciueugnon, Denis Jarril, Thomas ?.nndxpurg, Pierre Ehibppe Launay. S François Lionel, Max, Philippe Riviiîllori, Stéphane Schreiber, Lucien Turskï-Mareom PAO : Stéphane Schreiber, Support orthographique ; Christine (et) Robert. Répondeur téléphonique : Valérie (modèle uareoï.* Piqueuse de dopes î Aime avec l’aide de Pop t. *s Encouragements : la voisine d’en face qui n'a pas de rideaux à la fenêtre de sa salle de bain,*. Spécial thanks to ; Yvounet, GaëÜounetie, ïüod ineiie. S Bïbounet, Strïng, Poumt, Sined, Idéfix, Roger 7ahel. Flastojge : CohrWafr 5, rue de la Fidélité, 75(W Paris. 47,70,87,87 (désolé, j’avais pas la place pour le kmo). ; impression : MO Mont rouge. 9, rue Au hcr, 92120 Montr(mge, 46,562?,69 (désolé, j‘avais pas de logoj. ¦ Abonnements : MCM Anî, 16, Quai Jean-Baptiste Clément, 94140Alforivith, 43J8MJ.ll Ce numéro 29 de 1" Amiga NewsTech est dédié à uhjs ceux qui ont contribué, directement on indirectement, a mon épanouissement culturel ces cinquante dm nicres années, ainsi qu’à rinvemenr du treizième mois. Ce numéro 2 de Tamiga Newsïech n'est pus dédié à tons ceux qui ne >e sont pas abonné, ni â ceux qui ne connaissent même pas TANT* ;;; Ce numéro 29 de P Amiga NewsTech auraitpu eue dédié à tous mes amis, cens qui j’aime et qui me le rendent bien. Mais il ne Lest pas. LE C AMSI Nous débutons ici une nouvelle série à l’intérieur de la série... Au menu, les spécifications de la norme ANSI pour le langage C, avec comme plat de résistance les fonctions de la bibliothèque standard. !?! A NSI est l’abréviation de American National Standards Institute, ce qui signifie en français et à peu de choses près, Institut National Américain de Standardisation (INAS). Mais bon, ANSI, c’est tout de même plus simple. Le but de ce vénérable établissement est tout simplement et comme son nom l’indique, de fournir au bon peuple américain des standards pour tout ce qu’il est possible de standardiser. Et Dieu sait que rien qu’en informatique, ces gens-là ont bien du boulot... On ne reviendra pas particulièrement sur le rôle et l’utilité d’un standard, qu’il s’agisse de machines à laver ou de contrôleurs de disques optiques réinscriptibles à triple faisceau laser orthogonalement entrelacé. Les travaux informatiques de l’ANSI sont mondialement connus, ne serait-ce que concernant les codes de contrôles des consoles d’ordinateurs, codes auxquels l’Amiga a d’ailleurs totalement adhéré. Ainsi, un fichier texte ASCII contenant quelques codes ANSI de mise en valeur (gras, italique, etc.) sera visualisé exactement de la même manière sur un Amiga que sur un PC équipé du driver ANSI.SYS. Sauf que ce sera plus joli sur l’Amiga, paske bon, quand même, hein, faut pas déconner. L’un des travaux les plus importants de l’ANSI a surtout été de fournir une standardisation pour presque tout langage informatique évolué, de façon à le rendre indépendant de la machine. C’est ainsi qu’il existe une norme ANSI pour le Basic, pour le Pascal, le Lisp... Et bien entendu le C, qui nous intéresse plus particulièrement aujourd’hui. K&R vs ANSI Les créateurs du langage C, messieurs Kernighan et Ritchie, avaient déjà entrepris un effort de standardisation de leur bébé, que l’on a tout naturellement baptisé "norme K&R" e1 qu’ils ont exposé dans leur livre "Le Langage C" (1). Seulement voilà, deux hommes seuls, et malgré toute la bonne volonté dont ils ont pu faire preuve, ne sauraient penser à tout. Aussi les ANSI-mens se sont-ils penchés sur le problème et ont étendu cette première norme, tout en essayant d’en rester le plus près possible (le problème étant bien entendu de rester compatible). Résultat, la norme ANSI, par ailleurs elle aussi décrite dans un excellent livre 'Le Langage C, 2ème édition" (2) signé... Kernighan et Ritchie. Par la suite, nous ne parlerons plus de la norme K&R, qui n’est finalement plus qu’un sous-ensemble de la norme ANSI. Pour la petite histoire, on peut signaler que la norme K&R date de 1978, cependant que la norme ANSI date, elle, de 1983, et qu’elle fut définitivement acceptée fin 1988. PRINCIPES Aujourd’hui, on trouve de çà et de là divers compilateurs C, dont beaucoup se réclament compatibles ANSI. L’utilisation d’un tel compilateur ANSI sur une machine donnée, garantira que le code source sera directement accepté par un autre compilateur ANSI sur une autre machine, disposant d’un autre système d’exploitation. Celà suppose donc qu’un certain nombre de fonctions, notamment d’entrées-sorties, soit effectivement disponibles dans les deux environnements. Comble de bonheur, ces fonctions sont toutes regroupées dans une bibliothèque (en anglais, lïbrary) qui se doit d’être standard. Peu importe donc pour le programmeur C la manière dont ces fonctions ont été effectivement implémentées sur telle ou telle machine, il est sûr de les retrouver quelque soit l’environnement et surtout, il est sûr que le nombre et la signification des paramètres de chacune sont identiques. C’est ça, la standardisation. LIMITES Pour être indépendante de la machine, la norme doit faire quelques sacrifices. Premier exemple, très parlant : l’ouverture d’une fenêtre sur Amiga s’effectue par un appel de la fonction OpenWindow() de l’intuition.library. Bien. MS-DOS ne disposant pas de système de fenêtrage, un programme Amiga utilisant OpenWindow() ne sera pas directement portable en MS- DOS. Quant aux Macintosh, Archimedes, Atari ST et autre NeXT, même s’ils disposent de fenêtres graphiques, ils n’ont pas d’intuition.library, donc pas d’OpenWindow(), donc notre programme ne sera pas non plus portable sur ces machines. Ce qui explique sans aucun doute possible que la fonction OpenWindowQ ne fasse pas partie de la norme ANSI. Autre exemple, moins évident : supposons que l’on désire ouvrir un fichier à l’aide de la fonction ANSI appropriée. Assumons pour les besoins de l’exemple que cette fois-ci, la portabilité est totale, et que le source soit compilé sans aucune erreur particulière quelque soit le système. Des problèmes risquent encore de surgir à l’exécution du programme : AmigaDOS autorise des noms de fichiers d’une longueur de 30 caractères maximum, et le point décimal n’est pas considéré comme un séparateur particulier. Cette règle est également vraie sur Mac, mais pas en MS-DOS, où seuls 8 caractères maximum sont autorisés, plus le point, plus 3 autres caractères pour l’extension. Ce second exemple démontre clairement que toute la standardisation du monde ne saurait suffir à assurer une portabilité parfaite. Le programmeur doit également faire attention à ne pas utiliser, directement ou indirectement, telle ou telle particularité d’un système donné, sous peine de problèmes sérieux. En cas de conflit, comme dans l’exemple précédent, il devra se conformer aux exigences du système le plus contraignant (ici, MS-DOS) ou modifier explicitement chacune des versions de son oeuvre en conséquence - mais alors, à quoi donc sert une norme ? PROTOTYPES Encore une petite digréssion avant de parler des fonctions elles-mêmes. L’un des principaux apports de la norme ANSI pour le langage C est la possibilité de déclarer des prototypes pour les fonctions que le programme emploie. Le raisonnement est simple : avant, la norme K&R indiquait qu’une déclaration de fonction ne spécifiait que le type de la fonction, c’est-à- dire et plus exactement, le type du résultat que cette fonction renvoyait. Par exemple : int Puissance(); * Déclaration de fonction, façon K&R * Le nombre et le type des paramètres qu’elle exigeait n’était connu du compilateur qu’au moment-même de la compilation de la fonction. De plus, une fonction non-déclarée avant son utilisation était automatiquement considérée comme renvoyant un entier (int). Depuis la norme ANSI, une déclaration de fonction peut également indiquer le nombre et le type de ses paramètres. Ainsi, le compilateur peut vérifier dès l’appel de la fonction que le programmeur n’a pas commis d’erreur. Pour reprendre l’exemple ci-dessus, la déclaration de notre fonction Puissance() devient : int Puissance(int, int); * La même, façon ANSI * Il est même possible de donner également les noms des paramètres. Celà n’ajoute rien aux vérifications que le compilateur peut entreprendre, mais peut rendre le listing plus clair et plus facilement compréhensible par une tierce personne : int Puissance(int base, int n); * encore mieux J * L’ancienne forme est toujours valable, et tout compilateur se doit de l’accepter. Celà dit, les avantages de la seconde forme sont évidents, et je vous encourage plus que vivement à l’utiliser chaque fois que vous le pourrez. On pourrait continuer à disserter pendant des heures sur toutes les modifications, bonnes et mauvaises, que la norme ANSI a apporté à la norme K&R, mais ce n’est pas vraiment là le but de cet article... LA BIBLIOTHEQUE Nous reviendrons plus en détails dans les mois à venir sur les pièges à éviter si l’on veut que son logiciel soit portable. Pour l’heure, attachons-nous à découvrir quelles fonctions l’on trouve dans la bibliothèque standard ANSI, ainsi que leur utilité. Note : pour le compliateur SAS Lattice C 5.10, cette bibliothèque porte le nom évocateur de Ic.lib, ou les. Lib pour le modèle "small" (entiers 16 bits), ou lcr.lib pour la version ré-entrante, ou encore lcm.lib pour la version avec nombres en virgule flottante... Evidemment, seules les fonctions effectivement utilisées seront placées par le linker dans le programme exécutable final. En Manx Aztec C, je sais pas, vérifiez avec votre documentation. La bibliothèque ne fait pas partie du langage C proprement dit. Cependant, tout compilateur C ANSI fournira les déclarations de fonctions, de macros et de types de cette bibÜothèque. Elle se base sur plusieurs fichiers d’en-tête (header files), eux aussi standards : assert.h> float.h> math.h> stdarg.h> stdlib.h> ctype.h> limits.h> setjmp.h> stddef.h> string.h> errno.h> signal.h> stdio.h> time.h> Un ou plusieurs de ces fichiers seront bien sûr inclus au source principal par la directive iïinclude du pré-processeur. Ils peuvent être inclus plusieurs fois et dans n’importe quel ordre sans que cela ne provoque d’erreur, mais quoiqu’il arrive, et c’est chose normale en C, l’inclusion doit précéder toute utilisation des éléments qu’ils contiennent. Leur rôle est donc de définir les prototypes des fonctions de la bibliothèques (printfO et consoeurs), ainsi que de fournir au programmeur des constantes (la plus célèbre étant NULL), des macros (max() par exemple) et des types (sizej par autre exemple), utiles pour son travail de développement. Ils contiennent également des références aux variables globales de la bibliothèque, telle que ermo pour ne citer qu’elle, qui contient le code d’erreur éventuel de la dernière fonction appelée. Encore une fois et au risque de me répéter, toutes ces fonctions, constantes et macros sont (censées être) disponibles sur tous les systèmes de France, de Navarre et des environs. La multiplicité des fichiers d’en-tête s’explique tout simplement par une envie de regrouper par thèmes toutes les déclarations. Ansi, stdio.h> déclare les fonctions d’entrées-sorties, string.h>, celles destinées à manipuler les chaînes de caractères, et time.h> celles de gestion de l’heure système. C’est simple, pratique et économique en temps de compilation : si on n’a pas besoin de nombres flottants dans un programme, on n’inclut pas math.h> et c’est toujours ça de gagné. Bon, ben la place qui m’est impartie étant (bien) remplie, je me vois dans l’obligation de paraphraser mon idole de toujours, Lucien Jeunesse : "chers amis bonsoir, et au mois prochain, si vous le voulez bien !".
(1) Le Langage C, par B.W. Kemighan et D.M. Ritchie, 1978, Prentice Hall. Edition française par Masson.
(2) Le Langage C, 2ème Edition : le C ANSI, par B.W. Kemighan et D.M. Ritchie, 1988, Prentice Hall. Edition française par Masson. A noter l’excellent livre 'Le Langage C, Solutions"par C.L. Tondo et S.E. Gimpel, chez Masson, qui contient toutes les solutions aux exercices proposés dans 'Le Langage C", première et seconde éditions. Pur Denis Janil S IE Une fois n’est pas coutume, je ne vais pas vous donner de listing aujourd’hui, mais plutôt vous parler des nouvelles routines musicales disponibles pour AMOS. LA NOUVELLE EXTENSION MUSI Vous trouverez la nouvelle extension musicale sur la disquette de l’Amiga NewsTech de ce mois-ci. Elle sera également mise en téléchargement sur les deux serveurs de la Rédaction, j’ai nommé le 3615 ANT et le 3615 ComRev. J’y ai fourré bien sûr le programme de l’extension, mais aussi le source assembleur ainsi que l’exemple. INSTALLATION Bon, vous prenez votre Basic favori (AmigaBasic... heu, non, pardon, AMOS), vous chargez le programme Musique_Install.AMOS : la prochaine fois que vous chargerez l’interpréteur, les nouvelles instructions seront disponibles. QUOI DE NEUF ? Plein de choses.
• Les longs samples : j’ai totalement modifié la gestion des samples, ils utilisent maintenant les interruptions de fin de son. La conséquence est que l’on peut jouer des samples de plus de 64 Ko, en fait sans aucune limitation de taille (sauf la mémoire bien sûr).
• Le double-buffer sonore : de toutes nouvelles instructions permettent de jouer des samples aussi longs que vous le désirez, en utilisant très peu de mémoire. La méthode utilisée est celle du double-buffer. Comme pour les bobs, on va travailler dans deux espaces mémoire distincts : l’un est joué sur le haut-parleur pendant que l’on charge la suite des sons dans l’autre. Avant de voir comment programmer un tel système, on passe en revue les nouvelles instructions. SLOAD Fichier TO Adresse,Longueur SLOAD est mis pour "Sample LOAD". Il s’agit d un BLOAD amélioré.
- Fichier est le numéro d’un fichier déjà ouvert par OPEN IN.
- Adresse est l’adresse de chargement.
- Longueur est le nombre d’octets à charger. Si vous spécifiez une longueur supérieure à celle restant à charger, AMOS ne produira pas d’erreur et chargera simplement le nombre correct d octets. Cette instruction est conçue pour être utilisée conjointement aux fonctions de gestion des fichiers séquetiels =POF()=, =LOF(),
- EOF(). Vous pourrez l’utiliser pour faire bien plus de choses que simplement charger des samples... SAM SWAP Canaux TO Adresse_Buffer,Longueur Cette instruction permet de réaliser l’échange des buffers, et n a d’action qu’une fois que le buffer actuel est terminé.
- Canaux est un masque de bits représentant les voix affectées par l’instruction (comme pour SAM PLAY par exemple).
- Adresse_Buffer est l’adresse à laquelle doit se poursuivre la lecture du son. La jonction entre les deux buffers est faite sous interruption et est donc totalement inaudible.
- Longueur est le nombre d’octets sonores à lire dans le nouveau buffer. =SAM SWAPPED(Voix) Cette fonction permet de se synchroniser avec l’échange des buffers. C’est elle qui indique quand charger une nouvelle partie du sample.
- Voix est un nombre de 0 à 3. Elle peut retourner trois valeurs différentes : 0 : les circuits n’ont pas terminé la lecture du buffer actuel. Il faut encore attendre.
- 1 : ça y est, on peut y aller... +1 : on a attendu trop longtemps, le son est coupé. Il faut alors réinitialiser totalement la voix. SAM STOP [ Canaux] Une instruction qui manquait cruellement : il était quasiment impossible d’arrêter un sample, une fois lancé !
- Canaux est un masque de bits, comme pour SAM SWAP. UN EXEMPLE valant mieux qu’un long discours, en voici un petit permettant de jouer un sample de longueur indéfinie, en n’utilisant que 16 Ko de mémoire CHIP ! Voyez le listing en fin d’article. LES INSTRUCTIONS TRACK J’ai prévu les routines sonores de l’AMOS pour être aussi générales que possible. En théorie, il est possible de jouer n’importe-quelle musique, en utilisant un programme de conversion. Cet utilitaire de conversion s’est avéré difficile à réaliser, et finalement assez pénible à utiliser. De plus, je passais mon temps à le modifier, vu qu’un nouveau modèle de SoundTracker sort chaque semaine, au moins. Bien, pour essayer d’améliorer les choses, j’ai mis dans cette version de l’extension musicale, un player direct de module SoundTracker, celui de StarTracker pour être précis. Ce player est compatible avec la plupart des trackers (sauf MED) au moment où j’écris cet article. Quand vous le lirez il ne le sera certainement plus, mais bon, vous ferez avec ! Alors, il y a de nouvelles et toutes belles instructions. TRACK LOAD "Nom du module",Banque Comme son nom l’indique, cette instruction charge un module dans une banque. Elle se charge de réserver la banque en mémoire CHIP, et de charger le fichier. Elle appelle également TRACK BANK : tout est prêt pour jouer la musique. TRACK PLAY [Banque] [,Pattern] Démarre la musique !
- Banque est un paramètre facultatif qui précise la banque (ou l’adresse) où prendre la musique. S’il est omis, la banque fixée par TRACK BANK ou TRACK LOAD est utilisée...
- Pattern est facultatif lui aussi et précise le début de la musique. Attention, aucun contrôle n’est fait sur sa validité : vous devez être sûr de vous, sous peine de crasher la machine. Cette option peut être CALE ! Très utile pour avoir plus d’une musique dans un module ; il suffit LSAM=Lof(i) alors de choisir le premier pattern pour démarrer une autre musique... ' A fond, les potards l Volume 63 ' On initialise la première partie du sample Sload 1 To Start(10),LBANK ' Le lancement doit être fait par un SAM RAVI : c'est lui qui fixe ' la fréquence de reproduction utilisée par la suite... Sam Raw V, Start (10) , LBANK, F ' On soustrait la longueur d'un buffer à la longueur du sample. LSAM=LSAM-LBANK PSAM=1 TRACK BANK Banque Vous pouvez charger plusieurs modules dans plusieurs banques. TRACK BANK sert alors à spécifier la banque par défaut, comme SAM BANK pour les samples... TRACK STOP Pour... devinez quoi ? J’en vois un qui suit dans le fond. C’est ça, arrêter une musique en train d’être jouée. ' Boucle de chargement des samples. While LSAM>0 Repeat TRACK LOOP ON OFF Inhibe ou autorise le bouclage de la musique lorsque celle-ci est terminée. Mode par défaut: TRACK LOOP OFF. ' Une bouclette, pour simuler un mauvais accès disque: en ' maintenant la souris enfoncée on désynchronise la boucle. ' Essayez donc pour voir! While Mouse Key : Yïend ' On ne bouffe pas le temps des autres taches Multi Wait ' Peut-on maintenant charger? P=Sam Swapped(VX) r Until P f ' Ok, d'abord, faire le ménage dans la banque. Comme ça, ' lorsque l'on atteind la fin d'un sample, on entend plus ' rien. Je sais, j'aurais pu calculer la longueur restant à ' jouer. Mais bon, mon poil dans la main a pas mal grossi ' ces derniers temps... Fill Start(10+PSAM) To Start(10+PSAM)+LBANK,0 ' On charge la suite Sload 1 To Start(10+PSAM),LBANK f ' On initialise la suite: If P=-l f ' Ok, on peut swapper, on est toujours synchro Sam Swap V To Start (10+PSAM), LBANK Else f ' Arghhi On est désynchronisé, il faut réinitialiser ' le sample Sam Raw V, Start (10+PSAM) , LBANK, F End If i ' Ya moins d'octets à charger... LSAM=LSAM-LBANK PSAM=1-PSAM ! ' Et on exite en pressant une touche... If Inkey$ >,,,l : Sam Stop : Exit : End If wend ' Ne pas oublier de fermer le fichier... Close BON A SAVOIR... Plusieurs petites choses sont à noter :
• les musiques jouées par TRACK PLAY n’autorisent pas les interruptions comme on pouvait le faire avec une musique AMOS normale. Par exemple, vous ne pouvez pas faire de bruitage pendant l’exécution d’une musique Tracker, sans prévoir dans la musique, une voix libre spécifiquement pour cet usage. Pour un jeu complexe, il donc vaut mieux utiliser les banques de musique normales...
• Les vu-mètres fonctionnent parfaitement !
• Je ne vais pas vous proposer d’exemple, tout de même ! Oh ’pi si, un ’achement gros exemple. Track Load "mod.essai", 5 Track Play Et voila, en avant la musique ! Bien, j’en ai terminé. Désolé d’avoir un peu bousculé l’ordre (le désordre ?) Habituel de cette rubrique, mais je pense que ces nouvelles instructions feront plaisir à plus d’un (dont moi, hé, hé!). Exemple de double buffer sonore... Par F.Lionet Paru dans l'ANTl NB: le double buffer sonore fonctionne parfaitement, et à une grande fréquence de reproduction sur un disque dur ou un CDTV. Sur disquette, il est illusoire d espérer jouer convenablement des samples à plus de 8000 Herz, sans avoir recours à des accélérateurs de disquette. Reserve les banques. Il faut prévoir DEUX banques, en CHIP mémory bien sur: les circuits doivent y avoir accès... Plus la longueur des banques est importante, plus les accès disque seront rares... LBANK=1024*8 Reserve As Chip Work 10,LBANK Reserve As Chip Work 11,LBANK ' Définit les voix utilisées V=%11 : vx=0 ' Ouvre le fichier F$ ="Samessai.sam" Open In 1,F$ F=10000 Prend une fois pour toute la longueur du fichier, pour éviter les POF et autres EOF, qui bougent la tete de lecture... Par François C- Amiga NewsTech MM Numéro 29 - JAN 92 Après avoir réalisé quelques pas guidés en Arexx, il va falloir maintenant écrire soi-même ses programmes. Habituellement, cela ne va pas sans quelques erreurs... MMême le programmeur le plus chevronné sait combien il est difficile et nécessaire de traquer les erreurs diverses nommées "bugs" partout dans le monde informatique et "bogues" chez les irréductibles gaulois ! Heureusement, conscient par expérience de ces difficultés, le père d’ARexx a fourni à l’interpréteur du langage un environnement de déverminage tout à fait efficace. DEFAUTS La liste des défauts possibles est aussi immense que l’ingéniosité du programmeur, et il serait vain d’en tenter une revue exhaustive. Cependant, le seul type contre lequel on ne peut rien est le défaut de logique dans la réalisation. On peut alors déterminer les grandes classes de défauts et donner les méthodes pour leur détection et correction, soit par ordre de gravité : la faute d’orthographe, la faute de syntaxte et la faute de système. Faute d'orthographe Cette faute apparait sous deux formes : orthographe des mots réservés par le langage et orthographe d’une variable, non constante. Dans le premier cas, l’analyseur orthographique du langage peut, mais pas toujours, détecter l’erreur. Dans le deuxième cas, l’analyseur orthographique est impuissant puisqu’il s’agit de noms de variables donnés par l’utilisateur, qui ne lui sont donc pas connus. Il faut se rappeler que l’analyseur orthographique n’est pas tout puissant et qu’il ne sait détecter au mieux que l’endroit où il ne comprend plus le programme, endroit qui est fréquemment différent de celui où se situe réellement la faute. Il peut donc indiquer une faute qui n’est pas la bonne. Un travail d’interprétation est parfois nécessaire. Faute de syntaxe Cette faute traduit la mauvaise écriture d’une instruction : boucle non fermée, mauvais emploi (au sens de l’usage) de ses paramètres, etc. Elle peut être localisée ou répartie si elle est placée à cheval sur un sous programme. L’analyseur de syntaxe du langage trouve certaines erreurs mais seulement lorsqu’il ne comprend plus, si bien que l’indication de l’endroit et de l’erreur peuvent être erronés, indépendamment. Fréquemment, la détection d’une erreur est la seule chose que l’analyseur peut faire, il faut alors un travail de recherche en aveugle pour effectuer la correction. Faute de système Dans cette rubrique, on place toutes les fautes non couvertes par les définitions précédentes. La multitude se refuse à toute description. MOYENS DISPONIBLES Plusieurs moyens sont disponibles en Arexx et peuvent être employés concurremment. Analyseur orthographique et syntaxique Il est toujours présent et fonctionne à chaque mise en oeuvre d’un programme (la rançon est le ralentissement de l’exécution dudit programme). Un catalogue de 48 messages est donné ; certains sont très explicites, comme le numéro 3 (mémoire insuffisante), d’autres le sont moins, comme le numéro 34 (caractère étranger) qui ne précise RMINAGE rien et qui peut avoir rapport à un caractère non ASCII, donc invisible à l’écran. A chaque message est associé une sévérité qui permettra par la suite d’effectuer une recherche sélective en fonction du niveau de sévérité. Dans tous les cas, l’erreur provoque l’arrêt de l’exécution et l’affichage de la raison supposée. Une analyse est effectuée avant exécution du programme et certaines erreurs, comme le manque d’apostrophes (quotes) sont signalées dès le début ; d’autres ne sont signalées qu’à la découverte. Ecriture du résultat Dans la forme la plus simple, le résultat de la détection d’erreurs est affiché dans la fenêtre en cours. Cette disposition mélange le résultat du programme et celui de la détection d’erreurs, ce qui peut être désagréable à divers points de vue. Il peut être préférable d’utiliser une fenêtre séparée. C’est le rôle du petit programme nommé "tco" et distribué avec Arexx. "tco" signifie "Tracing Console Open". Ce programme doit être lancé en premier. Il ouvre une console spécifique dans laquelle on verra défiler les erreurs éventuelles. Pour le quitter, on utilise "tcc" (Tracing Console Close). Ces commandes doivent figurer dans le répertoire C:. Cette forme de détection d’erreurs implicite, si l’on peut dire, permet de trouver les erreurs grossières mais devient rapidement hors de propos lorsque les défauts sont plus subtils. La fonction TRACE Cette instruction qu’on inscrit dans le programme suit son déroulement et en fait un rapport instruction par instruction. Le "traçage" peut être paramétré pour ne s’intéresser qu’à certains éléments du programme. Il n’est pas non plus nécessaire de tracer tout le programme. Une instruction d’arrêt du traçage permet de contrôler précisément la portion de programme à tracer. La forme est donc : * Début du programme * trace ... * Partie tracée * trace off * Suite du programme * Si tco a été lancé, le résultat de la trace est écrit dans cette console. L’instruction TRACE s’écrit : TRACE symbole I chaine | VALEUR expression
- symbole peut être ? Ou !. Le ? Commande le mode interactif, dans lequel l’opérateur suit et peut modifier les valeurs en cours dans son programme et ré-exécuter telle ou telle instruction, pendant que le ! Commande le mode inhibition. Dans ce mode, les commandes à destination de l’hôte ne sont pas exécutées réellement, mais n’entravent pas le déroulement du programme. C’est particulièrement intéressant lors de l’émission de commandes à caractère destructif (DELETE ou FORMAT par exemple). Attention : ces symboles fonctionnent en bascule qui en change la signification chaque fois qu’ils sont rencontrés : ? Mode interactif ? Mode normal ? Mode interactif...
- chaine peut prendre les valeurs suivantes : ALL, COMMANDS, ERRORS, INTERMEDIATES, LABELS, NORMAL, RESULTS, SCAN, ou seulement la lettre initiale. L’exemple ci-après permettra de voir leurs résultats respectifs.
- VALEUR expression permet de sauter des instructions si l’expression spécifiée est négative. Le programme d’essai que voici n’a pas d’autre intérêt que de permettre l’évaluation des différentes options de trace qui seront écrites à la place de XXX à la ligne 3. Le symbole d’interdiction (!) Dans cette même ligne empêche la réalisation réelle de la ligne 4, sans pour autant perturber le fonctionnement du programme. î ** 2 ¦ ¦m m s%a Les tableaux ci-dessous résument les résultats de l’exécution de ce programme avec différentes valeurs pour XXX. 3 trace I XXX installe le mode trace avec interdiction (!) 6
* -* say i; 4 ADDRESS COMMAND 'dir dfl:' commande vers l'extérieur V> "1" idem 5 DO i=l TO 2 boucle 7
* -* a= test(i); 6 SAY i V> "1" appel avec variable=l 7 a= test(i) appel à sous-programme 12
* -* test: 8 SAY a 12
* _* . 9 END 13
* -* arg k; 10 TRACE OFF fin de traçage "1" résultat de l'extraction 11 EXIT fin du programme 14
* -* return(k
* *k); 12 test : label de sous programme V> "1" 1ère variable=l 13 ARG k extraction de la variable à traiter V> "1" 2ème variable=l 14 RETURN(k**k) retour avec calcul 0> "1" résultat de l'opération entre "1" F> "1"
• pour XXX égale ALL : trace de toutes les instructions. Cela permet de voir comment se déroule le programme. 4 *-* address command 'dir dfl:'; 5 *-* do i=l to 2; 6 *-* say i; 7 *-* a= test(i); 12 *-* test: 12 *-* ; 13 *-* arg k; 14 *_* return(k**k);
- * say a; 8 9 5 6 7 12 12 *-* ; 13 *-* arg k; 14 *-* return(k**k); 8 *-* say a; 9 *-* end; 5 *-* do i=l to 2; 10 *-* trace off;
• pour XXX égale COMMANDE sont tracées.
- * end;
- * do i=l to 2;
- * say i;
- * a= test(i);
- * test: seules les commandes vers l’extérieur résultat de l'expression (..) résultat de l'appel à fonction "1" résultat de l'expression 8
* -* say a; V> "1" 9
* -* end; 5
* -* do i=l to 2; on avance d'un cran V> "1" la variable est 1 0> "2" 1'incrément de 1 donne pour résultat 2 "2" le résultat de l'opération est 2 6
* -* say i; V> "2" 7
* -* a= test(i); appel au sous-programme V> "2" = 2 12
* -* test: 12
* _* . 13
* -* arg k; "2" extraction de la valeur transmise 2 14
* -* return(k**k) ; V> "2" variable 1=2 V> "2" variable 2=2 0> "4" résultat de K**K=4 "4" résultat de (...)=4 F> "4" résultat de return=4 "4" renvoi de 4 8
* -* say a; V> "4" 9
* -* end; 5
* -* do i=l to 2; V> "2" la variable actuelle est 2 0> "3" le résultat avec incrément de 1 est 3 "3" le résultat de l'incrément est 3 d'où abandon 10
* -* trace off; "dir dfl:" La commande vers l'extérieur est la lecture du répertoire de DF1:.
• pour XXX égale ERRORS : l’erreur provoquée était ligne 7 : a=test(z), z étant une variable nouvelle sans valeur attribuée. +++ Error 47 in line 14: Arithmetic conversion error +++ Error 47 in line 7 : Arithmetic conversion error La variable étant non initialisée, l’appel du sous-programme s’effectue mal, d’où l’erreur en ligne 7. En ligne 14, l’opération n’a donc pas pu se faire. Les +++ en tête de ligne indiquent une erreur de syntaxe ou de commande.
• pour XXX égale INTERMEDIATES : c’est la forme la plus complète, dans laquelle toutes les valeurs intermédiaires sont tracées. Plusieurs sigles sont utilisés, dont voici la signification : 4 *_* est une instruction, avec en tête son numéro de ligne +++ est une erreur de syntaxe ou de commande C> nom de tableau complet F> résultat d'un appel de fonction L> label 0> résultat d'une opération à deux termes P> résultat d'une opération préfixée U> variable non initialisée V> valeur d'une variable résultat d'expression .> place vide. 4 *-* address command 'dir dfl:'; L> "dir dfl:" la commande n'est pas effectuée 5 *-* do i=l to 2; L> "1" label de départ "1" résultat de l'expression L> "2" label d'arrivée V> "1" la variable est i=l
• pour XXX égale LABELS : ce sont les expressions suivies du signe deux-points (:), comme les sous-programmes ou les points de branchement. 12 *-* test: 12 *-* test: L’appel au sous programme a été fait dans une boucle à deux passes, il y a deux fois appel à ce sous-programme.
• pour XXX égale NORMAL : ce mode ne trace que les erreurs qui sont d’une sévérité supérieure à un niveau pré-établi ; on verra comment après.
• pour XXX égale RESULTS : ce mode n’affiche que les résultats. 4 *-* address command 'dir dfl:'; "dir dfl:" 5 *-* do i=l to 2; "1" "2" 6 *-* say i; "1" 7 *-* a= test(i); "1" 12 *-* test: 12 *-* ; 13 *-* arg k; "1" 14 *-* return(k**k); "1" "1" 8 *-* say a; "1" 9 *-* end; Bienvenue dans le fabuleux monde du Pascal ! Ensemble, nous allons découvrir ce langage de programmation créé spécialement pour renseignement par le Professeur Wirth. En ce moment-même, mais il obéit à des règles bien précises, autant sur le vocabulaire que sur la syntaxe (et c’est là toute la difficulté !). Pour débuter cette initiation, voici un petit exemple que nous allons étudier (accrochez-vous !). PROGRAM Premier_Exemple; BEGIN writeln('Vive AMIGA !') Whaou, l'exemple ! ) END. Et pour commencer, un peu de culture générale sur ce langage (ne vous inquiétez pas, ce ne sera pas long)... Le Pascal est un langage évolué (pour nous) développé comme une aide à la programmation des ordinateurs suivant une approche dite de "programmation structurée". Il a été créé par le professeur Wirth (également père du Modula II, qui descend du Pascal). Il est un des langages les plus utilisés (si ce n’est le plus utilisé) et peut servir aussi bien pour des applications système (par exemple, l’écriture du sytème Mac), que pour la programmation éducative et personnelle. Pascal existe sur de nombreuses machines (MS-DOS, Mac, UNIX) ce qui permet une certaine portabilité (il existe un standard décrit dans le livre de Wirth et Jensen: "Pascal User Manual and Report'). Le Pascal possède de nombreux avantages, dont ceux de structurer la pensée, de faciliter l’implémentation d’algorithmes, de simplifier la correction d’un programme (si on se borne à respecter quelques règles de présentation et d’écriture). De plus, le langage est rapidement assimilable et permet d’acquérir une méthodologie qui vous sera utile dans d’autres langages plus laxistes. Et comme pour tout langage, il dépend de son implémentation sur machine. Pour nous, ce sera le très célébré PCQ de Patrick Quaid. Vous pourrez trouver ce compilateur sur la disquette ANT numéro 22 ou la Fish 339 (reportez-vous à l’excellent article de Herr Doktor du numéro 22 pour l’installation et assurez-vous que votre Startup- Sequence contient la ligne assign inc: xxx inciude, où XXX est le chemin pour arriver au répertoire "include" du Pascal, ceci afin de le rendre compatible avec les listings des programmes comportant des inclusions). En résumé, nous avons une disquette nommée PCQ: devant contenir au moins les répertoires et fichiers suivants : c (dir) A68k Az (ou tout autre éditeur de votre choix) Blink Pascal include (dir) les ".i" du Pascal pcq.lib Pour compiler, j’utilise le script du Herr Doktor Von Glupa (à l’époque) que je nomme "make". Quelques notes sur le compilateur PCQ : il n’est pas tout-à-fait standard, mais P. Quaid a importé des facilités (procédures et autres conventions) du Turbo-Pascal de Borland et du Quick Pascal de Microsoft que l’on trouve dans le monde MS-DOS, ainsi que certaines du Modula II. Le source Pascal est traduit en assembleur et produit un fichier assez gros. Si vous avez de la mémoire (1 Mo minimum), utilisez le disk Ram :. Remarques importantes : si vous jonglez avec les minuscules et les majuscules, sachez qu’en Pascal, elles sont équivalentes : Toto = TOTO = TotO. Mais les caractères accentués, eux, ne le sont pas et je ne les recommande pas. Par la suite, nou$ suppposerons que vous connaissez tout ce qui est externe au Pascal, et même la façon de compiler, d’éditer un texte et d’exécuter un programme, car tout ceci dépend du sytème d’exploitation et ce n’est pas le but de cette initiation. Pour réussir quelque chose en Pascal, il faut pouvoir écrire un programme. Un programme est un texte, comme celui que vous lisez Tapez, sauvez, compilez puis exécutez (non pas au fusil !) Ce programme et, ô joie, le texte "Vive AMIGA !" Apparait sur l’écran. Vous aurez deviné le rôle du programme, ce que l’on nomme sa spécification : "afficher un texte chauvin sur la plus belle des bécanes". Ainsi, votre prochaine mission, si vous l’acceptez, sera de faire l’inverse : à partir d’une spécification, vous produirez un texte Pascal équivalent. ETUDE DU PROGRAMME (A LA NICOLAS HULOT) Séquence description Le premier mot du texte est PROGRAM suivit du nom du programme et d’un point-virgule, puis du mot BEGIN puis un grand mot writeln( Vive AMIGA ! );, un texte entre accolades et enfin, le mot END avec un point. Séquence explications Nous sommes en présence de ce que nous nommerons un bloc. Il commence au mot PROGRAM, qui signifie que tout ce qui suit forme un programme. Le mot Premier_Exemple est en fait un identificateur : une suite (ou plutôt une séquence, car le sens a de l’importance) de lettres et du signe de soulignement Le point-virgule termine ce que nous appelerons l’en-tête du bloc (ici, le bloc programme). Après cet en-tête, nous avons une grande phrase commençant par BEGIN et finissant par END. Cette partie est la zone (séquence, ou segment) d’instructions ; elle sera exécuté à chaque appel du programme. La seule chose qui semble compter est donc, en fait, le fameux grand mot dont seul ce qui est entre quotes (les français disent apostrophes) est affiché. C’est ce que l’on appelle une constante chaine de caractères. Le premier sous-mot est en fait l’appel d’une procédure qui porte le nom de writeln. Une procédure est le résumé d’une séquence d’instructions. A chaque référence de ce nom (un appel), cette séquence sera exécutée. Dans le cas de notre exemple, la procédure est appelée avec un argument, qui est la chaine de caractères. La spécification de writeln est : "envoie sur la sortie standard les arguments sous forme de chaînes ASCII avec un retour chariot tout à la fin". Cette procédure est prédéfinie, ce qui nous évite de le faire, car il existe une règle importante en Pascal : tout ce qui est utilisé doit être défini plus haut dans le texte. La règle n’est pas complète et nous verrons un peu plus tard comment définir quelque chose (on dira "définir un objet [du programme]"). J’ai volontairement passé sous silence la cinquième ligne (celle avec des accolades) parce que j’ai joué au compilateur : tout ce qui est mis entre les signes " " et "}" est ignoré (à l’exception des directives de compilation) et le tout est considéré comme un séparateur (comme un blanc ou une tabulation). En Pascal, il toujours bon de commenter un programme afin de le comprendre quelques mois plus tard. De ce que nous venons de voir, nous déduisons que le plus court programme Pascal qui soit est le suivant : PROGRAM plusPetit; BEGIN END. Si vous le compilez, vous verrez que le source produit par PCQ et assemblé par A68K est de 62 lignes et que le code final est de 2048 octets (2 Ko tout juste) en mémoire (2752 sur disque). Une autre constatation : les retour-chariots équivalent à un simple séparateur comme les commentaires, les espaces, les tabulations. Le seul séparateur d’instructions est le point virgule. Mais une question s’impose "qu’est-ce qu’une instruction ?". LES INSTRUCTIONS Une instruction est un ordre Pascal qui sera compilé sous forme de code machine exécutable (en opposition aux données qui sont les objets manipulés par le programme). Elle peut être une affectation, un appel de procédure, ou un contrôle du flux d’exécution. Nous avons déjà vu l’appel de procédure. Un résumé de sa syntaxe générale serait : le nom de la procédure à appeler suivi, si nécessaire, d’une parenthèse ouvrante, d’une séquence d’expressions (calcul au sens large) séparées par des virgules (les arguments) et une parenthèse fermante. Quelques exemples avec la procédure writeln (qui n’a pas un nombre d’arguments fixe) : writeln; writeln('toto' ) ; writeln ('toto', 'mon héro'); Dans un segment d’instructions, on peut mettre plusieurs instructions à la suite, que l’on sépare par un point-virgule comme par exemple : BEGIN Seul le segment d'instruction est donné > writeln 'on ne change pas de procédure'); writeln('toujours ce bon writeln'); writeln sans argument cette fois on passe simplement à la ligne } END. Remarquez que le dernier appel de fonction n’a pas de point vigule du fait que END est considéré comme la fin d’une instruction. En Pascal, le couple BEGIN... END (où les trois points représentent une séquence d’instructions) équivaut à une seule instruction. Donc, nous pouvons aussi avoir, en reprenant l’exemple ci-dessus : BEGIN Seul le segment d'instruction est donné > Begin writeln('on ne change pas de procédure'); writeln('toujours ce bon writeln') End; remarquez le point-virgule indiquant la fin d'une instruction } writeln; le point virgule n'est pas autorisé devant un end mais beaucoup de compilateurs dont PCQ l'acceptent } END. Dans cette exemple, cette technique n’est pas très pratique, mais pour certaines formes d’expression où une seule instruction est autorisée, il est très utile de l’étendre de la sorte. Nous ne verons pas tout de suite ces expressions car cela dépasse le cadre de cet article. LES VARIABLES Les variables sont des objets qui sont manipulés par le segment d’instructions. Une variable est une place réservée en mémoire dans laquelle on range des valeurs suceptibles de changer dans le temps. Le compilateur utilise une méthode pour coder cette valeur, méthode différente pour chaque type de variable. En informatique, une variable est souvent représentée par le quadruplet nom type portée adresse. Le nom permet simplement de référencer la variable (comme pour les procédures). Le type indique la méthode de stockage utilisée par le compilateur (qui est le plus souvent transparente au programmeur), ainsi que les opérations possibles sur cette variable. La portée indique en quel(s) endroit(s) du programme la variable est connue et donc référençable. C’est l’un des principes fondamentaux du Pascal, sur lequel nous reviendrons en temps et en heure. Enfin, l’adresse de la variable indique tout simplement où dans la mémoire de l’ordinateur elle est stockée. Comme précisé plus haut, pour utiliser un objet quelconque, il faut d’abord le déclarer. Donc ... LES DECLARATIONS Certains types de variables sont préféfinis en Pascal. Nous les étudierons le moment venu. Pour l’instant, sachez seulement que la forme syntaxique de la déclaration de variable en Pascal est : VAR Identificateur : type; où Identificateur est le nom de la variable, et type le nom du type de la variable. Le mot VAR indique au compilateur que ce qui suit est une zone de déclarations de variables (car il peut y en avoir plusieurs à la suite). Un exemple pour fixer les idées. VAR UnEntier s integer ; déclaration de la variable "UNENTIER" du type entier } VAR UnAutre, PuisUnAutre : integer ; déclaration multiple de variable de même type } Dans un programme Pascal, il faut mettre toute déclaration entre l’entête et le mot BEGIN. Cette zone est appelée (devinez ?) Zone de déclarations locales. Pourquoi locales ? Parce que les variables ne sont connues que du programme (et pas des autres, na!). Bon, à ce niveau, on peut oublier le local, mais on touche là l’une des difficultés du Pascal (ce que l’on nomme les "effets de bord" et la "localité"). Encore un petit programme, pour clarifier la situation. PROGRAM Essai_4; var UnPetitNbre ; integer ; déclaration de UNPETIT de type entier } BEGIN UnPetitNbre := 1 + 1 ; on affecte à la variable UnPetit la valeur 1+1 (1+1 est de même type qu'UNPETIT, c-à-d integer) ) writeln 'le résultat de 1 + 1 est ',UnPetitNbre); L'aventage de certains types prédéfinis est qu'ils peuvent être affichés sans difficulté supplémentaire > END. Bon, on s’arrêtera là pour aujourd’hui, ça fait déjà beaucoup de notions nouvelles à assimiler d’un coup : variables, architecture d’un programme simple (trop simple pour certains, je sais !), type integer et procédure writeln... Le mois prochain, on reprendra le tout mais avec plus de précision et on avencera un peu plus dans la pratique. En attendant, je vous laisse un petit devoir : trouvez la spécification du programme suivant . Program Pas_Encore_de_Specification; var âge,date, cetteAnnee : integer; BEGIN write ('Quel est-on âge, mon petit ? _'); readln (âge); writeln(' Ho ! Tu ne fais pas tes ',age,' ans, mon grand !'); avouez que je commence fort, non ? } write ('Quel est ton année de naissance :'); readln (date); cetteAnnee := âge + date; additionne la valeur de la variable âge avec celle de date et la stocke dans la variable CETTEANNEE ) en gros, je complique la mathématique } writeln ('On ne serait pas en CetteAnnee,' ?'); qui dit que l'informatique est très intellectuel ? } END. Bye et au mois prochain, pour de nouvelles z’ aventures Pascalissimes. LÉa-r 111®* I1MERDEVICE En quelques années, GFA Basic acquis une immense renommée, au point d’être possédé par environ un million de personnes. Et c’est un juste retour des choses après ses débuts difficiles. Comme tout nouveau produit, il avait souffert de nombreux bugs de jeunesse. Une seule instruction. Grain de sable par grain de sable Oui Pour aller plus vite à 1' essentiel Dessin et sauvegarde de 1' horloge Le timer en chiffre Ouverture d' un port pour les messages Ouverture du périphérique timer.device Remplissage de la structure timerequest Saisie de 1' heure en heure Amiga Formatage en heure humaine Visionnage de 1' heure Radio France Télécom MF 3699 Attente du clic Good night Enlever lors de la session de codage ! Nouveau port de message ! Création d'une sortie des réponses ! Manque de mémoire ! Fin Dare dare Structure timerrecjuest ! Entrée suivante Entrée précédante Indication du type Niveau de priorité Nom de la structure ! Port Longueur du noeud Périphérique Numéro du lecteur C ommande s cmd Drapeau Statut Les secondes Les 1 100 secondes Destruction de la structure Type Port des Messages Pointeur sur le device Mon Dieu, ça plante Dissolution du canal du timer Désintégration du canal Toujours tout refermer Les constantes du système ! Unité du périphérique. CIA-Timer ! Vertical Blank Timer ! Avec 0 les microsecondes sont inutiles Commande invalide Retour du timer à 1' état initial Lecture dans le périphérique Ecriture dans le périphérique Traitement des espaces tampons Effacement de tous les tampons Mise en place d' une pause Reprendre après la pause Interruption du travail en cours La suite de la structure En écriture romaine Copie d' une portion d' écran ! PCIRCLE et PELLIPSE ont été optimisés ! Pour le compilateur. Le Basic n' est Pas assez rapide GFA-Basic est maintenant plus performant que le C dans de nombreux domaines (NDLR : cet avis n’engage que l’auteur !). Et on va le prouver. J’utilise la version 3.52F mais attention, la dernière version disponible en France est la 3.042. (ni 3.1, ni 3.2, ni 3.3, ni même 3.4). Il faut également signaler qu’il existe plusieurs ouvrages, publiés par Micro- Application, qui traitent du GFA-Basic version Amiga. Un logiciel professionnel se reconnaît à la simplicité de son codage et à la puissance de son exécutable. Pour commencer la série, je voulais frapper un grand coup en proposant un Plasma, géré sur toutes les lignes et non pas une ligne sur deux comme cela se voit trop souvent dans les démos. Micro Application me dit qu’il serait plus professionnel de montrer la gestion d’un device. Mais voilà, c’est compliqué pour des lecteurs ne connaissant que l’aspect Basic du GFA. Sauf peut-être le timer.device. Et en plus, on s’aperçoit de l’ignoble vérité: GFA est souvent plus rapide que Lattice C, de 1% à 15%. Le codeur recherche toujours trois choses : la simplicité, la rapidité et la synchronisation. Le délai se calcule fréquemment avec les fonctions TIMER, DELAY et PAUSE. Pour plus de précision, on utilise également souvent le blanc vertical avec le registre VPOSR. Ou mieux, on ouvre le dispositif approprié. Timer.device permet de gérer les deux timers internes de l’Amiga grâce aux unités UNIT_VBLANK et UNIT_MICR OHZ. UNIT_VBLANK (valeur 1) sélectionne le timer de synchronisation sur le retour du faisceau d’électrons. C’est celui des longs moments (précision de 0.02 secondes). Avec UNIT_MICROHZ (valeur 0), on sélectionne le timer du CIA 8520, ultra précis, mais qui accapare trop le microprocesseur pour être valable sur des durées dépassant la seconde. Peut-on coder directement le Hardware en GFA? Oui, mais ce n’est pas élégant. La vraie solution passe donc par le timer.device, qui assurera la pérennité de vos applications avec l’évolution de l’Amiga. Le codage commence par charger instantanément une image de 5 plans de bits. Heureux utilisateurs des disquettes ANT, vous êtes des privilégiés car vous aurez l’exécutable IMENSITE et la source IMENSITE.GFA (deux fois 75 Ko, dont une bonne partie pour l’image). On crée ensuite une structure de port que l’on étend à 40 octets. Puis l’on ouvre le dispositif périphérique timer.device et l’on nomme les parties intéressantes de la structure timerequest%. On est prêt, timer.device peut commencer à s’amuser. Il charge donc le nombre de secondes écoulées depuis la création de l’univers, le premier janvier 1978, peu de temps avant la naissance des Mammouths préhistoriques. Après ces milliards et ces milliards de secondes, il affiche sa différence. Le programme est fortement inspiré des pages 677 et suivantes de la Nouvelle Bible de l’Amiga. Rassasié, on referme le tout puis on passe à la deuxième partie qui utilise là fonction CurrentTime de la bibliothèque Intuition. Une fois compilé, le codage se synchronise au début de la seconde suivante pour éviter les aberrations de mesure, puis il teste la ou les fonctions désirées. Une boucle à vide met 64 cycles en GFA compilé avec 1 plan de bits de 320 pixels sur 256. Ce résultat varie bien sûr selon les autres tâches en cours. Je trouve de 62 à 65 sur un Amiga 500, lecteur externe, 1 Mo. En Lattice C, on aura 70 cycles et plus. De même, pour afficher la lettre A avec printf('A'); on met 10535 cycles en Lattice C, contre 10490 en GFA qui déteste pourtant le PRINT. En utilisant des fonctions spécifiques GFA, on descend à 1409 cycles, et moins quand on ruse. ENDIF timerequest%=CreateExtIO(timerport%,40) IF timerequest%=0 ! Glou glou glçu
- DeletePort(timerport%) ! Remise à 1' état normal ENDIF RETURN PROCEDURE crEation.structure ABSOLUTE ln_succ%,timerequest' ABSOLUTE ln_pred%,ADD(timerequest ,4) ! ABSOLUTE ln_type|,ADD(timerequest%,8) ! ABSOLUTE ln_pri|,ADD(timerequest%,9) ! ABSOLUTE ln_name%,ADD(timerequest%,10) ! ABSOLUTE mn_replyport%,ADD(timerequest%,14) ABSOLUTE mn_length&,ADD(timerequest%,18) ABSOLUTE io_device%,ADD(timerequest%,20) ABSOLUTE io_unit%,ADD(timerequest%,24) ABSOLUTE io_command&,ADD(timerequest%,28) ABSOLUTE io_flags|,ADD(timerequest%,30) ABSOLUTE io_error|,ADD(timerequest%,31) ABSOLUTE tv_secs%,ADD(timerequest ,32) ABSOLUTE tv_micro%,ADD(timerequest ,36) RETURN PROCEDURE delete.extio extio%) ! BYTE ADD(extio%,8)}=-l ! LONG ADD(extio%,14)}=~1 ! LONG ADD(extio%,20)}=-18 ! ~MFREE(extio%,WORD ADD(extio%,18))) RETURN PROCEDURE ouvre.device ! Ouverture du timer.device erreur%=OpenDevice(V:dispositif$ ,unit_microhz%,timerequest%,unit vblank%) PROCEDURE copie.cercle COLOR 3,0 ~Disable() FOR rayon%=33 TO 38
- DrawEllipse(rastport%,92,110,60,rayon%) NEXT rayon%
- Enable() chiffre ! Le cadran GET 20,70,160,150,horloge$ COLOR 1 GRAPHMODE 0 ! OR TEXT 215,253,"Code PPL & CL" i Copyright cmd_invali d& = 0 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 tr_addrequest&=ADD(cmd_nonstd&,0) tr_getsystime&=ADD(cmd_nonstd&, 1) tr_setsystime&=ADD(cmd_nonstd&,2) RETURN PROCEDURE chiffre COLOR 3,0 TEXT 80,78,"XXII" TEXT 86,147,"VI" TEXT 25,113,"IX" TEXT 143,113,"III" RETURN programme PROCEDURE programme met•écran prEcalcule copie.cercle vaçiable crEation.port ouyre.device crEation.structure REPEAT charge.heure traduct.heure a f f i che.heure bip.heure UNTIL MOUSEK fin SYSTEM RETURN PROCEDURE crEation.port timerport%=CreatePort(0,0) IF timerport%=0 SYSTEM ? CODAGE Pierre Philippe Launay ? ? GRAPHISME Inconnu Domaine Public ? ? SCENARIO Catherine Lardy ? ? COPYRIGHT Mai 1991 ? ? EXTRAIT DE Annabella 3 exemple 2 ? ? * ? Résidence les Cottages-83 rue André ? ? Theuriet- F63000 CLERMONT-FERRAND ?
* *************************************** IF erreur% >0
- DeletePort(timerport%) delete.extio(timerequest SYSTEM ENDIF RETURN PROCEDURE variable A unit_microhz%=0 ! Unit_vblank%=1 REM dispositif$ =11 timer .device"+CHR$ (0) ?TIMER DEVICE
• * ***** ; Puis on passe à la troisième partie, qui ne dure que le temps que reste enfoncé le bouton de la souris. COLOR 18 TEXT 8,6,"GFA EST PLUS RAPIDE QUE LE C DE 10 %" ! La preuve GRAPHMODE 1 I Normal GET 0,0,297,7,titre$ ! Plus rapide RETURN PROCEDURE met.écran ! L'image DIM c%(31),bp%(4),a$ (4) ! Listes c%() et bp%() et a$ () FOR remplissage&=0 TO 4 ! Depuis remplissage&=0 jusqu'à 1 a$ (remplissages)=SPACE$ (10641) NEXT remplissage& ! Fin du bloc FOR NEXT b$ =SPACE$ (129) INLINE bpl%,10641 INLINE bp2%,10641 INLINE bp3%,10641 INLINE bp4%,10641 INLINE bp5%,10641 INLINE cou%,129 SWAP bp%(0),bpl% ! Echange des valeurs de bpl% et bp%(0) SWAP bp%(l),bp2% ! Echange des valeurs de bp2% et bp%(l) SWAP bp%(2),bp3% ! Echange des valeurs de bp2% et bp%(l) SWAP bp%(3),bp4% ! Echange des valeurs de bp2% et bp%(l) SWAP bp%(4),bp5% ! Echange des valeurs de bp2% et bp%(l) OPENS 1,0,0,320,256,5,0 ! N° 1 X320 x Y256 x 4Couleurs Standard OPENW 0,0,0,320,256,0,&H1800 ! Activate Borderless ecranl%=SCREEN(l) ! Pointeur sur la structure écran N° 1 FOR couleur%=0 TO 31 ! Lecture des couleurs SETCOLOR couleurs,LONG ADD(cou%,MUL(couleur%,4))) NEXT couleur% FOR plan%=0 TO 4 BMOVE bp%(plan%),V:a$ (plan%),10641 ! Copie 10641 octets de bp%(0) sur a$ (0) NEXT plan% SPUT a$ () I Affiche la première image rastport%= ADD(WINDOW(0),50)} ! Pour la fonction C DrawEllipse RETURN PROCEDURE prÉcalcule ! Résultats précalculés DIM cossec%(60),sinsec%(60),cosmin%(60),sinmin%(60) DIM cosheure%(24),sinheure%(24),secondex%(3),secondey%(3) DIM gamme%(3) centrex%=92 centrey%=110 FOR top%=0 TO 59 top2%=SUB(MUL(top%,6),90) cossec%(top%)=ADD(COSQ(top2%)*60,centrex%) sinsec%(top%)=ADD(SINQ(top2%)*33,centrey%) cosmin%(top%)=ADD(COSQ(top2%)*70,centrex°*) sinmin%(top%)=ADD(SINQ(top2%)*35,centrey%) NEXT top% cosheure%(0)=centrex% s inheure%(0)= SUB(centrey%,2 0) FOR top%=l TO 23 top2%=SUB(MUL(top%,30),90) cosheure%(top%)=ADD(COSQ(top2%)*30,centrex%) s inheur e% ( top% ) =ADD ( SINQ top2%) *20, cent rey% ) NEXT top% secondex% 1)=centrex% secondey%(1)=centrey% secondex%(2)=centrex% secondey%(2)=centrey% gamme%(0)=523 ! Do gamme%(l)=659 ! Mi gamme%(2)=784 ! Sol gamme%(3)=1046! Do octave%=l DEFFILL 2,2,21 ! Tramme des secondes RETURN PROCEDURE son(frequence%) 1 La flemme d' écrire SOUND frequence%,2 ! Son 880 hertz (LA) durant 2 cycles pause(1,0) I Délais de 1 seconde 0 bip RETURN PROCEDURE affiche.heure ! La montre qui tient ses promesses IF OR(temoin%osecondes%, secondes%=0 ) COLOR 2,0 ! L' aiguille des secondes secondes(0)=cossec%(secondes ) secondey%(0)=sinsec%(secondes ) secondex%(3)=secondex%(0) secondey%(3)=secondey%(0) ' PUT 20,70,horloge$ ! Dessin de 1' horloge déjà saisie POLYFILL 4,secondex%(),secondeÿ%() chiffre I Le cadran COLOR 4,0 ! Les aiguilles heures minutes LINE centrex%, centrey%, cosmins&(minutes%), sinmin%(minutes%) LINE centrex%,centrey%,cosheure%( heures0*), s inheur e%( heur es%) secondex%(2)=cossec%(secondes ) secondey%(2)=sinsec%(secondes ) COLOR 2,31 temoin%=secondes% ENDIF RETURN PROCEDURE bip.heure SELECT secondes CASE 0 ! Top top top top ! Flash au début de chaque minute PUT 20,70,horloge$ ! Dessin de l'horloge déjà saisie test.heure ! Changement de seconde COLOR 3,30 ! Changement de couleur du fond TEXT 10,6,"Il est très exactement sur Amiga pause(0,2) I Délais de 0 seconde 2 bips son(1000) ! Son 1000 hertzs durant 2 cycles son(800) ! Son 800 hertzs durant 2 cycles son(600) ! Son 600 hertzs durant 2 cycles PUT 0,0,titre$ j itself DEFFILL 2,2,SUCC(minutes% MOD 24) J Tramme de remplissage CASE 5,10,15,20,25,30,35,40,45,50,55 ! Toutes les 5 secondes test.heure ~DisplayBeep(0) ! Flashage de tous les écrans son(1446) octave%=SUCC(RAND(4)) DEFAULT test.heure * son(MUL(gammes(son%),octave%)) son%=SUCC(son%) MOD 4 ENDSELECT RETURN PROCEDURE charge.heure ! Le Load Heure io_command&=tr_getsystime& ! La commande ~DoIO(timerequest%) ! Mise en action du périphérique ' Fin au signal de fin donné alors par le timer.device seconde%=tv_secs% i C'est fait:on obtient les secondes tick%=tv_micro% ! Et les microsecondes RETURN PROCEDURE pause(secondes ,tick%) ! L' ultra précision FOR temps°*=l TO ADD(MUL(secondes%, 100), tick°*)
- DisableO ! Système presque complètement gelé xo_commandfc=tr_addrequest& ! Attente du temps imparti tv_secs%=0 tv_micro%=l ~DoIO(timerequest%) ! Mise en action. C' est déjà fini. Dégèlement de 1' Amiga La boucle n' est qu' un petit gag d'accélération temporelle Pour comparer
- Enable() ! NEXT temps ô ! RETURN J PROCEDURE test.heure ! TEXT 56,160,TIME$ TEXT 40,168,DATE$ TEXT 48,176,STR$ (seconde ,9) tick$ =STR$ (tick%) tick$ =STRING$ (SUB(6,LEN(tick$ )),"0")+tick$ TEXT 72,184,tick$ RETURN PROCEDURE traduct.heure ! En bon français bien de chez nous seconde indique le nombre de secondes depuis la création heures%=DIV(seconde ,3600) MOD 24 ! 24 heures de 3600 secondes mxnutes%=DIV(seconde%,60) MOD 60 ! 60 minutes de 60 secondes secondes%=seconde% MOD 60 RETURN
- DeletePort(timerport%)
- CloseDevice(timerequest%) delete.extio(timerequest%) SYSTEM END ! 60 secondes par minute Abolition du port du timer Libération du device Destruction de la structure Fin du programme la plus sûre La fin durant le codage Voici la preuve que le GFA est plus rapide que le C. Puisque vous me lisez vous saviez aussi que ce langage est beaucoup plus simple à manier que le C. En résumé, GFA est un langage simple et puissant. Pierre Philippe TEXT 2,75,"15 secondes de noir complet dès le clic" WHILE MOUSEK WEND REPEAT UNTIL MOUSEK SPUT a$ () GRAPHMODE 0 TEXT 215,253,"Code PPL & CL" ! Copyright seconde%=0 tick%=0
- CurrentTime(V: seconde ,V:tick%) ! Retourne 1' heure locale COLOR 10 TEXT 10,75,"EXEMPLE 2 AVEC CURRENTIME" COLOR 4 TEXT 10,85,"Seconde Système"+STR$ (seconde ,10) TEXT 10,95,"Tick Système "+STR$ (tick%,10) durEe%=15 ! En seconde pour ne pas se quiquiner COLOR 3,2 TEXT 10,105,"Départ du chronométrage " COLOR 1,0 TEXT 10,114,"Durée :"+STR$ (durÉe%,3)+" secondes" compteur%=0 ! Quelques variables departsec%=0 departtick%=0 chronosec%=0 chronotick%=0 DISPLAY OFF REPEAT J Départ synchro à la seconde suivante
- CurrentTime(V: départsec%,V: départtick%) UNTIL départsec% >seconde% REPEAT ' ••• i Mettre ici les instructions à tester INC compteur
- CurrentTime(V:chronosec%,V:chronoÇick%) UNTIL SUB(chronosec%,départsec%)>durEe% delais%=SUB(chronosec%,departsec%) MUL délais ,1000000 ! Résultat en microseconde COLOR 3,2 TEXT 10,123,"Fin du chronométrage " COLOR 1,0 TEXT 10,132,"Boucles "+STR$ (compteur ,10) TEXT 10,140, "Délais "+STR$ (delaisVcompteur%-62,10)+" 10A6" COLOR 4 TEXT 10,152,"En tournant à vide, GFA met 64 cycles" GRAPHMODE 1 ! 70 et 64 pour un plan de bits sans DISPLAY OFF TEXT 10,162,"En Latice C on enlève 70 pour avoir 0" TEXT 10,170,"En GFA on enlève 64 pour avoir 0" COLOR 30,4 TEXT 10,179," Attention : on est en multitâche 11 TEXT 10,187," Résultats variants de 62 à 66 " TEXT 10,195," Et selon le nombre de Plan de bits " PUT 10,200,titre$ DISPLAY ON t ' Je remercie BatchMan pour sa contribution au Basic GFA. REPEAT UNTIL MOUSEK SWAP a$ (0),a$ (1) SPUT a$ () TEXT 15,75,"Passez une bonne et agréable journée" TEXT 199,253,"Pierre Philippe" WHILE MOUSEK WEND RETURN eti§3*0*lippe L .LESJJSTES CHAINEES Cette nouvelle rubrique "Algorithmes et structures de Données" aura pour but de vous présenter chaque mois un exemple d’utilisation des structures de données, à travers quoi ? A travers un algorithme, oui. Supprimons maintenant deux éléments, "Bruno" et "Lucien" (cf. Schéma 4). Bien que nous ayons supprimé deux prénoms, le tableau conserve sa taille initiale et les "cases" non utilisées occupent toujours de l’espace mémoire. Au contraire, la liste chainée est réduite à son strict minimum. Les emplacements occupés par les noeuds supprimés ont été restitués au système. Aborder les listes pour commencer, P our notre premier article, nous allons doublement et simplement chaînées. Et une petite définition : une liste chaînée est une structure de données dynamiques. Il s’agit d’un noeud composé de deux parties : un morceau information et un autre morceau, appelé lien, qui permet de chainer les noeuds entre eux. Le schéma ci- dessous résume parfaitement la structure d’une liste chaînée. TABLEAU PIERRE information l lit! » iÉiialioiiî h 4 iÉitnlioiiî m I n dicc; LISTE STATIQUE, DYNAMIQUE DIFFERENCES H IL PIERRE Afin de bien comprendre ce qui effectuons un parallèle entre le (dynamique). Le tableau sépare ces deux organisations, tableau (statique) et la liste PRIMITIVES Maintenant que les listes nous sont familères, nous allons étudier les différentes opérations que nous pouvons leur faire subir. Les primitives sont en pseudo-code et elles concernent les listes simplement et doublement chainées.
• taille prédéfinie : il faut connaître à l’avance ses besoins en espace de façon bien précise. En effet, la taille du tableau doit être initialisée dans le code source du programme.
• taille figée : cette deuxième restriction découle de la première. En effet, une fois le code source compilé, l’on ne peut plus modifier (de façon décente) la taille d’un tableau, et ceci pendant toute la durée d’éxécution du programme. La liste chaînée
• taille non prédéfinie : l’on n’est pas obligé de connaître la quantité exacte de données nécessaires à l’application. Le schéma 1 montre très bien que rien n’empêche d’ajouter un autre noeud à la liste.
• taille modulable : l’on peut aussi supprimer un élément de la liste. De ce fait, nous voyons que notre liste peut croître ou décroître à volonté. Ceci est d’autant plus intéressant que toutes ces modifications peuvent intervenir pendant l’éxécution du programme, en fonction des besoins de l’utilisateur. Exemple : un répertoire téléphonique comporte trois noms. Représentons-les à l’aide de nos deux types de structures (cf. Schéma 2). Jusque là, tout est correct. A présent, ajoutons un élément "Franck" (cf. Schéma 3). Nous venons de voir à quel point il est facile d’ajouter un élément dans la liste. En revanche, le tableau n’accepte pas le nom supplémentaire, car il n’y a plus de place. 12 La liste double ne diffère de la simple que par la présence d’un lien supplémentaire, qui relie chaque noeud à son prédécesseur, permettant ainsi de parcourir la liste dans les deux sens. Insertion AVA HT INSERTION NIL information 1 @2 information 2 NIL @2 NIL information X NIL (n 1 : adresse du noeud 1 @2 : adresse du noeud 2 (SH : adresse du noeud à insérer HOEUD A INSERER
(1) noeud2_adr - noeudl.suivant ;
(2) noeudl.suivant - nouveau_noeud;
(3) nouveau_noeud.précédent - noeudl;
(4) nouveau_noeud.suivant - noeud2_adr;
(5) noeud2_adr.précédent - nouveau_noeud; Les étapes (3) et (5) ne concernent pas les listes simplement chainées.
(1) noeudl.suivant - noeud2.suivant; Suppression
(2) noeud3_adr - noeud2.suivant;
(3) noeud3_adr.précédent - noeudl; Seule l’étape (1) est nécéssaire aux listes simplement chainées. APPLICATION Après avoir été très théoriques, passons à des exemples pratiques. Les programmes présentés ci-dessous permettent d’insérer et de supprimer des noeuds d’une liste. L’insertion se fait en fin de liste, alors que la suppression se fait par la recherche de l’élément à supprimer. Le source Pascal traite le problème à travers une liste simplement chaînée, tandis que celui en C utilise une liste doublement chaînée (NDLR : pour des raisons évidentes de manque de place, le listing C ne sera pas publié dans cette rubrique. Retrouvez-le donc sur la disquette !). Avant que de nous quitter, sachez que vous pouvez nous joindre sur Minitel (3615 ANT, Bal SLEEPER). Nous répondrons dans la limite du possible à vos questions. Vous pouvez même déposer quelques suggestions au sujet d’algorithmes particuliers que vous désireriez voir traiter dans cette rubrique. compilation PCQ: } Pascal srcl.pcq srcl.asm } A68k srcl.asm > Blink srcl.o to srcl library pcq.lib } Program liste_chainee ; définition des modèles } type noeud Record num : integer ; structure de la liste > champ info ; ici un numéro } 'noeud; pointeur sur le noeud suivant } suivant end; lien = Anoeud ; var element_courant : lien ; nécessaire pour parcourir la } liste sans perdre le début } begin element_courant := début ; se place au début } afficher le num du noeud courant tant que son pointeur} suivant est différent de la fin de liste } while (element_courantA.suivant > NIL) do begin writeln ('numéro : ', element_courantA.num) ; element__courant := element_courantA.suivant ; end ; afficher le numéro du dernier noeud } writeln ('numéro : element_courantA.num) ; end ; procédure inséré(info : integer) ; var element_courant, element_insere : lien ; begin element_courant := début ; recherche de la fin de liste afin d'y ajouter un noeud } while (element_courantA.suivant > NIL) do element_courant ;= element_courantA.suivant ; allocation de l'espace mémoire pour le nouveau noeud } new (element_insere) ; element_courantA.suivant := element_insere ; element_insereA.num := info ; element_insereA.suivant := NIL ; affiche_liste ; end ; procédure supprime(info2 : integer) ; var element_courant, element_supprime : lien ; begin element_courant := début ; detecte le noeud a supprimer et la fin de liste } on va toujours vérifier le numéro du noeud suivant } de ce fait on empeche la suppression de début si} l'on saisit 0 comme num } while (element_courantA.suivantA.num > info2) and (element_courantA.suivant > NIL) do element_courant := element_courantA.suivant ; test pour savoit si fin de liste ou numéro trouve } if (element_courantA.suivant > NIL) then begin element_supprime := element_courantA.suivant ; element_courantA.suivant := element_supprimeA.suivant ; dispose (element supprime) ; end else writeln ('1 element n existe pas') ; affiche_liste ; end ; begin choix := 0 ; new(début) ; débutA.suivant := NIL ; débutA.num := 0 ; repeat writeln ('1 insérer numéro') ; writeln ('2 supprimer numéro') ; writeln '9 sortir') ; write ('votre choix : ') ; readln (choix) ; case choix of 1 : begin write ('numéro a insérer : ') ; readln (numéro) inséré(numéro) ; writeln ('pressez enter pour continuer') ; read (key) ; end ; 2 : begin write ('numéro a supprimer : ') ; readln (numéro) ; supprime(numéro) ; writeln ('pressez enter pour continuer') ; read (key) ; end ; end ; until (choix =9) ; dispose (début) ; end. déclaration des variables } lien début pointeur qui mémorisera le } début de notre liste } P il r Pu c i c n 7 il r s k i - A7 ci r c o n et B r u n o B ci i II a c t choix : integer ; numéro : integer ; key : char ; procédure affiche_liste ; VOIX DE PAULA HARDWARE Ah, quelle belle chose que d’avoir un ordinateur capable de générer autre chose que de vulgaires petits bips .. L’Amiga est, comme chacun sait, assez riche dans ce domaine puisqu’il dispose de quatre canaux sonores indépendants pour ravir vos oreilles en stéréo. $ DFF0+8 Volume du son (16 bits) AUD*VOL Juste une note pour ce registre : seuls les 6 bits inférieurs définissent le volume. Le volume maximal est donc de 63 et une valeur de 0 le coupe totalement. Les autres bits n’ont aucune utilité. Enfin, voici quelques notes supplémentaires sur ces addresses :
- elles sont uniquement accessibles en écriture ;
- le signe * représente le numéro du canal (0 à 3) ; $ C
- le signe + signifie égale $ A pour le canal 0, $ B pour le canal 1, pour le canal 2 et $ D pour le canal 3. Et qui doit-on complimenter pour celà ? C’est Paula (et accessoirement Agnus pour les transferts DMA). Mais ses pouvoirs ne s’arrêtent pas à un simple "recrachage" de samples. En effet, cette diva est capable de moduler l’amplitude et la fréquence de sortie d’un ou plusieurs canaux sonores afin de produire les effets voulus. Et si cela ne vous suffit pas, alors vous pouvez toujours faire joujou avec le filtre passe- bas mis à votre disposition. A QUOI TU JOUES, PAULA ? Un son étant une vibration, il est défini par deux critères : son amplitude et sa fréquence. Cette dernière définira si un son est grave ou aigu (plus la fréquence est élevée, plus le son est aigu). L’amplitude moyenne définit la puissance d’un son (ou le volume), tandis que les variations de cette même valeur définissent le son lui-même. La table de données transmise à Paula sera donc une suite d’amplitudes instantanées. Cette table sera découpée en octets, ce qui autorise des amplitudes de +127 à -128. Paula aura bien entendu besoin d’autres renseignements sur le son avant de le jouer : son adresse, sa longueur, sa période (correspondant à la fréquence du signal) et son volume (force avec laquelle il sera joué). Mais voyons tout de suite les registres mis en cause. AUD*LCH $ DFF0+0 Adresse du son (3 bits hauts) AUD*LCL $ DFF0+2 Adresse du son (16 bits bas) Ces deux registres peuvent bien entendu être initialisés en même temps de la façon suivante à l’aide d’une seule instruction 68000 MOVE.L. Notez que les données doivent se trouver en mémoire CHIP. $ DFF0+4 longueur du son (16 bits) AUD*LEN La longueur de l’échantillon est exprimée en mots. On remarque donc que le maximum est de 128 Ko... C’est déjà pas mal, non ? $ DFF0+6 Période du son (16 bits) AUD*PER Cela permet de fixer la rapidité de restitution de l’échantillon. Le nombre transmis dans ce registre s’exprime en cycles machines. Pour ceux qui préfèrent parler de fréquence (en octets par seconde), voila la formule de conversion : PERIODE = l (FREQUENCE) 279,365.10-9 Le dernier nombre n’est autre que la durée d’un cycle machine pour le 68000. Sachez de plus que le circuit audio a tout de même des limites du fait de sa synchronisation avec l’écran : sachant qu’il charge un mot de données sonores par ligne écran, on obtient une fréquence théorique maximale de (2 octets * 262.5 lignes écran * 59,94 écrans seconde), soit 31469 octets seconde. Mais tout ceci reste théorique : comme le contrôleur n’a pas que ça à faire, la fréquence maximale est de 28867 octets seconde, soit encore une période de 124 cycles. Si malgré celà, vous mettiez une valeur inférieure à 124 dans ce registre, Agnus n’aura pas forcément le temps de charger la donnée audio et c’est l’ancienne qui sera utilisée, d’où une déformation du son. DIS PAPA, COMMENT CA MARCHE ? Maintenant que vous connaissez les registres qu’il faut utiliser, on va pouvoir passer à la pratique. Nous allons débuter par une simple émission de son en mode automatique : Paula s’occupe de tout... ou presque. Tout d’abord, on initialise de la façon indiquée les registres décrits plus haut, et ceci pour chaque canal à mettre en oeuvre. Pour lancer le(s) son(s), il suffit alors d’autoriser les canaux DMA nécessaires (bits 9 et 0 à 3 du registre DMACON). L’émission du son commencera aussitôt et se poursuivra jusqu’à ce qu’on la stoppe : Paula, après avoir lu le nombre de mots indiqué dans AUD*LEN, se replacera automatiquement au début des données (hmmm, les belles digits bouclées). Pour stopper toute émission sonore, il suffit d’effacer les bits de DMACON correspondant aux canaux à bloquer. Notez que si vous remettez en route ces canaux DMA, PAULA recommencera le son du début, à une exception près : si l’intervalle de temps écoulé entre la coupure et la remise en route est inférieur à 2 fois la période, alors la lecture se poursuivra de là où PAULA l’avait laissée (ce phénomène sera expliqué ultérieurement). Arrivé ici, un rappel des bits important de DMACON n’est sans doute pas inopportun. $ dff096 (écriture) $ dff002 (lecture) DMACON DMACONR Bit Nom 15 SET CLR 9 DMAEN 3 AUD3EN 2 AUD2EN 1 AUDIEN 0 AUD0EN Fonction Lorsque ce bit est mis peuvent être utilisés. DMA sont bloqués En mettant ce bit à 1, on démarre la sortie audio du canal 3 (gauche). En effaçant ce bit, on interrompt la sortie Idem pour le canal 2 (droite) Idem pour le canal 1 (droite) Idem pour le canal 0 (gauche) tous les canaux DMA S'il est à 0, les canaux Note : lors d’une écriture, si le bit 15 SET CLR est mis, tous les autres bits à 1 du mot transféré sont mis à 1 dans DMACON, ceux à 0 restant inchangés. Si SET CLR est à 0, tous les bits à 1 de la source seront effacés dans la destination, ceux à 0 restant inchangés. ACTION ! Voilà un petit exemple pour achever de vous convaincre de la facilité de la chose... START SON: move.1 DATA_SON,$ DFF0A0 ; ADRESSE move.w 0001,$ DFF0A4 LONGUEUR en mots move.w 5000,$ DFF0A6 PERIODE move.w 0050,$ DFF0A8 VOLUME move.w $ 8201,$ DFF096 ; Envoie canal 0 _WAIT: btst 6,$ BFE001; bouton gauche bne. S BOUCLE_WAIT ; de la souris move.w 0001,$ dff096 ; SILENCE ! (*) rts DATA_SON:
dc. B 120,-120; Signal carré... Rien de plus simple (*) Vous remarquerez que je n’ai pas mis le bit 9 de DMACON à 0. En règle général, il vaut mieux s’abstenir, car celà interdirait tout travail du DMA. Pour être rigoureux, il faudrait le remettre comme il était avant. OH, PAULA, TU ME FAIS DE L’EFFET ! On peut distinguer deux sortes de modulations possibles : la modulation d’amplitude (volume) et la modulation de fréquence (période). La première pourra servir à faire des effets du type vibrato, trémolo, imitation du rapprochement ou de Péloignement d’un son, etc... La seconde permet entre autres de simuler des accords. De plus, il est possible de combiner les deux modulations. Bref, les possibilités sont énormes. Seule ombre au tableau : pour moduler une voix, on est obligé d’utiliser deux canaux consécutifs. Le premier (celui de plus basse numérotation) sert pour l’enveloppe et le second (celui de plus forte numérotation) sert pour le son de base. Les registres des canaux sont initialisés comme s’il s’agissait de sons ordinaires (il est toutefois inutile d’initialiser le volume du canal de modulation, puisque celui-ci ne sera pas joué). Par contre, pour le canal de modulation, la table de données n’est plus composée d’octets mais de mots représentant soit un volume (0 à 64) soit une période (avec les mêmes restrictions que celles citées plus haut). Si vous voulez faire une modulation en fréquence et en amplitude à la fois, la table doit contenir alternativement un volume et une période, dans cet ordre. Dans ce dernier cas, Il y aura deux lectures au lieu d’une afin que les modulations se fassent simultanément et non l’une après l’autre. Pas besoin donc de toucher à la période pour compenser. Une fois que vous avez initialisé correctement les registres de deux canaux consécutifs et fait votre table de modulation, il vous suffit de les "lier" pour la modulation à l’aide du registre ADKCON (qui sert aussi au pilotage des lecteurs de disquettes, alors soyez prudent). ADKCON $ dff09E (écriture) ADKCONR $ dffl)10 (lecture) Bit Nom Fonction 15 SET CLR Même fonctionnement que pour DMACON 7 ATPER3 Si ce bit est mis, la voix 3 ne module la période d'aucune autre voix (celà « a pour effet de la couper) 6 ATPER2 Si ce bit est mis, la voix 2 module la période de la voix 3 5 ATPER1 Même chose avec les voix 1 et 2 4 ATPER0 Même chose avec les voix 0 et 1 3 ATVOL3 Si ce bit est mis, la voix 3 ne module le volume d'aucune autre voix (celà a pour effet de la couper) 2 ATVOL2 Si ce bit est mis, la voix 2 module le volume de la voix 3 1 ATVOL1 Même chose avec les voix 1 et 2 0 ATVOLO Même chose avec les voix 0 et 1 (modulation d’amplitude avec une table composée de seulement deux valeurs, à savoir 0 et 64). Une fois que vous avez lié les deux canaux choisis, il ne reste plus qu’à autoriser le transfert DMA sur ces deux canaux avec DMACON (comme pour des sons ordinaires). L’effet sera le suivant : le son de base sera joué sur la voix la plus haute des deux. Il utilisera comme volume ou fréquence (ou les deux) les mots chargés à chaque période du canal de modulation. Notez que ces mots sont chargés à l’adresse du volume où de la fréquence du canal modulé. Si vous arrêtez la modulation, n’oubliez pas de réinitialiser le volume ou la fréquence des canaux modulés et de couper les canaux DMA des canaux modulants. Une dernière note : rien n’empêche de moduler un canal "à la main" en tripatouillant le volume ou la fréquence du canal voulu. Cela évitera d’utiliser deux canaux, mais adieu synchronisation et facilité d’emploi (sans compter que le 68000 sera alors utilisé en permanence pour le son). Enfin, ça peut toujours servir... ACTION 2, LE RETOUR ! Et voilà l’exemple tant attendu qui prouve une fois encore que ce n’est pas si compliqué que ça en a l’air. La suite de ce passionnant article dans notre prochain numéro. STARTSON: ; CANAL DE MODULATION ; MODULATION en fréquence move.1 DATA__MOD, $ DFF0A0 ; ADRESSE ; move.1 DATA_MOD2,$ DFF0A0 ;-> pour mod. Amplitude ; move.1 DATA_MOD3,$ DFF0A0 ;-> pour les deux mod. Move.w 0008,$ dff0A4 ; LONGUEUR en mots ; move.w 0016,$ dff0A4 ; -> pour les deux mod. Move.w 40000,$ DFF0A6 ; PERIODE ; SON DE BASE move. 1 DATA_SON,$ DFF0B0 ; ADRESSE move.w 0001,$ DFF0B4 ; LONGUEUR en mots move.w 5000,$ DFF0B6 ; PERIODE move.w 0050,$ DFF0B8 ; VOLUME move.w $ 8010,$ DFF09E ; On lie 0 et 1 ; move.w $ 8001,$ DFF09E ;-> pour mod. Amplitude ; move.w $ 8011,$ DFF09E ;-> pour les deux mod. Move. W $ 8203,$ DFF096 ; Envoit 0 et 1 BOUCLERAIT : btst 6,$ BFE001 ; bouton gauche bne. S BOUCLERAIT ; de la souris move.w $ 0011,$ dff09E ; FIN MODULATION move.w $ 0003,$ dff096 ; SILENCE ! Rts DATA_SON:
dc. B 120,-120; Toujours un signal carré... DATA_MOD:
dc. W 1000,2000,3000,4000,5000,6000,7000,8000 ; Ici, il s'agit d'un signal triangulaire DATA_MOD2:
dc. W 2,8 10,20,30,40,50,60 DATA_MOD3:
dc. W 2,1000,8,2000,10,3000,20,4000
dc. W 30,5000,40,6000,50,7000,60,8000 Note : les bits 7 et 3 ont le même effet : ils coupent tous les deux la voix 3, qui est la plus haute et ne peut donc pas en moduler d’autre. Bien qu’aucun son ne sorte, les données continuent à être chargées normalement par Agnus. Ces deux bits identiques n’ont en fait aucune utilité. On peut à la limite s’en servir pour créer un morcellement de la sortie audio dans la voix 3 (un coup rien, un coup de la musique et ceci à la fréquence avec laquelle vous mettez et enlevez ce bit). Mais il . | existe d’autres méthodes pas plus contraignantes pour faire cela *> Par PhHippénivaïtTon Ëtl, ¦ > 1 t • j 1 Ces derniers temps, les plasmas ont déferlé sur vos écrans... Encore un effet que seul Vamiga était capable d’offrir, et qui se révèle d’une étonnante simplicité. $ 0020,dmacon(a5) $ 8400,dmacon(a5) CALLEXECForbid move.b *10000111,$ bfdl00 lea CUSTOM,a5 Le principe est simple : il suffit de créer une enôôôrme CopperList qui ne contient quasiment que des instructions de changement de couleur. Classiquement, les changements de couleur se font au début de la ligne de raster (ce qui donne les effets de "barres de Copper" bien connus), mais ici, on change la couleur plusieurs fois durant la même ligne (en l’occurence 53 fois). Il n’y donc aucune image ’réelle’ affichée (0 bitplanes), seulement des changements de couleur, mais le résultat est saisissant ! De plus vous pouvez toujours ajouter une image par dessus ou par dessous ces plasmas. Les couleurs mises dans la CopperList sont prises dans un tableau (tabcol) puis rangées dans la CopperList à l’aide du Blitter pour plus de rapidité. Deux mouvements de sinus sont appliqués lors du transfert, ce qui donne cet effet de vague sur la composante x. Une double superposition de sinus est appliquée aussi sur y, en jouant sur le retard vidéo à chaque ligne. Le mouvement est donc composé de quatre sinus, deux sur X et deux sur Y. Il y a donc huit paramètres qui déterminent le mouvement : la vitesse de déplacement et le pas entre deux sinus consécutifs, et ce pour les quatre sinus, ce qui nous fait bien huit paramètres. Je vous conseille de modifier ces paramètres et d’observer le résultat. Vous pouvez aussi modifier le dégradé de couleurs pour en mettre un de votre crû. Il faut noter qu’il y a deux CopperLists, une qui est affichée tandis que l’autre est modifiée. Et à la prochaine trame, on inverse ces deux CopperLists. C’est l’equivalent du "double buffering" pour les CopperLists. Pour créer la table de sinus (qui est un tableau de 256 octets) il suffit de taper le petit programme GFA suivant : OPEN "o", 1,"datasin" FOR i=0 TO 255 val=INT(127*SIN(i*2*PI 256)) OUT 1,val NEXT i Il est facilement adaptable pour l’AmigaBasic. Il ne reste plus qu’à assembler le programme Plasma.s et à l’exécuter. Bon coloriage ! ; ; PLASMA T.Landspurg 91 ; ? A assembler sous devpac opt c+,o+,ow- NB_COL_COP=53 ; Nb de changements de couleurs par ligne NB_LIG_COP=264 ; Nombre de lignes de la plasma NB_BYTEPLASMA=(NB_COL_COP+l+l)*4 taillecop=20+(NB_COL_COP+2)*4*NB__LIG_COP; Taille de la copperlist NB_DEG=15*3 ; Utilise pour la création de dégradé NB_REP=10 ; idem CUSTOM=$ dff000 ; Registres hardware incdir "include:" include exec exec_lib.i- include hardware eustom.i ; DEBUT DU PROGRAMME start: lea b(pc),a4 ; a4 POINTE TOUJOURS SUR LA BASE! Lea graphname(pc),al; Ouverture de la graphies CALLEXECOpenLibrary move.1 d0,graphbase-b(a4) bsr initcop ; initialise la copper list bsr init col ; initialisation des couleurs de waitbout: ; BOUCLE PRINCIPALE sync: btst 0,vposr+l(a5) bne.s sync syncl: cmp.b 40,vhposr(a5) ; Syncronisation bne.s syncl movem.l p_coplist(pc),d0 dl exg dO,dl movem.l d0 dl,p_coplist-b(a4) move.l d0,copllc(a5) copjmpl(a5) move_plasma clr .w bsr btst bne out : move. W move.1 move.1 move.1 CALLEXEC Permit move.1 graphbase(pc),al ; CALLEXEC CloseLibrary move.w $ 0400,dmaconr(a5) move.w $ 8020,dmaconr(a5) moveq 0,d0 rts save_intena:dc.w 0 waitblit:macro waitblitW: 14,dmaconr(a5) waitblit @ 6,$ bfe001 ; Test le bouton de la souris waitbout save_intena-b(a4),intena(a5) ; interuption graphbase(pc),aO ; Restaure l'ancienne copperlist oldcop-b(a4),$ 32(aO) $ 26(aO),copllc(a5) On referme la libraire btst bne endm graphname:de.b even graphies.library',0 graphbase:de.1 0 LA COPPER LIST ; INITIALISATION DE initcop: lea coplist,a0 move.w NB_LIG_COP move.w $ 2a31,d0 ; ¦1, d7 Première ligne de 1'écran pour une ligne de plasma next_lig_plasma: ; move.w dO,(aO)+; le wait move.w $ fffe,(a0)+ move.l $ 01020000,(a0)+ ; add.w $ 0100,dO moveq.w NB_COL_COP-l, d6; move.w d7,dl ; decalage horizontal prochaine ligne on met le changmenents de couleur pour une ligne donnée next_col_plasma: ; add.w move.w move.w add.w move.w move.w next_lig_plasma2 and.w d5,dl and.w move.b ext. W move.b ext .w add.w asr .w add.w bset d5,d2 (a2, dl. W) , d3 d3 (a2,d2.w),d4 d4 d4,d3 4,d3 $ 20,d3 0, d3 move.1 $ 1800000,(aO)+ dbf d6,next_col_plasma dbf d7,next_lig plasma move.1 $ 01000000,(a0)+; 0 bitplane move.1 $ fffffffe,(aO)+; fin de la i lea coplist,aO lea coplist+taillecop,al move.w taillecop 4-l,d7 next_recopie: move.1 (aO)+,(al)+ dbf d7,next_recopie move.1 graphbase-b(a4),a0 move.1 $ 32(aO),oldcop-b(a4) rts ; MOVEMENT DES PLASMAS move_p 1a sma: move.1 lea move.w ; C'est le coeur du programme p_coplist(pc),aO; Pointeur sur la copperlist tabsin(pc),a2 ; Tableau de sinus $ ff,d5 ; =taille de la table de sinus D'abord on va creer les décalages sur y move.w p_sinusyl(pc),dl; première wave sur y speed_sinusyl(pc),dl dl,p_sinusyl-b(a4) p_sinusy2(pc),d2 ; première wave sur y speed_sinusy2(pc),d2 d2,p_s inusy2-b(a4) NB LIG_COP-l,d7 ; Nombre de lignes decalage sinus decalage sinus On ajoute les deux sinus decalage y de faible amplitude d3,l(a0) ; on le met dans la copperlist move.b add.w add.w lea dbf ; Maintenant les décalages sur waitblit move.w clr .w move.1 move.w clr .w move.w step_sinusyl(pc),dl step_sinusy2(pc),d2 NB_BYTE_PLASMA(aO),aO d7,next_lig_plasma2 X ; attend le blitter . $ 09f0,bltcon0(a5) bltconl(a5) ; mode suite -l,bltafwm(a5) ; Masque a -1 NB_BYTE_PLASMA-2,bltdmod(a5) ; Modulo bltamod(a5) ; En source pas de modulo ((NB_LIG_COP) 6+l),d6 ; Taille=une colonne ANCIENS NUMEROS DE L’ANT Tiens, si on profitait du fait que Thomas a écrit un article trop court, pour établir une compilation des sommaires des anciens numéros de TANT depuis Tlndépendance ? C'est parti. Numéro 20 (mars 91) AMOS Les extensions Concours Les fontes vectorielles Demos Les rastei s verticaux. ExecBase Les bibliothèques interview Franck Ostrowski SubWav 1 .es écrans ; le console.device ToolBox Devpac II vs K-Seka Utilitaire Le Screen Blanker - , Numéro 21 (avril 91) p_coplist(pc),aO tab_col_plasma+128,al p_sinusxl(pc),dl speed_sinusxl(pc),dl dl,p_sinusxl-b(a4) P_sinusx2(pc),d2; deuxième wave sur x speed_sinusx2(pc),d2 d2,p_sinusx2-b(a4) 6+4(aO),aO ; aO = début des couleurs ; première wave sur x AMOS Arexx CATS Concours Debug Demos ExecBase SubWay ToolBox Utilitaire add.w and.w and.w move.b ext .w move.b ext .w add.w asr .w lea waitblit move.l a3,bltapt(a5) aO,bltdpt(a5) d6,bltsize(a5) 4(aO),aO d7,next_col_plasma2 PCQ decalage sinus decalage sinus On ajoute les deux sinus d3 = offset dans la table AMOS Arexx CATS Concours Demos ExecBase Hardware SubWay ToolBox Utilitaire les DaisyDemOS le 68000 de A à Z (III) ; le DOS et ses devices move. 1 move.w lea dbf rts (If) tab col plasma.aO ; Table des couleurs $ fff,dO modifie la composante verte On cree trois dégradés idem avec la composante rouge -$ 110,dl cree_one_deg $ 100,dl cree_one_deg -$ l,dl cree_one_deg et la composante jaune AMOS Arexx Demos ExecBase Hardware SubWay ToolBox Transactor Utilitaire Cree un dégradé Nombre d'itérations Nombdre de fois ou l'on garde la meme couleur AMOS Arexx Demos ExecBase Hardware SubWay ToolBox Transactor Utilitaire 12: 11: move.w move.w NB_DEG 3-l,d7 NB_REP-l,d6 dO,(aO)+ dbf d6,11 add.w dl,d0 ; Prochaine couleur dbf d7,12 ; Tant qu'il y a des rts b: oldcop:
dc. L 0 p_coplist: de. 1 coplist p coplist old:
dc. L coplist+taillecop dir: de .w -1 ; Le fichier datasin est cree avec le programme GFA annexe tabsin: inebiç datasin ; Section qui contient les données section plasma,BSS_C tab_col_plasma: deb. W NB_DEG*NBREP coplist:dcb.b taillecop*2 ; Variables qui contiennent les données pour la plasma p_sinusxl:dc.w 0 p_sinusx2:dc.w 0 p_sinusyl:dc.w 0 P_sinusy2:dc.w 0 step_sinusxl:dc.w -3 speed_sinusxl:dc.w -1 step_sinusx2:dc.w -4 speed_sinusx2: de.w -1 step_sinusyl:dc.w 2 speed__sinusyl:dc.w 1 step_sinusy2:dc.w -3 speed_sinusy2:dc.w -5 ; Cree le dégradé de couleur pour la plasma init_col: lea move.w move.w bsr move.w bsr move.w bsr rts cree_one_deg: move.w move.1 lea move.w add.w move.w move.w add.w move.w lea moveq.w NB_C0L_C0P-2, d7 move.w step_sinusxl(pc),d0 next_col_plasma2 add.w dO,dl step_sinusx2(pc),d2 d5,d2 d5, dl (a2,dl.w) ,d3 d3 (a2,d2.w),d4 d4 d4, d3 1, d3 (al,d3 .w) ,a3 Source=table de couleur Destinâtion=copperlist Taille=une colonne Par Thomas La mis pur g Les Resources SAS Lmk : la Bible de Tamiga Le traqueur de virus Numéro 24 (juület cioiiLÿl} AMOS La musique Arexx La voie royale (III) CATS Question de style (U) Concours De mal en PI Demos La 3D faces pleines ExecBase Du C à l'assembleur ; le 68000 de A à Z (fin) Hardware Les disquettes SubWay La communication inter-tâches ; les menus Intuition ToolBox ReqLib & Par Net Utilitaire ScreenSaver Un interpréteur d'expressions Travail pratique (II) Scrolling "kick-otf Les overlays ; les interruptions sous Exec (II) ; la mémoire du monde (II) Les disquettes (complément) Les layers (II) Adebog ; Gawk Le bon octant ExecMaster AMOS Trucs en vrac ; les DaisyDemOS Arexx La voie royale (IV) CATS Le multitâche sur Amiga Demos La 3D faces pleines (if) ExecBase Programmer ré-entrant ; la mémoire du monde Hardware Les disquettes (II) SubWay La communication inter-tâches (II) ; le GELS ToolBox AMXLisp Transactor Gérer les ioysticks Utilitaire L’espion de la mémoire Numéro 26 (octobre 91) AMOS Les interruptions CATS Leçon de savoir-vivre Concours Un ciel étoilé Demo.s Bobs & Lissajous ExecBase Utiliser amiga.lib ; le 68000 de A à Z SubWay Les fenêtres Intuition ; le console.device (II) Pool Box DICE Utilitaire Le SuperShell '";C Numéro 22 (mai 91) q!: AMOS Les belles courbes ; les DaisyDemOS Arexx Travail pratique (III) Demos De toutes les couleurs ExecBase Les overlays (II) Hardware Le clavier (II) Routi nettes NoEvent SubWay Le GELS (III) ; les layers (HT) ToolBox Flex Transactor Sinus-Scroll Utilitaire Le transformeur : ExecMaster (H) Les banques de mémoire La voie royale Le débogage De toutes les couleurs Alea Jacta Est La 3D Utiliser amiga.lib (II) ; le 68000 de A à Z (II) Le trial-playtield Déboguer avec MonAm2 Le clavier Les layers ; le GELS (II) Draco Les rouleaux de lumière NewPic Trucs en vrac (II) ; les DaisyDemOS Travail pratique
- playtit liaisons Intuition Graphies 3 calculatrices du DP Les Gadget Le compilateur GFA Basic Easy Window Mélange C Assembleur Les CIAs 8520 les interruptions sous Exec Numéro 28 (décembre 97) Numéro 23 f juin 91) Les banques de mémoire (II) La voie royale (II) Question de style Scroll en rouleau Rasters ondulants Notre ToolBox de ce mois complète fort judicieusement la rubrique SubWay, puisqu’elle présente les meilleurs DP spécialement destinés à créer des programmes sources C à partir d’images IFF. LES CREATEURS D’IMAGES Le programme illustrant la rubrique SubWay utilise la sortie produite par un tel DP pour inclure directement dans le source, la définition du Bob (NDLR : pour des raisons de mise en page, j’ai modifié un tout petit peu le look de la sortie produite, mais bon, c’est pas si grave que ça). Il en existe plusieurs, dont voici illoco presto ceux que nous pensons être les meilleurs. Sans oublier bien entendu le Convertisseur de Denis Genot, promu Utilitaire du mois dernier. ILBM2IMAGE Sous ce répertoire de la disquette Fish 190 se cachent trois petits utilitaires, d’un emploi fort aisé, permettant de créer et d’afficher des structures Image, au sens Intuition du terme. Pour vous en servir, rien de plus simple. Vous dessinez d’abord l’image voulue avec votre programme de dessin favori et vous la sauvegardez au format IFF (le fait que ce soit une page entière ou une simple brosse n’a aucune importance). Vous êtes dès lors prêt à traiter votre fichier IFF suivant trois méthodes différentes. Imaginons pour commencer que vous désiriez créer une Bitmap correspondante à votre dessin, pour créer par exemple un Bob. Vous utiliserez dans ce cas ILBM2image en utilisant la syntaxe suivante : ILBM2image toto ; où toto est le nom de votre fichier IFF L’utilitaire générera alors un fichier toto.c qui n’est autre que la déclaration du tableau de UWORD correspondant à la Bitmap : UWORD toto[] = extern struct Window *Window; Drawlmage(Window->RPort,&totoimage,100,10); return(0); Que nous manque t-il ? Les plus perspicaces d’entre vous auront remarqué qu’il nous manque la palette ou table des couleurs associée à notre dessin. Et c’est là qu’intervient le dernier utilitaire, à savoir GetCMap. GetCMap analyse un fichier IFF à la recherche de sa palette de couleurs et génère un fichier C déclarant un tableau de mots (UWORD), soit: GetCMap Le logiciel vous demande alors le nom du fichier ILBM (IFF) ILBM File name ? Saisissez toto. GetCMap demande alors le nom du fichier à générer : C file name ? Par exemple : toto.c Finalement, le résultat obtenu sera de la forme : * Image toto Width: 64 Height: 58 Depth: 4 USHORT map[] = 0x0000, OxOeca, OxOfOO, OxOf16, 0x0fie. 0x0c2e, 0x072e, 0x033e, 0x066e, 0x089d, OxObbd, OxOaac, 0x099b, 0x099a, 0x0889, 0x0444 0x3e91, 0xa038, 0x1590, OxeleO, 0x33ff, 0xc03c, OxlfOl, 0xe2c0, 0x0, 0x0, 0x700, 0x0 ; Si maintenant vous désirez afficher sous Intuition une structure Image, vous aurez recours au programme ILBM2func, qui non seulement générera la Bitmap associée, mais également la structure Image correspondante et la fonction d’affichage dans une fenêtre dont le nom est Window. La fonction système utilisée pour l’affichage est bien sûr Drawlmage(). ILBM2func toto ; où toto est le nom de votre fichier IFF Ce qui donnera par exemple : include exec types.h> include intuition intuition.h> words = 12 ---* *----- bitmap : w = 64, h=3 ---- UWORD toto[] = *------plane 0: * 0x3e91, 0xa038, 0x1590, OxeleO, 0x33ff, 0xc03c, OxlfOl, Oxe2cO, 0x0, 0x0, 0x700, 0x0 ; struct Image totoimage = 0,0, 64 , 3 , 1 , &toto[0], 0xlf,0x00, NULL, totoimagefunc() Comme vous pouvez le voir, l’utilisation de ces programmes est enfantine, pour un résultat nécessitant des heures d’un travail fastidieux lorsqu’ accompli manutellement. SPRIGHT V1.2 Spright est un éditeur de sprites, qui permet de sauvegarder vos oeuvres sous formes de fichiers sources. Il s’agit d’un programme shareware que vous pourrez trouver sur la disquette Fish 484. Spright permet de créer des sprites d’une hauteur variant de 1 à 200 pixels. Bien que la largeur d’un sprite soit limitée à 16 pixels, le logiciel possède un mode double, permettant d’éditer deux sprites côte à côte. Il permet également d’éditer des sprites attachés, pour obtenir par superposition des bitplanes, un sprite unique de 15 couleurs + transparence. L’interface, très orientée Intuition, comporte deux boîtes : la première au centre de l’écran, permet de dessiner un sprite grossi 4 fois (pour faciliter de dessin). La deuxième boîte, sur le côté, affiche en permanence l’image taille réelle. Les fonctionnalités d’édition sont nombreuses.
• DUAL : ce mode utilise deux sprites, placés côte à côte. Des couleurs différentes peuvent être utilisées pour chaque sprite si le gadget ATTACH n’est pas sélectionné.
• SWITCH : en mode DUAL, ce gadget permet d’éditer alternativement l’un ou l’autre des deux sprites.
• ATTACH : permet d’attacher un sprite à un autre. Ceci permet d’utiliser, par superposition des bitplanes quinze couleurs au lieu de trois (transparence excluse).
• SAVE LOAD : sauvegarde chargement d’un sprite dans l’éditeur.
• PR1NT : impression de l’image zoomée.
• SNAPSHOT RESTORE : sauvegarde en mémoire d’un sprite. Ce sprite peut ensuite être rappelé à tout moment. Cette fonction est très utile en cas de fausse manipulation, ou si l’on veut effectuer un essai sans risquer de détruire l’oeuvre naissante. On utilise RESTORE pour récupérer l’image "snapshotée".
• RGB Slider Gadget : ces trois gadgets permettent de régler les intensités RVB de chaque couleur.
• COPY : permet de copier une zone de la boîte d’édition à une autre place.
• ROTATE : autorise la rotation du Sprite créé, soit vers la gauche soit vers la droite, par tranche de 90 degrés. Plus, bien évidemment, les commandes standard de déplacement dans la page de dessin. Après avoir dessiné un sprite dans l’éditeur, il faut utiliser la fonction SAVE qui va générer le source en C dont voici un exemple. * The sprite->height was 16 * UWORD titi_Colors[32] = 0x000, Oxfff, Oxf00, OxOfO, OxOOf, OxfOO, OxOff, OxOfO, OxOOf, Oxccc, Oxddd, Oxeee, 0x754, Oxfff, OxfOO, OxOfO, OxOOf, OxfOO, OxOff, Oxfff, OxfOO, OxOfO, OxOOf, OxfOO, Oxff0, Oxff0, OxfOf, Oxfff, Oxff0, Oxff0, Oxff0, Oxf f 0 }; UWORD titi data[36] 0 0 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7800, 0x0000, 0x4800, 0x0000, 0x4800, 0x0210, 0x7800, 0x0210, 0x7800, 0x0310, 0x4800, 0x029f, 0x480f, 0x025f, 0x480f, 0x0236, 0x0006, 0x0216, 0x0006, 0x0216, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000 Comme l’indique le commentaire, la hauteur du sprite est de 16 pixels. Spright sauvegarde à la fois la table des couleurs et l’image associée, qui je vous le rappelle, ne possède pas du tout la même organisation que celle d’une image Bitmap. IMAGE EDITOR V2.4 Ce programme, comme son nom l’indique, permet d’éditer directement des images afin de les sauvegarder sous forme de fichier source, en vue d’une inclusion dans un programme quelconque. Le lancement d’image Editor s’effectue sous shell en tapant simplement im24 et [Return]. Pour le quitter, tapez q ou cliquez dans le gadget de fermeture. Un requester apparait alors, vous demandant une confirmation, que vous lui donnerez en cliquant sur [O.K]. L’utilisation d’image Editor est des plus simples puisqu’une fois l’image dessinée, il suffit de sélectionner le gadget Disk pour sauvegarder votre travail sous la forme d’un source C ou, c’est là sa grande originalité, sous la forme d’un source assembleur. Au niveau de l’interface utilisateur, l’accès aux différentes fonctions peut se faire, soit grâce à la souris, soit par des raccourcis clavier, indiqués directement sur chaque gadget (ex: d pour le gadget Disk). Il possède une ergonomie correcte. Au niveau des fonctionnalités, Image Editor, permet de dessiner des images d’une taille maxi de 166*58 en haute résolution ou 83*58 en basse. Le nombre de couleurs possible est de 16 au maximum. Outre les possibilités classiques que nous sommes en droit d’attendre d’un tel programme (tracé, gomme, remplissage de surface, choix des couleurs...), Image Editor permet également de charger une Image IFF ILBM ou simplement la palette de couleurs qui lui est associée. Petite déception toutefois, il faudra indiquer au pixel près la largeur et la hauteur de l’image que vous allez charger, ainsi que son nombre de Bitplanes. Cette complication inutile est vraiment dommage, d’autant que toutes ces informations sont codées, bien évidemment, dans l’entête du fichier IFF. On se demande où voulait en venir le programmeur... Un examen rapide du source, montre la qualité et le soin apportés à la programmation. Aucune astuce n’est en effet utilisée et le programme se sort sans plantage de tous les problèmes qu’il peut rencontrer (comme un manque de mémoire par exemple). Je vous conseille de l’étudier, il en vaut la peine. Ce programme est disponible dans le domaine Public, et plus précisément sur la disquette Fish 355. Il s’agit d’un logiciel Shareware. ET LES AUTRES... Il existe bien entendu d’autres programme qui réalisent, avec plus ou moins de bonheur, ce travail. Je citerai, à titre informatif, les programmes suivants : CITAS Version 2.0 (Fish 475) Ce programme convertit une image IFF en source assembleur ou C en vue de son pilotage par le Blitter. IFF2Src (Fish 420) IFF2src convertit des images IFF en source C ou assembleur, avec génération des bitplanes, masques blitter, tables des couleurs. Il ne fonctionne que sous AmigaDos V 2.0. BI (Fish 375) Ce petit programme convertit une brosse IFF ILBM en source C, tout simplement. IFF2C (Fish 316) Ce convertisseur d’image IFF en source C possède deux fonctionnalités intéressantes, la génération de commentaires associés à l’image et un calcul automatique des champs PlanePick et PlaneOnOff, nécessaires à l’utilisation de l’image par le GELS. C’EST FINI Dans notre prochain numéro, nous reprendrons le cours normal de cette rubrique. Yacc sera bien entendu de la partie, comme promis la dernière fois. D’ici là, passez de bonnes fêtes de fin d’année. Le but de notre programme du mois est de créer l’effet d’un texte s’enroulant autour d’un tube transparent. Un effet qui commence certes à dater, mais qui reste toujours autant apprécié... Dans le source ci-dessous, j’en ai même fait un double pour des raisons quelques peu inattendues. On peut s’imaginer que j’ai agis ainsi pour me compliquer la tâche par plaisir, ou pour rendre l’effet plus efficace encore, mais en fait il n’en est rien : je n’ai fait cela uniquement que pour gagner du temps-machine. Là, surprise dans l’auditoire... En effet comment puis-je gagner du temps en ajoutant des éléments à l’écran ? Eh bien voilà la substantifique moëlle de cet article : je vais, dans un premier temps, vous expliquer comment je procède et vous en comprendrez les raisons à la fin (suspense insoutenable). Tout d’abord, je vous conseille de faire chez vous un petit croquis de façon à mieux percevoir la technique utilisée, car elle est relativement dure à expliquer. Je définis une petite fenêtre dans laquelle on fera scroller le texte. Le scroll est assez lent, un pixel par VBL. Cela vient du fait qu’à chaque VBL, j’affiche une colonne de un pixel de large appartenant à un caractère puis je fait scroller toute la fenêtre de un pixel vers le haut et de un pixel vers la gauche. Avant le scroll, on capture la ligne située tout en haut de la fenêtre et on la mémorise quelque part pour pouvoir ensuite la déposer tout en bas, le vide laissé par le scroll horizontal étant comblé par le prochain caractère. Au fil des VBLs, le texte va défiler à 45 degrés dans la fenêtre et une fois arrivé en haut, va repasser en dessous grâce à la ligne supérieure, que l’on fait descendre à chaque fois. Ainsi, avec le temps, on obtient une fenêtre hachurée sur toute sa largeur par du texte orienté à 45 degrés. La foule haletante s’impatiente, se demandant comment cela peut nous servir à construire un scroll en rouleau (c’est fou, je viens de m’apercevoir que j’ai raté une vocation d’écrivain a suspense...). Ensuite, je fais une CopperList qui définit un petit écran en couleur avec 2 plans. Un plan sera consacré à la partie rouge du tube, c’est-à- dire "l’avant", l’autre sera concacré à la partie bleue, représentant "l’arrière" du tube. Grâce au Copper, on peut changer à tout moment le pointeur écran de chaque bitplan, on va se servir de cet avantage pour déformer le plan avant de manière à donner l’impression qu’il épouse la forme d’un tube. On fait cela grâce à une belle formule mathématique écrite dans le programme. Pour embellir et renforcer la crédibilité de l’illusion, on change la couleur du texte sur le tube en calculant la distance entre le spectateur et le texte. Ainsi, pour la partie avant, plus le texte est près du centre plus il est clair, et inversement pour la partie arriéré. Le scroll ne s’effecutant que sur un plan et sur une partie d’écran relativement faible, le temps d’exécution est peu important. On obtient un effet pas trop médiocre pour peu de temps machine. Il est loin d’être suffisant pour une démo, mais peut sans honte être placé dans un slide show, par exemple. La phrase du mois, qui a pour auteur Douglas Adams : 'l'infinité est tout bonnement si énorme qu'en comparaison, l’énormité paraît franchement rikiki".
* ******************************************************
* ** SCROLL EN ROULEAU DE JEROME ETIENNE POUR L'ANT ***
* ****************************************************** c rVOv'CÇ vN -*• reg circuits spécialisés dmacon = $ 096 dmaconr = $ 002 vposr = $ 004 vhposr = $ 006 i reg color colobOO = $ 180 bplconl bplcon2 bpllpth bp1lpt1 bpl2pth ciaapra = reg blitter = $ 040 = $ 042 = $ 048 = $ 04a = $ 04c = $ 04e 4 $ 050 = $ 052 = $ 054 = $ 056 = $ 060 = $ 062 = $ 064 = $ 066 = $ 058 = $ 070 = $ 072 = $ 074 = $ 044 = $ 046 reg copper = $ 080 = $ 088 reg bitplane = $ 100 = $ 102 = $ 104 = $ 0e0 = $ 0e2 = $ 0e4 = $ 108 = $ 10a = $ 08e = $ 090 = $ 092 = $ 094 cia-
- a (use for î = $ bfe001 ; adr de la 1' list ; saut de la liste 1 exec library base offset openlibrary = ?I SCR( Ll TEXT EN ROULEAU reg 0 du contrôleur de bitplane 1 (valeur du scroll) 2 (priorité entre sprite & playfield) pointeur sur le ler bitplan pointeur sur le bitplane 2 valeur modulo pour les plans impairs valeur modulo pour les plans pairs début de la fenetre écran fin de la fenetre écran début dma bitplan fin dma bitplan itton) » - oufcipA
- 30-522 ;nom de la library, version
- 30-102 ; suppression du multitaksing
- 30-108 ; autorisation du multitaksing
- 30-168 ;nb d'octets,spécification d0,dl
- 30-180 pointeur mem,nb d'octets al,d0 al, dO forbid = permit = allocmem = freemem = ; for chip ram (cf:allocmem) ; for clear the memory chip = clear = $ 2 $ 10000 X n 'c- vposr(a5),d0 $ lff00,d0 $ 0c000,dO .wait_sync @ ; graphicbase startlist = 38 ; graphie library base offset , Co ownblitter =
- 30-426 disownblitter =
- 30-432 ; autres labels key = $ bfec01 custom = $ dff000 4 _ V o'OX £ V execbase = coplist_size = 4*2000 char_x = 32 char v = 32 fnt_width = 40 nb char per fnt = 50 char_width = char_x 8 fnt size = nb_char_per_fnt *char_y*char_width nb_char_per_line= fnt_width char_width .****** def macros allocmem: macro move.1 ,dO ; demande l'allocation de $ octets move.1 2,dl ; 2 type de ram sollicitée jsr allocmem (a6) move.1 d0, 3 ; 3= adr ds la mem recuperee endm
* ********** ; si erreur d'allocation => MEGA BUG ! ! ! ! Freemem: macro move.1 , al ; libérer 2 octet a partir move.1 2,dO ; de l'adresse jsr endm
* ********** vsync: macro .wait_sync @: move.1 and. 1 cmp. 1 bne. S endm freemem(a6) mémoire a nouveau libre C= Amiga NewsTech Numéro 29 - JAN 92 20 main_init init roller roller_x roller_y plane_width_roller roller_plane_size mobify_roller: bsr clr.w move.w move.w move.w move.w goto next degr dl= angle exit if d2=180 because it is finish
* modulo in byte
* modulo in byte next line move.1 lea move.1 lea move. 1 move.w move.w move.1 move. 1 lea move.1 move. W move.w addq.w 4,a0 moveq move.w mu lu add.l addq.w swap move.w swap addq.1 move.w moveq move.w bsr mulu lsl.l swap addq.w lsl.w addq.1 move.w moveq move.w neg. 1 add. 1 mulu add.l addq.w swap move.w swap addq.1 move.w moveq move.w bsr mulu lsl.l swap neg.w add.w addq.w addq.1 move.w compute the good adr to compute the good color color is between $ 3 and $ f l,d0 dO no_change_cur_txt_roller char_x-l,d0 * & cur_text += 1 4,cur_txt_roller * if new char cur_slide = 0 text_lenght*4,cur_txt_roller * > no_change_cur_txt_roller * 30*4,cur txt roller
* to modify bpl2pth * compute the good target adr to save dO to modify color of bpl2pth to compute the good color color is between $ 3 and $ f (execbase).w,a6 custom,a5 forbid(a6) move.l roller_base(pc),al lea plane_width_roller(al),al add.l plane__width_roller-l,al lea plane_width_roller*64(al),a2 moveq char_y-1, dO move.w cur_shift_roller(pc),dl loop_each_bit_modify_roller: move.l (a0),d2 lea fnt_width(aO), aO btst dl,d2 bne.s bit_true_modify_roller bit_false_modify_roller: bclr 0,(al) bclr 0,plane_width_roller(al) bclr 0,(a2) lea % plane_width_roller*2(al),al lea plane_width_roller(a2),a2 dbf dO,loop_each_bi t_modi fy_roller bra.s end_modify_roller bit_true_ modify__roller : bset 0,(al) bset 0,plane_width_roller(al) bclr 0,(a2) lea plane_width_roller*2(al), al lea plane_width_roller(a2),a2 dbf dO,loop_each_bit_modify_roller end_modi fy_roller: roller_base(pc)
- 2(aO),al * al,bltdpth(a5) * plane_width_roller(aO),al * al bltapth(a5) * $ f9f0,bltconO(a5) * A = D 1 shift roller_y*64+plane_width_roller 2+2,bltsize(a5) roller_base(pc),aO * a0,bltapth(a5) * plane_width_roller*roller_y(aO), aO * a0,bltdpth(a5) * $ 09f0,bltcon0(a5) * a = D 64 +plane_width_rol1er 2,bltsize(a5) vsync move.w $ fff,colorOO(a5) bsr mobify_roller bsr wait_blt clr.w colorOO(a5) move.b key,dO * not dO * ror .b 1, dO * cmp.b $ 45,dO * beq init_end *; bra main_loop tst if esc is pressed subq.w tst .w bpl. S moveq addq.1 cmp.l bne. S move.1 no_change_cur_txt_roller: move.w dO,cur_shift_roller lea coded_text(pc) ,a0 add.1 cur_txt_roller,aO move.l (aO),aO add.l picture+64,aO move.w $ f,color00(a5)
* ** MODIFY CUR_TXT & CUR SLIDE move.w cur_shift_roller(pc),d0 352 3*32 roller_x 8 plane_width_roller*(roller_y+10) wait_blt bltconl(a5) 0,bltamod(a5) 0,bltdmod(a5) -l bltafwm(a5) -l,bltalwm(a5) bsr bsr main_loop:
* >adr of actual char
* 1 line aO 0, d2 roller_var,d2 plane_width_roller,d2 roller_base(pc),d2 2,aO * d2 * d2,(a0)+ * >to modify the coplist with 3-2 * > the good target adr 2,aO * d2,(aO)+ * 0,d0 * to modify color of bpllpth roller_angle(pc),dO sin * 13,dO l,d0 dO 3,d0 8, dO 2, aO dO,(a0)+ 0, d2 roller_var,d2 d2 roller_y,d2 plane_width_roller,d2 rollerjbase(pc),d2 2,aO * d2 * d2,(a0)+ * >to modify the coplist with 32 * > the good target adr 2,aO * d2,(a0)+ * rts cur_shift_roller: ds.w 1 cur_txt_roller: ds.l 1
* *************************** init_roller: ; allocmem for bitplane allocmem rollerjplane_size,chip+clear,roller_plane_adr
* ** INIT SOME VARIABLES move.1 roller_plane_adr(pc),roller_base add.1 plane_width_roller,roller_base move.w char_x,cur_shift_roller move.l 30*4,cur txt roller
* ** MODIFY ROLLER COPLIST move.l coplist_adr(pc),aO lea delta_roller_coplist(aO),aO clr.w roller_angle clr.l roller_var init_roller_coplist: add.l $ 8888,roiler_var addq.w 1,roller_angle moveq 0,dl move.w roiler_angle(pc),dl cmp.w 180,dl beq init_roller_end move.1 dl,dO * bsr cos * muls 30,dO * lsl.l l,d0 * swap dO * cmp.w d4,d0 * beq.s init_roller_coplist * move.w d0,d4
* d4= sin(dl)* ray_y
* to go over wait of line's start
* to modify bpllpth 0, dO roller_angle(pc),d0 sxn 13,dO 1, dO dû dO 13,dO 3, dO 2, aO dO,(aO) bra init_roller_coplist init roller end: rts roller_base: ds.1 roller_plane_adr: ds.l roller_angle: ds.w 1 roller_var: ds.l 1
* *************************** main_init: move.1 lea jsr sin2 : l,dO sin_tab(pc,dO.w),dO lsl. W move.w rts ; dO = cos ou sin
* ******************************************* tableau tire de "graphisme en gfa" de Micro Aplication p 648 ; valeur des sin* 32768 ; valeur des sin* 2A15 a 90 deg a 90 deg sin tab: de 0 de 0 $ 08ed $ 1406 $ lef7 $ 29ac $ 340f $ 3e0e $ 4793' $ 508d $ 58ea $ 609a $ 678d $ 6db7 $ 730b $ 777f $ 7b0a $ 7da5 $ 7f4c $ 7f fb $ 0000, $ 0b27, $ 163a, $ 2120, $ 2bc7, $ 3618, $ 4000, $ 496a, $ 5246, $ 5a82, $ 620d, $ 68d9, $ 6ed9, $ 7401, $ 7847, $ 7ba3, $ 7e0e, $ 7f83, $ 023b, $ 0d61, $ 186c, $ 2348, $ 2ddf, $ 381c, $ 41ec, $ 4b3c, $ 53f9, $ 5cl3, $ 6379, $ 6ald, $ 6ff3, $ 74ef, $ 7906, $ 7c32, $ 7e6c, $ 7fb0, $ 0477,$ 06b2, $ 0f99,$ lld0, $ la9c,$ lccb, $ 256c,$ 278d, $ 2ff3,$ 3203, $ 3alcy$ 3cl7, $ 43d4,$ 45b6, $ 4d08,$ 4ecd, $ 55a6,$ 574b, $ 5d9c,$ 5flf, $ 64dd,$ 6639, $ 6b59,$ 6c8c, $ 7104,$ 720c, $ 75d3,$ 761d, $ 79bc,$ 7a68, $ 7cb8,$ 7d33, $ 7ecl,$ 7f0b, $ 7fd3,$ 7fec. 0-4 degr 5-9 degr 10-14 degr 15-19 degr de .w de .w de .w de .w de .w de .w de .w de .w de .w de .w de .w de .w de. W de. W de. W de. W de .w de .w ds.l 80-84 degr 85-89 degr dmacon,(aO)+ $ 87c0,(aO)+ bpllmod,(aO) + 0,(a0) + bpl2mod,(aO)+ 0,(a0)+ bplcon0,(aO) + move.w move.w move.w move.w move.w move.w move.w caculer par le prg tab90: tabl80 tab270 3*90 2 ; de 90 a 359 degr sin_tab+180*2 sin tab+270*2
* al= pointer on text
* ******************************************* move.w bplconl,(aO) +
* > no shift ; compute end of sin_table 90-359 move. W 0,(aO)+ * ; sintab 90-180 move.w bplcon2,(aO) +
* > no sprite priority lea sin tab,a0 ; al pointe sur le degr 180 move.w 0,(aO)+ * lea (90+90+1)*2(aO), al move.w ddfstrt,(aO) +
* > init ddfstrt move.w $ 7fff,90*2(aO) ; place degr 90 move.w $ 0031,(aO)+ * moveq 90-1,dO ; 90 deg are copy move.w ddfstop,(aO) +
* > init ddfstop copy_90_180: ; principe: sin 0= sin 180 move.w $ 00d9,(aO ) + * move.w (aO) + , - (al) ; sin 1= sin 179 move.w diwstrt,(aO)+
* > init diwstrt dbf d0,copy 90 180 ; sin 2= sin 178 etc... move. W $ 2a74,(aO)+ * ; sintab 180-270 move.w diwstop,(aO) +
* > init diwstop lea sin tab,a0 ; aO pointe sur 0 degr move.w $ 29d4,(aO)+ * lea 180*2(aO),al ; al pointe sur 180 degr moveq 90-1,dO ; 90 deg are copy roller_coplist = 40 moveq 0, d2 copy_180_270: move.w 61-1,dO
* d0= nbline -1 moveq 1, dl ; moveq $ 29,dl
* dl= first line swap dl ; dl=$ 10000 moveq 0,d2 * d2= target is useless buffer but clear move.w (a0)+,d2; roller_coplist: sub. 1 d2, dl ; move.b dl,(aO)+
* wait y move.w dl,(al)+ ;dl= $ 10000- d2 move.b $ 03,(aO)+
* wait x dbf dO,copy_180_270 move.w $ fffe,(aO)+
* wait mask ; sintab 270-359 move.w bpllpth,(aO ) + lea sin_tab+180*2,aO ; al pointe sur le degr 360 swap d2 lea (90+90)*2(aO),al move.w d2,(aO)+ move.w $ 8000,90*2(aO) ; place degr 270 swap d2 lea 2(aO),aO move.w bpllpth+2,(a0)+ moveq 89-1,dO ; 89 deg are copy move.w d2,(aO)+ copy_270_359: ; principe: sin 360= sin 180 move.w (aO)+,-(al) ; sin 359= sin 181 move.w color00+2*l, (aO ) + dbf dO,copy_2 7 0_3 5 9 ; sin 358= sin 182 etc... move.w $ f00,(aO ) + rts move.w bpl2pth,(aO) +
• **************************** f swap d2 ; réactivation de l'old coplist move.w d2,(aO)+ ; restore multitasking & dmacon swap d2 init_end: move.w bpl2pth+2,(a0)+ bsr wait_blt move.w d2,(aO)+ move.w $ 400,dmacon(a5) lea gfxname(pc),al move.w color00+2*9,(a0)+ moveq 0, dO move.w $ f,(a0) + jsr openlibrary(a6) move.1 d0,a4 addq.w 1, dl
* 1 ligne traite en + move.1 startlist(a4),copllc(a5); chargement de l'adr dbf dO,build_roller _coplist clr .w copjmpl(a5) ; l'old coplist move.w $ 83e0,dmacon(a5) ; activation des canaux dma move.w ttbplconO,(aO)+ jsr permit(a6) ; multi switching autorise move.w 0,(a0)+ freemem coplist_adr(pc), coplist_size move.1 $ fffffffe,(aO)+ * 1 cop_instruction f reemem roller plane adr(pc),roller_plane_size rts moveq 0,d0 ; flag d 'erreur desactive
* *************************** routine inspire de "graphisme en gfa" de Micro Aplication p 642 ; in: d0= angle . ************* wait for blitter ; out d0= cos or sin wait_blt: cos: add.w 90,dO ; prinsipe: cos(dO) = sin(d0+90) btst 14,dmaconr(a5) ) sin: cmp.w 360,dO ; angle sup ou equ a 360 bne. S wait_blt 3 3 bit. S sinl ; >if true d0=d0-360 rts 2 sub.w 360,dO ;
* ************* bra. S sin ; make test again once code_text: 2 sinl: tst .w dO ; négatif ? Lea ascii_table(pc),aO ; bpl sin2 ; >if true d0=d0+360 lea text(pc),al add.w 360,dO ; lea coded_text(pc),a2 bra. S sinl move.1 text_lenght-l+20,dl move.w $ 03e0,dmacon(a5) bsr init_plane bsr init_coplist bsr compute_sin_tab bsr compute_ascii_table bsr code_text move.1 coplist_adr,copllc(a5) clr .w copjmpl(a5) move.w $ 87c0,dmacon(a5) ; dma rts ; ail dma off except disk run my own coplist ; .****************************
* > dma blitter,copper & bitplane
* bltpri is true
* > no modulo *
* > no modulo *
* > 2 planes and dual playfield init_coplist: ; allocmem for coplist allocmem coplist_size,chip,coplist_adr move.1 coplist_adr(pc),aO init_plane: rts 1 ? 5
* -* do i=l to 2; "2" loop_code_t ext : 6
* -* say i; moveq 0, dO "2" move.b (al)+,dO 7
* -* a= test(i); sub.w 32,d0 »> "2" lsl .w 2, dO 12
* -* test: move.1 (aO,dO.w),(a2)+ 12
* _* . Dbf dl, loop__code_text 13
* -* arg k; rts 14 » "2"
* -* return(k**k)
* ************ compute the the adr of each char on with ascii code "4" comput e_a s c i i_ table : »> "4" moveq ' ',d3 8
* -* say a; compute_adr_of _each_char: » "4" lea char on picture(pc),aO 9
* -* end; moveq nb char on_picture-l,dO 5
* -* do i=l to 2; move.1 d3,d2 "3" search_char_in _ascii_table: * search the char in ascii table 10
* -* trace off; cmp.b (a0)+,d2 * >if it doesen't exist it will dbeq dO,search_char_in_ascii_table * be the last
• pour XXX égale SCAN sub. 1 char__on_picture+l, aO dl= adr of char 4
* _* address command 7dir dfl 5
* _ * do i=l to 2; 10
* _ * trace off; 11
* _* exit ; 12
* _* test: 12
* _* ; 13
* _ * arg k; 14
* _* return(k**k); Arexx (suite de la page 7) move.l aO dO * divu nb_char_per_line,dO * move. W dO, dl mulu fnt_width*char_y dl * swap dO * and.l $ ffff,dO * >isolate the remainder of divu in dO lsl.w 2, dO add.w dl,d0 * dl= adr of line of chai sub.w 32,d2 lsl.l 2,d2 * d2=4*d2 because the data is long word lea ascii_table(pc),aO move.l d0,(a0,d2.w) addq.w l,d3 * d3= ascii code of next char cmp.b 'Z',d3 * >if d3 sup than 'Z' then it's finish ble.s compute_adr_of_each_char rts Ce mode est particulièrement intéressant. Il trace toutes les instructions pour tester les erreurs, mais sans les exécuter réellement. Il est donc utile de le mettre en oeuvre avant l’exécution réelle du programme (solution anti-Guru). ;******* datas ; variables coplist_adr: ds.l 1 gfxbase: de. 1 1 gfxname: de .b "graphies.library",0
* ****** data for text ascii_table: ds.l 91-32 nb_char_on__p i c tur e= 50 char_on__p i c tur e :dc .b "ABCDEFGHI J" de .b "KLMNOPQRST"
dc. B "UVWXYZ: ; ! 7"
dc. B "0123456789" de .b text : dcb. B 30, '0' de .b "THE FONT WAS DRAWN BY KEFRENS de .b " THIS SCROLL USE BLITTER AND text_lenght=
* -text dcb.b 20, 7 ' even coded_text: ds.l text_lenght+20 * +20 spaces picture: inebin 7 fnt_32.bit7 end RDCD6FGHIJ KLMHOPORST
* +20 for the 20 last UVHXYX::!¦ Format de limage de la fonte : 320x256x1 Par Jérôme Etienne EXPLOITATION DES RESULTATS L’endroit où les résultats sont affichés dépend du choix qui a été effectué au préalable. Si rien de particulier n’a été décidé, tout se passe sur la console standard. Si tco a été lancé, seules les opérations de traçage apparaissent dans la fenêtre ou console spécialisée. Cependant, les dimensions de l’écran étant limitées et l’exécution pouvant concerner un grand nombre de lignes, il est possible qu’on ne puisse pas examiner à loisir tout le traçage. Tout au plus peut-on arrêter momentanément le défilement avec le bouton droit de la souris, mais cela ne permet pas d’aller et venir pour traquer le défaut. Il est possible, moyennant une ligne de programme supplémentaire, de diriger le flux qui apparaît sur la console tco vers le support le plus intéressant : imprimante, fichier en RAM: ou sur dique, etc. A partir d’un fichier, n’importe quel traitement de texte ou même l’éditeur dont on se sert pour écrire le programme permet l’édition du fichier de traçage et par là même, son analyse à loisir. L’instruction miracle qui peut être placée dans le programme avant l’instruction trace s’écrit : CALL OPEN(7STDERR7,'ZZZ7,'W') où zzz égale PRT: pour l’imprimante, ou RAM:test pour un fichier test en Ram, ou encore DH0:test essai pour un fichier essai dans le répertoire test du dique dur DHO:. On notera cependant que STDERR n’a pas de possibilité d’être ouvert vers plusieurs sorties simultanées. Pour terminer, à l’endroit où l’on veut on insérera l’instruction Call Close('STDERR') ce qui permet d’effectuer un traçage localisé si besoin est. Dans l’article suivant, nous verrons la fin des possibilités de déverminage telles que les points d’arrêt, les commandes te, signal, le return code (RC), le déverminage interactif, ou encore le transfert en cas d’erreur comme partie du programme. Par François Gueugnon ml 101 Si vous avez la nostalgie des anciens ordinateurs dont le Shell était plein écran, BigCLI est fait pour vous... _ WINDOW=NewCON lllI BigCLI_ Pour supprimer le gestionnaire BigCLI de la mémoire, il suffit de lancer une seconde fois BigCLI_Inst, ou de lui envoyer, au moyen de la commande Break, un CTRL-F bien placé entre les deux yeux. Une dernière note pour finir : si toutes les commandes CLI (Dir, Copy, etc.) s’affichent bel et bien dans notre écran, les programmes qui demandent explicitement une fenêtre Workbench ne sont pas détournés. Par exemple, si vous lancez More depuis une fenêtre BigCLI, sa fenêtre s’ouvrira de toute manière sur l’écran du Workbench. Et ça, on ne peut rien y faire. BigCLI vl.O - (c) Max pour ANT. Opt o+,ow- incdir "Include:" include "exec tasks.i" include "exec ports.i" include "exec memory.i" include "exec execbase.i" include "intuition intuition.i" include "libraries dos.i" include "libraries dosextens.i" include "exec exec_lib.i" include "intuition intuition_lib.i" include "libraries dos_lib.i" . ************************************ CALLSYS MACRO ; Petite macro très très pratique IFNC '',' 2' ; piquée à Loïc Far. Merci Loïc ! Movea.l 2,a6 ENDC jsr _LVO l(a6) ENDM EXEC MACRO CALLSYS l,$ 4.w ENDM DOS MACRO CALLSYS ,DosBase(a5) ENDM INT MACRO CALLSYS ,IntBase(a5) ENDM . ************************************ f rsreset args Arguments du CLI MsgPort standard DOSBase IntuitionBase Ancien vecteur OpenWindowO Ancien vecteur CloseWindow() Compteur d'écrans rs. 1 MsgPort rs .b DosBase rs .1 IntBase rs .1 OpenW rs. 1 CloseW rs.l count rs.w VARSIZErs.w NSFLAGS EQU NWFLAGS SET NWFLAGS SET MARQUE EQU MP_SIZE 1 1 1 1 1 0 CU STOMSCREEN BACKDROPIBORDERLESS|RMBTRAP1ACTIVATE NWFLAGS|SIMPLE_REFRESH|NOCAREREFRESH 'MAX 1' . ************************************ f Start lea VARS(pc),a5 movem.l dO aO,args(a5) lea dosname (pc ) , al moveq 33,d0 EXEC OpenLibrary move.l dO,DosBase(a5) beq NoDos BigCLI est un petit utilitaire très simple à réaliser, qui permet d’ouvrir chaque nouveau CLI ou Shell dans son propre écran - au sens Intuition du terme - et non dans une fenêtre sur le Workbench. Et quand je dis très simple à réaliser, je le pense vraiment. C’est tellement simple, que je m’étonne que personne ne l’ai fait avant (en tout cas, pas à me connaissance). COMMENT CA MARCHE La démarche que j’ai suivie n’est peut-être pas la plus orthodoxe qui soit. J’en discutais encore récemment avec Frédéric Mazué, qui avait, lui, trouvé le moyen de détourner un Shell sur n’importe quelle fenêtre Intuition déjà ouverte (imaginez le résultat d’un Dir au beau milieu de votre dessin DeluxePaint !). A son humble avis de pourfendeur de bugs devant l’Eternel, ma méthode n’est pas très sûre et peut planter ; dans certaines conditions, qu’il reste d’ailleurs à définir... Rassurez- vous, malgré tous les essais auxquels je me suis livré, je n’ai encore jamais réussi à provoquer le moindre Guru. BigCLI est donc un programme sûr à 99% (bien que je n’aie pu le tester en WB 2.0). La méthode en question consiste ni plus ni moins à détourner le vecteur OpenWindow() de la bibilothèque Intuition, de telle sorte que chaque fois que le Shell essaie d’ouvrir une nouvelle fenêtre, un écran particulier soit d’abord ouvert, qui accueillera ladite fenêtre. Cela suppose également, bien sûr, de détourner CloseWindo v() afin de refermer cet écran en même temps que la fenêtre lors du EndCLI final. Reste à savoir comment déterminer si c’est un Shell qui essaie d’ouvrir une nouvelle fenêtre, ou bien une application quelconque. Après maintes tentatives et étant donné la manière dont AmigaDOS gère l’ouverture d’une nouvelle console (à travers CreateTask() d’Exec), je me suis finalement décidé pour une petite astuce qui ne paye pas de mine : c’est le titre de la nouvelle fenêtre qui déterminera sa provenance. En d’autres termes, si la fenêtre à ouvrir possède un titre particulier, on assumera qu’il s’agit d’une fenêtre Shell, donc à ouvrir dans un écran propre. Afin d’éviter tout risque de conflit, ce titre a été choisi avec soin. Il s’agit de BigCLI , avec deux soulignés de part et d’autre, les majuscules étant différenciées des minuscules. Le problème se pose à nouveau lorsque, après un EndCLI vindicatif, le Shell veut refermer sa fenêtre : comment savoir s’il faut également fermer l’écran supplémentaire ouvert précédemment ? Là encore, la solution est simple : on utilisera le champ UserData de la structure Window associée à chaque fenêtre. Normalement, ce champ contient un pointeur sur des données propres au propriétaire de la fenêtre, s’il en a besoin. CON: ne l’utilisant pas, nous y inscrivons simplement une marque de reconnaissance. Dans notre propre routine CloseWindow(), ce champ est testé et, si la marque est reconnue, l’écran est fermé en même temps que la fenêtre. INSTALLATION Copiez le programme BigCLI_Inst dans votre répertoire C: et ajoutez dans votre Startup-Sequence, à l’endroit de votre choix (généralement juste avant la commande LoadWB), la ligne BigCLI_Inst (notez qu’il n’est pas utile de spécifier Run ou un équivalent, le programme incorporant une version simplifiée de BackStart.i de Frédéric Mazué, qui permet de lancer un programme en tâche de fond et de rendre immédiatement la main au CLI appelant). Si l’installation s’est correctement effectuée, un petit message vous en prévient. Une fois le gestionnaire principal installé, le meilleur moyen d’invoquer BigCLI est encore d’insérer la ligne suivante dans le fichier Shell-Startup de votre répertoire S : Alias BigCLI NewShell NewCON; BigCLI_ Ainsi, en tapant simplement BigCLI, vous obtiendrez un nouveau Shell plein écran. Les afficionados du Workbench pourront également mettre dans la partie ToolTypes de l’icône du Shell BigCLI ; afin de pouvoir ouvrir un écran identique pour chaque ; nouveau Shell lancé. Lea -sc_SIZEOF(sp),sp ; sizeof(struct Screen) lea intname(pc),al CALLSYS SetFunction moveq 33,dO CALLSYS OpenLibrary movea.1 IntBase(a5), al move.1 dO,IntBase(a5) lea (_LVOOpenWindow).w,aO beq Nolnt move.1 0penW(a5),dO CALLSYS SetFunction lea myname(pc),al ; On est déjà présent ? CALLSYS FindPort CALLSYS Permit tst .1 dO beq. S Install ; Supprime notre MsgPort lea MsgPort(a5),al movea.1 dO,al ; Si oui, on signale de quitter. CALLSYS RemPort movea.1 MP_SIGTASK(al),al move.1 SIGBREAKF_CTRL_F,dO lea offtxt(pc),aO CALLSYS Signal bsr ShowReq bra Exit ; Ferme 1'intuition.library
* ****************************** Exit movea.1 IntBase(a5),al . Lea MsgPort(a5),al EXEC CloseLibrary move.b NT_MSGPORT,MP+LN_TYPE(al) move.1 myname, MP+LN__NAME ( al ) Nolnt movea.1 DosBase(a5),al move.b PA_IGNORE,MP_FLAGS(al) CALLSYS CloseLibrary move.1 ThisTask(a6),MP_SIGTASK(al) CALLSYS AddPort ; Retour au CLI Shell NoDos moveq 0,d0 ; Ici, on recherche les informations sur l'écran du WB rts . ************************************ ShowReq move .1 a 0, - ( sp ) movea.l sp,aO suba.l al,al move.l sc_SIZEOF,dO moveq WBENCHSCREEN,dl INT GetScreenData ; Copie les paramètres de l'écran du WB ; dans notre propre structure NewScreen. Movea.l sp,aO lea ns(pc),al move.w sc_Width(aO),ns_Width(al) move. W sc_Height(aO),ns_Height(al) move.w sc_ViewPort+vp_Modes(aO),dO andi. W (V_HIRES|V_LACE),dO move. W dO,ns_ViewModes(al) lea sc_SIZEOF(sp),sp ; Détourne les vecteurs OpenWindowO et CloseWindow(). EXEC Forbid movea.1 IntBase(a5),al lea (_LVOOpenWindow).w,aO move.1 NewOpenWindow,dO CALLSYS SetFunction move.1 dO,OpenW(a5) ; Sauve movea.1 IntBase(a5),al lea (_LVOCloseWindow).w,aO move.1 NewCloseWindow,dO CALLSYS SetFunction move.1 dO,CloseW(a5) ; Sauve CALLSYS Permit ; Prévient l'utilisateur qu'on est installé, lea ontxt(pc),aO bsr ShowReq ; Ok, on a fini, il ne reste plus qu'à attendre qu'on ; nous demande de quitter. WaitEnd move. 1 SIGBREAKF_CTRL_F,dO EXEC Wait ; Reste-t-il des écrans BigCLI ouverts ? Tst.w count(a5) beq.s Remove ; Si oui, on affiche un Requester maison suba.1 aO, aO lea autoreq(pc),al lea buttonl(pc),a2 lea button2(pc),a3 moveq 0, dO moveq 0, dl move.1 320,d2 moveq 90,d3 INT AutoRequest tst. 1 dO beq. S WaitEnd ; Si on quitte quand même alors qu'il reste un (des) ; écran(s) ouvert(s), i.l(s) ne sera(ont) jamais fermé(s)! ; Restaure les vecteurs OpenWindowO et CloseWindow(). Remove EXEC Forbid movea.l intBase(a5),al lea (_LVOCloseWindow).w,aO move.l CloseW(a5),d0 lea nwreq(pc),aO INT OpenWindow move.1 dO,d2 beq NoReq lea request(pc),a0 move.1 (sp)+,rq_ReqText(a 0) movea.l d2,al CALLSYS Request move.l TICKS_PER_SECOND,dl DOS Delay lea request(pc),aO movea.l d2,al INT EndRequest movea.l d2,a0 CALLSYS CloseWindow rts addq.l 4,sp rts NoReq . ************************************ NewOpenWindow: movem.l d2-d3 a2-a6,-(sp) lea VARS (pc), a5 movea.l a0,a3 nos variables NewWindow movea.l nw_Title(aO),aO .title(pc),al (aO)+,(al)+ . Normal
- l(aO) .cmp ; Compare le titre de la ; nouvelle fenêtre ; à 'BigCLI'. Lea cmp cmpm.b bne tst .b bne. S ; C'est une fenêtre normale, ; On est obligé d'utiliser une COPIE de la structure ; NewScreen si on veut rester ré-entrant, c'est-à-dire ; pouvoir être appelé par plusieurs programmes à la fois lea -ns_SIZEOF(sp),sp lea ns(pc),aO movea.l sp,al moveq ns_SIZEOF-l,dO move.b (aO)+,(al)+ copy dbra dO,.copy movea.l sp,aO CALLSYS OpenScreen lea ns_SIZEOF(sp),sp move.l dO,nw_Screen(a3) beq .ratel Ouvre l'écran ; Modifie la structure NewWindow de la fenêtre, de sorte ; qu'elle s'accomode le mieux possible à l'écran, movea.l dO,aO move.b sc_BarHeight(aO),dO ext. W dO addq.w l,dO move.w sc_LeftEdge(aO),nw_LeftEdge(a3) move.w sc_TopEdge(aO),nw_TopEdge(a3) add.w dO,nw_TopEdge(a3) move.w s c_Width(a 0),nw_Width(a3) move.w sc_Height(aO),nw_Height(a3) sub.w dO,nw_Height(a3) EUXIEME ! Base des données ; Une erreur est très ; improbable ! Retour à la ligne Adresse de la chaine Longueur Demande le canal de sortie sans modifier d2 et d3 ! Astuss ! DosBase-Dt(a5), al _LVOCloseLibrary(a6) Marque le début Pousse le lock Demande le précédent On a atteint le premier? Non: on reboucle!
* Redescend les LOCKS en demandant leur NOM (a2 ) ":",d3 (sp),dl . Gd5 a3,d2 _LVOExamine dO . Gd4 8(a3),al (al)+,(a2 ) + . Gd3 d3,-1(a2) (a2) " ", d3 (sp)+,dl _LVOUnlock . Gd2 Un zéro a la fin Le premier est un disque On reprend les locks Si terminé... Poke dans la pile Demande le nom! En cas de problème... On recopie le nom! Met : ou Marque la fin Le seul 11 : " est le premier! Il faut maintenant effacer les locks! Et on boucle! Efface le buffer et le Clr Fin de la chaine ; Restaure les registres ; Début de la chaine ; Taille de la chaine a2,d0 (sp)+,al-a3 dl-d3 al,a0 a0,d0
- ---------------- Pitite mignone zone de donnée La base des accès à la zone de donnée Dt
* ROUTINETTE numéro 2 DosBase
* _GetDir: trouve un pathname complet. Buffer
* Par François Lionet, paru dans l'A.N.T. du 1er Janvier DosName 1992
* ________________________________________________________________
* ---------------------- Définition de variables système
* Appel du dos DosCall MACRO move.l a6,-(sp) de. 1 ds.b de .b de .b even 0 128 0 "dos.library",0 Par Tonton François Lionet En arrivant dans le monde de l’Amiga, j’ai pris AmigaDOS en grippe, comme beaucoup de monde. Il faut dire que la vitesse d’affichage d’un directory sur disquette est certainement la plus mauvaise publicité d’AmigaDOS. Sous prétexte d’une sécurité plus grande des disques (?!? J’ai bouzillé beaucoup plus de disquettes Amiga que PC ou Atari, car elles ont besoin d’être validées !) On est obligé de passer de longues minutes à écouter le lecteur grincer, en voyant d’afficher trois misérables noms de fichiers à la vitesse d’un escargot ashmatique. Si la personne responsable de cet état de fait (le programmeur initial d’AmigaDOS) voyait déferler sur lui le potentiel de haine accumulée par les millions d’Amigaïstes mécontents, il se désintégrerait immédiatement ! Quelle mauvaise publicité, donc, pour AmigaDOS. Mais la lenteur des répertoires n’est qu’une misérable façade, cachant un système finalement très bien conçu, dont on découvre les finesses avec l’usage, et que l’on se prend à aimer et finalement à préférer au MS-DOS ! Qui aime bien châtie bien, il reste tout de même quelques points bizarres dans le DOS. Certaines fonctions, qui semblent pourtant indispensables, sont tout bonnement omises, comme par exemple une fonction pour obtenir le directory courant. Il est tout de même primordial de savoir où l’on est pour pouvoir accéder au disque ! Quelle coïncidence, je vous propose aujourd’hui une routinette ramenant le path complet, depuis le nom du disque jusqu’à l’endroit d’où le programme a été lancé. LE BEAU PROGRAMME Pour appeler la routinette d’aujourd’hui, vous devez :
• ouvrir la dos.library et mettre son adresse de base dans DosBcise.
• charger AO avec un pathname pointant sur un fichier quelconque du directory dont vous désirez connaître le cheminement. Une chaîne nulle ramène le pathname courant.
• charger Al avec l’adresse d’un buffer de 128 octets minimum dans lequel sera inscrit le cheminement.
• appeler la routinette. Vous remarquerez que j’utilise A5 comme pointeur sur la zone de données. Pourquoi ? Pour faire du code relogeable. On peut parfaitement utiliser les instructions "relatif PC". Le problème est qu’avec un 68000, ces instructions ne sont valables que pour l’opérande source. En chargeant A5 avec l’adresse de la zone de données, on peut accéder en lecture et en écriture à cette zone. Grands avantages de ce système : plus rapide, plus court (on gagne deux octets par instruction !), réentrant (il suffit de changer A5 et on change de zone de données). Evidemment, on perd A5, mais bon, il reste tout de même cinq autres registres... LA BELLE CONCLUSION Qui sera aussi très courte : à plus. Youpie, youpla, voila la deuxième Routinette de Tonton François. La joie m’envahit et me rend tout fébrile. Quelle excitation !
* ----------------------Routinette
* En entrée A0= Nom d'un fichier, ou pointeur
* sur une chaine nulle pour avoir le
* directory courant...
* Al= Espace de 128 octets ou poker le nom
* En sortie A0= début du buffer
* D0= longueur de la chaine GetDir:
* Préparation des paramétrés movem.l al-a3 dl-d3,-(sp) move.l al,a2 ; A2 est un registre préserve lea -260(sp),sp ; Reserve un espace de travail move.l sp,a3 ; en A3
* Demande un lock sur le point d'entree move.l a0,dl moveq -2,d2 DosCall _LVOLock
* On travaille avec la pile clr.l -(sp) . Gdl: move.l d0,-(sp) move.1 dO,dl DosCall _LVOParentDir tst.l dO bne.s .Gdl move.1 jsr move.1 ENDM DosBase-Dt(a5),a6 Ka6) (sp)+,a6
* Offsets des fonctions dos _LVOExamine equ
- 102 LVOParentDir equ
- 210 LVOLock equ
- 84 _LVOUnLock equ
- 90 LVOWrite equ
- 48 _LVOOutput equ
- 60
* Offset des fonctions : EXEC _LVOOpenLibrary equ
- 552 _LVOCloseLibrary equ
- 414 Démons stration lea Ouvre le dos move.1 lea moveq jsr move.1 beq. S Dt(pc),a5 $ 4.w,a6 DosName-Dt(a5), al 0,d0 _LVOOpenLibrary(a6) dO,DosBase-Dt(a5) Err
* Va demander le chemin lea PathNul-Dt(a5), aO lea Buffer-Dt(a5),al bsr _GetDir
* Imprime sur le canal standart move. B 10,0(30,(10.1) addq.l l,d0 move.l a0,d2 ; move.1 „ dO,d3 ; DosCall _LVOOutput ; move.1 dO,dl DosCall _LVOWrite
* Ferme le dos move.1 jsr
* No problemo Err moveq rts clr .b moveq . Gd2 : move.1 beq. S move.1 DosCall tst. 1 beq. S lea . Gd3 : move. B bne. S move.b clr .b moveq . Gd4 move.1 DosCall bra. S
* Point de sortie! .Gd5 lea 260+4(sp),sp move.1 movem. 1 move.1 sub. 1 rts 0, dO 101 EUXIEME ! _LVOExamine JLVOParentDir _LVOLock _LVOUnLock _LVOWrite _LVOOutput JLVOOpenLibrary .LVOCloseLibrary lea Ouvre le dos move.1 lea moveq jsr move.1 beq. S Dt(pc), a5 Imprime sur le canal standart move.b 10,0(a0,d0.1) addq.l l,d0 move.l a0,d2 move.1 . DO,d3 DosCall _LVOOutput move.1 dO,dl LVOWrite DosBase-Dt(a5),al _LVOCloseLibrary(a6 i Marque le début Pousse le lock Demande le précédent On a atteint le premier? Non: on reboucle! Redescend les LOCKS en demandant leur NOM (a2) " : ",d3 (sp),dl . Gd5 a3,d2 _LVOExamine dO . Gd4 8(a3),al (al)+,(a2)+ . Gd3 d3,-1(a2) (a2 ) " ", d3 (sp)+,dl _LVOUnlock ,Gd2 Un zéro a la fin Le premier est un disque On reprend les locks Si terminé... Poke dans la pile Demande le nom! En cas de problème... On recopie le nom! . Gd2 : . Gd3 : Met : ou Marque la fin Le seul " :11 est le premier! Il faut maintenant effacer les locks! Et on boucle! Efface le buffer et le Clr Fin de la chaine . Gd4 move.1 sub. 1 rts al, aO a0,d0 En arrivant dans le monde de l’Amiga, j’ai pris AmigaDOS en grippe, comme beaucoup de monde. Il faut dire que la vitesse d’affichage d’un directory sur disquette est certainement la plus mauvaise publicité d’AmigaDOS. Sous prétexte d’une sécurité plus grande des disques (?!? J’ai bouzillé beaucoup plus de disquettes Amiga que PC ou Atari, car elles ont besoin d’être validées !) On est obligé de passer de longues minutes à écouter le lecteur grincer, en voyant d’afficher trois misérables noms de fichiers à la vitesse d’un escargot ashmatique. Si la personne responsable de cet état de fait (le programmeur initial d’AmigaDOS) voyait déferler sur lui le potentiel de haine accumulée par les millions d’Amigaïstes mécontents, il se désintégrerait immédiatement ! Quelle mauvaise publicité, donc, pour AmigaDOS. Mais la lenteur des répertoires n’est qu’une misérable façade, cachant un système finalement très bien conçu, dont on découvre les finesses avec l’usage, et que l’on se prend à aimer et finalement à préférer au MS-DOS ! Qui aime bien châtie bien, il reste tout de même quelques points bizarres dans le DOS. Certaines fonctions, qui semblent pourtant indispensables, sont tout bonnement omises, comme par exemple une fonction pour obtenir le directory courant. Il est tout de même primordial de savoir où l’on est pour pouvoir accéder au disque ! Quelle coïncidence, je vous propose aujourd’hui une routinette ramenant le path complet, depuis le nom du disque jusqu’à l’endroit d’où le programme a été lancé. LE BEAU PROGRAMME Pour appeler la routinette d’aujourd’hui, vous devez :
• ouvrir la dos.library et mettre son adresse de base dans DosBase.
• charger AO avec un pathname pointant sur un fichier quelconque du directory dont vous désirez connaître le cheminement. Une chaîne nulle ramène le pathname courant.
• charger Al avec l’adresse d’un buffer de 128 octets minimum dans lequel sera inscrit le cheminement.
• appeler la routinette. Vous remarquerez que j’utilise A5 comme pointeur sur la zone de données. Pourquoi ? Pour faire du code relogeable. On peut parfaitement utiliser les instructions "relatif PC". Le problème est qu’avec un 68000, ces instructions ne sont valables que pour l’opérande source. En chargeant A5 avec l’adresse de la zone de données, on peut accéder en lecture et en écriture à cette zone. Grands avantages de ce système : plus rapide, plus court (on gagne deux octets par instruction !), réentrant (il suffit de changer A5 et on change de zone de données). Evidemment, on perd A5, mais bon, il reste tout de même cinq autres registres... LA BELLE CONCLUSION Qui sera aussi très courte : à plus. Youpie, youpla, voila la deuxième Routinette de Tonton François. La joie m’envahit et me rend tout fébrile. Quelle excitation ! H 1
* --------7------------- Routinette
* En entree A0= Nom d'un fichier, ou pointeur
* sur une chaine nulle pour avoir le
* directory courant...
* „ . Al= Espace de 128 octets ou poker le nom
* En sortie A0= début du buffer
* D0= longueur de la chaine GetDir:
* Préparation des paramétrés movem.l al-a3 dl-d3,-(sp) move.l al,a2 ; A2 est un registre préserve lea -260(sp),sp ; Reserve un espace de travail move.l sp,a3 ; en A3 Demande un lock sur le point d'entree move.l a0,dl moveq -2,d2 DosCall _LVOLock
* On travaille avec la pile clr.l -(sp)
• Gdl: move.l d0,-(sp) move.1 dO,dl DosCall _LVOParentDir tst.l dO bne.s .Gdl move. 1 DosBaS' jsr l(a6) move.1 (sp)+ ,1 ENDM
- Dt(a5) 6 , a6 5 dos equ
- 102 equ
- 210 equ
- 84 equ
- 90 equ
- 48 equ
- 60 EXEC equ
- 552 equ
- 414 Démonstration clr .b moveq move.1 beq. S move.1 DosCall tst. 1 beq. S lea move.b bne. S move.b clr .b moveq move.1 DosCall bra. S
* Point de sortie! Gd5 lea 260+4(sp),sp move.1 - - - ; Retour a la ligne ; Adresse de la chaine ; Longueur ; Demande le canal de sortie ; sans modifier d2 et d3 ! ; Astuss !
* Va demander le chemin lea PathNul-Dt(a5),a0 lea Buffer-Dt(a5) ,al bsr GetDir $ 4 .w, a6 DosName-Dt(a5),al 0, dO _LVOOpenLibrary(a6) dO,DosBase-Dt(a5) Err DosCall
* Ferme le dos move.1 jsr
* No problemo Err moveq rts ; Une erreur est très ; improbable ! ; Base des données a2, dO 0, dO movem.l (sp)+,al-a3 dl-d3 ; Restaure les registres ; Début de la chaine Taille de la chaine Pitite mignone zone de donnée
* ____________________________________________________________ _ * ka base des accès à la zone de donnée
* ROUTINETTE numéro 2 DosBase dr 1 n
* _GetDir: trouve un pathname complet. Buffer ds b 128 1992 Par Prançois Lionet' î>aru dans l'A.N.T. du 1er Janvier DoISe dclb "dos.library", 0
* _________________________________________________________ _ even
* ---------------------- Définition de variables système
* Appel du dos DosCall MACRO move.l a6, (sp) Ptfr Tonton François Lionet *1 Contrairement aux Vsprites, qui utilisent les sprites hardware de Vamiga, les Bobs sont gérés exclusivement par le Blitter. D’où le nom de Bob, d’ailleurs, contraction de "Blitter Object". ?I PERMETTEZ QUE JE * Première ligne * * Deuxième ligne * 0x1777, OxfceO, 0x4444, 0x4444, LES COULEURS Le choix du registre de couleur associé à un pixel s’effectue de la même manière que pour les playfields. Le numéro du registre de couleur est induit par chaque bit de chaque biplane du Bob, le playfield de plus haut numéro étant le bit de poids le plus fort. Cette simple différence de gestion entraine, comme vous l’allez pouvoir constater, quelques différences dans la programmation de leur affichage... Comme le sprite virtuel, le Bob fait partie intégrante du GEL System. Mais contrairement aux Vsprites, qui, de par leurs liens avec les sprites hardware, sont indépendants du playfield, le Bob en fait partie intégrante. On peut donc utiliser un Bob comme une brosse (comme le fait Deluxe Paint, par exemple) ou au contraire, simuler un sprite en sauvegardant la zone du playfield correspondant au rectangle englobant le Bob lors de son affichage, et en la ré-affichant lorsque le Bob s’est déplacé. Le Bob n’étant plus lié à un sprite hardware mais au playfield, le nombre de couleurs que l’on peut associer à un Bob est le même que celui du playfield, ainsi que le contenu des registres de couleurs. Il vous faudra donc faire attention à ne pas utiliser les mêmes registres pour ces deux éléments sous peine de voir le Bob disparaître dans le playfield. Dans un playfield à 32 couleurs, on pourra par exemple utliser les 16 premières pour le fond et les 16 autres pour le ou les Bobs. La structure de données associée à un Bob contient des champs définissant sa structure propre ainsi qu’un pointeur sur une structure Vsprite qui contient la définition des attributs communs aux sprites virtuels et au Bob. Ces données communes sont liées en grande partie à la position du Bob. Ainsi, il sera possible de gérer cette position indépendamment du type d’élément manipulé. Il s’agit là d’une excellente initiative, évitant une duplication inutile du code de gestion des positions. Au niveau de la structure de données des Bobs, nous allons étudier simplement les champs propres à la structure Bob et les champs de la structure Vsprite possédant une valeur spécifique. Pour la description du reste des données, je vous renvoie à l’article du mois dernier sur les Vsprites. Par exemple les combinaisons possibles pour un Bob possédant deux bitplanes sont : Bitplane 0 : Bitplane 1 : Couleur A première vue, lorsque l’on utilise un Bob de deux bitplanes sur un playfield de trois bitplanes ou plus, seuls les quatre premiers registres sont disponibles (0 à 3). Pour palier à ce problème, vous avez la possibilité, grâce aux champs PlanePick et PlaneOff, de définir quels sont les registres qui vont être réellement utilisés. Ils servent donc à établir une table de correspondance entre le numéro de registre théorique (ex : 0, 1, 2, 3) et le numéro réel du registre utilisé (ex: 10, 11, 14, 15). PlanePick permet d’associer à chaque bitplane du Bob, un bitplane du playfield. Ainsi, si on reprend l’exemple d’un Bob de deux biplanes sur un playfied de cinq : N° bitplane PlanePick entrainera l’écriture des données du bitplane 0 du Bob dans le bitplane 1 du playfield et le bitplane 1 du Bob dans le bitplane 4 du playfield. Dans ce cas, les registres de couleurs utilisés ne seront plus (0, 1, 2 et
3) mais (0, 2, 8 et 10). PlanePick ne permet toutefois pas toutes les combinaisons possibles, d’où le champ PlaneOnOff. Ce champ contient une valeur sur 6 bits, comme PlanePick, qui permet par un OU logique entre chaque registre de couleur et sa valeur de modifier les registres choisis pour afficher le Bob. Ainsi, si l’on positionne PlaneOnOff à 5, on obtiendra la combinaison suivante : L’IMAGE DU BOB Vous vous rappelez sans doute que l’image d’un Vsprite (limitée à 16 pixels en largeur) est définie par une série de couples de deux mots de 16 bits, permettant pour chacun de définir une ligne du Vsprite : ligne 1 du Vsprite * 0x0fc3, 0x0000, Registre 1 I PlaneOnOff I Reg. Réel I 0 0 1 1 1 -> registre COLOR 7 Idem pour les autres registres, ce qui nous donne (0, 7, 13 et 15). Pour obtenir dans notre exemple précédent (10, 11, 14 et 15), nous aurions du placer les valeurs suivantes dans PlanePick et PlaneOnOff : Pour un Bob, l’organisation des données est différente. Comme nous l’avons vu précédemment, un Bob possède autant de couleurs que le playfield auquel il est associé. De plus, un Bob n’est pas limité arbitrairement dans ses dimensions, mais seulement par la taille du playfield auquel il est associé. Ainsi, rien n’empêche de réaliser un Bob de 64 pixels de large sur 100 lignes de haut. Dans cet exemple, les dimensions ne sont pas choisies innocemment. En effet, la taille en largeur d’un Bob doit être impérativement un multiple de 16 (nombre de mots de 16 bits). Par contre, sa hauteur s’exprime en nombre de lignes sans contraintes. Pour définir un Bob de 32 pixels de large sur deux lignes de haut, évoluant sur un écran à deux bitplanes, nous déclarerons l’image associée à ce Bob de la manière suivante : * Biplane 0 * 0x0000, OxfceO, Oxcccc, 0x1111, * Première ligne * * Deuxième ligne * * Bitplane 1*1 PlaneOnOff I PlanePick I AVANTAGES ET INCONVENIENTS Un des principaux avantages d’utiliser des Bobs par rapport à des Vsprites, c’est qu’ils peuvent être de la taille de votre choix, aussi bien en largeur qu’en hauteur. Ceci tant que vous avez encore assez de mémoire CHIP pour stocker leurs images. Par contraste, nous avions vu que le Vsprite était limité à seize pixels en largeur. Du point du vue des couleurs, nous sommes également loin de la limitation du Vsprite (trois couleurs effectives, plus une transparente). En effet, nous disposons pour le Bob du même nombre de couleurs que pour le playfield auquel il est attaché. Cela peut donc aller jusqu’à 4096 en mode HAM. Pour les Bobs, vous pouvez définir les priorités d’affichage, à l’aide des pointeurs Before et After qui leur sont associés. Vous avez ainsi la maîtrise totale de l’affichage des objets en cas de recouvrement. * nombre maxi de Bobs crées * * données du sprite * plan 0 : 0x0, 0x88, 0x30, 0x3 e, 0x3 a, 0x10, 0x8, OxaOlc, 0x3fac, 0x5800, 0x8020, 0x8000, 0xc03c, OxcOlc, 0x2000, 0x2008, 0xa03c, 0xe038, 0xc024, 0x2000, 0xe038, 0xe03c, 0xa03c, 0x8010, 0x800c, OxeOlO, 0x6030, 0x0, 0x0, plan 1; 0x30, Oxf 8, 0x3 c, 0x3e, 0x3a, 0x10, 0x0, 0x0, 0x10, 0xa63c, 0x783c, 0xe03c, 0xe03c, OxcOlc, 0x2000, 0x0, 0x0, 0x4, 0x2018, 0xc03c, 0xe03c, 0xe03c, 0xa03c, 0x8010, 0x0, 0x0, 0x0, 0x2020, 0x0, plan 2 : 0x0, 0x0, 0x0, 0x0, 0x5, 0x802f, 0xc03f, 0xe03d, 0x7fbc, 0xfe3c, Oxf83c, 0xe03c, 0xe03c, OxcOlc, 0x2000, 0x0,
- -* 0x0, 0x0, 0x0, 0x99a0, OxebeO, 0x3380,
- 0x20, , 0x33e0, . OxôfaO, 0x4240, 0x0, 0xe7e0, Oxe2cO, 0x100, 0x21a0, OxeOeO, 0x6020, 0x0, 0xe020, 0xe020, OxeOOO, 0x0, OxeOOO, OxeOOO, 0x4200, 0x0, Oxff00, OxeOOO, 0x0,
- * 0x0, 0x0, 0x20, OxffeO, OxebeO, 0x3380, 0x0, 0x0, 0x8040, OxadaO, 0xe7e0, 0xe7e0, Oxe2cO, 0x100, 0x0, 0x0, 0x80c0, 0xe060, 0xe060, 0xe020, OxeOOO, 0x0, 0x0, 0x0, OxbcOO, 0x0, 0x0, 0x0, 0x0,
- * 0x0, 0x0, 0x0, 0x0, 0x1400, 0xcc60, OxffeO, OxffeO, OxefeO, OxefeO, Oxe7eO, 0xe7e0, Oxe2cO, 0x100, 0x0, 0x0, 0x0, 0x0, 0x20, Oxce, 0x3ff, 0xa34, 0x2000, 0x2c80, 0x3e00, 0x2c9a, 0x300, 0x804, 0x33ff, 0x3b01, 0x3f00, 0x0, OxlfOO, 0x3f01, OxlaOO, 0x400, OxlfOO, 0x3f80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, *------ 0x0, 0x8, 0x3 c, Oxfe, 0x3ff, 0xa34, 0x0, 0x0, 0x0, 0x1365, 0x3cff, 0x3fff, 0x3fff, 0x3b01, 0x3f00, 0x0, 0x0, 0x0, 0x2501, 0x3b01, 0x3fOl, 0x3f81, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, *------ 0x0, 0x0, 0x0, 0x0, 0x0, 0x5cb, 0x3fc7, 0x3f81, 0x3f00, 0x3fff, 0x3fff, 0x3fff, 0x3fff, 0x3b01, 0x3f00, 0x0, 0x0, 0x80, 0x80, 0x187, 0x39e, 0x110, 0x8101 0x6191 Oxf705 0x600, 0x4000 0x1399 OxlfOl 0x580, 0x1, 0x1, 0x280, 0x680, 0x281, 0x1, 0x100, 0x580, 0x781, 0x501, 0x682, 0x280, 0x7ff, 0x359, 0x420, 0x0, 0x80, 0x98, 0xl9f, 0x39e, 0x110, 0x0, 0x0, 0x98, 0x7999, 0x7f99, 0x3f99, Oxlf81, 0x580, 0x0, 0x0, 0x1, 0x101, 0x501, 0x781, 0x780, 0x780, 0x780, 0x500, 0x1, 0x0, 0x0, 0x4a6, 0x3c0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x8 68f, 0xc79f, 0xe79d, Oxf79d, 0x7f99, 0x7f99, 0x3f99, Oxlf81, 0x580, 0x0, 0x0, 0x0, 0x0, 0x6a, Oxlfb, 0x64d, 0x2 0, 0x2000, 0x3700, 0x3900, 0xl5e4, 0x20, 0x3e91, 0x3f7f, 0x3900, 0x200, 0x801, 0x3e01, 0x1701, 0x2900, 0x0, 0x2701, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x7 e, Oxlff, 0x64d, 0x20, 0x0, 0x0, 0x600, 0x2alb, 0x3fff, 0x3fff, 0x3fff, 0x3900, 0x200, 0x0, 0x0, 0x2800, 0x1601, 0x3f01, 0x3f01, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xlb2, Oxlfcf, 0x3fc3, 0x3f80, 0x3f00, 0x3fff, 0x3fff, 0x3fff, 0x3fff, 0x3900, 0x200, 0x0, 0x0, 0x120, 0x2 c, 0x2 a, 0x8018, 0x0, 0x8035, 0x603c, 0x3f34, 0x2000, 0x0, 0xa038, OxeOlc, 0x4004, 0x0, OxaOlc, 0x603c, 0xe03c, 0x4000, 0x0, 0xa03c, 0xe03c, 0xa024, 0x0, 0x6020, 0x2030, 0x2030, 0x2000, 0x0, 0x7 0, Oxlf8, 0x3c, 0x2a, 0x8018, 0x0, 0x0, 0x0, 0x8, 0xdc3c, Oxf03c, 0xe03c, OxeOlc, 0x4004, 0x0, 0x0, 0x0, 0x0, 0xa03c, 0xe03c, 0xe03c, 0xe03c, 0xa024, 0x0, 0x0, 0x0, 0x4000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x14, 0x27, 0xc03f, 0xe03d, Oxf03c, 0x3f3c, 0xfc3c, Oxf03c, 0xe03c, OxeOlc, 0x4004, 0x0, 0x0, 0x0, 0x80, 0x180, 0x29f, 0x18e, 0x0, 0x513, 0xe79d 0xd7 81 0x1100 0x1291 0x1590 Oxf91, 0x700, 0x1, 0x81, 0x381, 0x601, 0x301, 0x301, 0x580, 0x781, 0x581, 0x401, 0x180, 0x700, 0x6ff, 0x4, 0x0, 0x0, 0x90, 0x198, 0x29f, 0x18e, 0x0, 0x0, 0x0, 0x201c, 0x6è99, 0x3f99, Oxlf90, Oxf91, 0x700, 0x0, 0x0, 0x0, 0x181, 0x481, 0x781, 0x780, 0x780, 0x580, 0x400, Oxf, 0x0, 0x100, 0x7fa, 0x700, 0x0, 0x0, 0x0, 0x100, 0x211, 0x879f, 0xc79f, 0xe79d, 0xf79d, 0x7 f 9.9, 0x3f99, Oxlf90, Oxf91, 0x700, 0x0, 0x0, VOUS APPELLE BOB ? De part le fait que les Bobs font partie intégrante du playfield, leur utilisation est plus lente que celle des Vsprites. Il est d’ailleurs vivement conseillé d’utiliser un écran double-buffer. Il ainsi possible de tracer dans un écran pendant que l’on affiche l’autre, rendant ainsi l’animation plus fluide. Les Bobs utilisent, à taille et profondeur égale, plus de mémoire que les Vsprites. En effet, il est presque toujours nécessaire de positionner le flag SAVEBACK afin d’avoir une sauvegarde automatique du fond. Dans ce cas, il faut donc la mémoire nécessaire à sauvegarder cette portion en plus de la mémoire liée à l’image du Bob. PROGRAMMATION Nous en savons désormais assez pour écrire un programme d’affichage et d’animation de Bobs. Ce programme va afficher des logos "ANT" en 16 couleurs sur un écran possédant lui aussi 16 couleurs. Les précisions nécessaires sont incluse dans le listing que j’ai le plus possible commenté. Le logo a été réalisé grâce à un utilitaire du domaine public.il existe de nombreux programmes permettant de vous aider dans la tâche fastidieuse consistant a inclure le source C d’une image dans un programme. Vous trouverez une description de quelques uns de ces logiciels dans la rubrique ToolBox du mois prochain. Sur ce, je vous souhaite une bonne étude sur l’animation et je vous retrouve dans un mois pour une nouvelle rubrique qui va faire du bruit. Mais je ne vous en dit pas plus.... Surprise. * ----------------------------------------------------------- * Programme d'affichage et d'animation de BOBs * * Exemple de programmation des BOBs * * P. AMIABLE 1991 * v *_________ ' * * Quelques includes utiles...... * * - -------- * include exec types.h> include exec memory.h> include intuition intuition.h> include stdio.h> include graphics gels,h> *_________
• * * Les defines maintenant * *___________ s ' i t ------------------------------------------------------ 5 ?e?i'ne 1NTUITI0N_REV OL * Version d'intuition * define GFX_REV OL * Version de Graphics * define NBRBOBS 1 * Nombre de BOBs affichés* Refîne LARGEUR 64 * Largeur en pixel du bob * ffdefine HAUTEUR 58 * Hauteur en ligne du bob * defme PROFONDEUR 4 * Profondeur en bitplane du bob * *__________ ' 7777------------------------------------------------* * Définition des variables externes * * * i * Declararation des fonctions définies dans le programme * void referme(); void init(); void detruit_bobs(); void ouvrefenetre(); void refermegel(); int initgel(); void graphique(); void déplacé(); int bidon(); struct Bob *cree_bob(); struct Vsprite *cree_vsprites(); struct IntuitionBase *IntuitionBase = NULL; Struct GfxBase *GfxBase = NULL; struct NewScreen nouvecran = 0 0 * LeftEdge, TopEdge * 320, 256, * Width, Height * f* * Depth, soit 16 couleurs possibles * 1 0, * DetailPen, BlockPen * SPRITES, * ViewModes valeur de 0 = basse resolution * CUSTOMSCREEN, * Type d'écran * NULL, * Font -> NULL = fonts par défaut * NULL, * DefaultTitle pour le titre -> Aucun* NULL, * gadgets, aucun* NULL }; * adresse de la CustomBitmap -> aucune ici * struct NewWindow nouvfenetre = 0 * LeftEdge position en x de la fenêtre * 0 * TopEdge position en y de la fenêtre * 320, * Width 320 pixels de large * 256, * Height 256 pixels de hauts * 0' * DetailPen Le texte doit être écrit dans la couleur 0 * 1, BlockPen les blocks doivent être dans la couleur 1 * CLOSEWINDOW, * IDCMPFlags Rien de particulier * WINDOWCLOSE|WINDOWSIZINGIWINDOWDEPTH|ACTIVATE, NULL, * FirstGadget Pas de gadgets personnels * NULL, * CheckMark Pas de Checkmark particulière * "ANT a pris des couleurs" , * Title Titre de la fenêtre * NULL, * Screen Attaché l'écran en cours de programme * NULL, * BitMap pas de Bitmap personnelle * 320, * MinWidth La fenêtre ne peut être plus petite * 320, 256, CUSTOMSCREEN * Type On accroche la fenêtre au Workbench * J struct Window *fenetre = NULL; struct Screen *ecran = NULL; struct RastPort *rastport = NULL; struct ViewPort *viewport = NULL; SHORT vitesse[] = 1, 2, -1, -2 }; * Echelle de vitesse * SHORT xmouv[NBRBOBS], ymouv[NBRBOBS]; * Direction des bobs * struct Bob *bob[NBRBOBS]; * On va créer NBRBOBS Bobs donc on se reserve les pointeurs nécessaires * 0x0, 0x0, 0x40, OxffeO, 0x3d80, 0x0, 0x2020, , OxffeO, , 0xc60, , 0x80, , 0x6780, , OxeleO, 0xe240, 0x2020, 0x180, OxeOeO, 0x80a0, 0x8020, 0xa020, 0xa020, 0x0, OxeOOO, OxeOOO, Oxf800, 0x0, 0x0, Oxf800, 0x0, 0x0, 0x0, 0x0, 0x60, OxffeO, 0x3d80, 0x0, 0x0, 0x0, 0xe380, OxefeO, 0xe7e0, OxeleO, 0xe240, 0x0, 0x0, 0x2000, 0x6040, 0xe060, 0xe020, 0xa020, 0x0, 0x0, 0x0, 0x0, Oxff80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc260, OxffeO, OxffeO, OxffeO, OxefeO, OxefeO, Oxe7eO, OxeleO, 0xe240, 0x0, 0x0, 0x0, struct Vsprite *vsprite short max_cree = 0; struct Vsprite *tete = NULL; struct Vsprite *queue = NULL; struct Gelslnfo gelinfo; UWORD chip bobimage[]= bitmap : largeur = 64, hauteur = 58 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4000 0x0, 0x0, 0x1, 0x20, 0x0, 0x0, 0x1, OxeOOO 0x0, 0x0, 0x1, OxeOOO, 0x0, 0x0, 0x1, OxeOOO 0x0, 0x4000, 0x1, OxeOOO, 0x0, 0x4018, 0x201, OxeOOO 0x1, 0x602c, 0x281, OxeOOO, 0x1, 0xe03c, 0x381, Oxf800 0x1, 0xe03c, 0x783, OxfeOO, 0x0, 0xe038, 0x78f, Oxff80 0x0, 0xe038, 0x780, 0x0, 0x0, 0x6030, 0x780, 0x0, 0x0, 0x6030, 0x7ff, OxffOO, 0x0, 0x6030, 0x7ff, Oxf800 0x0, 0x2020, 0x7ff, OxeOOO, 0x0, 0x2020, 0x7fe, 0x0, 0x0, 0x0, 0x7eO, 0x0, 0x0, 0x0, 0x700, 0x0,
* __ plan 3 :
- -* 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x200, 0x0, 0x0, 0x10, 0x120, 0x0, 0x20, 0x1000, , OxlaO, 0x400, 0x2020, Oxall, 0xe2e0, 0x601, 0xa038, 0x881, OxeleO, 0x1, 0xc03c, 0x781, OxeleO, 0x3d01, 0xe03c, 0x781, OxeleO, 0x3f01, 0xe03c, 0x781, OxeOeO, 0x3f01, 0xe03c, 0x781, OxeOeO, 0x3f01, 0xe03c, 0x781, OxeOeO, 0x3f01, 0xe03c, 0x781, OxeOeO, 0x3f01, 0xe03c, 0x781, 0xe060, 0x3f01, 0xe03c, 0x781, 0xe060, 0x3f01, 0xe03c, 0x781, 0xe060, 0x3f01, 0xe03c, 0x781, 0xe020, 0x3f01, 0xe03c, 0x781, 0xe020, 0x3f01, 0xe03c, 0x781, 0xe020, 0x3f01, 0xe03c, 0x781, 0xe020, 0x3f01, 0xe03c, 0x781, OxeOOO, 0x3f81, 0xe03c, 0x781, OxeOOO, 0x1, 0xe03c, 0x781, OxeOOO, 0x1, 0xe03c, 0x781, OxeOOO, 0x1, 0xe03c, 0x781, OxeOOO, 0x1, 0xe03c, 0x781, OxeOOO, 0x1, 0xe03c, 0x781, Oxf800, 0x1, 0xe03c, 0x783, OxfeOO, 0x0, 0xe038, 0x78f, Oxff80, 0x0, 0xe038, 0x780, 0x0, 0x0, 0x6030, 0x780, 0x0, 0x0, 0x6030, 0x7ff, OxffOO, 0x0, 0x6030, 0x7ff, Oxf800, 0x0, 0x2020, 0x7ff, OxeOOO, 0x0, 0x2020, 0x7fe, 0x0, 0x0, 0x0, 0x7e0, 0x0, 0x0, 0x0, 0x700, 0x0 } ; UWORD tablecouleur[] = 0x0000, OxOeca, OxOfOO, OxOf16, OxOfle, 0x0c2e, 0x072e, 0x033e 0x066e, 0x089d, OxObbd, OxOaac, 0x099b, 0x099a, 0x0889, 0x0444 } ; *-------------------------------------------------------------* * Programme principal * *-------------------------------------------------------------* main() struct intuiMessage *message; SHORT i; init(); ouvrefenetre() ; * ouverture de l'écran et de la fenêtre * initgel(); * initialisation du GELS * graphique(); while(1) déplacé() ; * on bouge les bobs par Vsprite interposés * message = (struct IntuiMessage *)GetMsg(fenetre->UserPort); if (message) switch(message->Class) case CLOSEWINDOW: for(i=0; i max_cree; i++) if(bob[i]) detruit_bobs(bob[i]->BobVSprite); refermegel(); referme (); exit(TRUE); break; case INTUITICKS: déplacé(); break; default: break; ReplyMsg(message); } } * * A* Init() Ouvre la bibliothèque * *-------------------------------------------------------------* void init() char *OpenLibrary(); IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",INTUITION_REV); if(!IntuitionBase) exit(FALSE); GfxBase = (struct GfxBase *) OpenLibrary("graphies.library",GFX_REV); if(!GfxBase) referme (); exit(FALSE); } } *-------------------------------------------------------------* * ouvrefenetre() ouvre la fenetre et 1'écran * *-------------------------------------------------------------* void ouvrefenetre() void referme (); if(!(écran =(struct Screen*)OpenScreen(fcnouvecran))) referme(); exit(FALSE); nouvfenetre.Screen = écran; if(!(fenetre=(struct Window*)OpenWindow(&nouvfenetre))) referme (); exit(FALSE); viewport = &(écran->ViewPort); rastport = &(écran->RastPort); LoadRGB4(viewport, &tablecouleur[0], 16); * * * Cette fonction referme la fenetre et les bibliothèques * *-------------------------------------------------------------* void referme() if(fenetre) CloseWindow(fenetre); if(écran) CloseScreen(écran); if(IntuitionBase) CloseLibrary(IntuitionBase); if(GfxBase) CloseLibrary(IntuitionBase); } * * * Cette fonction déplace les max_cree bobs * *-------------------------------------------------------------* void déplacé() short i; for (i=0; i max_cree; i++) vsprite = bob[i]->BobVSprite; vsprite->X = xmouv[i]+vsprite->X; vsprite->Y = ymouv[i]+vsprite->Y; * Test de dépassement de l'écran. * if(vsprite->X >= 256 II vsprite->X = 0) xmouv[i]=-xmouv[i]; if(vsprite->Y >= 192 II vsprite->Y = 0) ymouv[i]=-ymouv[i]; } SortGList(rastport); * réordonne la liste des Vsprites * DrawGList(rastport, viewport); MakeScreen(écran); * on régénère l'écran* RethinkDisplay(); * et on visualise le tout * * * * routine appelée lors de la détection de collision * *-------------------------------------------------------------* int bidon() * elle ne fait rien * return(0); } *-------------------------------------------------------------* * Cette fonction initialise la structure Gels. * *-------------------------------------------------------------* int initgel() if ((tete = (struct Vsprite *)AllocMem(sizeof (struct Vsprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0) return(-1); if ((queue = (struct Vsprite *)AllocMem(sizeof (struct Vsprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0) refermegel(); if (tete != NULL) FreeMem(tete, sizeof(struct Vsprite)); return(-2); } gelinfo.sprRsrvd = OxFC; if ((gelinfo.nextLine = (WORD *)AllocMem(sizeof(WORD) * 8, MEMF_PUBLIC | MEMF_CLEAR)) == NULL) refermegel(); if (tete != NULL) FreeMem(tete, sizeof(struct Vsprite)); if (queue != NULL) FreeMem(queue, sizeof(struct Vsprite)); return(-3); } if ((gelinfo.lastColor = (WORD **)AllocMem(sizeof(LONG) * 8, MEMF_PUBLIC | MEMF_CLEAR)) == NULL) refermegel(); if (tete != NULL) FreeMem(tete, sizeof(struct Vsprite)); if (queue != NULL) FreeMem(queue, sizeof(struct Vsprite)); return(-4); } * Maintenant on préçare une table de pointeurs vers des routines qui seront exécutées quand la fonction DoCollision détectera une collision. Nous étudierons le fonctionnement d'un tel système en détail le mois prochain. * if ((gelinfo.collHandler = (struct collTable
* )AllocMem(sizeof(struct collTable), MEMF_PUBLIC I MEMF_CLEAR)) == NULL) refermegel(); if (tete != NULL) FreeMem(tete, sizeof(struct Vsprite)); if (queue != NULL) FreeMem(queue, sizeof(struct Vsprite)); return(-5); } gelinfo.leftmost = 0; gelinfo.rightmost = rastport->BitMap~>BytesPerRow *8-1; gelinfo.topmost = 0; gelinfo.bottommost = rastport->BitMap->Rows - 1; rastport->GelsInfo = &gelinfo; InitGels(tete, queue, &gelinfo ); SetCollision(0, bidon, &gelinfo); WaitTOF(); * Attente de fin de trame * *-------------- * * Cette fonction désalloue la structure gels . * *------------------------------------------------------------- void refermegel() if (gelinfo.collHandler != NULL) FreeMem(gelinfo.collHandler, sizeof(struct collTable)); if (gelinfo.lastColor != NULL) FreeMem(gelinfo.lastColor, sizeof(LONG) * 8); if (gelinfo.nextLine != NULL) FreeMem(gelinfo.nextLine, sizeof(WORD) * 8); if (gelinfo.gelHead != NULL) FreeMem(gelinfo.gelHead, sizeof(struct Vsprite)); if (gelinfo.gelTail != NULL) FreeMem(gelinfo.gelTail, sizeof(struct Vsprite)); Cette fonction crée l'ensemble des éléments graphiques void graphique() int erreur; int i,j,x,y; erreur = initgel(&gelinfo, rastport); for(i=0; i NBRB0BS; i++) xmouv[i] = vitesse[RangeRand(4)]; ymouv[i ï = vitesse[RangeRand(4)]; RangeRand(246); RangeRand(182) ; bob[i] = cree_bob(LARGEUR,HAUTEUR,PROFONDEUR,bobimage,0x3f,0x3f,x, y,SAVEBACK|OVERLAY); if(bob[i] == 0) break; * plus de mémoire * if (i > 0) 3 = i-1; bob[i]->After = bob[j]->Before; bob[i]->After->Before = bob[j]; AddBob(bob[i], rastport); max cree++; * ----------------------------------------- * Cette fonction détruit un bob et libère ses ressources * *-------------------------------------------------------------* void detruit_bobs(vsprite) struct Vsprite *vsprite; if (vsprite != NULL) if (vsprite->VSBob != NULL) if (vsprite->VSBob->SaveBuffer != NULL) FreeMem(vsprite->VSBob->SaveBuffer, sizeof(SHORT)*vsprite->Width*vsprite->Height*vsprite->Depth); if (vsprite->VSBob->DBuffer != NULL) if (vsprite->VSBob->DBuffer->BufBuffer != 0) FreeMem(vsprite->VSBob->DBuffer->BufBuffer, sizeof(SHORT)*vsprite->Width*vsprite->Height*vsprite->Depth); FreeMem(vsprite->VSBob->DBuffer, sizeof(struct DbufPacket)); } FreeMem( vsprite->VSBob, sizeof(struct Bob)); } if (vsprite->CollMask != NULL) FreeMem(vsprite->CollMask, sizeof(WORD)*vsprite- Height*vsprite->Width); } if (vsprite->BorderLine != NULL) FreeMem(vsprite->BorderLine, sizeof(WORD)*vsprite-
* Width) ; } FreeMem(vsprite, sizeof(struct Vsprite)); } SHORT nb_mot; nb_mot = (largeur+15) 16; if(( v = cree_vsprites(hauteur,image,NULL,x,y,nb_mot,profondeur,flags)) == 0) return(0) v->PlanePick = planepick; v->PlaneOnOff = planeonoff; if(( b = (struct Bob *)AllocMem(sizeof(struct Bob),MEMF_PUBLIC | MEMF_CLEAR)) == 0) return(0) ; v->VSBob = b; b->Flags = 0; if((b->SaveBuffer = (WORD
* )AllocMem(sizeof(SHORT)*nb_mot*hauteur*profondeur, MEMF_CHIP|MEMF_CLEAR)) == 0) FreeMem(b,sizeof(struct Bob)); return(0); } b~>ImageShadow = v->CollMask; b->Before = NULL; b->After = NULL; * les priorités d'affichages seront indiquées plus tard * b->BobVSprite = v; b->BobComp = NULL; * il ne s'agit d'une partie d'un objet plus complexe * b->DBuffer = NULL; * il n'y a pas de double buffer * return(b); } * * * * struct Vsprite *cree_vsprites(hauteur, image, tablecol, x, y,nb_mot,profondeur,flags) SHORT hauteur; WORD *image; WORD *tablecol; SHORT x, y; SHORT nb_mot,profondeur,flags; Cette fonction crée un Vsprite struct Vsprite *vsprite; if ((vsprite = (struct Vsprite *)AllocMem(sizeof(struct Vsprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0) return(0); v vsprite->Flags = flags; vsprite->Y = y; vsprite->X = x; vsprite->Height = hauteur; vsprite->Width = nb_mot; vsprite->Depth = profondeur; vsprite->MeMask = 1; vsprite->HitMask = 1; vsprite->ImageData = image; * associe l'image au vsprite * if ((vsprite->BorderLine = (WORD
* )AilocMem(sizeof(WORD)*nb_mot, MEMF_PUBLIC I MEMF_CLEAR)) == 0) FreeMem(vsprite, sizeof(struct Vsprite)); return(0); } if ((vsprite->CollMask = (WORD
* )AllocMem(sizeof(WORD)*hauteur*nb_mot,MEMF CHIP I MEMF CLEAR)) == 0) FreeMem(vsprite, sizeof(struct Vsprite)); FreeMem(vsprite->BorderLine, nb_mot*sizeof(WORD)); return(0); } vsprite->SprColors = tablecol; vsprite->PlanePick = 0x00; vsprite->PlaneOnOff = 0x00; InitMasks(vsprite); return(vsprite); * C'est un bob * * * * * struct Bob
* cree_bob(largeur,hauteur,profondeur,image,planepick,planeonoff,x ,y,flags) SHORT largeur; * Largeur en pixels du Bob * SHORT hauteur; * hauteur en lignes du Bob * SHORT profondeur; * nombre de bitplanes * WORD *image; * image associée au Bob * SHORT planepick, planeonoff; SHORT x,y; * la position du Bob lors de sa création * SHORT flags; * les flags divers associés au Bob * struct Bob *b; struct Vsprite *v; Cette fonction crée un bob Par Herr Dokîor von GluttenStimellmDorf ‘Ttcltls actor
1. ) La rubrique Transactor de l Amiga NewsTech est la rubrique écrite par les lecteurs, pour les lecteurs. Son but est de leur permettre de s’exprimer librement sur tout sujet qui les passionne, dans quelques langage de programmation que ce soit. Seule restriction : la Rédaction doit avoir la possibilité de tester le bon fonctionnement de tous les programmes fournis, complets ou simples routines d’illustration. Non mais. Règlement e t P rop o siti on d ’Article
2. ) Tout lecteur désirant participer à la rubrique Transactor devra envoyer son article sur disquette au format Amiga, en respectant les quotas définis aux paragraphes 4 et 5. Les disquettes ne seront pas retournées, sauf demande expresse et écrite de l’auteur, et encore.
3. ) Tout article publié sera rémunéré au tarif forfaitaire de 1, 500 F HT les deux pages ; un article de plus de deux pages sera publié en plusieurs fois, a concurrence de trois épisodes maximum. Le paiement a lieu le mois suivant celui de la parution. Les auteurs des articles retenus pour parution seront directement prévenus par téléphone. It n , . ,
4. ) Les articles doivent parvenir au format ASCII standard (utilisez un éditeur de textes ou l’option de sauvegarde "text only' ou ASCII de votre traitement üe texte). Les programmes illustrant les articles, qu’ils soient complets ou de simples routines d’exemple, doivent également être fournis sous forme ASCII, et éventuellement en format "brut" le cas échéant Basic, AMOS...). Le(s) fichier(s) exécutable(s) doivent se trouver sur la disquette. L’auteur doit fournir a 1 AN1 la possibilité de recompiler ou d’interpréter ses programmes sans difficulté (joindre au besoin une version "run-only du langage utilisé).
5. ) La taille totale du fichier ASCII donne le nombre de signes de votre article ; une page de l’ANT contient en moyenne 7, 000 signes de texte. Une colonne de listing contient 80 lignes de 65 caractères de large. Un programme de 160 lignes occupe donc une page entière. Les programmes en assembleur particulièrement longs peuvent être publiés en trois colonnes de 40 caractères chaque (240 lignes par page).
6. ) Toute proposition d’article pour Transactor devra être accompagnée du bon ci-dessous, découpé ou photocopié, mais en aucun cas reproduit a la main.
7. ) Toute proposition d’article pour Transactor entraîne l’acceptation par l’auteur que les programmes joints soient placés sur la disquette d’accompagnement de l’ANT. L’auteur doit préciser dans des commentaires en tête de listing s’il place son programme dans le Domaine Public ou s’il désire conserver son copyright. Aucun commentaire implique la mise en Domaine Public.
8. ) Ni TANT, ni Commodore Revue SARL, ni les auteurs collaborant à la rubrique Transactor ne sauraient être tenus pour responsables en cas de dommages quelconques survenus à l’ordinateur, suite à une mauvaise utilisation des documents (textes et programmes) publiés dans cette rubrique.
9. ) Toute proposition d’article pour Transactor entraîne l’entière acceptation par l’auteur de ce règlement, et sans discuter. ’mTT C’est nouveau, c’est pas encore sorti : à partir du mois prochain, si vous êtes déjà abonné, vous pourrez parrainer un nouveau venu dans la grande famille et gagner des cadeaux offerts par CIS. Je ne veux pas gâcher la surprise, vous en saurez plus en temps voulu. Si votre abonnement arrive à échéance, n’oubliez pas de le renouveler le plus tôt possible. Ce serait quand même dommage de rater un ou plusieurs numéros ! Ca aussi c’est nouveau, vous pouvez commander les anciens numéros de l’ANT à la pièce, afin de compléter votre collection. Tout est indiqué dans le bon de commande ci-dessous. Bon de commande à découper ou photocopier (pas de recopie manuelle SVP) et à retourner correctement rempli et accompagné de votre règlement à MCM Europe, 16, Quai Jean-Baptiste Clément, 94140 Alfortville, France. OUI, je m’abonne à Amiga NewsTech. Je choisis la formule : ? 1 an (11 numéros) sans disquette 350 FF ? 1 an (11 numéros) avec disquette 600 FF ? (cochez cette case pour un ré-abonnement) Je commande les anciens numéros suivants : (? Avec disquette) (? Avec disquette) (? Avec disquette) (? Avec disquette) ? N°20 (? Avec disquette) ? N°25 ? N°21 (? Avec disquette) ? N°26 ? N°22 (? Avec disquette) ? N°27 ? N°23 (? Avec disquette) ? N°28 ? N°24 (? Avec disquette) au tarif unitaire de 45 F (60 F avec disquette), pour un total de Nom Prénom Adresse Code Postal Ville Pays TE UNIQUEMENT P A R ABONNEMENT ExecBase : Le C ANSI 2 Denis Jarril AMOS : La nouvelle extension musicale 4 François Lionet Arexx : Travail pratique (III) 6 François Gueugnon Pascal : Présentations 8 Olivier Garrigues GFA Basic : Le timer.device 10 Pierre Philippe Launay Algos : Les listes chaînées 12 Lucien Turski et Bruno Bailiuet Hardware : La voix de Paula 14 Philippe Rivai II on Transactor : Les Plasmas 16 Thomas Landspurg ToolBox : Les créateurs d’images 18 Herr Doktor von Glupa Demos : Le RollerText 20 Jérôme Etienne Utilitaire : BigCLI 24 Max Routinettes : GetDir 27 Tonton François Lionet SubWay : Les Bobs 28 Herr Doktor von Glupa Le pont de San Francisco dans le brouillard. Font-size:medium;font-family:Arial, sans-serif;font-weight:bold;">4 François Lionet Arexx : Travail pratique (III) 6 François Gueugnon Pascal : Présentations 8 Olivier Garrigues GFA Basic : Le timer.device 10 Pierre Philippe Launay Algos : Les listes chaînées 12 Lucien Turski et Bruno Bailiuet Hardware : La voix de Paula 14 Philippe Rivai II on Transactor : Les Plasmas 16 Thomas Landspurg ToolBox : Les créateurs d’images 18 Herr Doktor von Glupa Demos : Le RollerText 20 Jérôme Etienne Utilitaire : BigCLI 24 Max Routinettes : GetDir 27 Tonton François Lionet SubWay : Les Bobs 28 Herr Doktor von Glupa Le pont de San Francisco dans le brouillard.

Click image to download PDF

AMIGA NEWS TECH numero 29 (01-1992)

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


Thanks for you help to extend Amigaland.com !
frdanlenfideelhuitjanoplptroruessvtr

Connexion

Pub+

35.5% 
16.3% 
6.7% 
5% 
4.1% 
3.5% 
3.1% 
2.4% 
1.6% 
1.2% 

Today: 25
Yesterday: 91
This Week: 217
Last Week: 630
This Month: 2193
Last Month: 3072
Total: 66333

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