Omikron BASIC 3.01 sur Atari ST

Si vous avez acheté votre ST autour de 1990, il est possible qu’il était livré avec le BASIC Omikron 3.01 et une littérature assez approximative. Cette page, écrite en 1991 sous forme de brochure, devrait y remédier.
Quelques corrections et ajouts le 2022.02.26

Le BASIC Omikron 3.01 a été écrit par Artur Södler (et Thomas Kemp pour les routines mathématiques) en assembleur 68000, langage d’une grande concision : il tient en 106 Ko. Avec cela vous pourrez faire à peu près ce que vous voudrez, et même du graphisme. Mais si vous voulez utiliser le GEM (Graphic Environment Manager) pour disposer de fenêtres et de menus, vous devrez trouver de la documentation et éventuellement un constructeur de ressources, ce qui sera moins évident.

Vous n’avez plus de ST? Il est possible d’utiliser ce BASIC en émulation Atari : Aranym signifie «Atari Runs on ANY Machine», et Hatari semble également universel…

Pour le concurrent GFA, voyez la page de Freddo!

1. Commencer

1.1 Éditeur standard
1.2 Éditeur graphique

2 Variables et valeurs

2.1 Variables numériques
2.2 Bases numériques
2.3 Opérateurs de base
2.4 Fonctions mathématiques
2.5 Chaînes de caractères
2.6 Conversions de types
2.7 Tableaux et matrices
2.8 Opérateurs logiques

3. Structures

3.1 Conditions
3.2 Boucles
3.3 Procédures

3.4 Fonctions
3.5 Exploitation des données
3.6 Branchements
3.7 Routines

4. Périphériques

4.1 Les trois écrans
4.2 Affichage
4.3 Saisie
4.4 Autres ports
4.5 Son YM2149

5. Stockage

5.1 Système de fichiers
5.2 SAVE et LOAD
5.3 Fichiers séquentiels
5.4 Fichiers relatifs
5.5 Disquettes

6. Graphisme

6.1 Souris
6.2 Boîtes
6.3 Texte graphique
6.4 Points et lignes
6.5 Figures géométriques
6.6 Remplissage
6.7 BITBLT
6.8 Sprites
6.9 Couleurs

7. Système

7.1 La mémoire
7.2 Routines en assembleur
7.3 Date et heure
7.4 Traitement des erreurs
7.5 Programmation système
7.6 Précautions utiles
7.7 Bugs et faiblesses

1. Les éditeurs et commandes de contrôle ( → .en)

L’Omikron 3.01 possède deux éditeurs.

1.1 L’éditeur standard ( → .en)

Le premier éditeur ressemble aux éditeurs classiques tels qu’ils existaient sur les premières plateformes, tels le Commodore-64, où chaque ligne de code est préfixée d’un numéro.

Saisissez 10 print "Bonjour, tout le monde! et votre première ligne de programmation est enregistrée. Saisissez list et vous le verrez apparaître :

10 PRINT "Bonjour, tout le monde!

LIST affiche le programme dans l’ordre des numéros de ligne
LIST n affiche la ligne n uniquement
LIST m-n affiche les lignes de programme de m à n
LIST -n affiche le programme jusqu’à la ligne n
LIST m- affiche le programme à partir de la ligne m

RENUM renumérote les lignes du programme, de 10 en 10
RENUM m précise le numéro de la première ligne
RENUM l, m, n la ligne m devient l, les suivantes de n en n

CLS efface l’écran et place le curseur en haut à gauche de l’écran
CLEAR met les variables à 0, ferme les fichiers, vérifie les boucles et débranche les sous-programmes conditionnels

NEW ! ATTENTION : efface le programme *.BAS en mémoire.
QUIT ou SYSTEM quitte l’interpréteur

RUN met les variables à 0, vérifie et exécute le programme
RUN 100, RUN Aum …à partir de la ligne 100 ou de l’étiquette -Aum
GOTO n exécute un programme en n sans mettre les variables à 0

Touches spécifiques à l’éditeur standard ( → .en)

[Enter] ou [Return] valide et mémorise une ligne de programme
[ClrHome] remet le curseur en haut à gauche (0, 0)
[Ctrl]-[ClrH] efface l’écran (LIST pour réafficher le programme)
[Ctrl]-[Del] efface la ligne à droite du curseur.
[Ctrl]-[Fl.H] escamote une ligne (fait remonter les suivantes)
[Ctrl]-[Fl.B] insère une ligne.
[Ctrl]-[Fl.G] définit le coin supérieur gauche d’une fenêtre (=CHR$(4))
[Ctrl]-[Fl.D] définit le coin inférieur droit de la fenêtre (=CHR$(5))
[ClrH] [ClrH] annule la fenêtre délimitée par les précédents
[Ctrl]-[S] suspend un défilement ou un programme
[Ctrl]-[Q] reprend le défilement ou le programme
[Ctrl]-[C] arrête un défilement ou un programme
[Sft]-[Sft] permet une commande en mode direct\ pendant le déroule-
[Ctrl]-[Alt] efface le buffer-clavier (63 car.)/ ment d’un programme

KEY n définit les 20 touches-fonction (KEY 13= [Sft]-[F3]).
KEY 10= CHR$(27)+ "E" ' =CLS (vaut 2 caractères, maximum 32)
KEY 20= "quit+"CHR$(13)+ "y" ' = quitter Omikron
KEY LIST liste les 20 touches-fonction de l’éditeur standard. Il est possible de sauvegarder ces définitions par le menu Mode » Save settings du super-éditeur.

Pour utiliser une touche-fonction dans un programme, lui attribuer un caractère avec KEY et guetter son scancode : $3B à $44 pour [F1] à [F10]; $70 à $79 pour [Sft]-[F1] à [Sft]-[F10]

1.2 L’éditeur graphique ( → .en)

L’éditeur graphique (au sens du GEM en 1985) comporte des menus et gère la souris. Il permet également de se passer des numéros de ligne. De l’éditeur standard, il faut saisir EDIT pour accéder à l’éditeur graphique.

[Sft]-[F1] divise l’écran
[F3] [F2] remplace une chaîne
[Sft]-[F6] [F9] coupe une ligne
[F7] [F8] sauve le bloc en ASCII
[F8] sauve un programme
[F9] insère une ligne
[F10] affiche la page suivante
[F1] [Fl.H] en haut de l’écran
[Sft]-[F3] change de police
[Sft]-[F2] passage d’une fenêtre à l’autre
[F3] [F3] remplace toutes les chaînes
[Sft]-[F6] [Sft]-[F9] colle deux lignes
[F7] [Sft]-[F8] charge un bloc en ASCII
[Sft]-[F8] charge un programme
[Sft]-[F9] supprime une ligne
[Sft]-[F10] affiche la page précédente
[F1] [Fl.B] en bas de l’écran
[F6][n] répète n fois le dernier caractère

[Sft]-[F7] permet de définir les touches [F4], [F5], [Sft]-[F4], [Sft]-[F5]
et le bouton droit de la souris : [Sft]-[F7] [Fn][t][e][x][t][e] [Sft]-[F7]

[Ctrl]-[Return] coupe une ligne de programmation
[Ctrl]-[ClrHome] (dés)active la numérotation-lignes
[Ctrl]-[Fl.H]/[Fl.B] curseur sur page précédente / suivante
[Ctrl]-[Sft]-[Fl.H]/[Fl.B] curseur sur la première / dernière ligne
[Ctrl]-[Fl.G]/[Fl.D] curseur sur le mot précédent / suivant
[Ctrl]-[Sft]-[Fl.G]/[Fl.D] curseur en début / en fin de ligne

Dans un programme ( → .en)

STOP s’écrit dans un programme pour faire une pause
DUMP affiche les variables suivies de leur valeur
DUMP V, W, … affiche les variables ayant pour initiales V, W,
CONT dans l’éditeur standard, reprendra le programme interrompu par STOP ou [Ctrl]-[C]
 CONT TO n reprend le programme pour s’arrêter à la ligne n
 CONT m TO n reprend le programme en m pour s’arrêter en n

REM permet d’écrire une remarque, remplaçable par une '

END termine le programme et ferme tous les fichiers

2. Les variables ( → .en)

Tout groupe de lettres non accentuées comprenant ou non "_" ou des chiffres, mais ne commençant pas par un chiffre, peut être une variable, à condition de ne pas être une instruction, procédure ou fonction.

2.1 Les variables numériques ( → .en)

L’Omikron reconnaît différents types de nombres, ceux-ci remplissant différemment les mémoires de la machine.

Pour éviter les problèmes, il faut être attentif à utiliser les variables adéquates. Par exemple le calcul : V= .1: PRINT 1/V produit l’erreur "Division by zero" parce que le basic interprète la variable V comme un entier et l’arrondit à 0. Pour pallier cet inconvénient, il faut utiliser une variable décimale :
V!= .1: PRINT 1/V!

V% (ou V%W) représente un entier court, de 16 bits, (2 octets), et peut contenir des valeurs de -32 768 à 32 767
V (ou V%L) représente un entier long, de 32 bits, (4 octets), et peut contenir des valeurs de -2 147 483 648 à 2 147 483 647
V! représente un réel «simple précision», prenant 6 octets en mémoire
V# représente un réel «double précision», prenant 10 octets en mémoire

Réels «simples» et «doubles» ont un exposant allant de -4 931 à 4 941, et ne diffèrent que par leur précision : 9 chiffres significatifs pour les premiers, 19 pour les seconds.

V%F est une variable booléenne, soit un bit de valeur de 0 ou -1
V%B est une variable représentant un octet, soit 8 bits, ayant pour valeur possible les entiers de 0 à 255

Ces deux formats ne peuvent s’utiliser que dans des tableaux.

Il est possible de décomposer un entier Long en deux entiers courts :

PRINT HIGH($12345678) donne 4660 ($1234 converti en décimal). Mot de «poids fort»
PRINT LOW($12345678) donne 22136 (soit $5678), mot de «poids faible».

L’Omikron convertit de lui-même le type des résultats des calculs qu’il effectue. Par exemple, PRINT LN (3) affichera un réel. Mais il arrive qu’il soit nécessaire de préciser le résultat du nombre (attention aux arrondis et aux dépassements de capacité) :

V#=CDBL( ) convertit en Réel simple
V!=CSNG( ) convertit en Réel double
V%=CINT( ) convertit en Entier court
V=CINTL( ) convertit en Entier Long

Déclaration de type ( → .en)

Il est possible de déclarer a priori le type des variables utilisées, permettant de négliger de le préciser. Mais on ne doit pas, comme c’est l’usage dans d’autres langages, déclarer les variables en début de programme.

DEFINT "A, R" A… et R… sont des entiers courts (% ou %W)
DEFINTL "Q" Les variables commençant par Q sont des entiers longs (par défaut).
DEFSNG "C, L" C… et L… sont des réels simples
DEFDBL "D-K" D… E… F… G… H… I… J… et K… sont des réels doubles

Les DEF… doivent s’écrire avant toute programmation! Sinon, il faut les ajouter en début de programme, sauver en ASCII avec SAVE "NOM.BAS", A (pas de LIST !), puis recharger le programme avec LOAD.

2.2 Les bases numériques ( → .en)

% (ou &b) binaire avec ses caractères 0 et 1 : %1000101
& (ou &o) octal avec ses caractères de 0 à 7 : &7532136
rien (ou &d) décimal (mode par défaut)
$ (ou &h) hexadécimal (de 0 à 9 et de A à F) : $-7F3AD5

47 = $2F (2*16+15) = &57 (5*8+7) = %101111 (32+8+4+2+1)

&b, &o, &d et &h assure la compatibilité avec d’autres BASICS.

Il est possible de convertir la base d’un nombre quelconque, à condition de respecter les limites imposées aux entiers longs :

BIN$( ) convertit en %binaire. PRINT BIN$(25) est 11001
OCT$( ) convertit en &octal. PRINT OCT$(35) est 43
HEX$( ) convertit en $hexadécimal. PRINT HEX$(72) est 48
VAL("") convertit en décimal PRINT VAL("$7FFF") est 32767

Il est possible de convertir les nombres binaires, de base octale ou hexadécimale par la fonction VAL même s’ils ne sont pas entiers. L’inverse n’est pas possible.

2.3 Opérateurs de base ( → .en)

LET alloue un nombre ou une chaîne à une variable : LET Var=43
LET Var$ A$=A$+"43" est possible

En fait, il n’est pas nécessaire, gardé que pour la compatibilité avec d’autres basic. Attention au type de variable :
Var=3.14159 n’entrera que 3 dans la variable, qui est ici entière.

Dans l’expression A=B=6, A vaudra -1 (le vrai logique) si B est égal à 6, 0 sinon (faux).

+, -, *, / s’organisent entre eux comme on a appris à l’école
\ division entière : le résultat est un entier, sans considération du reste : ?43\5 = 8
MOD modulo : reste d’une division ?43 MOD 5 = 3

ABS donne la valeur absolue d’un réel : ?ABS(-43) = 43
SGN donne le signe d’un réel : ?SGN(-43) = -1, ?SGN(43) = 1, ?SGN(0) = 0

FRAC retourne la partie décimale d’un réel : ?FRAC(4.3) =.3
FIX retourne la partie entière d’un réel : ?FIX(4.3) = 4
INT arronndit au nombre inférieur : ?INT(-4.3) = -5

= est également utilisé comme comparateur d’égalité
< strictement plus petit, <= ou =< plus petit ou égal
> strictement plus grand, >= ou => plus grand ou égal

?MIN(A, B) retourne la plus petite des deux valeurs (ou la première par ordre alphabétique)
?MIN(A, B) retourne la plus grande des deux valeurs (ou la seconde par ordre alphabétique)

2.4 Fonctions mathématiques ( → .en)

Trigonométrie ( → .en)

DEG pour travailler en degrés (à spécifier absolument!)
RAD pour retourner en mode radian (mode par defaut)

PI rend la valeur PI en double précision : 3.1415926535897932…

L’Omikron possède les principales fonctions trigonométriques :

SIN - COS - TAN - COT - SEC - COSEC - - ARCSIN - ARCCOS - ARCTAN (ou ATN) - ARCCOT
SINH - COSH - TANH - COTH - SECH - COSECH - - ARSINH - ARTANH - ARCOTH

Puissances et logarithme ( → .en)

^ indique la puissance. 2^16 = 65536
LOG(A, B) logarithme en base A du nombre B LOG(2, 8) = 3
SQR(n) racine carrée rapide de n : ?SQR(7744) = 88

EXP(n) exponentielle en base e du nombre n
LN(n) logaritme népérien (de base e= 2.7182818287983537…)
Pour rappel, un logarithme n’est défini que pour un nombre supérieur à 0

FACT(n) Factorielle de l’entier n. FACT(5) donne 120 (5*4*3*2*1)

Fonctions aléatoires ( → .en)

RND(1) donne une valeur aléatoire entre 0 et.99999999
RND(n) donne une valeur entière entre 0 et n-1
-RND(-n) donne une valeur entière entre 1 et n
RND(0) rend le dernier nombre aléatoire généré

RND(6)+1 ou -RND(-6) simule le lancer d’un dé
-RND(-6)-RND(-6) simule la somme de deux dés, ce qui n’est pas égal à -RND(-12) ni même à 1-RND(-11), car les onze résultats (de 2 à 12) n’ont pas la même probabilité d’apparaître.

XBIOS(R, 17) la variable R retourne un nombre semi-aléatoire de 24 bits

2.5 Les chaînes de caractères ( → .en)

Les chaînes de caractères sont entourées de guillemets. Les variables qui les représentent et les instructions qui retournent des chaînes doivent posséder le suffixes $ (mais pas LEN() ni INSTR() qui retournent un nombre). Comme pour les variables numériques, il est possible de prédéfinir des variables-chaînes en début de programme : DEFSTR A, B-D .

A$= "Holy": B$= "Graal": PRINT A$ +B$ donne HolyGraal (sans espace)
PRINT "Ni!"*3 donne Ni!Ni!Ni! (le multiplicateur doit s’écrire derrière)
B$= SPACE$(n) ou SPC(n) construit une chaîne de n espaces
PRINT STRING$(3, "6") donne 666 multiplie 3 fois un (seul) caractère…
PRINT STRING$(n, asc) le caractère étant défini ici par son code ASCII
PRINT LEN("Camelot") donne 7 , soit le nombre de caractères d’une chaîne. Attention : une chaîne d’origine numérique peut comporter un signe de plus, le signe "plus" étant sous-entendu

PRINT LEFT$("Aaaargh", 3) donne Aaa , les trois caractères de gauche
PRINT RIGHT$("Aaaargh", 4) donne argh , les quatre caractères de droite
PRINT INSTR(n, A$, B$) rend la position du 1° caractère de la chaîne B$ si elle se retrouve dans la chaîne A$, en cherchant à partir de la position n (0 si elle ne s’y trouve pas)
PRINT MID$("Camelot", 3) donne melot , tous les caractères à partir de la 4° lettre
PRINT MID$("Camelot", 3, 4) donne melo , 4 caractères à partir de la 3° lettre. Cette fonction peut les déterminer de la manière suivante :

V$= "Spam": IF MID$(V$, 3, 1)= "a" THEN MID$(V$, 3, 1)= "i": PRINT V$

PRINT MIRROR$("Spam") donne mapS , renverse les caractères de la chaîne
PRINT LOWER$("SPAM") donne spam , transforme les majuscules en minuscules
PRINT UPPER$("spam") donne SPAM , transforme les minuscules en majuscules

2.6 Conversions de types ( → .en)

CVI("") convertit une chaîne de 2 caractères en un Entier court
CVIL("") convertit une chaîne de 4 caractères en un Entier long
CVS("") convertit une chaîne de 6 caractères en un Réel simple précision
CVD("") convertit une chaîne de 10 caractères en un Réel double précision
ASC("") donne le code ASCII du 1° caractère de la chaîne
VAL("") convertit une chaîne représentant un nombre en sa valeur numérique, si c’est effectivement possible :

?VAL("&63"), VAL("$FF"), VAL("%1011") mais pas PRINT VAL("1A") ni PRINT VAL("$1G")

MKI$(V%W) un entier court en une chaîne de 2 caractères
MKIL$(V%L) un entier long en une chaîne de 4 caractères
MKS$(V!) un réel simple en une chaîne de 6 caractères
MKD$(V#) un réel double en une chaîne de 10 caractères
STR$(V) une expression numérique en chaîne
CHR$(n) donne un des 256 caractères ASCII, n de 0 à 255 :

FOR A= 32 TO 255 ' de 0 à 31 invisibles sauf PRINT CHR$(1)+ CHR$(n)
 PRINT USING "####"; @(4+A MOD 16, 5* ((A\16)-2)); A; CHR$(A)
NEXT

2.7 Tableaux et matrices ( → .en)

DIM T#(9) dimensionne un tableau de 10 réels double-précision
DIM Goban%B(18, 18) contient les 19*19 intersections d’un jeu de Go
Aum%(3, 4)=29 indique que l’élément 4°ligne-5°colonne du tableau vaut 29
Sans DIM, la dimension est par défaut de 10*10
MAT CLEAR Echiquier%B(7, 7) efface le tableau mentionné
MAT CLEAR T(n) efface un tableau de nombres à une dimension jusqu’à T(n)

SWAP V$, W$ échange le contenu de 2 variables de même type
SORT T$(0) trie tous les types de tableaux à une dimension
SORT ASC A$(0) trie un tableau de chaînes selon le code ASCII
SORT T(0) TO V(0) trie le tableau V(0) selon l’ordre du tableau T(0)

Matrices ( → .en)

Les matrices sont des tableaux de réels à deux dimensions :

MAT A#(l, c)*n multiplie chaque élément de la matrice par n
MAT A!(m, n)= B!(m, p)* C!(p, n) multiplie deux matrices. Le nombre de colonnes de la 1° égale le nombre de lignes de la 2°
MAT A#(n, n)= INV B#(n, n) inverse une matrice carrée
MAT A#(n, n)=1 permet de générer une matrice-unité (carrée)
X!= DET(A!(n, n)) donne le déterminant de la matrice (carrée)

2.8 Les opérateurs logiques ( → .en)

Les opérations logiques concernant les bits, on exprime les nombres en binaire.

NOT inverse le contenu des bits :

NOT %10 = …11111111101 =-3

(un nombre est négatif si le bit le plus significatif=-1)

AND sélectionne les bits 1 communs aux deux nombres :

%1100 AND %1010 est %1000

OR accepte qu’un bit soit positionné pour l’un ou l’autre nombre :

%1100 OR %1010 est %1110

XOR n’accepte qu’un bit un seul bit :

%1100 XOR %1010 est %0110

NAND exclut la véracité simultanée des bits de deux binaires

%1100 NAND %1010 est -9 (ou NOT %1000, soit NOT AND)

NOR vérifie la non-véracité des bits deux binaires

%1100 NOR %1010 est -15 (ou NOT %1110, soit NOT OR )

EQV admet la véracité ou la non-véracité des bits de 2 binaires

%1100 EQV %1010 est -7 (ou NOT %110, soit NOT(A XOR B)

IMP est l’implication logique : A implique B signifie que l’on ne peut pas avoir A sans B. Sous forme algébrique, A IMP B est équivalent à NOT(A AND NOT(B)).

%…001100 IMP %…001010 est -5 (ou NOT %…00100, soit %…11011)
 A   B   NOT(B)   A AND NOT(B)   NOT(A AND NOT(B)) 
1
1
0
0
1
0
1
0
0
1
0
1
0
1
0
0
1
0
1
1

SHR(n) (SHift Right) : décale les bits d’un nombre n fois vers la droite, ce qui équivaut à n divisions entières par 2.

SHL(n) (SHift Left) : décale les bits d’un nombre n fois vers la gauche, ce qui équivaut à n multiplications par 2.

BIT(n, A) rend la valeur 0/-1 du bit n de A : PRINT BIT(3, %11001) =-1 (le bit 0 est le premier en commençant par la droite)

3. Structures ( → .en)

3.1 Conditions ( → .en)

IF <…> THEN <…> ELSE <…> : ENDIF

L’instruction IF teste une condition et ordonne ce qui suit THEN si la condition est rencontrée. ELSE (facultatif) ordonne ce qu’il y a lieu de faire en cas de condition non rencontrée. ENDIF est obligatoire dans le cas où une séquence IF / THEN / ELSE est écrite sur plusieurs lignes ou si THEN est suivi d’un ":". On peut imbriquer une ou plusieurs conditions dans une autre, mais attention à bien structurer le programme pour ne pas s’y perdre.

10 N= -RND(-100): B=1
100 REPEAT
110  INPUT "Un nombre de 1 à 100: "; A
120  IF A=N THEN PRINT "Trouvé en"; B;" fois": END ' pour finir
130  IF A < N THEN
140   PRINT "Un peu plus…"
150  ELSE
160   PRINT "Un peu moins…"
170  ENDIF
180  B=B+1
190 UNTIL 0  ' le 0 est le "faux" logique: condition jamais vraie

3.2 Les boucles ( → .en)

Les boucles sont des portions de code permettant un travail répétitif.

FOR V= n TO m (STEP p) : < > : NEXT V ( → .en)

V varie de n à m à chaque réitération. STEP (facultatif) précise un pas différent de +1 (entier, négatif ou réel).

FOR A = 0 TO 31
 Ligne=8+A MOD 8:Colonne=12+9*(A\8)
 PRINT USING "###"; @(Ligne, Colonne);A;" "; CHR$(1)+ CHR$(A)
NEXT

REPEAT : <…> : UNTIL <…> ( → .en)

Le programme répète les instructions qui suivent REPEAT jusqu’à ce que la condition écrite après UNTIL soit rencontrée. Elle est donc parcourue au moins une fois.

REPEAT : PRINT @(RND(25), RND(80));"*" UNTIL MOUSEBUT = 1

WHILE < > : < > : WEND ( → .en)

WHILE teste une condition avant de pénétrer dans la boucle définie jusqu’à WEND : il se peut qu’elle ne soit pas parcourue du tout. Pour une boucle infinie : WHILE -1 ("toujours vrai")

WHILE MOUSEBUT= 0: DRAW 320, 200 TO MOUSEX, MOUSEY : WEND

EXIT ( → .en)

Quitte, ferme et saute à la fin d’une boucle bien que la condition de sortie ne soit pas rencontrée.

WHILE -1
 <instructions>
 IF <condition> THEN EXIT
WEND

EXIT TO est un composé d’EXIT et de GOTO. Il faut donc prévoir une étiquette.

3.3 Procédures ( → .en)

Les procédures sont des sous-programmes appelables directement par leur nom.

Une procédure peut en appeler une autre. On peut définir des variables locales par LOCAL V$=, W$=, qui n’interféreront pas avec les variables globales de même nom, ce qui permet d’appeler des programmes avec CHAIN MERGE sans se préoccuper des homonymies éventuelles des variables.

Pour éviter l’erreur "Illegal direct", les procédures se définissent après END.

10 INPUT "Rayon et Hauteur: "; R!, H!: Cone ' appel de procédure
20 PRINT "Le volume du cône est: "; V!
30 END
1000 DEF PROC Cone ' pas d'accent dans un nom de fonction ou variable!
1010  V!= R!^2 *PI *H!/3
1020 RETURN

Les variables étant globales en Omikron (elles sont les mêmes dans le corps du programme que dans les procédures et fonctions, contrairement à d’autres langages où des variables des fonctions sont locales et n’interfèrent pas avec une variable de même nom dans le reste du programme), il n’est pas nécessaire prévoir de variables de réceptions, mais cela peut être pratique :

10 PRINT Hypoth(3,4)
20 END
30 DEF PROC Hypot(C1,C2)
40   PRINT SQR(C1^2+C2^2)
50 RETURN

Une procédure peut retourner des paramètres :

10 INPUT "A!, B!"; A!, B! : Rapport(A, B) ' appel de procédure
20 PRINT A!, B!
30 END
1000 DEF PROC Rapport(R X!, R Y!) ' R pour Retour
1010  X!= X!/Y!: Y!= 1/X!
1020 RETURN

3.4 Fonctions-utilisateur ( → .en)

Les fonctions se définissent selon le principe des procédures, mais retournent une (seule) valeur, précisée après RETURN. Elles sont appelées par PRINT FN Nom$. Les fonctions en une ligne sont définies par une égalité et se passent de RETURN.

10 PRINT FN Hasard
20 END
100 DEF FN Hasard = -RND(-6) -RND(-6) ' différent de -RND(-12)

Autre exemple, retournant une chaîne :

10 A$= "Nuit noire": PRINT FN Inverse$
20 END
100 DEF FN Inverse$ ' $ car elle retourne une chaîne
110  A$= CHR$(27)+ "p"+ A$+ CHR$(27)+ "q"
120 RETURN A$

Un exemple très classique, où la fonction utilise la récursivité :

10 TRON : INPUT "X: "; X ' pour X pas trop grand
20 PRINT FN Factorielle(X): TROFF
30 END
100 DEF FN Factorielle(X)
110  IF X=0 THEN RETURN
120 RETURN X* FN Factorielle(X-1)

La fonction fait appel à elle-même tant que la décrémentation de X n’atteint pas 0.

3.5 Exploitation des données ( → .en)

DATA exprime des données (expressions, variables, tableaux)
READ V$, W$ lit une ou plusieurs données dans la ligne des DATA

10 CIRCLE 250, 136, 40: DRAW 300, 50
20 FOR I=1 TO 6: READ X, Y: DRAW TO X, Y: NEXT
30 DATA 200, 50, 150, 136, 200, 222, 300, 222, 350, 136, 300, 50

RESTORE replace le pointeur sur la 1° ligne des DATA
RESTORE 1000 ou RESTORE Etiqu après la ligne 1000 ou -Etiqu

ON n RESTORE Et1, Et2, … envoie le pointeur sur le DATA suivant l’étiquette choisie selon n

10 INPUT "Espagnol=1, Anglais=2, Néerlandais=3:"; Langue
20 INPUT "Quel chiffre? "; C
30 ON Langue RESTORE Cifras, Digits, Cijfers' choisit la ligne
40 FOR I= 0 TO C: READ C$ : NEXT I' choisit la donnée
50 PRINT "Le chiffre";C;" se dit "; C$ : END
100 -Cifras: DATA "Cero", "Uno", "Dos", "Tres", "Quatro"
110 DATA "Cinco", "Seis", "Siete", "Ocho", "Nueve"
120 -Digits: DATA "Zero", "One", "Two", "Three", "Four", "Five"
130 DATA "Six", "Seven", "Eight", "Nine"
140 -Cijfers: DATA "Nul", "Één", "Twee", "Drie", "Vier", "Vijf"
150 DATA "Zes", "Zeven", "Acht", "Negen"

3.6 Les branchements ( → .en)

GOTO 300 fait sauter le programme à la ligne 300
GOTO Aum va directement à l’étiquette -Aum. Pour définir une étiquette la faire précéder d’un tiret
GOTO 500+n les opérations sont possibles
GOTO (V) ou (V$) le numéro ou l’étiquette est contenue dans la variable
ON n GOTO n1, n2, … pour n de 1 à x, le programme sautera à la ligne n1, n2, … ou nx

RENUM respecte les branchements, la désactivation des n° de ligne dans le super-éditeur non: utilisez les étiquettes. Pour une meilleure lisibilité du programme, préférez les boucles et EXIT TO pour en sortir, qui remet le compteur de la boucle à 0.

3.7 Les routines ( → .en)

GOSUB Aum envoie à un sous-programme, à l’étiquette -Aum
ON n GOSUB n1, n2, n3 choisit le sous-programme en fonction de n
RETURN renvoie à l’instruction suivant le GOSUB appelant

Les sous-programmes (ou routines) s’écrivent en fin de programme après END pour que le programme ne tombe pas sur un RETURN sans avoir été envoyé au sous-programme par GOSUB.

De façon générale, on préférera les procédures et les fonctions.

Sous-programmes conditionnels ( → .en)

S’écrivent en début de programme et permettent au système de réagir à des sollicitations diverses, à condition que les routines aient été prévues.

ON TIMER n GOSUB Etiq réagit toutes les n secondes
ON MOUSEBUT GOSUB Etiq réagit à un bouton de la souris
ON HELP GOSUB Etiq réagit à la touche [Help]
ON KEY GOSUB Etiq réagit à n’importe quelle touche

Cette dernière garde la touche en mémoire-tampon: il faut la vider avec V$=INKEY$ ou V$=INPUT$(1) dans la routine appelée pour éviter qu’elle s’appelle elle-même.

Pour annuler un sous-programme conditionnel, ON < > GOSUB 0

Voir le traitement d’erreur pour les sous-programmes conditionnels ON TRON GOSUB et ON ERROR GOTO.

4. Périphériques ( → .en)

Le BIOS possède des fonctions de très bas niveau permettant d’envoyer un octet vers un périphérique. Vous ne devriez normalement jamais les utiliser, mais sait-on jamais. R est une variable qui recevra une valeur de retour. P designe le périphérique : 0 =imprimante, 1 =RS232, 2 =console, 3 =MIDI, 4 =processeur-clavier :

BIOS(R, 1, P) teste si un caractère est en attente d’être lu (R vaudra alors -1) sur le périphérique
BIOS(R, 2, P) lit un octet sur le périphérique indiqué, récupérer par R
BIOS(R, 8, P) teste si le périphérique peut recevoir ( R vaudra alors -1) un caractère (0-1-3-4)
BIOS(, 3, P, n) envoie un octet sur la sortie indiquée (0-1-2-3-4)

4.1 Les écrans ( → .en)

L’Omikron 3.01 dispose de trois écrans, celui par défaut étant l’écran 0. On passe de l’un à l’autre par la commande SCREEN 1 et SCREEN 2, SCREEN 0 permettant de revenir à l’écran par défaut. Pour l’écran 1 et 2 :

Adr=(MEMORY(32256) AND $FFFF00)+256: SCREEN 1, Adr

Note : concernant les TOS <1.6, une adresse doit être un multiple de 256 (ce qui signifie terminer avec 00 en hexadécimal). Pour ajuster l’adresse, vous devez réserver un peu plus de 32000 octets, raboter l’adresse avec AND $FFFF00 et ajouter 256 octets pour ne pas détruire les éventuelles données qui se trouvent peu l’endroit du début de réservation.

Fonctionnent avec l’écran 0 (par défault) ( → .en)

PRINT CHR$(1) taper [Ctrl]-[A] [Ctrl]-[Lettre] ou PRINT CHR$(1)+CHR$(1 à 31) pour des caractères spéciaux
PRINT CHR$(2) insère un caractère à l’endroit du curseur (et repousse ceux situés à droite)
PRINT CHR$(3) en efface un. (=[Ctrl]-[C] si IPL 3 + (1 SHL 31))

Fonctionnent avec l’écran 1 et 2 ( → .en)

PRINT CHR$(27);"w" annule le suivi automatique  \ retour chariot
PRINT CHR$(27);"v" repasse en suivi automatique / en fin de ligne

Fonctionnent avec les trois écrans ( → .en)

PRINT CHR$(4) la position du curseur définit le coin supérieur gauche
PRINT CHR$(5) la position du curseur définit le coin inférieur droit
[ClrH] [ClrH] pour revenir à la normale
PRINT CHR$(7) fait entendre un chping!
PRINT CHR$(8) déplace le curseur à gauche en effaçant ( =[BackSp])
PRINT CHR$(9) la position du curseur à la tabulation suivante (toutes les 8 colonnes)
PRINT CHR$(10) curseur une ligne vers le bas (= CHR$(11) et CHR$(12))
PRINT CHR$(13) retour du curseur en début de ligne mais [Ctrl]-[M]=[Enter]

GEMDOS(R, 16) R=FFFF si l’écran est en état d’afficher, sinon R=0
XBIOS(R, 2) retourne l’adresse Physique de l’écran, les 32000 octets affichés
XBIOS(R, 3) retourne l’adresse Logique de l’écran, là où les affichages sont réalisé. Il s’agit le plus souvent de la même adresse que la précédente
XBIOS(R, 4) R= 0 si basse; 1 si moyenne; 2 si haute Resolution
XBIOS(, 5, L Log, L Ph, Res) fixe ces 3 paramètres (si -1 : inchangé). Voir début de section pour l’explication :

Adr= (MEMORY(32256) AND $FFFF00)+256 ' réserve et fixe une adresse divisible par 256

XBIOS 5 est utilisé pour travailler avec plusieurs écrans en parallèle. De plus, n’afficher un nouvel écran qu’une fois qu’il est entièrement réalisé est plus confortable à la vue. Il s’agit évidemment de bien gérer les différentes addresses! L’exemple fonctionnel qui suit travaille sur deux écrans, affichant l’un pendant qu’il écrit sur l’autre et inversant ces deux écran avec le bouton gauche de la souris.

Adr1=( MEMORY(32256) AND $FFFF00)+256
Adr2=( MEMORY(32256) AND $FFFF00)+256
PRINT CHR$(27)+"f" ' éteint le curseur, allumé par défaut sur Omikron 3.01
WHILE MOUSEBUT <2 ' bouton droit pour en terminer
  XBIOS (,5,L Adr1,L Adr2,-1) ' écriture Adr1, affichage d'Adr2
  FILL STYLE =2, RND(24) ' remplissage au hasard
  PBOX RND(10)*50, RND(10)*30,50,50 ' un carré rempli s'affiche au hasard
  WHILE MOUSEBUT >0: WEND ' attend le relâchement
  WHILE MOUSEBUT =0: WEND ' attent un clic, gauche ou droite
  XBIOS (,5,L Adr2,L Adr1,-1)
  FILL STYLE =2, RND(24)
  PCIRCLE 40+ RND(10)*55,40+ RND(10)*30,35 ' un cercle rempli s'affiche au hasard
  WHILE MOUSEBUT >0: WEND
  WHILE MOUSEBUT =0: WEND ' attent un clic, le droit sort de la boucle principale
WEND

XBIOS(R, 7, c, n) fixe la couleur c, n de $000 à $777; lit si n =-1. Voir PALETTE pour les 16 niveaux à partir du TOS 1.6.

4.2 Affichage ( → .en)

CLS efface l’écran et place le curseur en haut à gauche de l’écran
PRINT @(ligne, colonne); précise l’emplacement du curseur pour un affichage ou une saisie

PRINT CHR$(27)+"f" cache le curseur texte
PRINT CHR$(27)+"e" montre le curseur texte

CSRLIN retourne le numéro de ligne du curseur (de 1 à 25!)
POS(0) retourne le numéro de colonne du curseur, le (0) est curieusement obligatoire

PRINT "Le carré de A est:"; A^2 affiche un texte et un résultat
PRINT COS(PI/4) affiche le résultat de la fonction cosinus
PRINT "COS(PI/4)" affiche COS(PI/4) (sans les guillemets)
WRITE "Texte" affiche "TEXTE" (conserve les guillemets)
PRINT 3*5; "H"*2 affiche 15HH sans séparation (point-virgule)
PRINT COS(0), "*" affiche 1, * à la tabulation suivante (car virgule)
PRINT A$;:PRINT B$ ";" force l’affichage de B$ à la suite de A$
PRINT CHR$(34); "3"; CHR$(34) affiche "3", CHR$(34) codant le guillemet
PRINT SPC(n);"&" affiche n espaces avant & (voir 2.3 Chaînes)
PRINT TAB(c);V$ affiche à la colonne définie par TAB
PRINT @(l, c);V$ affiche à la ligne et à la colonne indiquée
PRINT @(l, c);V$; terminer par un point-virgule permet d’éviter le retour à la ligne

10 CLS : DEG ' programme incluant des @(l, c) dans une seule chaîne
20 FOR X=0 TO 78
30  Y!= SIN(X*5)+ SIN(X*13) : Sin$=Sin$+ @(Y!*6+12, X)+ "W"
40 NEXT : PRINT Sin$

PRINT CHR$(n) permet l’affichage des caractères dont le code varie de 32 à 255
PRINT CHR$(1)+CHR$(n) permet l’affichage des caractères dont le code varie de 1 à 31

Tableau ASCII de l’Atari

Tête d’homme fumant la pipe à partir des octets 28 à 31

Remarques
  • l’eszett ou scharfes S ß (158 / $9E) et le bêta β (225 / $E1) sont identiques
  • l’assemblage des quatre derniers caractères graphiques de la première colonne permet d’afficher une tête d’homme fumant la pipe. De mémoire d’atariste, je n’ai jamais vu cette fonctionnalité utilisée, et il y avait certainement de meilleurs candidats pour ces quatre octets, comme quelques lettres grecques : ε γ χ ω utiles en mathématiques ou en physique.

PRINT … USING ( → .en)

USING permet de formater l’affichage décimal pour l’instruction PRINT

USING "####" prévoit 4 espaces pour un entier. Imprime % en cas de dépassement.
USING "####.##" prévoit 2 chiffres pour les décimales
USING ", ####.###" la virgule sépare les milliers
USING ".#####, ####" la virgule et le point sont intervertis
USING "####, ###-" le "-" sera affiché après le nombre (pas le "+")
USING "+#####.####" force l’affichage du signe ( + ou - )
USING "## #. # #" sépare les caractères comme indiqué
USING "*$#######, ##" ce qui suit * sera caractère de remplissage
USING "##_+.##" force l’affichage de ce qui suit le _
USING "###^^^^" laisse 4 places pour la notation scientifique

PRINT USING "###, ###", V! ne formate que la ou les variable(s) de ce PRINT
USING "##, ##" concerne tout affichage par PRINT, STR$ et PRINT#
USING sans argument annule un USING "####" utilisé seul

Exemple :

10 USING "+*@## ###, ##" : PRINT SQR(2000000) ' affiche @@@+1 414, 21
20 USING : PRINT SQR(2000000) ' affiche 1414.2136

4.3 Saisie ( → .en)

Lorsque le programme arrive à une intruction de type INPUT, il imprime le texte écrit entre guillemets (ou un point d’interrogation par défaut de texte) et attent une donnée du type de la (ou des) variable(s) écrite(s) après INPUT, et une saisie :

INPUT A imprime un ? et attend le nombre (et la saisie)
INPUT "A:"; A imprime A:, attend la saisie d’un entier long
INPUT Nom$ $ pour entrer une chaîne de caractères
INPUT @(l, c);"Texte: ";V$ affiche le texte à l’endroit indiqué
INPUT A, B, C 3 entiers à entrer, séparés par des virgules
LINE INPUT A$ permet d’entrer une (seule) chaîne avec virgules
A$= INPUT$(n) attend n caractères et les saisit avant de poursuivre

INKEY$ renvoie une chaîne de 4 caractères :
  le 4° contient le code ASCII
  le 3° est vide
  le 2° contient le Scancode (le code de la touche)
  le 1° contient cinq bits :
  bit 0=[Shift-Droit]
  bit 1=[Shift-Gauche]
  bit 2=[Ctrl]
  bit 3=[Alt]
  bit 4=[CapsLock]

Cette instruction n’attend pas, il faut donc la mettre en boucle :

10 A$=""
20 REPEAT
30   A$= INKEY$
40 UNTIL A$ > ""
50 Ascii$= RIGHT$(A$, 1) : PRINT ASC(Ascii$)
60 Scan$= MID$(A$, 2, 1) : PRINT ASC(Scan$)
70 Key$= LEFT$(A$, 1) : PRINT (BIN(ASC(Key$)))

Tableau des code de touche (scancode)

codes des touches de l’Atari ST

L’adresse $484 contient un octet dont les bits (dés)activent: 3°: [Ctrl] et [Alt] - 2°: "Ping" - 1°: répétition - 0°: "Tik"
POKE $484, %1010 désactive le "tik" des touches et le "ping" d’erreur
XBIOS(R, 35, D, V) règle le Délai avant la répétition et la Vitesse de répétition d’une touche maintenue appuyée (en 1/50 sec) Si D et V=-1, R renseigne 1 octet pour D et 1 pour V
XBIOS(R, 16, L Adr1, L Adr2, L Adr3) fixe les 3 tables d’affectation des caractères pour le clavier, soit 3 chaînes de 128 octets (1° inutile) selon l’ordre du Scancode. Adr1 pour touches normales, Adr2 shiftées, Adr3 avec CapsLock, -1 pour ne rien changer
XBIOS(, 24) annule les modifications du XBIOS 16 (clavier standard)
XBIOS(, 25, n-1, L Ad) envoie une commande au processeur-clavier

INPUT … USING ( → .en)

INPUT @(l, c);"Texte"; V$ USING "Commande", R, n, asc, P

"Commande" permet ou interdit certains caractères :
 0 permet tous les chiffres
 A permet toutes les lettres, accentuées ou non
 % permet les caractères spéciaux (%, é, !, ?, &, @, …)
 ˆ permet les [Ctrl]-[Touche]
 U (Upper) affiche en majuscule, L (Lower) en minuscule
 + autorise le caractère qui suit (l’espace, par exemple)
 - interdit le caractère qui suit
 C&% remplace le premier signe par le deuxième (& par %)
 < permet la saisie par un dépassement par la gauche
 > permet la saisie lors d’un dépassement par la droite
 ax_" la saisie peut se faire par le caractère _ spécifié
 +"x"+CHR$(A) ou par son code ASCII
 +"s"+CHR$(S) ou par la touche dont le Scanscode est défini

R retourne CVIL(INKEY$) de la touche qui a permis la saisie, ou
 0 pour [Enter],
-1 pour > (dépassement par la droite)
-2 pour < (sortie par la gauche)

n est la longueur de la chaîne à entrer (255 max et par défaut)
asc est le code ASCII du caractère à remplir ("_" par défaut)
P est la Position du curseur sur la chaîne lors de la sortie

L’exemple :

INPUT A$ USING "0+, C., s" + CHR(1), R, 10, , P

permet la saisie des chiffres et de la virgule, change le point en virgule, et permet la saisie par la touche [Esc] (scancode 1). La longueur du champs de saisie est limité à 10 caractères ("_" si vide).

4.4 Autres périphériques ( → .en)

Imprimante ( → .en)

LPRINT affiche sur imprimante ([Alt]-[L])
LLIST liste le programme sur imprimante
LDUMP imprime le contenu des variables sur l’imprimante
MODE LPRINT "F" permet les accents sur imprimantes à marguerite
LPOS(0) mode caractère : rend la positìon de la tête d’imprimante

HCOPY imprime un écran, si l’imprimante est bien paramétrée
HCOPY TEXT imprime l’écran 0, mais sans graphisme

LPRINT "" envoie une chaîne vers le port parallèle, où était en général située l’imprimante

GEMDOS(R, 17) R=0 si l’imprimante n’est pas en état d’imprimer
GEMDOS(, 5, n) envoie un caractère vers l’imprimante
XBIOS(, 33, F) F détermine la catégorie de l’imprimante :

bit543210
=0 :listingparallbrouillonAtaricouleurmatricielle
=1 :feuillesériecourrierEpsonmonochrmarguerite

Série RS232 ( → .en)

GEMDOS(R, 18) R=0 si la RS232 ne délivre aucun caractère
GEMDOS(R, 3) lit un caractère venant de la série RS232
GEMDOS(R, 19) R=0 si la RS232 ne peut envoyer aucun caractère
GEMDOS(R, 4) envoie un caractère vers la serie RS232
XBIOS(, 15, Baud, Mod, Ucr, Rsr, Tsr, Scr) règle les paramètres de la sortie "série" RS232 :
Baud : 0 à 15 pour taux de transferts de 19200-9600-4800-3600-2400-2000-1800-1200-600-300-200-150-134-110-75-50
Mod : 0 : pas de handshake; 1 : XON/XOFF; 2 : RTS/CTS; 3=1+2
Ucr : bit 1= 0/1 impair/pair; bit 2= 0/1 non parité/parité
bits 3-4 : 0=synchr; 1=1 stopbit; 2=1.5; 3=2 stopbits
bits 5-6 : 0=8 bits; 1=7 bits; 2=6 bits; 3=5 bits
bit 1 : si synchr : 1/0 divise ou non la frequence
Rsr : bit 0=1 reception activée; bit 1=1 pour recevoir
Tsr : bit 0=1 émission activée; bit 1=1 pour émettre
Scr contient l'octet de synchronisation
-1 laisse les paramètres antérieurs inchangés

Port MIDI ( → .en)

XBIOS Ret, 12, n, L Adr envoie n octets situés à l’adresse Adr vers la sortie MIDI. n est un mot court.

Adr= MEMORY(20)
FOR I = 0 TO 19: READ Byt: POKE Adr+I, Byt: NEXT
XBIOS , 12, n, L Adr
DATA
 …20 octets, séparés par une virgule

4.5 Son du processeur sonore Yamaha 2149 ( → .en)

Les instructions qui suivent exploitent le processeur sonore Yamaha 2149, qui dispose de trois voies productrices de notes (onde carrée), un générateur d’enveloppe et de bruit blanc filtré.

PRINT CHR$(7) donne un bip sonore correspondant à TUNE 1, 59
TUNE 1, n, 2, m, 3, p définit une hauteur de son pour au moins une voie (3 maximum), qui va du plus aigu (1) au plus grave (4095). LA 440 = 125000/440=282
TUNE 1, 0, 2, 0, 3, 0 éteint tout
VOLUME v, n définit un son maintenu, de volume 0 à 15 pour chaque voie
VOLUME v, e, d définit le type d’enveloppe et sa durée (un seul type d’enveloppe pour les 3 voies). Les 2 syntaxes de VOLUME s’excluent pour une même voie.

d= 7860 
donne une durée d’environ une seconde ($FFFF max)
e= 9 et 0, 1, 2, 3 
15 et 4, 5, 6, 7 

12 
14 
10 
13 
11 
sont de type piano : pic puis descente
sont inverses : montée puis effondrement
est un "piano" répété (9+9+9+…)
est un "inverse" répété (15+15+15+…)
est une montagne : montée puis descente
est un piano plus une montagne (0+14)
est une montée sans descente
est un piano puis un son maintenu

NOISE m, f les voies concernées par le bruit (V1=1, V2=2, V3=4) s’additionnent pour définir le masque (de 0 à 7), f choisit une plage de fréquence 0 pour la plus aiguë.
NOISE 0, 0 annule.

5 Disque et fichiers ( → .en)

5.1 Système de fichiers ( → .en)

* remplace un(e partie de) nom ou une extension, ? une lettre:
"A*.*" concerne tous les fichiers commençant par A
"*.PI?" concerne tout fichier "*.PI1", "*.PI3", "*.PIC", etc…

FILES "A:\*.*" affiche le contenu du disque du chemin spécifié
FILES "A:\DIVERS\*.BAS" affiche tous les programmes *.BAS du dossier DIVERS du lecteur "A:"

COPY "A:\fichier" TO "C:\dossier\" copie un fichier de A: sur C:
NAME "nom.Ext" AS "autre.Ext" renomme un fichier
BACKUP "Nom" copie de sauvegarde *.BAK de la version précédente

KILL "A:\dossier\Nom" supprime le fichier (selon le chemin spécifié)
KILL "A:\dossier\*.*" supprime tous les fichiers dudit dossier

MKDIR "A:\nom_dossier" crée un dossier sur le lecteur spécifié
RMDIR "C:\dossier" efface un dossier, mais uniquement s’il est vide

CHDIR "doss" entre dans le dossier doss
CHDIR "C:\doss" ou CHDIR "A:\" définit le chemin d’accès actif
CHDIR ".." sort d’un sous-dossier et remonte vers le dossier

BIOS(R, 9, Lect) changement de disquette? 0 : non; 1 : peut-être; 2 : oui
BIOS(R, 10) renseigne les lecteurs connectés : bit 0=A :, 1=B :, 2=C :, comme LPEEK($4C2)

GEMDOS(R, 14, Lect) fixe le lecteur par défaut (0=A:, 1=B:, 2=C:…)
GEMDOS(R, 25) retourne le lecteur par défaut (au format GEMDOS 14)
GEMDOS(R, 59, L Ch) fixe le Chemin par défaut d’un lecteur, inscrit à l’adresse indiquée et se terminant par un octet nul

5.2 SAVE et LOAD ( → .en)

SAVE "MYPROG.BAS" sauvegarde un programme BASIC en FIT (Fast Interpreting Technic)
SAVE "MYPROG.BAS", A sauve un programme BASIC en ASCII (caractères lisibles)
LOAD "MYPROG.BAS" charge un programme BASIC sauvegardé en FIT ou en ASCII
LOAD "A:\DIVERS\MYPROG.BAS" spécifie le chemin du fichier demandé
RUN "MYPROG.BAS" charge et exécute le programme spécifié

CHAIN "OTHERPRG.BAS" chaîne un programme, et efface le précédent
MERGE "OTHERPRG.BAS" ajoute un programme ASCII sans effacer le précédent sauf si les numéros de lignes sont les mêmes
CHAIN MERGE "OTHERPRG.BAS", n chaîne un programme, sans écraser le précédent, n pour en préciser le début
COMMON V$, W$, pour conserver les variables d’un programme chaîné. L’instruction doit se trouver sur la première ligne de chaque programme concerné

LIBRARY GEM, "A:\GEM\GEM.LIB" charge la bibliothèque GEM

BSAVE "Nom" sauve l’écran complet (bit par bit) sur disque(tte)
BSAVE "Nom", Adr, n sauve le nombre d’octets à partir de l’Adresse

BLOAD "Nom" charge un fichier sur l’écran (Ex : image en BITMAP)
BLOAD "Nom", Adr charge un fichier en mémoire à l’Adr indiquée

5.3 Fichiers séquentiels ( → .en)

OPEN "O", canal, "Nom" crée et ouvre un fichier à l’écriture (l’écrase s’il existe déjà!) et lui attribue un Canal, de 1 à 16
PRINT #canal, A$, B$ écrit des données sur le Canal spécifié
WRITE #canal, A$, "Aum" permet l’écriture avec guillemets et virgules
CLOSE canal écrit les données sur la disquette et ferme le fichier ouvert sur ce canal
CLOSE ferme tous les fichiers

OPEN "A", 5, "Nom.Ext" réouvre un fichier pour y ajouter des données

OPEN "I", 16, "Nom" ouvre un dossier à la lecture
INPUT #16, V$, W$, lit une ou plusieurs données
LINE INPUT #16, V$ charge un texte contenant des virgules

A$=INPUT$(n, canal) lit le n caractères sur le Canal spécifié
EOF(canal) rend -1 quand le fichier spécifié a été complètement lu
LOF(canal) rend le nombre d’octets du fichier ouvert sur le Canal spécifié, y compris l’octet de fin de fichier

GEMDOS(R, 60, L Nom, Attr) crée un nouveau fichier
Nom contient une chaîne se terminant par l’octet nul CHR$(0)
Attr = 1 : lecture seulement, 2 : cache, 4 : Système 8 : nom de la disquette, 16 : dossier, 32 : fichier GEM
R retourne un Handle (canal) si supérieur à 5, une erreur si négatif
GEMDOS(R, 61, L Nom, F) ouvre un fichier. F =0 lit; =1 écrit; =2 : 0+1
GEMDOS(, 62, H) ferme le fichier H, handle retourné par GEMDOS 60 et 61
GEMDOS(, 63, H, L n, L Buf) transfère n octets (fichier H vers Buffer)
GEMDOS(, 64, H, L n, L Buf) transfère n octets (Buffer vers fichier H)
GEMDOS(R, 67, L Nom, F, Attr) lit ou fixe (F=0/1) l’Attribut du fichier
GEMDOS(R, 87, L Adr, H, F) lit ou fixe (F=0/1) la date et l’heure du fichier H déjà ouvert par GEMDOS 60
GEMDOS(R, 71, L Ad, F, Lect) rend le chemin d’accès actuel (sans le lecteur) dans les 64 octets réservés à Ad

Autres types de fichiers séquentiels ( → .en)

OPEN "K", canal envoie des commandes au processeur-clavier (keyboard)
OPEN "P", canal imprimante (printer)
OPEN "V", canal Modem
OPEN "M", canal port MIDI
OPEN "C", canal écran (console).

CMD Canal redirige les instructions de sortie vers un fichier séquentiel préalablement ouvert. Peut être utile lors de la mise au point d’un programme :

OPEN "O", 1, "liste.txt"
CMD 1
PRINT "Ce programme en ascii" ' normalement destiné à l’écran
LLIST ' normalement destiné à l'imprimante
CLOSE

5.4 Fichiers relatifs ( → .en)

OPEN "R", canal, "NOM", L ouvre un fichier relatif, chaque enregistrement aura la taille globale de taille L
FIELD canal, long1 AS V$, long2 AS W$ détermine le champ (la longueur) de chaque Variable-tampon. Un champ peut ne pas être attribué.

PUT canal, n écrit dans l’enregistrement n les données de FIELD
GET canal, n lit l’enregistrement n et l’envoie sur le FIELD
GET canal, 0 … donne le n° de fichier suivant celui qui a été lu
SEEK canal, n, mode déplace le pointeur de n enregistrements (mode=0 : à partir du début du fichier; 1 : déplacement à partir de l’enregistrement actuel; 2 : à partir de la fin)

LSET V$="Olé" formate la chaîne pour la variable-tampon par la gauche (l’excès à droite est ôté, le défaut est rempli)
RSET W$= B$ formate B$ pour W$ de la même manière par la droite

LOF(canal) donne le nombre d’enregistrements du fichier relatif
LOC(canal) rend le pointeur du dernier enregistrement lu ou écrit

CLOSE canal écrit les changements sur le disque

Autres fichiers relatifs

OPEN "U", canal, "Nom" ("U" pour User) ouvre en lecture ou écriture un fichier relatif où les champs peuvent avoir des tailles variables ; gestion avec PUT, GET et SEEK

OPEN "F", canal, "C:\atari\*.*", m donne le contenu du répertoire; m est le masque de sélection des fichiers : 1=lecture seule, 2=fichiers cachés, 4=système, 8=nom du disque, 16=dossiers, 32=modifiés, 63=tous. Voici un exemple d’utilisation (notez que les 14 premiers octets du FIELD ne sont pas utilisés) :

OPEN "F", 3, "C:\*.*", 63 ' on ouvre sur le canal 3
FIELD 3, 14, 2 AS Z$, 4, 1 AS Mask$, 1 AS Type$, 4, 4 AS L$, 14 AS Nom$
FOR I=0 TO LOF(1)-1
 GET 3, I : PRINT CVI(Z$), ASC(Mask$), ASC(Type$), CVIL(L$), Nom$
NEXT I

GEMDOS(R, 47) la variable R rend l’adresse du Disk Transfert Address (OPEN "F")
GEMDOS(, 26, L Buffer) détermine l’adresse du DTA (44 octets) :
21 : attribut du fichier
22-23 : heure de création du fichier
24-25 : date de création du Fichier
26-29 : taille du fichier
30-43 : nom et extension du fichier

5.5 Disquettes ( → .en)

Ce qui suit est approprié aux disquettes, mais peut être adapté aux disques durs.

GEMDOS(R, 54, L Buffer, Lect) la variable R retourne 4 entiers longs d’information sur le disque à l’adresse Buffer :
  1° : nombre de clusters de données
  2° : nombre de clusters disponibles
  3° : lecteur : 0= Lect par defaut, 1=A:, 2=B:, 3=C:, n d’octets par secteur
  4° : nombre de secteurs par cluster

BIOS(R, 7, Lect) la variables R retourne une adresse qui pointe sur 13 mots courts :
  1° : nombre d’octets par secteur (512)
  2° : nombre de secteurs par cluster (2)
  3° : nombre d’octets par clusters (1024)
  4° : nombre de secteurs pour le répertoire
  5° : numéro du secteur de la File Allocation Table
  6° : numéro du secteur pour la deuxième FAT
  7° : numéro du 1° cluster de données
  8° : nombre de clusters de données du disque
  9° : toujours vide ou drapeaux?
 10° : nombre de faces (1 ou 2)
 11° : nombre de pistes par face (40 ou 80)
 12° : nombre de secteurs par piste (9 ou 10)
 13° : voir Inter de XBIOS 10 ci-dessous

BIOS(R, 4, F, L Adr, N, Dep, Lect) lit ou écrit N secteurs se trouvant à l’Adresse indiquée à partir de Dep
F =0 ou 2 pour lire, 1 ou 3 pour écrire, 2 et 3 ignorent les changements de disque
XBIOS(R, 8, L Adr, 0, 0, Lect, Sect, Piste, Face, N) lit N secteurs
Adr=MEMORY(512) pour 1 secteur
Lect = 0, 1, 2, pour A:, B:, C:,
Sect de 1 à 9 ou 10 selon le formatage
Piste de 0 à 79
Face 0 ou 1 en double face, 0 seulement en simple
XBIOS(R, 9, L Adr, 0, 0, Lect, Sect, Piste, Face, N) écrit N secteurs
XBIOS(R, 19, L Adr, 0, 0, Lect, Sect, Piste, Face, N) vérifie N secteurs
XBIOS(R, 10, L Adr, 0, 0, Lect, Sect, Piste, Face, Inter, L 987654321, Oct) formate une piste, idem que ci-dessus sauf :
Adr= MEMORY(9216) ou (10240) pour 9 ou 10 secteurs par piste
Sect vaut au choix 9 ou 10
Inter vaut 1 (ordre croissant des secteurs) ou 2 (135792468, Oct)
Oct est l’octet d’écriture, $E5 par exemple (éviter $F0 et $F5)
R rend 0 si tout va bien ou un n° d’erreur. Voir alors à l’Adr

XBIOS(R, 18, L Adr, L Serie, Type, Exec) écrit un boot-secteur
Serie contient un numéro de série de 24 bits
Type : 0 : 1 face de 40 pistes -- 1 : 2 faces de 40 pistes -- 2 : 1 Face de 80 pistes -- 3 : 2 faces de 80 pistes
Exec : 0 : boot-secteur non-exécutable, 1; exécutable
-1 pour chacun de ces paramètres laisse les précédents inchangés

6. Graphisme ( → .en)

Changement d’unité de base : le pixel (de picture element), soit le plus petit élément graphique de l’écran. Sur un Atari ST, il y a 640*400 pixels en haute résolution, 640*200 en moyenne et 320*200 en basse. L’Atari TT dispose aussi du mode 320×480 en 256 couleurs et le mode 640×480 en 16 couleurs (mais l’Omikron BASIC 3.01 fonctionne-t-il sur un TT?). Le point (0, 0) se trouve en haut à gauche; la première coordonnée exprime la largeur et la seconde la hauteur (négative). Il est préférable d’éteindre la souris et le curseur-texte avant tout affichage.

CLIP x, y TO u, v ou CLIP x, y, l, h définit une fenêtre d’action en dehors de la quelle rien ne peut s’afficher
CLIP sans paramètre pour annuler un CLIP précédent
CLIP 0, 0, 320, 200 limite exactement l’écran en basse résolution

Il existe 4 modes de superpositions pour les affichages des fonctions graphiques, définissables par l’instruction MODE

MODE=1 remplace (par défaut : le noir et le blanc recouvrent)
MODE=2 transparent (le blanc ne recouvre pas; OR)
MODE=3 exclusif (noir sur noir donne blanc; XOR)
MODE=4 inverse transparent

WVBL attend le nouveau balayage de l’écran, permet un affichage moins scintillant.

NDC x, y, l, h passe en coordonnées virtuelles. Tout affichage sera réduit à un rectangle défini par le rectangle défini. 0, 0 de ce qui est affiché est en bas à gauche du rectangle, et 32767, 32767 en haut à droite.
NDC revient au mode normal.

6.1 Souris et joystick ( → .en)

MOUSEON affiche le curseur souris. À faire avant l’affichage d’une boîte de dialogue
MOUSEOFF cache le curseur souris. À faire avant affichage graphique

À l’intérieur d’un programme, il suffit d’un MOUSEOFF pour annuler trois MOUSEON, mais il faut 4 MOUSEON après 3 MOUSEOFF pour affichier le curseur souris

MOUSEBUT contient l’état de la souris, soit 0 : pas de bouton; 1 : bouton gauche; 2 : bouton droit; 3 : simultanément les deux boutons

WHILE MOUSEBUT= 0 : WEND' attend un clic

MOUSEX indique en pixels la position horizontale de la souris
MOUSEY indique en pixels la position verticale de la souris

JOYSTICK(n) donne l’état de la manette JOYSTICK (n = 0 ou 1) :

10 Ad= MEMORY(CHR$(20)): XBIOS(, 25, 0, L Ad)'  XBIOS 25 permet
20 WHILE -1: PRINT BIN$(JOYSTICK(0)): WEND' de potentialiser
30 Ad= MEMORY(CHR$(8)): XBIOS(, 25, 0, L Ad)'  le bouton de tir

6.2 Boîtes d’alerte et sélecteur de fichiers ( → .en)

FORM_ALERT(C, "[S][ Tex | te ][ Bouton1 | Bouton2 | Bouton3 ]", R)

FILESELECT (Chemin$, Nom$, R) appelle une boîte de sélection. R rend pour [annuler] ou 1 pour [confirmer]

Exemple :

' pour sauver la partie d'écran en haute résolution:
Adr=MEMORY(13200): BITBLT 157, 54, 328, 312 TO Adr
MOUSEON
' pas de chaîne littérale dans l'instruction:
Chemin$="A:\*.*" ' cette variable sera probablement modifiée
FILESELECT (Chemin$, Nom$, R)
MOUSEOFF
BITBLT Adr TO 157, 54, 328, 312 ' réinstalle le bloc
Adr= FRE(Adr) ' libère la mémoire
PRINT Nom$, R

6.3 Texte graphique ( → .en)

Il est possible de colorer l’affichage avec TEXT.

TEXT permet un affichage spécialisé dans le style, la hauteur la direction et la couleur, et plus précis en coordonnée.

TEXT x, y, V$ affiche un texte au point x, y (exprimés en pixels)
TEXT x, y, "Texte", L, m, c L définit la longueur réservée au texte
si m=1 et c=0, les mots restent compacts
si m=0 et c=1, tous les caractères sont espacés

Les trois fonctions qui suivent sont valables jusqu’à une nouvelle spécification (rétablir avant de terminer un programme)

TEXT STYLE= n se place avant un TEXT (pour annuler : TEXT STYLE=0)
1 : gras - 2 : grisé - 4 : italique - 8 : souligné - 16 : évidé
Les styles se combinent par addition des paramètres. 13 donne un texte souligné, italique et gras (8+4+1)

TEXT HEIGHT= n donne la hauteur en pixel du TEXT à afficher
1 à 3 : texte complètement illisible
4 : juste lisible et bien proportionné
6 : même largeur que le standard, mi-hauteur
9 : intermédiaire bien réussi
12 : même hauteur que le standard, double largeur
13 : corps standard (pour revenir à la normale)
26 : double largeur, double hauteur, taille max

Les hauteurs intermédiaires sont possibles, mais pas toujours réussies. En moyenne et basse résolution, le corps standard est 6

TEXT ROTATION= 900 affiche un texte de bas en haut
TEXT ROTATION= 1800 à l’envers
TEXT ROTATION= 2700 de haut en bas
TEXT ROTATION= 0 remet le texte à l’endroit (par défaut)

6.4 Points et lignes ( → .en)

Il est possible de colorer ces lignes.

DRAW x, y affiche un pixel au point défini ((0, 0) est en haut à gauche)
DRAW x, y TO u, v TO … trace une ligne de x, y _ u, v (à …)
DRAW TO x, y relie le dernier point affiché au point x, y, utilisé surtout en boucle

CLIP 0, 0, 640, 400
DRAW 200, 50 TO 200, 350: DRAW 100, 100 TO 400, 100
FOR I! =2 TO .01 STEP -.01
 DRAW TO 100*(2+I!), 100*(1-LOG(10, I!)) ' essayer DRAW sans TO
NEXT

LINE WIDTH= n (impair, jusqu’à 39) impose une largeur de ligne
LINE STYLE= n défini la ligne :
0 blanche (MODE=1) ou invisible (MODE=3)
1 **************** pleine
2 ************   tiret long
3 **  **   pointillée
4 ******** **   tiret-point
5 ********   discontinu
6 ***** **  *   composée
7 paramétrable avec LINE PATTERN

LINE PATTERN= nn est un entier court 16 bits, soit exprimé en binaire %0110110100101111 (1 allume un pixel), soit en hexadécimal : $6D2F, où chaque caractère représente 4 pixels : 0=0000, 1=0001, 2=0010, 3=0011, 4=0100, 5=0101, 6=0110, 7=0111, 8=1000, 9=1001, A=1010, B=1011, C=1100, D=1101, E=1110, F=1111

6.5 Figures géométriques ( → .en)

Il est possible de colorer ces contours.

BOX x, y TO u, v définit un rectangle selon deux sommets opposés
BOX x, y, l, h définit selon le sommet supérieur gauche et les dimensions
RBOX x, y TO u, v définit un rectangle aux coins arrondis

CIRCLE x, y, r définit un cercle de centre (x, y) et de rayon r
CIRCLE x, y, r, d, a définit un arc de cercle dont d = l’angle de départ et a = l’angle d’arrivée (en 1/10 de degrés)

ELLIPSE x, y, r1, r2 r1 = rayon horizontal, r2 = rayon vertical
ELLIPSE x, y, r1, r2, d, a définit un arc d’ellipse (voir CIRCLE)

POLYGON T(0, 2*n +2) défini un polygone de 63 côtés maximum. Pour un dodécagone, dimensionner un tableau à 1*27 éléments soit 2*nombre de côtés +3 (?)

CLIP 0, 0, 640, 400: CLS : DIM P%(0, 26) ' = 27 éléments
MOUSEON
FOR I=0 TO 23 STEP 2
 WHILE MOUSEBUT=0: WEND ' clic souris pour définir un point
 P%(0, I)= MOUSEX: P%(0, I+1)= MOUSEY
 WHILE MOUSEBUT >< 0: WEND ' attent le retour du clic
NEXT
P%(0, 24)=P%(0, 0): P%(0, 25)=P%(0, 1) ' répétion du 1° point
MOUSEOFF : POLYGON P%(0, 26) ' appel du polygone

6.6 Remplissages ( → .en)

Il est possible de colorer ces surfaces.

PBOX, PRBOX, PCIRCLE, PELLIPSE, PPOLYGON acceptent un remplissage.

OUTLINE OFF efface les contours des figures remplies
OUTLINE ON annule l’instruction précédente

FILL STYLE= 0, 1 blanc
1, 1 noir (par défaut)
2, 1 à 2, 24 motifs-dessins
3, 1 à 3, 12 motifs-lignes
4, 1 le sigle ATARI, ou à définir avec FILL PATTERN

Motifs de remplissage de la fonction FILL STYLE: 2, n avec n de 1 à 8 pour n pixels sur 8; 2, 9 briques de face; 2, 10 briques en biais; 2, 11 2, 11 tout petits chevrons espacés; 2, 12 petites arcades; 2, 13 courtes lignes tissées; 2, 14 gros points épars; 2, 15 points épars; 2, 16 bandes tissées; 2, 17 zig-zag horizontaux; 2, 18 carrés pointillés centrés; 2, 19 boules avec reflet; 2, 20 tuiles de face; 2, 21 tuiles de biais; 2, 22 petit damier horizontal; 2, 23 damier oblique; 2, 24 chevrons horizontaux alternes; 3, 1 lignes de biais; 3, 2 lignes épaisses de biais; 3, 3 croisement de biais; 3, 4 lignes verticales; 3, 5 lignes horizontales; 3, 6 croisement horizontal/vertical; les motifs des six suivantes sont plus espacés (3, 8: les lignes sont plus grosses; 3, 12 = 3, 6 pour les TOS 1, xx)
Note : Dans les TOS 1.xx, FILL STYLE 3, 12 équivaut à FILL STYLE 3, 6

FILL x, y, -1 remplit une surface contenant le point (x, y). La surface doit être bien délimitée.

CLS : CLIP 0, 0, 640, 400
BOX 100, 100, 440, 200
FILL STYLE= 2, 20: PRBOX 150, 150, 340, 100
FILL STYLE= 2, 13: FILL 120, 120, -1

FILL PATTERN= Tableau%(0) fonctionne comme LINE PATTERN, mais avec 16 Entiers Courts dans un Tableau% de 16 éléments

Pour déterminer les nombres à entrer dans le tableau, dessiner un damier de 16*16. Chaque ligne en nombre binaire, interprétée en hexadécimal (voir LINE PATTERN) est un élément du tableau. Utiliser NOT si le nombre dépasse $7FFF.

6.7 BITBLT, BIT-BLock-Transfert ( → .en)

BITBLT x, y, l, h TO u, v, m, n transpose une partie de l’écran défini par x, y, l, h au point supérieur gauche u, v
BITBLT x, y, l, h TO Adr sauve en mémoire une partie de l’écran.
BITBLT Adr TO x, y, l, h, m affiche la partie d’écran mémorisée, m étant le mode dont elle s’imprime (3= couvrant, par défaut, mais mieux vaut le préciser)

Les 15 autres modes sont, pour S=Source et C=Cible :

0= blanc
1= S AND C
2= S AND (NOT C)
4= (NOT S) AND C
5= C
6= S XOR C
7= S OR C
8= NOT(S OR C)
9= NOT(S XOR C)
10= NOT C
11= S OR (NOT C)
12= NOT S
13= (NOT S) OR C
14= NOT (S OR C)
15= noir

Exemple :

CLS: PRINT @(0, 0); "*"
Ad= MEMORY(28)
BITBLT 0, 1, 7, 11 TO Ad
REPEAT
 BITBLT Adr TO 10+RND(610), 10+RND(365), 10, 11, 7 ' ou 3…
UNTIL MOUSEBUT=2

Détermination de la mémoire à réserver : Le BITBLT comprend en mémoire un "seize bits" comprenant la résolution (2 pour la haute, 4 pour la moyenne et 8 pour la basse), le deuxième la largeur, le troisième la hauteur. Pour la haute résolution, il y a toujours un nombre pair d’octets. Pour une image de X pixels de largeur sur Y de hauteur, il faudra prévoir 6 + ((X-1)\16 +1) *2 *Y octets.

6.8 Les sprites ( → .en)

Un sprite est un petit dessin très facilement manipulable (l’abeille, la flèche…). Il existe en Omikron des petits et grand sprites pour chacune des résolutions. Il faut veiller à réserver de la mémoire pour le fond et le dessin. Le dessin s’écrit ligne par ligne en mémoire (1° ligne masque, 1° ligne avant-plan, 2° ligne masque, etc). Le masque sert à faire ressortir l’avant plan sur un fond de couleur et à ne pas afficher le sprite comme en MODE= 3 (XOR, noir sur noir donne blanc).

DEF SPRITE n, dim, Fond

définit un numéro de sprite (1 à 6), Fond est l’adresse en mémoire où se conserve la partie de l’écran cachée par le sprite, et dim la dimension :

basse : dim = 1 (petit : 16 octets) ou 2 (grand : 64 octets)
moyenne : dim = 3 (petit : 32 octets) ou 4 (grand : 128 octets)
haute : dim = 5 (petit : 64 octets) ou 6 (grand : 256 octets)

SPRITE n, x, y, Dess, Cm, Ca

affiche le sprite n, aux coordonnées x, y dont le dessin a été préalablement inscrit à l’adresse Dess, Cm et Cd sont les Couleurs du masque et de l’avant-plan.

DEF SPRITE n, 0 efface le sprite (utile en cours de programme)

6.9 Couleurs ( → .en)

Les Atari ST et STE peuvent afficher simultanément seize couleurs en basse résolution (320*200px) ou quatre en moyenne résolution (640*200px), dans ce dernier cas, les pixels sont rectangulaires.

LINE COLOR= n pour définir la teinte des points et lignes avec DRAW, et des formes géométriques avec BOX, RBOX, CIRCLE, ELLIPSE et POLYGON

FILL COLOR= n pour définir la teinte du remplissage de PBOX, PRBOX, PCIRCLE, PELLIPSE, PPOLYGON
TEXT COLOR= n pour définir la teinte du texte graphique TEXT.

n vaut de 0 à 15 (compris) en basse résolution, et de 0 à 3 en moyenne résolution. Chaque couleur est un mélange des trois lumières fondamentales rouge signal, vert émeraude et bleu outremer. Les couleurs par défaut reprises plus bas peuvent être modifiées par le Panneau de contrôle CONTROL.ACC.

Atari ST

Couleurs exprimées en hexadécimal
ATARI ST - TOS 1.4
0 blanc
7·7·7
2 rouge
7·0·0
4 bleu
0·0·7
6 marron
4·2·0
8 gris
5·5·5 clair
10 cyan
0·7·7
12 magenta
7·0·7
14 sable
4·4·0
1 noir
0·0·0
3 vert
0·7·0
5 marine
4·0·0
7 bouteille
0·4·0
9 gris foncé
2·2·2
11 acier
0·4·4
13 violet
4·0·4
15 jaune
7·7·0
Seules les quatre couleurs de gauche sont concernées par la moyenne résolution.

Atari STE

À partir du STE (TOS 1.6), chaque fondamentale connaît 16 nuances, de 0 à 15 ($F), portant les teintes possibles à 4096 (163). Il est à noter que le marron et le vert foncé sont nettement plus sombres, et que le jaune et le sable sont intervertis.

Couleurs exprimées en hexadécimal
ATARI STE - TOS 1.6
0 blanc
15·15·15
1 noir
0·0·0
2 rouge
15·0·0
3 vert
0·15·0
4 bleu
0·0·15
5 marine
8·0·0
6 marron
8·4·0
7 bouteille
0·8·0
8 gris clair
10·10·10
9 gris foncé
4·4·4
10 cyan
0·15·15
11 acier
0·8·8
12 magenta
15·0·15
13 vviolet
8·0·8
14 jaune
15·15·0
15 sable
8·8·0
La première rangée seule est concernée par la moyenne résolution.

Afin de garder la compatibilité avec les teintes du ST, les nuances supplémentaires (les demi-intensités) du STE sont indiquées par l’ajout du nombre 8, valeur du bit le plus à gauche, dont le ST ne se préoccupe pas :

0 - $08 - $81 - $19 - $92 - $210 - $A3 - $311 - $B4 - $412 - $C5 - $513 - $D6 - $614 - $E7 - $715 - $F
%0000%1000%0001%1001%0010%1010%0011%1011%0100%1100%0101%1101%0110%1110%0111%1111

Moyenne résolution

Les couleurs des panneaux de contrôle sont limitées au quatre de gauche (ST) ou à la première rangée (STE) : blanc 777 ou 15·15·15, noir 0·0·0, rouge 700 ou 15·0·0 et le vert 070 (ST) ou 0·15·0 (STE).

SCREEN 1, Adr, 4 permet le passage de la basse résolution (320*200) en moyenne (640*200). N’oubliez pas 32256 octets en mémoire pour Adr, arrondie à un multiple de 256 (pour les TOS <1.6) :

Adr=(MEMORY(32256)+256) AND $FFFF00
SCREEN 1, Adr, 4

Couleurs VDI

L’ordre «VDI» de l’interface graphique GEM n’est pas le même que l’ordre du panneau de contrôle. En basse résolution : PALETTE 0, 2, 3, 6, 4, 7, 5, 8, 9, 10, 11, 14, 12, 15, 13, 1

PALETTE $a, $b, $c, $d, $e, … définit la nuance des couleurs sans passer par l’accessoire Panneau de Contrôle. Pour le ST, chaque paramètre se compose de trois chiffres, chacun de 0 à 7. Le premier dose le rouge, le deuxième le vert et le troisième le bleu.

POINT (x, y) teste et rend le n° de couleur «VDI» du point x, y

PRINT CHR$(27);"b";CHR$(n) impose la couleur «VDI» du texte, n va de 0 à 15
PRINT CHR$(27);"c";CHR$(n) impose la couleur «VDI» du fond

Cette représentation est plus proche de l’interprétation de la machine. La couleur de chaque pixel est représentée par des bits appartenant à quatre mots courts différents. C’est pour cela qu’une image en basse résolution d’un seul pixel aura nécessairement huit octets de data. Le premier mot donne le bit de poids le plus faible, le quatrième le bit de poids le plus fort

W1: 0 1 1 0 1 0 1 1 0 1 1 1 0 1 0 1
W2: 0 1 1 1 1 0 1 0 0 0 1 1 0 1 0 1
W3: 0 1 1 0 0 0 1 0 0 0 1 1 1 1 0 1
W4: 0 1 1 0 0 0 1 0 0 0 1 0 0 1 0 1

Le premier pixel est représenté par la première colonne de 4 bits, le second par la deuxième colonne, etc, ce qui fait :

%0000 =  0, première couleur
%1111 = 15, seizième et dernière couleur
%1111 = 15, dernière couleur
%0010 =  2, troisième couleur
%0011 =  3, quatrième couleur
%0000 =  0, première couleur
etc.

VDI en moyenne résolution

En moyenne résolution : PALETTE 0, 2, 3, 1

Par exemple, on peut redéfinir les couleurs traditionnelles de la moyenne définition (blanc, rouge, vert et noir) :

PALETTE $777, $707, $077, $555 donnera du blanc, magenta, cyan et anthracite.

Sur l’écran, il suffit de deux mots de seize bits pour coder seize pixels : quatre couleurs peuvent être définies par deux bits.

W1: 0 1 1 0 1 0 1 1 0 1 1 1 0 1 0 1
W2: 0 1 1 1 1 0 1 0 0 0 1 1 0 1 0 1
%00 =  0, première couleur
%11 =  3, quatrième et dernière couleur
%11 =  3, dernière couleur
%10 =  2, troisème couleur
%11 =  3, quatrième couleur
%00 =  0, première couleur
etc.

7. Système ( → .en)

7.1 Mémoire ( → .en)

CLEAR n réserve n octets de mémoire globale pour les MEMORY
Adr=MEMORY(2000) réserve 2000 octets à l’emplacement Adr en mémoire
Adr=MEMORY("Monty Python") réserve la place nécessaire et y place la chaîne

FRE(Adr) libère la mémoire réservée par MEMORY
FRE("C:") retourne la place libre sur un disque
FRE(0) donne la place disposible en mémoire
FRE("") idem, mais force auparavant un "garbage collection", libération de la mémoire utilisée pour le travail sur les chaînes :

PRINT FRE(0)
A$="1": B$="=100"
FOR I=1 TO 99: A$=A$+"+1": NEXT
PRINT A$;B$
PRINT FRE(0) ' on a utilisé 10710 octets
PRINT FRE("") ' on en a récupéré 10594: en tout la chaîne finale utilise 216 octets.

Octet=PEEK(Adr) lit un octet à l’adresse indiquée
Court=WPEEK(Adr) lit un mot court à l’adresse indiquée
Long=LPEEK(Adr) lit un mot long à l’adresse indiquée

POKE Adr, Octet écrit un octet à l’adresse indiquée
WPOKE Adr, Court écrit un mot court à l’adresse indiquée
LPOKE Adr, Long écrit un mot long à l’adresse indiquée

MEMORY_MOVE D, Adr TO Ac déplace un bloc de mémoire de l’Adresse départ à l’Adresse cible (adresses paires)
MEMORY_MOVEB D, Adr TO Ac permet d’utiliser des adresses impaires

MEMORY_BLOCK xx, n, Adr réserve une plage de n octets à la variable-Adresse pour un bloc de mémoire (numéroté de 00 à 99) qui sera sauvé avec le programme. Lors d’un futur chargement, la même instruction replace le bloc à l’Adresse indiquée

VARPTR(V) rend l’adresse de la variable indiquée

SEGPTR donne l’adresse de départ du tableau SEGment PoinTeR qui contient des pointeurs (adresses) de débuts de tableaux :

+0 octet n° de lignes
+4 début du programme
+8 pointeurs de variables
+12 variables
+20 tableaux
+24 tampon fichier
+28 chaînes
+36 ordre exécuté
+40 garbage top
+44 garbage bottom
+48 garbage high
+52 valeur max de la Pile
+56 bas de la Pile
+60 la plus grande adresse de la mémoire

VARPTR(A$) contient l’adresse relative de la chaîne à partir de SEGPTR+28.

Adresse = LPEEK(SEGPTR+28)+LPEEK(VARPTR(A$))

IPL n fixe le niveau d’interruption du système, de 0 à 7
IPL 3 niveau standard
IPL 3+(1 SHL 31) plus de [Ctrl]-[C]
IPL 4 écran gelé
IPL 6 ni clavier, WAIT ou TIMER

7.2 Routines en langage-machine ( → .en)

Les routines en langage-machine sont utiles quand on cherche la rapidité ou l’accès à des modes de programmation réservés à ce langage.

INLINE "A009" permet d’entrer une ligne d’instructions en code hexadécima1. L’exemple donné fait appel à la ligne A, instruction machine commençant par la valeur 10, engendrant une exception du processeur, récupérée par le système pour une redirection vers des fonctions graphiques. "A009" fait apparaître le curseur souris, "A00A" le fait disparaître.

DEF USR =Adr fixe l’adresse d’une routine en assembleur
Ret= USR(Val) appelle la fonction à l’adresse fixée. Une valeur est passée sur le registre D0 (4 octets); à la fin de la routine, la valeur présente en D0 est retournée en Ret.

Ad= MEMORY(6)'       réserve 6 octets pour la routine
LPOKE Ad, $06000009'    add.b #9, d0
WPOKE Ad+4, $4E75'      rts
DEF USR =Ad'         fixe l'adresse en mémoire de la routine
PRINT USR(16)'       appel avec la valeur 16 en d0, retour de la valeur 25

CALL Adr(L param1, L param2…) appel d’une routine en assembleur chargée à une adresse avec d’éventuels paramètres qu’on retrouve à partir de 4(A7) (adresse indiquée par la valeur de la pile (A7) + 4)

Il est évidemment assez long de composer les instructions en code machine à la main. Il vous faut donc disposer d’un assembleur 68000. Le binaire qui en résulte peut être chargé à partir du fichier BASIC avec BLOAD "Fichier", Adr (voir BLOAD). Il est également possible de l’inclure définitivement dans le programme avec MEMORY_BLOCK 00, L, Adr (voir section précédente). Attention :

7.3 Date et heure ( → .en)

TIME$ contient l’heure connue de la machine
TIME$="15:58:12" met la machine à l’heure

TIMER donne le nombre de 1/200 de secondes depuis la mise en marche de la machine, équivalent à LPEEK($4BA)
WAIT n attend un certain nombre de secondes, précision au 1/200

DATE$ contient la date connue de la machine
DATE$="" ajuste la date selon le mode :
MODE"USA" mois/jours/années : "02/14/2009" (par défaut)
MODE"GB" jours/mois/années : "14/02/2009" (MODE"F")
MODE"D" jours.mois.années : "14.02.2009"

BIOS(R, 6) donne en millisecondes le délai entre deux tops d’horloge

GEMDOS(R, 42) la variable R retourne la date sous la forme :
Bits 15-9 : année si on y ajoute 1980 (2022=42) – 7 bits code de 0 à 127, ce qui code jusqu’en 2107 !
Bits 8-5 : mois (1 à 12) ; Bit 4-0 : le jour (1 à 31)
GEMDOS(, 43, Date) Date est l’Entier court qui fixe la date
GEMDOS(, 45, Heure) Heure est l’Entier Court qui fixe l’heure
GEMDOS(R, 44) R retourne l’heure sous la forme :
Bit 15-11 : heures - Bit 10-5 : minutes - Bit : 4-0 doubles-secondes (0=0s, 1=2s, 2=4s…)
XBIOS(, 22, L Adr) met à l’heure l’horloge-système. Adr contient la date dans son mot fort et l’heure dans le faible
XBIOS(R, 23) retourne l’heure et la date au format de XBIOS 22

GEMDOS 42, 43, 44 et 45 d’une part et XBIOS 22 et 23 de l’autre s’ignorent.
Attention : GEMDOS 43 accepte la date 31/2/92 (mais pas 32/1/92).

7.4 Traitement des erreurs ( → .en)

ERR contient le n° de la dernière erreur et permet IF ERR=n THEN …
ERR$ contient le libellé de la dernière erreur
ERL contient le n° de ligne de la dernière erreur, ou 00 en mode direct
LIST ERL affiche la ligne erronée

ON ERROR GOTO branche vers une routine de traitement d’erreur
RESUME sort de la routine de traitement d’erreur et tente une nouvelle fois l’exécution de l’instruction douteuse
RESUME NEXT saute à l’instruction suivant celle de l’erreur
RESUME Etiq saute à la ligne indiquée par l’étiquette Etiq
ERROR n simule l’erreur n, ce qui permet la mise au point d’une routine de traitement d’erreur

Les boucles sont intactes après un RESUME : il faut un EXIT pour remettre la boucle à 0. Si ON ERROR GOTO est débranché par CLEAR ou est interrompu par [Ctrl]-[C], le message d’erreur est affiché

TRON (TRace ON) passe en mode TRACE : affiche le n° de ligne et chaque instruction exécutée du programme
TROFF annule le mode TRACE (à faire 3 fois s’il y a eu 3 TRON?)
ON TRON GOSUB à la condition que TRON soit actif, branche vers une routine après chaque instruction

Erreurs renvoyées par l’interpréteur : ( → .en)

  1. Structure too long une procédure ou boucle mesure plus de 64 Ko
  2. Syntax error instruction inexploitable. Mauvaise ponctuation
  3. RETURN without GOSUB mettre les sous-programmes après un END
  4. Out of DATA pas assez de données (DATA) pour l’instruction READ
  5. Illegal function call la plupart des fonctions ont des limites
  6. Overflow les variables numériques ont des capacités limitées
  7. Out of memory plus de mémoire pour le GEMDOS ou la Pile
  8. Undefined Statement la ligne pour un GOTO/GOSUB n’existe pas
  9. Subscript out of range dépassement des limites d’un tableau
  10. Duplicate definition deux procédures/fonctions ont le même nom
  11. Division by zero pas toujoure visible au premier coup d’oeil
  12. Illegal direct une procédure ne peut être rencontré par l’interpréteur ; écrire les procédure après le END
  13. Type mismatch le contenu ne correspond pas au type de variable
  14. RETURN without function lorsque le programme rencontre RETURN sans qu’une fonction n’ait été appelée
  15. String too long la chaîne contiendrait plus de 32767 caractères
  16. Formula too complex trop d’imbrications pour la Pile
  17. Can’t continue pas de CONT après un changement qui suit STOP
  18. Undefined user function aucune fonction, mot-clé ou procédure ne correspond à ce nom.
  19. No RESUME un RESUME manque à une routine de traitement d’erreur
  20. RESUME without error le programme tombe sur un RESUME sans avoir rencontré d’erreur
  21. Use EXIT ce message arrive souvent lorsqu’il manque un ENDIF à une structure IF/THEN dans une autre boucle
  22. Missing operand aucun terme ne suit un opérateur ou une virgule
  23. Line buffer overflow ligne de programme trop longue : plus de 255 caractères (en affichage : 512)
  24. REPEAT without UNTIL
  25. UNTIL without REPEAT
  26. FOR without NEXT
  27. NEXT without FOR
  28. IF without THEN or EXIT il manque un THEN ou un ENDIF à un IF
  29. WHILE without END
  30. END without WHILE
  31. THEN, ELSE or ENDIF without IF or THEN l’inverse de 28
    Pour s’y retrouver dans les boucles, il est recommande de le structurer visuellement :
REPEAT
 FOR I= -5 TO 5
  IF I= 0 THEN
   PRINT I; " est plus grand que zéro"
  ELSE
   PRINT I; " n'est pas plus grand que zéro"
  ENDIF
 NEXT I
 PRINT "Clic souris pour arrêter"
UNTIL MOUSEBUT = 0
  1. ERROR 32 [Enter] pour obtenir le copyright Omikron 3.01
  2. RESET le programme a été conservé après un RESET à chaud. C’est normal, mais il ne faut pas toujours s’y fier.
  3. Bus error erreur de BUS : adressage dans une zone non autorisée
  4. Address error erreur d’adressage (ex : mot en adresse impaire)
  5. Unknow opcode instruction inconnue au niveau du processeur
  1. Out of memory. Save or re-CLEAR immediatly Sauvez au plus vite
  2. EXIT without structure de quelle boucle faut-il sortir?
  3. Use EXIT TO in functions pour sortir des fonctions à plusieurs lignes
  4. Matrix not regular voir conditions imposées aux matrices
  1. Bad file number il n’y a que 16 numeros de canaux
  2. Field overflow trop de données pour le FIELD concerne
  3. Internal error erreur fatale obligeant à un RESET à froid
  4. Bad file number il n’y a que 16 numéros de canaux
  5. File not found le fichier n’existe pas sur le chemin spécifié
  6. Bad file mode instruction illégale sur un fichier
  7. File already open fichier déjà ouvert, donc non-ouvrable
  8. File not open avant tout, attribuer un canal au fichier
  9. TOS Error n voir le point suivant
  10. File already exists un fichier déjà existant n’est plus à créer
  11. File type mismatch erreur dans le type des fichiers
  12. Bad disk disque défectueux
  13. Disk full disque plein
  14. Input past end lecture de données au-delà de la fin du fichier (manque l’octet 26?) LOF pour en connaître la position
  15. Bad record number le numéro d’enregistrement n’existe pas (voir LOF)
  16. Bad file number un caractère interdit dans le nom du fichier.
  17. Path not found le chemin spécifié n’existe pas
  18. Direct statement in file le programme à charger ne contient pas de n° de ligne : utiliser "Load Block" du menu "Files"
  19. Too many file trop de fichiers sur la disquette
  20. Write error erreur d’écriture
  21. Read error erreur de lecture
  22. Disk write protected disquette protégée contre l’écriture

Erreurs retournées par le système ( → .en)

BIOS-XBIOS GEMDOS
  1. Erreur générale
  2. Lecteur pas prêt
  3. Instruction inconnue
  4. Erreur de checksum
  5. Instruction incorrecte
  6. Secteur introuvable
  7. Boot-secteur défectueux
  8. Secteur non trouvé
  9. Plus de papier
  10. Erreur d’écriture
  11. Erreur de lecture
  12. Erreur générale
  13. Disquette protégée
  14. Disquette changée
  15. Périphérique inconnu
  16. Secteur défectueux
  17. Introduire une disquette
  1. Numéro de fonction non-valide
  2. Fichier non trouvé
  3. Chemin d’accès non trouvé
  4. Trop de fichiers ouverts
  5. Accès impossible
  6. Numéro de fichier non-valide
  7. Mémoire insuffisante
  8. Adresse de bloc-mémoire incorrecte
  1. Désignation incorrecte de lecteur
  1. RENAME sur plusieurs unités
  2. Plus d’autre fichier
  1. Dépassement de capacite du fichier
  2. Erreur interne du GEMDOS
  3. Programme à exécuter incorrect
  4. Erreur de bloc-mémoire

7.5 Programmation système ( → .en)

Les fonctions BIOS (Basic Input/Output System), XBIOS (eXtended BIOS, et GEMDOS (Disk Operating System) sont reprises dans cette page, dans la mesure où elles ne sont pas exploitées dans les instructions classiques.

R est toujours une valeur-Retour, qui n’est pas toujours utile (conserver néanmoins la virgule). Elle peut retourner une adresse, une erreur TOS ou le numéro du lecteur ou d’un fichier (Handle).

Il est nécessaire de réserver de la mémoire avant de faire appel aux fonctions retournant un certain nombre d’octets par l’intermédiaire d’une adresse. Les fonctions PEEK permettent de les lire. À l’inverse, les fonctions POKE permettent d’écrire des données sur une adresse réservée en mémoire avant d’appeler une fonction. La manière la plus pratique d’écrire une chaîne en mémoire et d’en connaître l’adresse est la suivante :

Ad= MEMORY("Chaine"+CHR$(0))

la plus classique étant :

V$= "texte"+ CHR$(0) : Adr= LPEEK (SEGPTR + 28) + LPEEK (VARPTR(V$))

LPEEK (SEGPTR + 28) est un pointeur sur l’emplacement des chaînes en mémoire et LPEEK(VARPTR(V$)l’adresse relative au pointeur pour la chaîne V$. Chaque caractère sera récupérable par PEEK(adr), PEEK(Adr+1)…

Ces fonctions étant proches du langage du processeur 68000, les paramètres doivent se passer par Entiers Courts et l’adresse d’un buffer doit se décomposer en HIGH(Adr) et LOW(Adr). L’Omikron permet de le faire plus facilement avec L Adr :

GEMDOS(, 26, HIGH(Buffer), LOW(Buffer)) devient GEMDOS(, 26, L Buffer)

Il est normal d’éprouver certaines difficultés avec ces fonctions, ceci n’étant plus vraiment du BASIC. Par exemple, XBIOS 0 (pour la souris) requiert des informations complémentaires, et dépasse largement l’objet de cette page. Ci-dessous, GEMDOS 10 permettra de se convaincre du confort du BASIC classique. Il existe néanmoins des instructions-système qu’il faut connaître pour que l’Omikron soit un langage complet.

GEMDOS(R, 48) R divisé par 256 retourne la version du GEMDOS.

XBIOS(R, 17) R rend un nombre semi-aléatoire de 24 bits.

GEMDOS(R, 10, L Buffer) permet la saisie d’une ligne. Les 2 premiers octets contiennent la longueur maximale et effective de la chaîne, terminée par CHR$(13) :

Saisie(12, Ch$): PRINT Ch$: END ' tiré du LIVRE OMIKRON-BASIC
DEF PROC Saisie (N, R T$) ' R pour retourner une chaîne
 T$= CHR$(N)+ CHR$(0)* (N+2) ' 1° octet et tapis d'octets nuls
 Adr= LPEEK(SEGPTR+28)+ LPEEK (VARPTR(T$) ' adresse de la chaîne
 GEMDOS (, 10, L Adr) ' attend N caracteres maximum ou [Enter]
 T$= MID$(T$, 3, ASC(MID$(T$, 2)))' rend le texte à partir du 3° caractère
RETURN ' INPUT$ ou INPUT (USING) est quand même plus pratique !

7.6 Quelques précautions utiles ( → .en)

7.7 Bugs et faiblesses de l’Omikron BASIC 3.01 ( → .en)