Omikron BASIC 3.01 (rough english version)

IF you bought your Atari-ST computer around 1990, it is possible (France, Benelux...) that Omikron 3.01 BASIC was given along, and an approximate literature. This page should fix it. Omikron BASIC was written out by Artur Södler (and Thomas Kemp for the mathematical routines) in 68000 assembly language, a very concise one: the application is only 106KB large, around the weight of this web page. In those times, it was a very complete language.

In order to use the GEM (Graphic Environment Manager) with menus and windows, an additional documentation is necessary, and a resources constructor is useful.

You don't have anymore ST, TT or Falcon? It is currently possible to use this BASIC on Atari emulation (.fr): Aranym means 'Atari runs on any machine', and so does Hatari...

2020.05.11 - more than 100 guests a month!

1. Editors and commands

1.1 Standard editor
1.2 Graphical editor

2 Variables and values

2.1 Numerical variables
2.2 Numerical bases
2.3 Operators
2.4 Mathematical functions
2.5 Character strings
2.6 Types conversions
2.7 Arrays and matrices
2.8 Logical operators

3. Structures

3.1 Conditions
3.2 Loops
3.3 Procedures

3.4 Functions
3.5 Data exploitation
3.6 Connections
3.7 Routines

4. Devices

4.1 Screens
4.2 Console out
4.3 Console in
4.4 Others devices
4.5 Sound YM2139

5. Storage

5.1 Disks and files
5.2 SAVE and LOAD
5.3 Sequential files
5.4 Random files
5.5 Disks

6. Graphics

6.1 Mouse and joystick
6.2 Alert boxes and selector
6.3 Graphical text
6.4 Dots and lines
6.5 Geometrical forms
6.6 Filling
6.7 BITBLT
6.8 Sprites
6.9 Colours

7. System

7.1 Memory
7.2 Binary routines
7.3 Time
7.4 Errors processing
7.5 BIOS, XBIOS and GEMDOS
7.6 Useful precautions
7.7 Bugs and weaknesses

1. Editors and commands ( → .fr)

Omikron 3.01 has two editors.

1.1 The standard editor ( → .fr)

The first editor looks like the traditional editors such as they existed on the first platforms (Commodore 64), where each line of code is prefixed by a number.

Type 10 print "Hulloder!" (and [Return]) and your first code line is recorded. Type LIST and 10 PRINT "Hulloder! appears.

LIST lists the whole program in the order of the numbers of line
LIST n only lists line n
LIST -n lists the program up to line n
LIST m- lists the program starting from line m
LIST m-n lists the lines of programme from m to n

RENUM renumbers the lines of the program, 10 by 10
RENUM m ...by specifying the number of the first line
RENUM l, m, n the line m becomes l , the following ones n by n

CLS erases the screen and places the cursor in the top left corner
CLEAR puts the variables at the 0, close all files, checks the loops and disconnects the conditional subroutines

NEW ! CAUTION: erases a *.BAS-file in memory
QUIT or SYSTEM leaves the interpreter. You will be asked to confirm.

RUN puts the variables at 0, checks and runs the program
RUN 100 , RUN Aum ...starting from line 100 or at the label -Aum
GOTO n runs a program from then line n without putting the variables at 0.

Keys specific to the standard editor ( → .fr)

[Enter] or [Return] validates a line of program
[ClrHome] place the text-cursor in the left top of the screen
[Ctrl]-[ClrH] erases the screen (LIST to list out the program)
[Ctrl]-[Del] erases the line after the cursor.
[Ctrl]-[Arrow-Up] erases the cursor line, and pull up the following ones
[Ctrl]-[Arrow-Dn] inserts a line and push down the following ones
[Ctrl]-[Arrow-Lf] sets the left-higher corner of a window (=CHR$(4))
[Ctrl]-[Arrow-Rg] sets the right-lower corner of the window (=CHR$(5))
[ClrH] [ClrH] cancels the frame set by the the two previous key-combinations
[Ctrl]-[S] suspends a running program
[Ctrl]-[Q] starts again a suspended program
[Ctrl]-[C] stops a program
[Sft]-[Sft] allows a command during a running program (63 characters buffer)
[Ctrl]-[Alt] erases the content of the keyboard-buffer

KEY n defines the 20 function-keys (KEY 13= [Sft]-[F3])
KEY 10=CHR$(27)+"E" '= CLS (here 2 characters, maximum 32)
KEY 10="quit"+CHR$(13)+"y" to quit Omikron from standard editor
KEY LIST lists the 20 function-key of the standard editor. Do use the super-editor menu in order to save the function-key definitions: /mode/save settings .

To use a function-key in a program, watch its scancode: $3B to $44 for [F1] to [F10]; $70 to $79 for [Sft]-[F1] to [Sft]-[F10]

1.2 The graphical editor ( → .fr)

The graphical editor has a menu-system and manages the mouse. It can also hide off the line numbers. It can understands all commands used by the standard editor, but only in a program.

[F1] goes to a precise numberline
[F1] [Arrow-Up] goes to the top of the screen
[F1] [Arrow-Dn] goes to the bottom of the screen  
[Sft]-[F1] divides the screen
[Sft]-[F2] passage from a window to the other
[Sft]-[F3] changes the police height
[F3] [F2] replaces a string
[F3] [F3] replaces all the strings
[F6][n] repeats n time the last character
[Sft]-[F6] [F9] cuts a line
[Sft]-[F6] [Sft]-[F9] pastes two lines
[F7] [F8] saves the block in ASCII
[F7] [Sft]-[F8] loads a block in ASCII
[F8] saves a program
[Sft]-[F8] loads a program
[F9] inserts a line
[Sft]-[F9] removes a line
[F10] displays the following page
[Sft]-[F10] displays the previous page

[Sft]-[F7] allows to define the keys [F4], [Sft]-[F4], [F5], [Sft]-[F5] and the right mousebutton:
[Sft]-[F7] [key-to-define] [c] [o] [m] [m] [a] [n] [d] [Sft]-[F7]
By default, the right mousebutton inserts a selected block, very useful.

[Ctrl]-[Return] cuts a code line
[Ctrl]-[ClrHome] displays/hides the line-numbers
[Ctrl]-[Arrow-Up]/[Arrow-Dn] sends the cursor on previous/following page
[Ctrl]-[Sft]-[Arrow-Up]/[Arrow-Dn] sends the cursor on the first/last line
[Ctrl]-[Arrow-Lf]/[Arrow-Rg] sends the cursor on the preceding/following word
[Ctrl]-[Sft]-[Arrow-Lf]/[Arrow-Rg] sends the cursor at the beginning/end of the line

In a program ( → .fr)

STOP or [Ctrl]-[C] is written in a program to have a pause
DUMP it's then possible to display the variables and their value
DUMP V, W... ...only beginning by V, W, ...
CONT in the standard editor, will take again the program stopped by STOP or [Ctrl]-[C]
CONT TO n takes again the program to stop with line n
CONT m TO n takes again the program in m until n

REM makes it possible to write a remark, as a ' single quotation mark

END finishes the program and closes all the files

2. Variables ( → .fr)

Any string of letters (with no accent), figures or underline "_", but not starting with a figure, can be a variable, with the proviso of not being an instruction, procedure nor function.

2.1 Numerical variables ( → .fr)

Omikron processes various types of numbers. To avoid problems, it is necessary to be attentive to use the adequate variables. For example calculation: V=.1: PRINT 1/V produces the error "Division by zero" because the BASIC interprets the variable V like an integer and rounds in such a case the value to 0. To prevent this error, use a "real" variable:

V!=.1: PRINT 1/V!

V% (or V%W) is a short integer, 16 bits/2 bytes, and contains values from -32 768 to 32 767
V (or V%L) is a long integer, 32 bits/4 bytes, and contains values from -2 147 483 648 to 2 147 483 647
V! is a "single precision" real, taking 6 bytes in memory
V# is a "double precision" real, taking 10 bytes in memory

Single and double-precision "reals" have an exponent of -4,931 to 4,941, and only differ by the precision of their mantissa: 9 significant figures for the first, 19 for the second.

V%F is a Boolean variable, that is to say a bit of value of 0 or -1
V%B is a variable representing a byte, 8 bits of values, from 0 to 255
These two latest formats can only be used in arrays.

It's sometimes useful to break up a long integer into two short ones:

?HIGH($12345678) returns 4660 ($1234 converted into decimal), word of "strong weight"
?LOW($12345678) returns 22136 ($5678), word of "weak weight".

Omikron uses to convert the type of the results. For example ?LN (3) will give a "real". But it happens that it is necessary to specify the result type (attention to round-offs and capacity overflows):

V#=CDBL(value) converts into single Real
V!=CSNG(value) converts into double Real
V%=CINT(value) converts into short Integer
V=CINTL(value) converts into long integer

Type declaration ( → .fr)

It is not mandatory to declare the variables at the beginning of a program, as it is mandatory in other languages, but it is possible to declare a priori the type of the variables used.

DEFINT "Q" all variables starting with Q will be short integers, without % nor %W
DEFINTL "R" all variables starting with R will be long integers, without %L (default)
DEFSNG "C, L" C... and L... will be 'single' reals, without !
DEFDBL "D-H" D... E... F... G... and H... will be 'double' reals, without #

The DEF... must be written before any programming! If not, it is necessary to add them at the beginning of program, to save in ASCII with SAVE "NOM.BAS", A (no LIST !), then to reload the file with LOAD .

2.2 Numerical bases ( → .fr)

% (or &B ) binary with its characters 0 and 1 : %1000101
& (or &0 ) octal with its characters from 0 to 7 : &7532136
nothing (or &d ) decimal (mode by default)
$ (or &h ) hexadecimal (from 0 to 9 and A to F ): $-7f3ad5

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

&b , &o , &d and &h ensure compatibility with other BASICS.

It is possible to convert the base of an unspecified number, with the proviso of respecting the limits imposed on the long integers:

BIN$() converts into %binaire: PRINT BIN$(25) is 11001
OCT$() converts into &octal: PRINT OCT$(35) is 43
HEX$() converts into $hexadecimal: PRINT HEX$(72) is 48
VAL("") converts into decimal PRINT VAL("$7fff") is 32767

It is possible to convert binary, octal or hexadecimal numbers to decimal ones by the function VAL even if they are not integer. The reverse is not possible.

2.3 Operators ( → .fr)

LET allocate a number or a string to a variable: LET Var=43
LET Var$ A$=A$+"43" is also possible: adds the string "43" to the first.

LET is not necessary, but kept for compatibility with other basics. It's necessary to pay attention to variable type:
Var=3.14159 will only allocate 3 , because Var can only receiver an integer.

In A=B=6 , A is -1 (logical "true") if B is equal to 6 , 0 else ("false").

+ - * / as usual
\ integer division: the result is integer: ?43\5= 8
MOD modulo: the rest of a division ?43 MOD 5= 3

ABS absolue value or a real: ?ABS(-43)= 43
SGN gives the sign of a number: ?SGN(-43)= -1, ?SGN(43)= 1, ?SGN(0)= 0

Therefore, each number Nr is ABS(Nr)*SGN(Nr)

FRAC returns the decimal part of a real: ?FRAC(4.3)=.3
FIX returns the integer part of a real: ?FIX(4.3)= 4
INT rounds to the roof integer: ?INT(-4.3)= -5

= is also used as equality comparator
< strictly lesser than, <= ou=< lesser or equal
> strictly greater than, >= ou=> greater or equal

?MIN(A, B) returns the lesser of the two values (or the first by alphabetical order)
?MIN(A, B) returns the greater of the two values (or the second by alphabetical order)

2.4 Mathematical functions ( → .fr)

Trigonometry ( → .fr)

DEG degrees mode
RAD radian mode (default)

PI returns PI (double precision: 3.1415926535897932...)

Omikron knows the main trigonometrical functions (you should know them if you need them):

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

Power and logarithm ( → .fr)

^ power: 2^16= 65536
LOG(A, B) logarithm base A for the number B LOG(2, 8)= 3
SQR(n) SQuare Root of n : ?SQR(7744)= 88

EXP(n) exponentia1 (base e) of the number n
LN(n) natural logarithm (base e= 2.7182818287983537..., with n greater than 0

FACT(n) factorial of n (integer). FACT(5) gives 120 (5*4*3*2*1)

Random ( → .fr)

RND(1) returns a random value between 0 and .99999999
RND(n) returns an integer value between 0 and n-1
-RND(-n) or RND(n)+1 returns an integer value between 1 and n
RND(0) returns the last given random number

RND(6)+1 ou -RND(-6) is the same as a six-faced dice play
-RND(-6)-RND(-6) two six-faced dices play, which is not the same as -RND(-12) nor 1-RND(-11) , since the 11 results don't have the same chance to come.

XBIOS(R, 17) the R variable returns a 24 bits semi-random number

2.5 Character strings ( → .fr)

A string is composed by several characters surrounded by quotation marks. The variables which represent them and the instructions which return strings must have the suffix $ (but not LEN() nor INSTR() which return a number). As for the numerical variables, it is possible to define string-variables at the beginning of program: DEFSTR A .

A$= "Holy": B$= "Graal": ? A$ +B$ gives HolyGraal (without space)
"Ni!"*3 gives Ni!Ni!Ni! (the multiplier must be written after the string)
B$= SPACE$(n) or SPC(n) builds a string of n spaces
STRING$(3, "6") gives 666 multiplies 3 times one (only) character...
STRING$(n, asc) character is defined here by its ASCII code
LEN("Camelot") gives 7 , the number of characters of a string. Caution: a positive numerical string can have one character more, the sign "plus", even undisplayed: PRINT LEN(STR$(123)) returns 4.

LEFT$("Aaaargh", 3) give Aaa , the three characters of left
RIGHT$("Aaaargh", 4) give argh , the four characters of right-hand side
INSTR(n, A$, B$) return the position of the 1st character of the B$ string if it is found in the A$ string, while seeking starting from position n (0 if it is not there)
MID$("Camelot", 3) returns melot , all the characters starting from the 3rd letter
MID$("Camelot", 3, 4) returns melo , 4 characters starting from the 3rd letter. This function can determine them in the following way:

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

MIRROR$("Spam") returns mapS , inverts the order of the characters
LOWER$("SPAM") returns spam , transforms capital letters in small letters
UPPER$("spam") returns SPAM , transforms small ones in capital letters

2.6 Types conversions ( → .fr)

CVI("") converts a two-character string into a short integer
CVIL("") converts a four-character string into a long integer
CVS("") converts a six-character string into a single precision real
CVD("") converts a ten-character string into a double precision real
ASC("") gives the ASCII code of the 1st character of the string
VAL("") converts a number-string into its numerical value, when it is possible:

?VAL("&63") , VAL("$FF") , VAL("%1011") but not ?VAL("1A") nor ?VAL("$1g")

MKI$(V%W) converts an short integer into two character string
MKIL$(V%L) converts a long integer into four character string
MKSS(V!) converts a single precision real into six character string
MKD$(V#) converts a double precision real into ten character string
STR$(V) converts a numerical expression into a string
CHR$(n) returns one of the 256 ASCII characters, n from 0 to 255:

FOR A= 32 TO 255 ' from 0 to 31 non-printable characters, use CHR$(1)+CHR$(n)
  PRINT USING "####"; @(4+A MOD 16, 5*((A\16)-2));A;CHR$(A)
NEXT

2.7 Arrays and matrices ( → .fr)

DIM T#(11) dimensions an array of 12 double-precision real (t#(0) is the first element). Without DIM dimensions is by default 10*10
DIM Goban%B(18, 18) contains the 19*19 intersections of a Go-ban

Aum%(3, 4)=29 indicates that the element 4th line/5th column array is 29
MAT CLEAR Chess%B(7, 7) erases the mentioned array
MAT CLEAR T(n) erases an array of numbers to a dimension until T(n)

SWAP V$, W$ exchanges the standard contents of 2 variables in the same way
SORT T$(0) sorts all the types of arrays to a dimension
SORT ASC A$(0) sorts an array of strings according to the ASCII code
SORT T(0) TO V(0) sorts the array V(0) according to the order of the array T(0)

Matrices ( → .fr)

Matrices are two-dimension real-arrays:

MAT A#(l, c)*n multiplies each element of the matrix by N
MAT A!(m, n)=B!(m, p)*C!(p, n) multiplies two matrices. The number of columns of the 1st matrix must be the same as the number of lines of the 2nd one

For square matrices only:

MAT A#(n, n)=INV B#(n, n) inverts a square matrix (columns become lines, lines become columns)
MAT A#(n, n)=1 makes it possible to generate a unit-matrix
X!=DET(A!(n, n)) returns the matrix determinant

2.8 Logical operators ( → .fr)

The logical operations concern the bits: numbers are written in binary.

NOT reverses the contents of the bits:

NOT %10=...11111111101= -3

(a number is negative if the more significant bit is 1)

AND selects the common '1' bits of two numbers:

%1100 AND %1010 are %1000

OR accepts that a bit is positioned for one or the other number:

%1100 OR %1010 is %1110

XOR excludes the common bits from two numbers:

%1100 XOR %1010 are %0110

NAND excludes the simultaneous veracity from the bits of two binary:

%1100 NAND %1010 are -9 (or NOT %1000, is NOT AND)

NOR the non-veracity of the bits checks two binary:

%1100 NOR %1010 is -15 (or NOT %1110, is NOT OR)

EQV admits the veracity or the non-veracity of the bits of 2 binary:

%1100 EQV %1010 are -7 (or NOT %110, is NOT(A XOR B)

IMP is the logical implication: A implies B means that A cannot be true when B is not. A IMP B is equivalent to NOT(A AND NOT(B)) :

%... 001100 IMP %...001010 is -5 (or NOT %...00100, is %...11011)
 With   B   NOT(B)   With 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

BIT(n, A) returns value 0/-1 of bit n of A: ?BIT(3, %11001)= -1 (bit 0 is the first from right)

SHR(n) (Right Shift): shifts the bits of a number n times towards the right, which is equivalent to n divisions by 2.

SHL(n) (Shift Left): shifts the bits of a number n times towards the left, which is equivalent to n multiplication by 2.

3. Structures ( → .fr)

3.1 Conditions ( → .fr)

IF condition THEN commands ELSE commands : ENDIF

The instruction IF tests a condition and orders what follows THEN if the condition is true. ELSE (optional) permits what follows it in the event of condition not met. ENDIF is mandatory if a sequence IF/THEN/ELSE is written on several lines or if THEN is followed by a ": ". Two or more conditions can be imbricated.

10 N= -RND(-100): B=1
100 REPEAT
110   INPUT "a number from 1 to 100: "; A
120   IF A=N THEN PRINT "Found in"; B;" time ": END
130   IF A < N THEN
140     PRINT "A little more..."
150    ELSE
160     PRINT "A little less..."
170   ENDIF
180   B=B+1
190 UNTIL 0 ' 0 is logic 'false': condition never true

3.2 Loops ( → .fr)

The loops are portions of code which allow a repetitive work.

FOR V= n TO m (STEP p): commands : NEXT V ( → .fr)

V varies from n to m with each reiteration. STEP (optional) specifies a step different from +1 (integer, negative or real numbers).

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

REPEAT commands UNTIL condition ( → .fr)

The program repeats the instructions which follow REPEAT until the condition written after UNTIL is met.

REPEAT
  PRINT @(RND(24), RND(79));"*"
UNTIL MOUSEBUT= 2

WHILE condition: commands WEND ( → .fr)

WHILE tests a condition before penetrating in the loop defined until WEND . For an infinite loop: WHILE -1 ('always true')

WHILE MOUSEBUT < 2 ' right button to leave the loop
  DRAW 320, 200 TO MOUSEX, MOUSEY
WEND

EXIT ( → .fr)

Leaves, closes and jumps at the end of a loop although the 'while' or 'until' condition is not true.

WHILE -1
  instructions
  IF condition THEN EXIT
WEND

EXIT TO -Lbl leaves, closes and jumps at the label Lbl (compound of EXIT and GOTO .

3.3 Procedures ( → .fr)

The procedures are subroutines, callable directly by their name. One can define local variables by LOCAL V$=, W$= which will not interfere with the aggregate variables of the same name, which makes it possible to call programs with CHAIN MERGE without being concerned with possible homonymies of the variables.

A procedure can call another of them. In order to avoid the error "Direct Illegal", the procedures are defined after END .

10 INPUT "Radius and Height: "; R!, H!: Cone ' call of procedure
20 PRINT "the volume of the cone is: "; V!
30 END
1000 DEF PROC Cone
1010 V!= R!^2 * PI * H!/3
1020 RETURN

A procedure can return parameters:

10 INPUT "A!, B!"; A!, B! : Rapport(A, B) ' call of procedure
20 PRINT A!, B!
30 END
1000 DEF PROC Rapport(R X!, R Y!) ' R for Return
1010   X!= X!/Y!: Y!= 1/X!
1020 RETURN

3.4 User-function ( → .fr)

The functions are defined according to the principle of the procedures, but returns one (and only one) value, specified after RETURN . They are called by FN Nom$ . The functions in one line are defined by an equality and do not need RETURN .

10 PRINT FN Hasard
20 END
100 DEF FN Hasard= -RND(-6) -RND(-6) ' different from -RND(-12)

Another example, returning a string:

10 A$= "Black night": PRINT FN Inverse$
20 END
100 DEF FN Inverse$ ' $ since it returns a string
110 A$= CHR$(27)+ "p"+ A$+ CHR$(27)+ "q"
120 RETURN A$

A very traditional example, where the function uses recursivity:

10 TRON: INPUT "X: "; X ' for X not too large
20 PRINT FN Factor(X): TROFF
30 END
100 DEF FN Factor(X)
110 IF X=0 THEN RETURN
120 RETURN X * FN
Factorielle(X-1)

The function calls upon itself as long as the decrementation of X does not reach 0

3.5 Data exploitation ( → .fr)

DATA expresses data (expressions, variables, arrays)
READ V$, W$ reads one or more data in the line of 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 replaces the pointer on the 1st line of DATA
RESTORE 1000 or RESTORE Etiqu after the line 1000 or -Etiqu

ON n RESTORE Et1, Et2... sends the pointer on DATA according to the label chosen according to n

10 INPUT "Spanish=1, English=2, Dutch=3:"; Language
20 INPUT "Which figure? "; C
30 ON Language RESTORE Cifras, Digits, Cijfers ' choose the line
40 FOR I= 0 TO C: READ Word$: NEXT I' chooses the data
50 PRINT "the figure"; C; " is "; Word$: 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 Connections ( → .fr)

GOTO 300 have the program jumped to line 300
GOTO Aum goes directly to the label -Aum . A label is preceded by an hyphen
GOTO 500+n operations are possible
GOTO (V) or (V$) a variable can contain a number or a label
ON n GOTO n1, n2... for n from 1 to X, the program will jump to the line n1, n2... or nx

RENUM respects the connections, the desactivation of the number of lines in the super-editor not: use labels. For a better legibility of the program, do use loops and EXIT TO to leave there, which gives the meter of the loop to 0.

3.7 Routines ( → .fr)

GOSUB Aum sends to a subroutine, with the label -Aum
ON n GOSUB n1, n2, chooses the subroutine according to n
RETURN returns to the instruction according to the appealing GOSUB

The subroutines (or routines) are written at the end of the program after END so that the program does not meet RETURN without to be sent to the subroutine by GOSUB .

In a general way, one will prefer procedures and functions.

Conditional subroutines ( → .fr)

These four comands are to be written out in the beginning of the program.

ON TIMER n GOSUB Etiq reacts every n seconds
ON MOUSEBUT GOSUB Etiq reacts if a mouse button is clicked
ON HELP GOSUB Etiq reacts if the [Help]-key is clicked
ON KEY GOSUB Etiq reacts is any key is typed

This last command keeps the key in the buffer: you must clear it with V$=INKEY$ or V$=INPUT$(1) in the subroutine in order to avoid a recursive call.

To set off a conditional subroutine: ON < > GOSUB 0

See also ON TRON GOSUB et ON ERROR GOTO at Error processing.

4. Devices ( → .fr)

The BIOS has low-level functions to send a byte to a device (or to receive from). You normally should/would never use it, but who knows? For P: 0=parallel-port printer, 1=Serial port RS232, 2=console (screen), 3=MIDI, 4=keyboard-processor:

BIOS(R, 1, P) returns -1 if the device (1-2-3) has got a byte to send
BIOS(R, 2, P) reads a byte from the device (0-1-2-3)
BIOS(R, 8, P) returns -1 if the device (0-1-3-4) can receive a byte
BIOS(, 3, P, n) sends a byte to the device (0-1-2-3-4)

4.1 Screens ( → .fr)

Omikron 3.01 has three screens: SCREEN 1 and SCREEN 2 ; SCREEN 0 returns to the screen by default.

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

Note: for TOS <1.6, a screen address must be a multiple of 256 (i.e. must end with 00 in hexadecimal). To adjust a screen address, you have to prepare a little greater memory amount, shorten the address by AND $FFFF00 and add 256 bytes in order not to spoil the datas staying before the new address.

Only with screen 0 (by default)

PRINT CHR$(1) helps to type [Ctrl]-[A] [Ctrl]-[Lettre] or ?CHR$(1)+CHR$(1 to 31)
PRINT CHR$(2) inserts a character into the place of the cursor
PRINT CHR$(3) erases one of them (= [Ctrl]-[C] if IPL 3 + (1 SHL 31) )

Only with screen 1 and 2

? CHR$(27);"w" cancels the automatic follow-up
? CHR$(27);"v" automatic follow-up at the end of the line

With the three screens

PRINT CHR$(4) the position of the cursor defines the top-left corner
PRINT CHR$(5) the position of the cursor defines the bottom-right corner
[ClrH] [ClrH] back to the normal
PRINT CHR$(7) gives a 'shping!'
PRINT CHR$(8) moves the cursor on the left while erasing (= [BackSp])
PRINT CHR$(9) the position of the cursor to the following tabulation (every 8 columns)
PRINT CHR$(10) moves the cursor a line lower (= CHR$(11) and CHR$(12))
PRINT CHR$(13) moves the cursor at the beginning of line, but [Ctrl]-[M]=[Enter]

GEMDOS(R, 16) R=$FFFF if the screen is ready to display, otherwise R=0

XBIOS(R, 2) returns the screen physical address (which is displayed)
XBIOS(R, 3) returns the screen logical address (where you print your graphical functions)
XBIOS(Rez, 4) Rez= 0 for low; 1 for medium; 2 for high resolution
XBIOS(, 5, L Log, L Ph, Rez) sets theses 3 parameters (-1 for unchanged). For the TOS < 1.60, the screen address is to be a multiple of 256:

Addr=(MEMORY(32256) AND $FFFF00)+256

XBIOS 5 is used to manage different screens at the same time, e.g. displaying the physical screen while using graphical functions on the logical one, giving more comfort to the eyes.

Addr1=( MEMORY(32256) AND $FFFF00)+256 ' useful to adjust the screen memory to $xxxx00
Addr2=( MEMORY(32256) AND $FFFF00)+256
PRINT CHR$(27)+"f" ' text cursor off (default is ON in Omikron 3.01)
WHILE MOUSEBUT <2 ' right button to end
  XBIOS (,5,L Addr1,L Addr2,-1) ' display on Addr2, work on Addr1
  FILL STYLE =2, RND(24) ' random filling mode
  PBOX RND(10)*50, RND(10)*30,50,50 ' filled square at random place on screen
  WHILE MOUSEBUT >0: WEND ' waiting for no clic
  WHILE MOUSEBUT =0: WEND ' waiting for a left or right clic
  XBIOS (,5,L Addr2,L Addr1,-1) ' display on Addr1, work on Addr2
  FILL STYLE =2, RND(24)
  PCIRCLE 40+ RND(10)*55,40+ RND(10)*30,35 ' filled circle at random place on screen
  WHILE MOUSEBUT >0: WEND
  WHILE MOUSEBUT =0: WEND ' waiting for a clic, right one to exit the main loop
WEND

XBIOS(R, 7, c, n) sets the colour c, n from $000 to $777; reads if n=-1. See PALETTE for the 16 color levels (STE).

4.2 Console out ( → .fr)

CLS CLear the Screen and place the text-cursor top-left
PRINT @(line, column); place the text-cursor at a precise place

?CSRLIN gives the number of line of the cursor (from 1 to 25!)
?POS(0) the number of column of the cursor gives, (0) obligatory
LOCATE line, column place the cursor at a precise place (line from 1 to 25)

PRINT CHR$(27)+"f" hides the text cursor
PRINT CHR$(27)+"e" shows the text cursor

PRINT "the square of A is:"; A^2 displays a text and a result
PRINT COS(PI/4) displays the result of the function cosine
PRINT "COS(PI/4)" displays COS(PI/4) (without the quotation marks)
WRITE "Text" displays "TEXT" (preserves the quotation marks)
PRINT 3*5;"H"*2 displays 15HH without separation (semicolon)
PRINT COS(0), "*" displays 1, * separated by a tabulation (since comma)
PRINT A$;:PRINT B$ ";" force the displaying of B$ following A$
PRINT CHR$(34);"3";chr$(34) displays "3" , CHR$(34) coding the quotation mark
PRINT SPC(n);"&" displays n spaces before & (see Strings)
PRINT TAB(c);V$ displays with the column defined by
PRINT @(l, c);V$ displays with the line and the column indicated
PRINT @(l, c);V$; to finish by a semicolon makes it possible to avoid the alinea

10 CLS: DEG ' programs including @(l, c) in a string
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) displays characters from 32 to 255
PRINT CHR$(1)+CHR$(n) displays characters from 1 to 31

Atari ASCII Table

The address $484 keeps a byte which bits represents: 3°: [Ctrl] and [Alt] - 2°: "Ping" - 1°: repetition - 0°: "Tik"
POKE $484, %1010 unsets key-"tik" and error-"ping" (bit 0 is the right one)
XBIOS(R, 16, L Addr1, L Addr2, L Addr3) sets the 3 character-tables for the keyboard, three 128-bytes strings following the Scancode. Addr1 pour unshifted keys, Addr2 for the shifted ones, Addr3 with CapsLock, -1 for no change
XBIOS(, 24) undoes all XBIOS 16 modifications (standard keyboard)
XBIOS(, 25, n-1, L Addr) sends a command to the keyboard-processor.

PRINT ... USING ( → .fr)

USING format decimal displaying for instruction PRINT

USING "####" next PRINTs will display a 4 character integer. Prints % if the integer is larger
USING "####.##" displays two digits after the decimal point
USING ", ####.###" the comma separates the thousands
USING ".#####, ####" commas and points are inverted
USING "+#####.####" displays the sign (even '+')
USING "####, ###+" '+' or '-' will be displayed after the number
USING "####, ###-" only '-' will be displayed after the number
USING "# # #. # #" separates the characters as indicated
USING "*$#######, ##" what follows * will fill blank characters
USING "##_+.##" forces displaying of what follows the _
USING "###^^^^" leaves 4 places for the scientific notation

PRINT USING "# # #, ###", V! formats only display of this PRINT
USING "##, ##" formats any displaying with PRINT , STR$ and PRINT #
USING without argument cancels any USING "####"

Example:

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

4.3 Console in ( → .fr)

When the program arrives at a intruction INPUT type, it prints the text written between quotation marks (or a question mark by default of text) and waits for a data:

INPUT A prints a question tag and waits for a number (and [Enter])
INPUT "A:"; A prints A: , the seizure of a long integer waits
INPUT Nom$ $ to enter a character string
INPUT @(l, c);"Texte: ";V$ displays the text at the place indicated
INPUT A, B, C 3 integers to enter, separated by commas
LINE A$ INPUT makes it possible to enter one (only) string with commas
A$= INPUT$(n) awaits n characters and [Return] before continuing

INKEY$ returns a string of 4 characters:

the 4th contains the ASCII code
the 3rd is empty
the 2nd contains Scancode (code of the key)
the 1st contains five bits: bit 0 is on: [Shift-Right] is pressed
bit 1 is on: [Shift-Left] is pressed
bit 2 is on: [Ctrl] is pressed
bit 3 is on: [Alt] is pressed
bit 4 is on: [CapsLock] is pressed

This instruction does not wait, it must be put in loop:

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$)))

Atari ST key-codes

XBIOS(R, 35, D, V) sets the time before repetition et repetition speed of a maintained key (expressed in 1/50 sec). If D and V=-1 , R returns 1 byte for D and one for V

INPUT ... USING ... ( → .fr)

INPUT @(l, c);"Text"; V$ USING "Command", R, N, asc, P

"Command" allows or prohibits some characters:
    0 allow all digits
   A allows all letters, accentuated or not
   % allows the special characters (%, !, ?, &, @...)
   ^ allows them [Ctrl]-[Key]
   U (Upper) displays in capital letter, L (Lower) into small one
   + the character authorizes which follows (space, for example)
   - prohibited the character which follows
   C&% replace the first sign by the second (& by %)
   < the left arrows has the [Return] effect
   > the right arrows has the [Return] effect
   ax_ " the specified character _ has the [Return] effect
   +"x"+CHR$(A) or by its ASCII code
   +"s"+CHR$(S) or by the key which Scanscode is defined

R returns CVIL(INKEY$) of the key which allowed the seizure, or
   0 for [Enter],
  -1 for > (going beyond by the line)
  -2 for < (left by the left)

N is the length of the string to enter (255 max and per default)
asc is the ASCII code of the filling character ("_" by default)
P is the Position of the cursor on the string at the exit

The example

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

allows figures and comma, changes the point into comma, and allows [Esc]-key (scancode 1). Fields length is up to 10 characters ("_", by default).

4.4 Other devices ( → .fr)

Printer ( → .fr)

LPRINT prints a string on the parallel printer ([Alt]-[L])
LLIST list the BASIC program on the parallel printer
LDUMP prints all variables ont the printer
MODE LPRINT "F" sets accent-mode for a daisy-printer
LPOS(0) character-mode: gives the position of the printer-head

HCOPY prints the screen
HCOPY TEXT prints the screen, without any graphism

LPRINT "" sends a string to parallel port, generally to the printer

GEMDOS(R, 17) R=0 if the printer is not readyr
GEMDOS(, 5, n) sends a byte to the parallel port
XBIOS(, 33, F) F sets the printer category (twenty years ago!):

bit543210
=0:listingparalldraftAtaricolourmatricial
=1:sheetserialcourrierEpsonmonochrdaisy

Serial port RS232 ( → .fr)

GEMDOS(R, 18) R=0 if the serial ports doesn't have a byte to deliver
GEMDOS(R, 3) reads a byte form the serial port RS232
GEMDOS(R, 19) R=0 if the RS232 is not ready
GEMDOS(R, 4) sends a character to the serial port RS232
XBIOS(, 15, Baud, Mod, Ucr, Rsr, Tsr, Scr) sets the parameters of the serial port RS232:
Baud: 0 to 15 transfert-rates 19200-9600-4800-3600-2400-2000-1800-1200-600-300-200-150-134-110-75-50
Mod: 0: no handshake; 1: XON/XOFF; 2: RTS/CTS; 3=1+2
Ucr: bit 1= 0/1 odd/even; bit 2= 0/1 non parity/parity
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: if synchr: 1/0 divides the frequency, or not
Rsr: bit 0=1 active reception; bit 1=1 to receive
Tsr: bit 0=1 active emission; bit 1=1 to emit
Scr contains the synchronisation byte
-1 let a parameter unchanged

MIDI Port ( → .fr)

XBIOS R, 12, n, L Addr sends n (short integer) bytes at Addr to the MIDI-processor

Addr= MEMORY(20)
FOR I= 0 TO 19: READ Byt: POKE Addr+I, Byt: NEXT
XBIOS , 12, n, L Addr
DATA
  ...20 bytes, comma-separated

4.5 Sound Yamaha 2149 and MIDI ( → .fr)

Three square wave, an envelop generator and filtered noise. This page for a french guide on the Yamaha 2149 chip.

PRINT CHR$(7) gives a 'beep' corresponding to TUNE 1, 52
TUNE 1, n, 2, m, 3, p defines a height of sound for at least a way (3 maximum), which goes from treble (1) to most bass (4095). 440= 125000/440=282
TUNE 1, 0, 2, 0, 3, 0 extinct all
VOLUME W, n sets a continuous sound, volume 0 to 15 for each Way
VOLUME v, e, d defines the type of envelope and its duration (only one type of envelope for the 3 ways). The 2 syntaxes of VOLUME are excluded for the same way.

d= 7860  gives an approximate duration of 1 second
e= 9 and 0, 1, 2, 3 
15 and 4, 5, 6, 7 

12 
14 
10 
13 
11 
are of piano type: peak then descent
are opposite: rises then collapse
is a repeated "piano" (9+9+9+...)
is a repeated "opposite" (15+15+15+...)
is a mountain: rises then descent
is a piano plus a mountain (0+14)
is a rise without descent
is a piano then a maintained sound

NOISE m, f the ways concerned with the noise (V1=1, V2=2, V3=4) are added to define the mask (from 1 to 7), f chooses a frequency filter
NOISE 0, 0 cancels.

5 Storage ( → .fr)

5.1 File system ( → .fr)

* replaces name or an extension, ? a letter:
"A*.*" relates to all the files starting with an A
"*.PI?" relates to any file "*.PI1", "*.PI3", "*.PIC", aso.

FILES "A:\*.*" display the contents of the disc of the specified way
FILES "A:\DIRECTO\*.BAS" displays every *.BAS file of the directory DIRECTO of "A:"

Copy "A:\file" TO "C:\director \" copy a file of A: on C:
NAME "name.ext" AS "other.ext" rename a file
BACKUP "NAME" backup copy *.BAK of the preceding version

KILL "A:\director\filename" removes the file (according to the specified way)
KILL "A:\director\*.*" removes all the files of the aforesaid directory

MKDIR "A:\director" creates a directory on the specified reader
RMDIR "C:\director" erases a directory, but only if it is empty

CHDIR "director" enters the file doss
CHDIR "C:\director" or CHDIR "a:\" defines the active access path
CHDIR ".." leaves a under-directory and goes up towards the parent one

BIOS(R, 9, Lect) floppy change? 0: no; 1: maybe; 2: yes
BIOS(R, 1O) connected disks: bit 0=A:, 1=B:, 2=C:, as LPEEK($4C2)

GEMDOS(R, 14, Lect) sets the default disk (0=A:, 1=B:, 2=C:...)
GEMDOS(R, 25) returns the default disk (GEMDOS 14 format)
GEMDOS(R, 59, L Path) sets the default path, from a string null-terminated at address Path .

5.2 SAVE and LOAD ( → .fr)

SAVE "*.*" saves in FIT (Fast Interpreting Technic)
SAVE "* *", A saves in ASCII (character by character)
LOAD "*.*" charges a file saved in FIT or ASCII
LOAD "A:\SOME\*.*" specifies the way of the required file
RUN "*.*" charges and carries out the specified program

MERGE "Name" adds an ASCII program without crushing the precedent except if the numbers of lines are the same ones
CHAIN "Nom", n chains a program, and erases the precedent
CHAIN MERGE "Nom", n chains a program, without crushing the precedent, n to specify the beginning of it
COMMON V$, W$... to preserve the variables of a chained program. The instruction must be on the first line of each program concerned

LIBRARY GEM, "A:\GEM\GEM.LIB" charges library GEM

BSAVE "Name" saves the complete screen (bit by bit) on floppy
BSAVE "Name", Addr, n save the number of bytes starting from the Address

BLOAD "Name" loads a file on the screen (eg: image in BITMAP)
BLOAD "Name", Addr loads a file in memory with the Addr indicated

5.3 Sequential files ( → .fr)

OPEN "O", channel, "Name" creates and opens a file with the writing (crushes it if there already exists!) and allots to him a channel from 1 to 16
PRINT #channel, A$, B$ writes data on the specified channel
WRITE #channel, A$, "Aum" allows the writing with quotation marks and commas
CLOSE channel writes the data on the diskette and closes the channel

OPEN "A", 5, "Nom.Ext" open an existing file to add data to it

OPEN "I", 16, "Name" opens a file only with the purpose of reading
INPUT #16, V$, W$ reads one or more data (separated by commas)
LINE INPUT #16, V$ load a text containing commas

A$=INPUT$(n, channel) reads n characters on the specified channel
?EOF(channel) returns -1 when the specified file was completely read
?LOF(channel) returns the number of bytes of the file open on the specified channel, including the byte of end of file

Other sequential files ( → .fr)

OPEN "K", channel sends commands to the processor-keyboard (keyboard)
OPEN "P", channel printer (printer)
OPEN "V", channel Modem
OPEN "M", channel MIDI port
OPEN "C", channel screen (console).

CMD canal redirects output-instructions to an open sequential file. Can be useful during a program development:

OPEN "O", 1, "liste.txt"
CMD 1
PRINT "My program in ascii" ' normally to the screen
LLIST ' but also to the printer
CLOSE

5.4 Random files ( → .fr)

OPEN "R", channel, "FILENAME", l open a random file of total field of size L
FIELD channel, long1 AS V$, long2 AS W$ determine the field (the length) of each Variable-buffer. A field can be not allotted.

PUT channel, n write in recording n channel the data of FIELD
GET channel, n reads recording n and sends it on the FIELD
GET channel, 0 ... gives the n° file following that which was read
SEEK channel, n, mode move the pointer of n recordings (mode=0: starting from the beginning of the file; 1: displacement starting from the current recording; 2: starting from the end)

LSET V$="Ugh" formate the string for the variable-plug by the left (excess on the right is cut off, the default is filled)
RSET W$= B$ formates B$ for W$ in the same way

?LOF(channel) gives the number of recordings of the relative file
?LOC(channel) returns the pointer of the last recording read or written

CLOSED channel writes the changes on the disc

Other random files

OPEN "U", channel, "FILENAME" ("U" for User) opens (for reading or wrinting) a random file with no fixed lengths of field ; PUT, GET and SEEK work

OPEN "F", channel, "C:\atari\*.*", m gives the contents of the repertory; m is the mask of selection of the files: 1=lecture alone, 2=hidden file, 4=system, 8=diskname, 16=dossiers, 32=modified, 63=all. Here an example of use (note that the first 14 bytes of the FIELDS are not used):

OPEN "F", 3, "C:\*.*", 63 # one open on the channel 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) R returns the Disk Transfert Address (OPEN "F")
GEMDOS(, 26, L Buffer) write a DTA data (44 octets):
  byte 21: file attribute
  bytes 22-23: file creation time
  bytes 24-25: file creation date
  bytes 26-29: file length
  bytes 30-43: file name and extension

5.5 Disks ( → .fr)

All that follows is floppy-oriented, but you could adapt it to harddisks.

GEMDOS(R, 54, L Buffer, Lect) R returns 4 long integers on the disk at Buffer address:
  1°: number of data clusters
  2°: number of free clusters
  3°: disk: 0= default, 1=A:, 2=B:, 3=C:, nbr of byte per sector
  4°: number of sectors per cluster

BIOS(R, 7, Lect) R returns an address of 13 short integers:
  1°: byte amount per secteur (512)
  2°: sector amount per cluster (2)
  3°: byte amount per cluster (1024)
  4°: sector amount for directory
  5°: sector number of the File Allocation Table
  6°: sector number of the second FAT
  7°: 1° data cluster number
  8°: data cluster amount
  9°: empty or flags?
 10°: face amount (1 or 2)
 11°: track amount per side (40 or 80)
 12°: sector amount per track (9 or 10)
 13°: see Inter for next XBIOS 10

BIOS(R, 4, F, L Addr, N, Start, Disk) reads or writes N sectors at Address from Start
  F =0 or 2 to read, 1 or 3 to write, 2 and 3 ignore disk changes
XBIOS(R, 8, L Addr, 0, 0, Disk, Sect, Track, Side, N) reads N sectors
  Addr=MEMORY(512) for 1 sector
  Disk = 0, 1, 2, for A:, B:, C:,
  Sect from 1 to 9 or 10 following formating
  Track from 0 to 79
  Side 0 or 1 for doub1e sided floppies, 0 only for one-sided floppies
XBIOS(R, 9, L Addr, 0, 0, Disk, Sect, Track, Side, N) writes N sectors
XBIOS(R, 19, L Addr, 0, 0, Disk, Sect, Track, Side, N) verifies N sectors
XBIOS(R, 10, L Addr, 0, 0, Disk, Sect, Track, Side, Inter, L 987654321, Oct) formats a track, same as above, excepted:
  Addr= MEMORY(9216) or MEMORY(10240) for 9 or 10 sectors per side
  Sect 9 or 10
  Inter 1 (123456789 order for sectors) or 2 (135792468 order)
  Byte written byte value, often $E5 (avoid $F0 and $F5)
  R returns 0 or an error number (see then Addr)

XBIOS(R, 18, L Addr, L Serie, Type, Exec) writes a boot-sector
  Serie is a 24 bits serial number
  Type : 0: 1 side of 40 tracks - 1: 2 sides of 40 pistes - 2: 1 side of 8O tracks - 3: 2 sides of 80 tracks
  Exec : 0: non-executable boot-sector, 1; executab1e
  -1 leaves unchanged parameter for each sector

6. Graphics ( → .fr)

New unit: pixel (picture element), a dot on the screen. The ST (TT and Falcon have more screen dimensions), there are 640*400 pixe1s in high resolution, 640*200 in medium and 320*200 in low resolution. (0, 0) is the upper-left pixel: the first number is the distance from the left and the second one the distance form the top (negative height). You always shoud set off the mouse (MOUSEOFF) before any graphical display.

CLIP x, y TO u, v ou CLIP x, y, l, h nothing can be displayed outside this rectangle
CLIP alone to cancel a previous one
CLIP 0, 0, 320, 200 sets the exact limits to low resolution, very safe, not to invade and spoil the RAM (screen is a part of the common RAM: a bit 'set' is black)

There are four superposition modes of graphical display:

MODE=1 replace (black and white cover a former drawing; by default)
MODE=2 transparent (white does not cover, as OR)
MODE=3 exclusif (black on black gives white; as XOR)
MODE=4 transparent inverse

WVBL waits for the new screen wave, for a more stable display

NDC x, y, l, h towards virtual coordonnates. Every display will be reduced to a rectangle defined by the coordinate. 0, 0 is the left bottom of this rectagle and 32767, 32767 the right top of the rectangle
NDC back to the normal mode.

6.1 Mouse and joystick ( → .fr)

MOUSEON sets the mouse cursor (before displaying a dialog box)
MOUSEOFF hides the mouse cursor (before graphic display)

Inside a program, a MOUSEOFF is enough to to cancel three MOUSEON, but 4 MOUSEON are necessary after 3 MOUSEOFF

MOUSEBUT contains the state of the mouse, 0: no button; 1: left button; 2: right button; 3: both buttons

WHILE MOUSEBUT <2: WEND ' awaits right-button click

MOUSEX horizontal position of the mouse in pixels
MOUSEY vertical (negative) position of the mouse in pixels

JOYSTICK(n) returns the state of JOYSTICK (N= 0 or 1):

10 Addr= MEMORY(CHR$(20)): XBIOS(, 25, 0, L AD) ' XBIOS 25 allows to potentiate
20 WHILE -1: PRINT BIN$(JOYSTICK(0)): WEND    ' the button of shooting
30 Addr= MEMORY(CHR$(8)): XBIOS(, 25, 0, L AD)  ' [Ctrl]-[C] to stop

6.2 Alert boxes and File selector ( → .fr)

FORM_ALERT(Df, "[S][Te|xt] [Button1 | Button2 | Button3] ", R)

FILESELECT (Chemin$, Nom$, R) calls a selection-box. R returns 0 for [cancel] or 1 for [Confirm]

Example:

Addr=MEMORY(13200): BITBLT 157, 54, 328, 312 TO Addr ' saves the part of screen in high resolution
MOUSEON
Path$="A:\*.*" ' no literal string, which is dedicated to change!
FILESELECT (Path$, File$, R)
MOUSEOFF
BITBLT Addr TO 157, 54, 328, 312 ' reinstalls the Addr block
FRE(Addr) ' frees memory
PRINT File$, R

6.3 Graphical text ( → .fr)

TEXT allows specialized style: height, direction and color, with a more precise co-ordinate than PRINT@(l, c) :

TEXT x, y, V$ displays a text at the point x, y (expressed in pixels)
TEXT x, y, "Texte", L, m, c L defines the length reserved in the text
m=1 and c=0: the words remain compact
m=0 and c=1, all the characters are spaced

The three functions which follow are valid until a new specification (to restore before finishing a program)

TEXT STYLE=n sets a style for a TEXT (to cancel: TEXT STYLE=0 )
1: bold - 2: grayed - 4: italic - 8: underlined - 16: outlined
The styles are combined by addition of the parameters: 13 gives an underlined, ialic and bold text (8+4+1)

TEXT HEIGHT=n sets the height in pixel of the displayed TEXT
1 to 3: completely unreadable text
4: just readable and well proportioned
6: same width as the standard, middle height
9: pretty intermediary
12: same height as the standard, double width
13: standard body (back to the normal)
26: double width, double height: maximal size

The intermediate heights are possible, but not all pretty. On medium and low resolutions, the standard body is 6

TEXT ROTATION= 900 from bottom to top
TEXT ROTATION= 1800 upside down
TEXT ROTATION= 2700 from top to bottom
TEXT ROTATION= 0 back to the normal (by default)

6.4 Dots and lines ( → .fr)

DRAW x, y displays a pixel at the definite point ((0, 0) is upper-left)
DRAW x, y TO u, v [TO...] draws a line from x, y to u, v [to...]
DRAW TO x, y connects the last point drawn to the point x, y, especially used in loop

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!)) ' do test DRAW without TO
NEXT

LINE WIDTH=n (odd, up to 39) sets the line width
LINE STYLE=n sets the line style:
0 white (MODE=1) or invisible (MODE=3)
1 **************** full
2 ************   long dash
3 **    **     dotted
4 ******** **    dash and dot
5 ********     discontinuous
6 ***** **  *    composite
7 user-defined with LINE PATTERN

LINE PATTERN=n where n is an short integer (16 bits), expressed into binary %0110110100101111 (one digit is one pixel), or into hexadecimal: $6D2F, where each character represents 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 Geometrical figures ( → .fr)

BOX x, y TO U, V defines a rectangle according to two opposite corners
BOX x, y, w, h defines a rectangle a according to the left higher top and dimensions
RBOX x, y TO u, v defines a rectangle with rounded corners

CIRCLE x, y, r defines a circle of centre (x, y) and r
CIRCLE x, y, r, D, A defines an arc of circle whose D is the starting angle and A is the angle of arrival (in 1/10 of degrees)

ELLIPSE x, y, r1, r2 defines an ellipse: r1= horizontal radius, r2= vertical radius
ELLIPSE x, y, r1, r2, D, A defines an arc of ellipse (see CIRCLE)

POLYGON T(0, 2*n+2) defines a polygon up to 63 sides. A dodecagon needs an array with 1*26 elements: 2*sides +2 (for the repeated coordonate)

CLIP 0, 0, 640, 400: CLS: DIM P%(0, 26)
MOUSEON
FOR I=0 TO 11
  WHILE MOUSEBUT=0: WEND ' waits for a mousebutton click
  P%(0, I*2)= MOUSEX: P%(0, I*2+1)= MOUSEY
  WHILE MOUSEBUT >< 0: WEND ' awaits a relaxing a mouse button
NEXT
P%(0, 24)=P%(0, 0): P%(0, 25)=P%(0, 1) ' repeats the 1st coordonates
MOUSEOFF: POLYGON P%(0, 26) ' call of the polygon

6.6 Fillings ( → .fr)

PBOX, PRBOX, PCIRCLE, PELLIPSE, PPOLYGON accept a filling.

OUTLINE OFF omits the border of the filled figures
OUTLINE ON cancels the former instruction

FILL STYLE= 0, 1   white
1, 1   black (default)
2, 1 to 2, 24   24 built-in drawings, see below
3, 1 to 3, 12   24 built-in lines, see below
4, 1   ATARI logo, or to define with FILL PATTERN

FILL STYLE built-in patterns
Note: In TOSes 1.xx, FILL STYLE 3, 12 is equivalent to 3, 6

FILL X, Y, -1 fills a surface containing the point (x, y). Surface must be delimited

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

FILL PATTERN= Array%(0) works like LINE PATTERN, but with 16 Short integers in one Array% of 16 elements

To determine the numbers to enter in the array, draw a "checkerwork" of 16*16. Each line will be a binary number, ('1' for black, '0' for white) converted into hexadecimal (see LINE PATTERN in 6.4) is an element of the array. Do use LOW if the number exceeds $7FFF: LOW($FFFF) returns -1, the right way to draw a full line.

6.7 BITBLT, Bit-Block-Transfer ( → .fr)

BITBLT x, y, l, h TO u, v, m, n copies a part of the screen defined by x, y, w, h to u, v
BITBLT x, y, w, h TO Addr saves in memory a part of the screen
BITBLT Addr TO x, y, l, h, mode displays the part of screen memorized, mode is the mode of which it is printed (3 covers: mode by default)

The 15 other modes are, for S=Source and C=Cible:

0= white
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= black

Example:

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

Determination of the memory to be reserved: The BITBLT includes in memory a short integer (whose values are: 2 for the high resolution, 4 for the middle one and 8 for the low one), a short integer the width of the image, a third one for its height. For the high resolution, there is always an even number of bytes for a line: for an image of X pixels-width and Y pixels-height, you will need 6 + ((X-1)\16 +1) *2 *Y bytes.

6.8 Sprites ( → .fr)

A sprite is a small drawing very easy to handle (the bee, the arrow...). There are in Omikron small and large sprites for each resolution. It is necessary to reserve memory for the hidden part of the screen and the drawing itself. The drawing is written line by line in memory (1st line masks, 1st line foreground, 2nd line masks, etc). The mask is used to emphasize the foreground and to avoid to show the sprite as in MODE=3 (XOR, black on black gives white).

DEF SPRITE n, dim, Backgr

sets a sprite (1 to 6), Backgr is the address in memory 'caching' the part of the screen hidden by the sprite, and dim is the dimension:

low: dim= 1 (small: 16 bytes) or 2 (large: 64 bytes)
average: dim= 3 (small: 32 bytes) or 4 (large: 128 bytes)
high: dim= 5 (small: 64 bytes) or 6 (large: 256 bytes)

SPRITE n, x, y, Dess, Cm, Cd

displays sprite n, with the coordonates x, y whose drawing was registered beforehand with Dess address, Cm and Cd are the colors of the mask and the foreground.

DEF SPRITE n, 0 erases the sprite (useful in the course of program)

6.9 Colours ( → .fr, much more complete, I apologize)

Couleurs hardware exprimées en hexadécimal
Control Panel - ATARI ST - TOS 1.4

SCREEN 1, Addr, 4 allows the passage from low resolution (320*200) to middle resolution (640*200). Don't forget 32256 bytes in memory for Addr:

Addr=MEMORY(32256) AND $FFFF00
SCREEN 1, Addr, 4

LINE COLOR=n to define the line 'Hardware' colour
FILL COLOR=n to define the filling 'Hardware' colour
TEXT COLOR=n to define the text 'Hardware' colour

«Hardware» colors are those of Control Panel accessory CONTROL.ACC (ST):

777 white - 000 black - 700 red - 070 green - 007 blue - 400 marine - 420 brown - 040 meadow - 555 light gray - 222 dark gray - 077 cyan - 044 steel - 707 magenta - 404 purple - 440 sand - 770 yellow

Hardware colours in hexadecimal
Control Panel - ATARI STE - TOS 1.6+

From the STE (TOS 1.6), each fundamental light has 16 shades, from 0 to 15 ($F), which means 4096 possible hues (163). In order to keep compatibility with the ST colours, the additional grades (half intensities) are indicated by adding the number 8: 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7 and 15, or binary: %0000, %1000, %0001, %1001, %0010, %1010, %0011, %1011... where bit 3 (the first left one) is set for the halftones. See XCONTROL.ACC control panel:

FFF white - 000 black - F00 red - 0F0 green - 00F blue - 800 marine - 840 brown - 080 meadow - AAA light gray - 444 dark gray - 0FF cyan - 088 steel - F0F magenta - 808 purple - FF0 yellow - 880 sand

VDI colours

«VDI» order of the colors defined by PALETTE does not correspond to the «hardware» one. In low resolution:

PALETTE 0, 2, 3, 6, 4, 7, 5, 8, 9, 10, 11, 14, 12, 15, 13, 1

Medium resolution:

PALETTE 0, 2, 3, 1

For instance, to set other colors than traditional ones of the middle resolution (white, red, green and black):

PALETTE $777, $707, $077, $555 gives white, magenta, cyan and anthracite.

PRINT POINT(x, y) tests and returns the n° of color «VDI» of the point x, y

PRINT CHR$(27); "b"; CHR$(n) sets a «VDI» color for the foreground (n goes from 0 to 15)
PRINT CHR$(27); "c"; CHR$(n) sets a «VDI» color for the background

PALETTE $a, $b, $c, $d, $eE... sets a color. Each parameter is composed of three digits, each one from 0 to 7. The first proportions the red, the second the green and the third blue. Note: STE (TOS 1.6) has 16 nuances of colors, 0 to 15. The half-intensities are indicated by the addition of 8: 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7 and 15. In binary: %0000, %1000, %0001, %1001, %0010, %1010, %0011, %1011... where bit 3 (the first on the left) gives the half-tones.

7. System ( → .fr)

7.1 Memory ( → .fr)

CLEAR m reserves a global amount of m bytes for MEMORY (64 Kb by default)
CLEAR m, n reserves also n bytes for the stack, meter of loops, procedure calls, aso
Addr=MEMORY(n) reserves n bytes, Addr returns the address of the beginning
Addr=MEMORY("Monty Python") puts a string at a precise address

FRE(Addr) frees the amount of bytes formerly reserved
FRE("C:") returns the free place on a disk
FRE(0) returns the free place in memory
FRE("") does first a "garbage collection": frees memory used for the string processing:

PRINT FRE(0)
A$="1": B$="=100"
FOR I=1 TO 99: A$=A$+"+1": NEXT
PRINT A$;B$
PRINT FRE(0) ' 10710 bytes are used
PRINT FRE("") ' 10594 are now freed: the final string uses 216 bytes.

Byte=PEEK(Addr) reads a byte at the given address
Word=WPEEK(Addr) reads a short integer (two bytes) at the given address
Long=LPEEK(Addr) reads a long integer (four bytes) at the given address

POKE Addr, Byte writes a byte at the given address
WPOKE Addr, Word writes a short integer (two bytes) at the given address
LPOKE Addr, Long writes a long integer (four bytes) at the given address

MEMORY_MOVE n, Dep TO Targ copies n bytes form Dep address to Targ address (even addresses)
MEMORY_MOVEB n, Dep TO Targ makes it possible to use odd addresses (slower)
MEMORY_BLOCK xx, n, Addr reserves n bytes with variable-Addresses (xx from 00 to 99, no variable) which will be saved within the program. It's then possible to BLOAD a file at the address. Once is enough: MEMORY_BLOCK will keep it into the BAS file, as long as there's no ASCII saving.

VARPTR(V) returns the address of the indicated variable

SEGPTR gives the address of the SEGment PoinTR array, which contains pointers (addresses):

+0 byte n° of lines
+4 beginning of the program
+8 pointers of variables
+12 variables
+20 arrays
+24 file buffer
+28 strings
+36 executed order
+40 garbage top
+44 garbage bottom
+48 garbage high
+52 value max of the stack
+56 bottoms of the stack
+60 the largest address of the memory

?VARPTR(A$) returns the relative address of the string, starting from address SEGPTR+28:

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

Interruptions ( → .fr)

IPL n sets the interrupt level of the system, from 0 to 7:
IPL 3 standard level
IPL 3+(1 SHL 31) sets off [Ctrl]-[C]
IPL 4 cold screen
IPL 6 ...nor keyboard, WAIT or TIMER (no more control, but faster): don't forget to set it back to IPL 3 when the task is over.

7.2 Binary routines ( → .fr)

Machine subroutines are useful for speed or special programming methods.

INLINE "A009" enters a line of binary code in hexadecimal. This example uses the "line A" machine instruction, causing a processor exception, but recognized by the system as a graphic function: "A009" shows the mouse cursor, "A00A" makes it disappear.

DEF USR=Addr sets the address of a binary routine
Ret= USR(Val) calls the function. The Val ue is placed onto the register D0 (4 bytes); when the routine ends, the D0 value is returned to Ret .

Ad= MEMORY(6)'     6 bytes reservation for the routine
LPOKE Ad, $06000009'   add.b #9, d0
WPOKE Ad+4, $4E75'     rts
DEF USR=Addr'     sets the memory address of the routine
PRINT USR(16)'     calls the routine with a 16-value in d0; 25 will be printed

CALL Addr(L param1, param2...) calls a binary routine, loaded at an addr ess with parameters. The routine will find them from 4(A7) on. 4(A7) means the address indicated by the value of the stack (A7) + 4.

It's rather long (8:) to build by hand the machine code instructions. Therefore, you should have an 68000 assembler. The resulting binary file can be loaded with BASIC BLOAD "File", Addr (see BLOAD). It is also possible to include in the binary routine with MEMORY_BLOCK 00, L, Addr (see previous section). Warning:

7.3 Time ( → .fr)

TIME$ contains the machine time
TIME$="15:58:12" sets the time to the machine

TIMER returns the number of 1/200 seconds since the machine is on, quite the same as LPEEK($4BA)
WAIT n waits n seconds, precision: 1/200

DATE$ returns the machine known date
DATE$="" sets the date following the mode:
MODE"USA" months/days/years: "02/14/2007" (by default)
MODE"GB" days/months/years: "14/02/2007" (MODE"F" )
MODE"D" days.months.years: "14.02.2007"

BIOS(R, 6) gives the delay (milliseconds) between two clock-top

GEMDOS(R, 42) returns the date:
Bits 15-9: years if 1980 is added (2007=27)
Bits 8-5: months (1 à 12)
Bit 4-0: days (1 à 31)
GEMDOS(, 43, Date) Date is a short integer as described in GEMDOS 42
GEMDOS(R, 44) returns the hour:
Bit 15-11: hours ; Bit 10-5: minutes;
Bit: 4-0 double-seconds (0=0s, 1=2s, 2=4s...)
GEMDOS(, 45, Heure) Heure is a short integer as described in GEMDOS 44
XBIOS(, 22, L Addr) sets the time. Addr must contain two short integers: the date and the hour
XBIOS(R, 23) returns hour and date at the XBIOS 22 format

GEMDOS 42, 43, 44 and 45 and XBIOS 22 and 23 are not linked
Look out: GEMDOS 43 accepts the date 31/2, but not 32/1

7.4 Error processing ( → .fr)

ERR last error number ; to use with IF ERR=n THEN ...
ERR$ last error message
ERL last error line, or -1 in direct mode
LIST ERL lists the program line error

ON ERROR GOTO sends to an error processing routine
RESUME leaves an error processing routine and tries again the problematic command
RESUME NEXT goes to the instruction following the error
RESUME Lbl goes to the line containing the label -Lbl
ERROR n provokes the error n , to work out an error processing routine

The loop-meter is safe after a RESUME: you need an EXIT to reset it at zero. If ON ERROR GOTO is off with CLEAR or is interrupted by [Ctrl]-[C], the error message is shown.

TRON (TRace ON) sets the TRACE mode: shows the line-number and every executed instruction
TROFF gives up the TRACE mode (is there a meter for the number of TRON and TROFF?)
ON TRON GOSUB is TRON is set, goes to a routine at every instruction

Interpretor's errors ( → .fr)

  1. Structure too long a procedure or a loop is more than 64 Ko
  2. Syntax error
  3. RETURN without GOSUB subroutines should be placed after an END
  4. Out of DATA more DATA needed for READ
  5. Illegal function call
  6. Overflow the numerical variables are limited
  7. Out of memory GEMDOS or the stack need more memory: CLEAR morememory
  8. Undefined Statement GOTO or GOSUB send to nowhere
  9. Subscript out of range arrays are limited
  10. Duplicate definition several procedures or functions have the same name
  11. Division by zero
  12. Illegal direct a function or procedure is met without a call
  13. Type mismatch don't mix strings and numbers
  14. RETURN without function your program meets a RETURN out of a function , procedure of subroutine
  15. String too long a string longer than 32767 characters?
  16. Formula too complex the stack must remember inclusion you wrote. Too many here.
  17. Can't continue CONT after a STOP doesn't stand a change in your program
  18. Undefined user function a name without function, token or procedure
  19. No RESUME an error processing routine misses a RESUME
  20. RESUME without error RESUME is met out of an error processing routine
  21. Use EXIT often when IF/THEN misses an ENDIF in a loop
  22. Missing operand nothing after an operator or a comma
  23. Line buffer overflow too long line
  24. REPEAT without UNTIL
  25. UNTIL without REPEAT
  26. FOR without NEXT
  27. NEXT without FOR
  28. IF without THEN or EXIT an IF misses a THEN or an ENDIF
  29. WHILE without END
  30. END without WHILE
  31. THEN, ELSE or ENDIF without IF or THEN you should structure your imbricated loops:
REPEAT
  FOR I=-5 TO 5
    IF I=0 THEN
      PRINT I; " is greater than zero"
    ELSE
      PRINT I; " is not greater than zero"
    ENDIF
  NEXT I
  PRINT "A mouse-click to stop"
UNTIL MOUSEBUT=0
  1. ERROR 32 [Enter] gives the Omikron copyright
  2. RESET Omikron didn't die after a RESET. It's normal, but don't abuse.
  3. Bus error a POKE in a forbidden memory address
  4. Address error addressing error (a Word at an odd address)
  5. Unknow opcode unknow instruction for the processor
  1. Out of memory. Save or re-CLEAR immediatly try to save!
  2. EXIT without structure from which LOOP to go out?
  3. Use EXIT TO in functions from several depth loops
  4. Matrix not regular some matrices must be square-ones
  1. Bad file number you can't open more than 16 files
  2. Fie1d overflow DATA doesn't fit in a FIELD
  3. Internal error fatal error - cold RESET
  4. Bad file number only 16 file-channels
  5. File not found
  6. Bad file mode illegal instruction on a file
  7. File already open
  8. File not open
  9. TOS Error n see next section
  10. File already exists
  11. File type mismatch
  12. Bad disk
  13. Disk full
  14. Input past end tries to read after the End Of File. LOF(channel) can help
  15. Bad record number
  16. Bad file name forbidden character in a filename
  17. Path not found
  18. Direct statement in file a file to load does not have linenumbers: use 'Load Block' of 'Files' menu
  19. Too many file in a directory?
  20. Write error
  21. Read error
  22. Disk-write protected

System errors ( → .fr)

BIOS-XBIOS GEMDOS
  1. General error
  2. Disk not ready
  3. Unknown opcode
  4. Checksum error
  5. Non correct instruction
  6. Sector not found
  7. Bad boot-sector
  8. Sector not found
  9. No more paper
  10. Writing error
  11. Reading error
  12. General error
  13. Protected floppy
  14. Changed floppy
  15. Unknown device
  16. Bad sector
  17. Introduce a floppy
  1. Invalid function number
  2. File non found
  3. Path non found
  4. Too many files open
  5. Invalid access
  6. Non valid file number
  7. No more memory
  8. Non correct block-memory address
  1. Non correct disk
  1. RENAME on several units
  2. No more files
  1. File overflow
  2. GEMDOS internal error
  3. Incorrect program
  4. Bloc-memory error

7.5 System programming ( → .fr)

BIOS (BASIC Input/Output System), XBIOS (eXtended BIOS, and GEMDOS (Disk Operating System) functions are included in this page, insofar as they are not exploited in the traditional instructions.

R is always a Return-value, which is not always useful (do nevertheless preserve the comma). It can contain an address, a TOS error, a device number or a file handle.

It is necessary to reserve memory before calling the functions processing a certain amount of bytes, by the intermediary of an address. Functions PEEK make it possible to read them. On the contrary, functions POKE makes it possible to write data on an address reserved in memory before calling a function. The most practical manner to write a string in memory and to know its address is:

Addr=MEMORY("String"+CHR$(0))

the most traditional is:

V$="text"+CHR$(0): Addr=LPEEK(SEGPTR+28)+LPEEK(VARPTR(V$))

where LPEEK(SEGPTR+28) is a PoinTeR towards the place of the strings in memory and LPEEK(VARPTR(V$)) the span to the pointer for the V$ chain. You can PEEK(Addr), PEEK (addr+1) aso. the characters.

These functions are close to the language of 68000 procesor: the parameters must be short integers and the address of a buffer must break up into HIGH(Addr) and LOW(Addr) . Omikron makes it possible to do it more easily with L Addr :

GEMDOS(, 10, HIGH(Buffer), LOW(Buffer)) becomes GEMDOS(, 10, L Buffer)

These functions are more tricky than the old good BASIC. For instance, XBIOS 0 (for the mouse) requires additional information, and largely exceeds the object of this page. Below, GEMDOS 10 will make it possible to be convinced of the comfort of the traditional BASIC. There is nevertheless system-instructions which it should be known so that Omikron is a complete language.

GEMDOS(R, 48) value R divided by 256 returns the version of the GEMDOS.

GEMDOS(R, 10, L Buffer) allows the input of a line. The first two bytes contains the maximum and effective length chain, finished by CHR$(13):

Saisie(12, Ch$): PRINT Ch$: END
DEF PROC (N, R T$) ' R to turn over a T$
String=CHR$(N) CHR$(0)*(N+2) ' 1st two bytes and bed of null bytes
Addr= LPEEK(SEGPTR 28)+ LPEEK (VARPTR(T$) ' addresses string
GEMDOS (, 10, L Addr) ' awaits n characters maximum or [Enter]
T$=MID$(T$, 3, ASC(MID$(T$, 2))) ' returns the text starting from the 3rd character
RETURN ' INPUT$ or INPUT (USING) is quite more practical!

7.6 Some useful precautions ( → .fr)

7.7 Omikron BASIC 3.01 bugs and weaknesses ( → .fr)