It currently works with DOS XL by just entering TCL and hitting return. It should work with other DOS systems but it may be necessary to specify the run address yourself. The run address is 0x2600. There are probably many errors in this document, since it was last update a long time before my last version of the compiler (1986). I have just update a few areas I knew were wrong but memories fade and I have probably missed some bits. If you have any problems or queries regarding this documentation send an Email message to me and I'll find the answer and update this guide. E-Mail: david@signus.demon.co.uk

Test Computer Language, Version 2.2

Table of Contents

  1. Introduction
  2. Editor Commands
  3. Compiler Commands
  4. Assembler Commands
  5. Compiler Directives
  6. Compiler Expressions
  7. Memory Usage
  8. Limitations
  9. Some useful Functions
  10. Floating point procedures
  11. Error Codes
  12. Known Bugs

Introduction

This language has been designed for the programmer with an in-depth knowledge of ATARI's 8 bit computers, also it may be useful to know a little 6502 machine code, to help extend the language via user defined functions and procedures.

This language will also be of use for somebody starting to learn 6502 machine code as small ( or large ) routines can be included within the main program.

NOTE: Since it will not be clear where in memory your machine code will go, any machine code must be re-locatable. It is possible to locate the code by preceding it with a pointer definition, the defined variable will contain the address of the code. System requirements This language requires an ATARI 8 bit computer with at least 24K of memory and a disk drive. Syntax Conventions The following conventions are used in this manual when defining the syntax of a command :- 1. Capital letters designate the names of the procedures or functions and must be typed in exactly as shown ( eg. LIST, COMPILE, AND, GOTO etc). 2. Lower case letters specify the type of argument to the commands : lno - A label number between 1 and 65535, inclusive. hxnum - A string of hexedecimal numbers. dcnum - A positive decimal number. exp - Any valid expression. string - A string of ASCII characters enclosed in double quotes ( eg. "String of Characters"). adr - The address of some data, adr may be an expression. 3. Items enclosed within square brackets denote an optional part of the syntax ( eg. exp [,exp...] ). When an optional item is followed by ... the item may be repeated as many times as needed.

Editor Commands

BOOT

Purpose:    To compile the source program directly to a BOOT Disk
Syntax:     BOOT
Before pressing return insert a blank formatted disk in D1: the compiled program will be written to the disk as a single part boot disk. The disk image can then be copied onto a standard multiboot type menu.

COMPILE

Purpose:    To compile the source program.
Syntax:     COMPILE [ #file1 ] [ ,#file2 ]
This command will call the compiler which will go through the program line by line, converting it into machine code. If file1 is specified the object code will be created and sent to file1, together with a small runtime package ( about 1.5K ). If file2 is specified the listing will be produced and sent to this file2.

In the process the compiler will check the syntax of the commands in the source code, and check that labels have not been defined twice or referenced when they don't exist. Note that this is a two pass compiler and therefore it will not matter where the labels are defined.

After the program has been compiled, an address map will be produced if file2 has been specified.

If an error has been detected the compiler will issue an error message and will then continue to create the object code. If after receiving an error you run the program, the results may be unpredictable.

The compiled program should be given a file extender of '.COM' then the program can be run from dos just by entering the name of the program. The run address of the Program will always be $260E.

DOS

Purpose:    To return to the disk operating system.
Syntax:     DOS
This command will return you to the disk operating system. The compiler may be re-entered by simply typing RUN in a memory resident dos, such as Sparta Dos or Dos XL, or by typing RUN 2600.

ENTER

Purpose:    To merge source code from file with loaded source code
Syntax:     ENTER #filespec

LIST

Purpose:    To list a program to a device.
Syntax:     LIST [ #filespec, ][ dcnum1 [ ,dcnum2 ] ]
This command will list the source program to the specified device. If a device is not specified, the screen editor will be used as default. If only dcnum1 is specified, then only that line will be displayed, but if both dcnum1 and dcnum2 are specified, all the lines between and including dcnum1 and dcnum2 will be listed. When dcnum1 and dcnum2 are not specified, the complete source program will be listed out to the required device.
Example:  LIST #P:,2000,2050
This will list all the lines between 2000 and 2050 inclusive to the printer.

LOAD

Purpose:    To reload a stored source program into memory.
Syntax:     LOAD #filespec
This command will first clear the program that currently resides in memory, and will then load the previously saved source file into memory, from the specified filespec.

NEW

Purpose:   To erase program in editors memory.
Syntax:    NEW
This command is used to clear an old program out of memory, before starting to enter a new program. Once this command has been issued, the program cannot be retrieved, and therefore it must be saved to disk if it will be needed again.

RENUMBER

Purpose:   To renumber all line numbers ( not labels )
Syntax:    RENUMBER [ dcnum1 ] [ ,dcnum2 ]
Used to renumber all the editors line numbers (not label numbers). If no dcnums are specified the source program will be renumbered starting from line 10 in increments of 10. If dcnum1 is specified, this will be taken as the start lines number, and if dcnum2 is specified, this will be taken as the increment. The renumber command is mainly used to insert spaces between line numbers, so that lines can be inserted between them.
Example:  RENUMBER 1000,10
This will renumber the current program from line 1000 in increments of 10.

RUN

Purpose:    To execute the program without creating an object file.
Syntax:     RUN
This command is similar to the COMPILE command, except that no files may be given. When the compile is in run mode it must perform a third pass on the sourc program to determine a safe place to store the object code.

NOTE: If any errors are detected, the compile program will not be run.

SAVE

Purpose:    To save a source program.
Syntax:     SAVE #filespec
Used to save a program so that you can resume editing it at a later stage.

SIZE

Purpose:    To display remaining memory
Syntax:     SIZE
Used to find out how much memory is left for use with the COMPILER. If you start to run out of memory you can save the current file, and INCLUDE it in the main program, this will give more memory for the compiler to build the symbol tables.

Compiler Commands

AFTER

Purpose:    After time period, go to address
Syntax:     AFTER ( exp, adr )
When this command is executed it sets up one of the count down timers to count down from the value of exp. When the timer reaches zero control will be passed to 'adr' which is an address of some machine code, or commands in this language. The called routine must execute a RETURN command to resume normal proccessing. If a return is not used the stack could quickly overflow causing the program to crash. To avoid this you could reset the stack pointer to $FF ( LDX #$FF : TXS ), but if this is done, it is the same as the program, being totally restarted from the current point (all return address will have been lost). The time may range from 1 to 65535 where 1 is 1/50th Second.
Example:   SOUND (0,100,10,10)
           AFTER (10,SOUNDOFF)

           REST OF PROGRAM

           POINTER SOUNDOFF
           SOUND (0,0,0,0)
           RETURN
This will switch on the sound channel and continue to process the rest of the program. Then after 10/50th of a second the program will call 'SOUNDOFF' which switches the sound off, and returns back to the main program.

ASCII

Purpose:    To include ASCII text in program.
Syntax:     ASCII string
This command enables ASCII text to be placed in the code, which can be used for filenames etc. The command must be positioned so that it will never be executed as this will make the program crash. If necessary jump over the text with a GOTO command.
Example:    GOTO 10
            POINTER FILENAME
            ASCII "D:DISKFILE.DAT"
         10 OPEN (1,FILENAME,4,0)
This will store the characters "D:DISKFILE.DAT" in memory. These characters are accessed by defining a pointer just before them. The program opens the disk file with via the pointer.

BEGIN

Purpose:    To define the start of the program
Syntax:     BEGIN
This command allows you to start the program execution from any point in the source code. There must be one, and only one BEGIN statement in the program. If at runtime the program reaches the associated END statement the program will either 1. Return to the language (if RUN command was used), 2. Return to DOS (if loaded from DOS) or 3. REBOOT (If booted from disk).

CLOSE

Purpose:    To close an IOCB channel.
Syntax:     CLOSE (exp)
This command will close the specified IOCB, which will allow it to be used again at a later time. The exp must evaluate to between 0 and 7 although if it is out of range it will be truncated & no error will be issued.
Example:    CLOSE (1)
            OPEN (1,FILENAME,4,0)
This ensures that channel one is closed before you try to re-open it.

COLOUR

Purpose:    To select a new colour
Syntax:     COLOUR (exp)
This command (note the ENGLISH spelling) is used to select a new colour register. The colour is used to select what value will be stored on the screen. The graphics hardware will interpret this value differently from one graphics mode to another. In text modes it will select a character, and in graphics mode it will select a colour for each screen pixel. The pen colours may be changed by the SETCOLOUR command.

CODE

Purpose:    To enter hexedecimal data.
Syntax:     CODE hxnum [ hxnum... ]
This command will enable you to enter hexedecimal data into memory at the current memory location (at compile time). This command enables you to include machine language directly in the program. Values can be passed to and from the routine using the PUSH & PULL commands.
Example:    CODE A9008DC602
            ; LDA #0
            ; STA $2C6
This places the code to change the screen colour to black in memory. The comments after give the assembler source code (not required).

DO

Purpose:    Repeat some code a given number of times
Syntax:     DO var = exp1, exp2, exp3
This command is used to repeat a loop a given number of times. The exp1 is the initial value, exp2 is the termination number, and exp3 is the increment the control variable takes each time round the loop. Note that an increment of 65535 is equal to -1 allowing you to count down.
Example:    DO X=1,10,1
              WRITE (X)
            END DO
This will cause the 'X' variable ( control variable ), to take the values 1 through 10, and write them to the screen.

DPOKE

Purpose:    To store values in memory
Syntax:     DPOKE (adr,exp)
This command will store a 16 bit number denoted by the values of exp, into the specified memory address. The 16 bit number will be stored low byte first and high byte at adr+1.
Example:    POINTER RESET
            DPOKE (2,RESET)
            POKE (9,2)
This will store the address of reset at memory address 2 and then change memory address 9 to indicate cassette boot. This will cause execution begining again at RESET when the reset key is pressed.

DRAWTO

Purpose:    To draw a line on the screen
Syntax:     DRAWTO (exp1,exp2)
This command will draw a line from the current graphics cursor position, using the last colour selected to the location of exp1 and exp2. exp1 is the 'X' coordinate and exp2 is the 'Y' coordinate.
Example:    GRAPHICS (8+16)
            COLOUR (1)
            DO X=0,319,1
              PLOT (X,0)
              DRAWTO (X,191)
            END DO
This selects graphic mode 8 without a text window using colour 1. Then the program will fill the screen going from left to right.

ELSE

This command is used within a conditional IF block, and will cause all the code after it up to the END IF statement, to be executed, if the IF or all ELSE IF conditions evaluated to FALSE.

ELSE IF

This command is used within a conditional IF block, and will cause all the code following it, up to the next ELSE IF, ELSE or END IF (at the same level of nesting) to be executed, if the expression evaluates to TRUE, and the expression in the IF, and any preceding ELSE IF statements evaluated to FALSE. There must be a space between ELSE and IF.

END

Purpose:    To execute a cold start/Terminate Function
Syntax:     END
This command is used to terminate a block of instructions. If it terminates a function, the function returns to the calling statement. If it is used outside a function (terminating the BEGIN statement) it will perform a coldstart.

END DO

Purpose:    To define end of DO loop.
Syntax:     END DO
This command terminates the current DO loop. It must always be lower down the source program than its associated DO command. There must be a space between END and DO.
Example:    DO X=1,10,1
              WRITE (X)
            END DO
This will loop round and take the values of X from 1 up to and including 10. Note that the loop will not be terminated until the X variable has had the value of ten when the END DO is reached. If the X increment was 2, the X variable would never reach 10 & therefore the loop would NEVER terminate.

END IF

This command is used to terminate a conditional IF block. There must be a space between END and IF.

END WHILE

This command is used to terminate a WHILE exp DO block. When the expression in the WHILE command evaluates to FALSE the program continue after the END WHILE command. There must be a space between END and WHILE.

ERROR

Purpose:    To force a runtime error
Syntax:     ERROR exp
This command will allow a your programs to generate a runtime error. This error is trapable in the normal way.

EVERY

Purpose:    Every time period gosub address
Syntax:     EVERY ( exp, adr)
This command is identical to the AFTER command exept that the interupt will occur every x/50ths of a second. The interrupt can be disabled by issuing the command with a time of zero.

FAST

Purpose:    To increase the execution speed
Syntax:     FAST
This command will increase the execution speed of the program. It does this by disabling all interupts and by switching the screen display off. This should be used while the screen display is not required, and then by executing a SLOW command at the end.
Example:    FAST
            Y=0
            DO X=1,5000,1
              Y=Y+1
            END DO
            SLOW
            WRITE (Y)
This program first switches the screen and interupts off. Sets the 'Y' variable to 0, and then adds 1 to 'Y' 5000 times. The screen and interupts are then re-enabled and the value of 'Y' is displayed on the screen.

FILL

Purpose:    Fill an area of memory with a value.
Syntax:     FILL (adr, exp1, exp2)
This command fills an area of memory from memory location adr for exp1 consecutive locations with the low byte value of exp2.
Example:    FILL (1636,256,0)
This fills page 6 (memory locations 1536 to 1791 inclusive) with a value of zero.

FLOAT

Purpose:    To place a floating point number into memory
Syntax:     FLOAT const [ ,const ... ]
Allow you to place a floating point number into memory at the current memory address. The number can be located by placing a pointer variable directly before the FLOAT command. Although the compiler does not support floating point numbers, they can be implemented through the use of procedures and functions (see section on floating point procedures), but they cannot be used in expressions. ie. you could define an add command (ADD (destination,source)) which could add the floating point number at the address pointed to by source to the number pointed to by destination, with the result stored at destination.

FUNCTION

Purpose:    User defined functions with arguments
Syntax:     FUNCTION lblnm (var1 [ ,var2....] )
Since their are no inbuilt functions in the language, this command enable you to define your own. The function will be called lblnm and a variable of the same name will also be automaticaly set up to contain the result. The arguments will be given values when the routine is called. The result of the function is passed back to the calling routine by assigning the value to the functions name. The function is terminated by executing an END command.
Example:    VARIABLE X
            FUNCTION TEST (X)
            TEST=X*2
            END
            ;
            VARIABLE Y
            BEGIN
              Y=TEST(5)
              WRITE (Y)
            END
This will cause the value of 10 to be printed on the screen.

GET

Purpose:    To get recieve some data from an IOCB
Syntax:     GET (exp1, adr, exp2)
This command is used to receive some data from the IOCB specified by exp1, this may be in the range of 0-7 but will be truncated if required. The command will recieve exp2 bytes from the IOCB and store them in consecutive memory locations starting with adr.
Example:    POINTER KEYBRD
            ASCII "K:"
            POINTER KEYPRESS
            RESERVE 5
            ;
            BEGIN
              OPEN (1,KEYBRD,4,0)
              GET (1,KEYPRESS,5)
              PRINT (0,KEYPRESS,5)
              CLOSE (1)
            END
This program inputs 5 characters from the keyboard, and store them at 'KEYPRESS'. The characters will then be printed out via the screen editor.

GOSUB

Purpose:    To call a subroutine.
Syntax:     GOSUB lblnm
Argh not GOSUB. I wouldn't even it in a language today! Anyway it enable you to call a label number directly. To return from the subroutine a RETURN command must be executed. This command can be useful to save rewriting similar pieces of code more than once.
Example:    VARIABLE X
            BEGIN
              X=1
              GOSUB 10
              X=2
         10   WRITE ("X = ",X)
            END
This program will first write out the value 1 followed by the value 2. In this case the END has the same effect as a return statement.

GOTO

Purpose:    To change flow of program
Syntax:     GOTO lbl
Oh no! another one! This command executes in the same way as the GOSUB command, exept that it does not expect a RETURN command.
Example:    VARIABLE X
            BEGIN
            X=0
         10 IF X<>5 THEN
              X=X+1
              GOTO 10
            END IF
            WRITE (X)
            END
This program loops until X is equal to 5, and then it goes to label 20 and write out the current value of 'X' (5) before returning control to DOS.

GRAPHICS

Purpose:    To change screen mode
Syntax:     GRAPHICS (exp)
This command will call the operating system to set up the required graphics mode using IOCB 6. Normaly the screen will be set up in a split screen mode, but by adding 16 to exp, the screen will be set up without a split screen. Adding 32 to the exp will cause the screen to be set up without clearing the screen memory.
Example:    GRAPHICS (8+16)
This command will set up the high resolution one colour mode (320 by 192) without a text window using IOCB 6.

IF

Purpose:    To make decisions
Syntax:     IF exp THEN (or DO)
This command starts a conditional block of code. The first block will be executed if the expression is TRUE (non zero low byte value), otherwise the program will resume after the ELSE, ELSE IF (if exp true) or END IF
Example:    VARIABLE X
            BEGIN
              X=0
              WHILE X<3 DO
                X=X+1
                IF (X=1) THEN
                  WRITE ("ONE")
                ELSE IF X=2 THEN
                  WRITE ("TWO")
                ELSE
                  WRITE ("THREE")
                END IF
              END WHILE
            END

INCLUDE

Purpose:    To include source programs from a file
Syntax:     INCLUDE #filespec
This command will INCLUDE the specified file name in with the code as it is being compiled. This can be used to bring in library routines, or it may be used to build large programs, where it is not all resident at the same time.
Example:    VARIABLE X
            INCLUDE #D:PEEK.FUN
            BEGIN
              X=PEEK (20)
              WRITE (X)
            END
This program includes the file D:PEEK.FUN into the main program at compile time (if it exists on the disk).

INPUT

Purpose:    To input records terminated with an end of file.
Syntax:     INPUT (exp1, adr, exp2)
This command is used to input records terminated with an end of file marker. exp1 is the IOCB to use, adr is the address where the recieved data is to be stored and exp2 is the maximum number of bytes that can be in the record. Any extra bytes will be ignored.
Example:    POINTER TEXT
            RESERVE 10
            BEGIN
              INPUT (0,TEXT,10)
              PRINT (0,TEXT,10)
            END
This program enters up to ten bytes from IOCB 0 (screen editor) and store them at TEXT. The program then PRINTs it out.

IRQ OFF

Purpose:    Disable interupt requests
Syntax:     IRQ OFF
This command ensures that no interrupts can occur. It disable both the EVERY and the AFTER interrupts. The non maskable interupts are not be affected.

IRQ ON

Purpose:    Enable interput requests
Syntax:     IRQ ON
This command enables all the interrupt requests again.

LOCAL

Purpose:    Define a new local variable region
Syntax:     LOCAL
This command defines the start of a new local variable region. A variable defined as being local is only available for use in the local region it was defined in. Up to 250 local regions may be used. Local variables are defined by preceding the variable name with a '?' character.
Example:    LOCAL
            VARIABLE ?X
            BEGIN
              ?X=2
              GOSUB 10
              WRITE (?X)
            END

            LOCAL
            VARIABLE ?X
         10 ?X=6
            RETURN
This program defines two local regions both with the variable 'X' defined. In the first it is set to 2, and in the second it is set to 6. While the program is executing in the first local region 'X' will have the value of 2. Therefore the number 2 will be written to the screen by the WRITE statement.

MOVE

Purpose:    To move blocks of memory around
Syntax:     MOVE (adr1, adr2, exp)
This command moves exp bytes from adr1 to adr2. Care must be taken so that an overlap of adr1 and adr2 does not occur.
Example:    MOVE (1536,1792,256)
The above command will move all of page 6 into page 7, leaving page 6 un-change.

OPEN

Purpose:    Open a input / output file
Syntax:     OPEN (exp1, adr, exp2, exp3)
This commands opens an input or output file. exp1 is the IOCB to use, adr is an address that contains the name of the file to open, exp2 holds the input/output operation and exp3 holds a device dependent auxiliary code. Valid values for exp2 are:-
  4  =  Input operation
  6  =  Disk directory operation
  8  =  Output operation
  9  =  End of file append (output)
 12  =  Input and output operations ( together )

Example:    LOCAL
            VARIABLE ?IOCHAN
            POINTER ?FSPEC
            ASCII "D:*.*"
            POINTER ?TEXT
            RESERVE 20
            PROCEDURE DIR (?IOCHAN)
              CLOSE (?IOCHAN)
              OPEN (?IOCHAN,?FSPEC,6,0)
              TRAP 65532
      65530   INPUT (?IOCHAN,?TEXT,20)
              PRINT (0,?TEXT,20)
              GOTO 65530
      65532   CLOSE (?IOCHAN)
              POP
              TRAP -1
            END
This procedure displays the disk directory on the screen using the supplied IOCB.

PLOT

Purpose:    To plot a single point on the screen
Syntax:     PLOT (exp1, exp2)
This plots a single point on the screen using the last selected colour. exp1 holds the 'X' coordinates and exp2 holds the 'Y' coordinates.
Example:    VARIABLE X
            BEGIN
              GRAPHICS (11)
              DO X=0,79,1
                COLOUR (X MOD 16)
                PLOT (X,0)
                DRAWTO (X,191)
              END DO
         10   GOTO 10
            END
This program set up graphics mode 16 and then draw bands of colour going from the top to the bottom of the screen.

POINTER

Purpose:    To locate a section of the compiled code.
Syntax:     POINTER lblnm
This command defines a variable, but instead of the variable being initialised to zero, it is initialised to the value of the next address. This allows you to locate parts of the compiled code (text, data and buffers etc).
Example:    POINTER Filename
            ASCII "D:FILE.DAT"
            BEGIN
              OPEN (1,Filename,4,0)

              Rest of program

              CLOSE (1)
            END
This program will open a file called D:FILE.DAT, and then continue and execute the rest of program.

POKE

Purpose:    To store values in memory
Syntax:     POKE (adr,exp)
This command stores an 8 bit number denoted by the low byte of exp at memory address adr.
Example:    POKE (710,0)
This stores a zero at memory address 710, which in this case turns the screen black.

POP

Purpose:    To clear values off stack
Syntax:     POP
This command pops a 16 bit number off the stack. This can be used to remove unwanted return addresses or parameters from stack.
Example:    GOSUB 10

            rest of program

         10 IF (EXIT) THEN
              RETURN
            END IF
            POP
            continue program here
In this case the POP command has the effect of turning the GOSUB 10 into a GOTO 10 (ie. once it has been POPed off the stack you cannot return ).

PRINT

Purpose:    To print out a buffer
Syntax:     PRINT (exp1, adr, exp2)
This command prints a buffer to a given device. The buffer is considered to be empty when either an end of file is found in the data or when the maximum number of bytes has been sent. exp1 holds the number of the IOCB to use, adr holds the address of the data buffer, and exp2 holds the maximum number of bytes in the buffer.
Example:    POINTER BUFFER
            RESERVE 10
            BEGIN
              INPUT (0,BUFFER,10)
              PRINT (0,BUFFER,10)
            END
This program enters up to 10 characters from the screen editor, and output up to 10 characters to the screen editor.

PROCEDURE

Purpose:    To add new commands to the language
Syntax:     PROCEDURE lblnm (var1 [,var2...] )
Defines the start of a new command. The new command may be called just like any of the resident commands (ie. by typing its name followed by correct number of arguments). A procedure is terminated by an END statement.
Example:    LOCAL
            VARIABLE ?EXP
            PROCEDURE WriteEXP (?EXP)
              WRITE (?EXP)
            END
            ;
            BEGIN
              WriteEXP (5+6*7*100/2)
            END
This procedure allows you to directly write an expression to the screen. Normally you would have to calculate the value in a tempoary variable before writing it out.

PULL

Purpose:    To obtain values off the stack
Syntax:     PULL (var1 [,var2...] )
This command causes a number of 16 bit values to be pulled off the stack (one for each variable specified). The first number pulled off the stack will be used as the high byte and the second byte as the low byte.
Example:    PUSH (A,B)
            PULL (A,B)
This has the effect of swapping the values of 'A' and 'B'. (since 'A' is pushed on First and 'B' is pushed on second, 'B' is the first one pulled off, and it is stored in 'A' )

PUSH

Purpose:    To place 16 bit values on stack
Syntax:     PUSH (exp1 [,exp2...] )
This command will allow you to be able to push values onto the 6502 stack for use by your machine language routines etc. The low byte will be stored on the stack first followed by the high byte of the expression. For an example see the previous command ( PULL ).

PUT

Purpose:    To send some data to a file
Syntax:     PUT (exp1, adr, exp2)
This command will put the data starting at memory address adr for exp2 consecutive memory locations to the IOCB specified by exp1.
Example:    POINTER Return
            CODE 9B
            BEGIN
              PUT (0,Return,1)
            END
This will send an EOL ( End of line ) character to the editor.

REPEAT

Purpose:    Repeats a loop until a condition is met.
Syntax:     REPEAT
This command is used in conjunction with the UNTIL command, and allows you to repeat all the lines between the 'REPEAT' command and the 'UNTIL' command until a given condition evaluates to true (1).
Example:    REPEAT
              X=X+1
              WRITE (X)
            UNTIL X=10
This causes the loop to be repeated until the 'X' variable has a value of 10.

RESERVE

Purpose:    To reserve some memory
Syntax:     RESERVE dcnum
This reserves a specified number of bytes within the compiled program for use as buffers etc.
Example:    RESERVE 10
This will reserve 10 bytes in memory, there are no restrictions as to what this space is to be used for, but the program must never execute this statement, unless you know there is a machine langauge file stored there. Usually this command will be preceded with a POINTER definition so that you can locate the reserved memory.

RETURN

Purpose:    Return from a routine
Syntax:     RETURN
From inside the main program (not in a subroutine etc) this command will return you to DOS. This command is also used to return from a GOSUB.

SETCOLOUR

Purpose:    Change a colour registers value
Syntax:     SETCOLOUR (exp1, exp2, exp3)
This command is used to define a new colour for the specified colour register. exp1 holds the colour register ( 0 to 8 ) where register 0 is address 704, 1 is address 705 etc. exp2 holds the new colour and exp3 holds the luminance of the colour. Only the lower 4 bits of both exp2 and exp3 have any significace.

SLOW

Purpose:    Enables screen display and interupts
Syntax:     SLOW
This command is used to bring the computer out of fast mode. (ie. switch the display and interupts on again). For an example see the FAST command.

SOUND

Purpose:    Control sound voices
Syntax:     SOUND (exp1, exp2, exp3, exp4)
This enables you to use the ATARI's sound registers. exp1 holds the voice number (0 to 4), exp2 holds the frequency (0 to 255), exp3 holds the distortion level (0 to 15) and exp4 holds the volume (0 to 15)

TRAP

Purpose:    To trap input / output errors
Syntax:     TRAP (lno)
This command re-direct the program to your error handling routine should an error be detected. The error code will be stored at location 195 (as in basic). If the supplied label number is invalid or missing, the default error routine is used. This default handler outputs a message giving the error number and the approximate address where the error occured. With reference to the compilation address map you should be able to identify the approximatly line in error. A user defined error handler may return to the source line after the error by executing a RETURN command. If the program should continue without returning to the line after the error, you must execute a POP command to clear the stack (as in the definition of the DIR procedure). The only statement that you can't return to is after it has happend in a WRITE statement.

WHILE

Purpose:    Execute a block of code while the expression is TRUE
Syntax:     WHILE exp DO
This commad will first evaluate the expression, if the result is TRUE (low byte of result is non zero) the following code up to the END WHILE at the same nesting level will be executed, the program will then loop round and test the expression again. If the expression is FALSE, the program will continue on te line following the END WHILE command.
eg.          VARIABLE 53279=CONSOL
             BEGIN
               WHILE (CONSOL.AND.255)=7 DO
                 WRITE ("PRESS OPTION, SELECT OR START")
               END WHILE
             END

WRITE

Purpose:    Write data and variables to device
Syntax:     WRITE [ dcnum, ] (string/var/const[,string/var/const...]) [ ; ]
This command will write out the data to the IOCB specified by dcnum. If dcnum is not given the default IOCB is zero (screen editor). All items to be printed must be seperated by commas. If there is a ';' character following the close bracket, no end of line will be written to the device. Normally when writting the value of a variable, the value will be integer but by preceding the write statement with a F (FWRITE) all the following variables will be taken as pointers to floating point numbers, and the floating point number will be printed out instead.
Example:    VARIABLE A
            POINTER PI
            FLOAT 3.142
            BEGIN
              A=25
              WRITE ("The value of 'A' is ",A)
              WRITE ("The value of 'A' is ");
              WRITE (A)
              FWRITE ("PI = ",PI)
            END
This short program will write out 'The value of 'A' is 25' twice to the default device (screen editor). Note the use of the ';' for the second WRITE command. Then the program then prints 3.142.

UNTIL

Purpose:    Terminate REPEAT UNTIL loop
Syntax:     UNTIL exp
This command is used to terminate a REPEAT UNTIL loop structure, and can be used so that a loop will REPEAT, UNTIL a condition is true (1).
Example:    VARIABLE 53279=CONSOL
            BEGIN
              REPEAT
                rest of loop
              UNTIL (CONSOL .AND. 255)=6
            END
This loop will be repeated until the low byte value of CONSOL is equal to 6 (ie. the start key has been pressed)

VARIABLE

Purpose:    To manipulate numeric data.
Syntax:     VARIABLE [ dcnum= ]lblnm [ ,[ dcnum= ]lblnm...]
This command is used to define some variables. A variable is a name that represents a numeric value. This numeric value may be changed by an assignment statement. If the lblnm (label name) is preceded by 'dcnum=' then this dcnum will be taken as the address of the variable. If dcnum is not specified, then the compiler will select its own memory address. Defining your own memory locations for the variable will give you the ability to manipulate these locations. Care must be taken when using these variables as you must take into consideration the other half of the word (if you are only using a byte). A local variable is defined by the first character of the variable name being a '?' character.
Example:    VARIABLE 53279=CONSOL, 53248=HPOSP0
To access low byte of CONSOL you must mask out the high byte with a bitwise '.AND.'opperation.
            VALUE = CONSOL .AND. 255
To access the high of CONSOL you must divide divide by 256.
            VALUE = CONSOL / 256
To change the low byte (only) of HPOSP0 (53248), their is a special character that you place in from of the variable that is about to be assigned.
            

the high byte is change in the same way but with a different character
preceding the variable name. In this case address 53249.

            >HPOSP0=25
In addition, the result of the expression may be stored at the addressxi pointed to by the value of the variable by preceding the variable name with an '@' character, you may still use the '<' or '>' character as well, to change only the low byte or high byte of the address pointed to by the variable.
eg. to fill a block of memory without the fill command you may use any of
    the following examples.

     VARIABLE ADR
     BEGIN
       DO ADR=1536,1791,1
         <@ADR=0
       END DO

       DO ADR=1536,1790,2
         @ADR=0
       END
     END

Assembler Commands

Inside the language there are several assembler instructions defined, these commands were added to make it easier to interface with a machine code program. Example: JSR $E456 ( in decimal ) TYA PHA PHA PULL (STATUS) IF (STATUS .AND. 255)<>136 THEN RETURN END IF ERROR 136 This would call address $E456 and push the status onto the stack. The pull command then places it in the variabe 'STATUS' and test the low byte for being 136 (end of file). If the end of file has been reached a runtime error will be generated. These commands are exactly the same as the assembler commands of the same names. Reference 6502 manual for further details.

JMP

Purpose:    Jump to a machine language routine
Syntax:     JMP dcnum

JSR

Purpose:    Jumps to a machine language subroutine
Syntax:     JSR dcnum

PHA

Purpose:    Pushes accumulator onto stack
Syntax:     PHA

PHP

Purpose:    Pushes status register onto stack
Syntax:     PHP

PLA

Purpose:    Pulls accumulator off stack
Syntax:     PLA

PLP

Purpose:    Pulls status register off stack
Syntax:     PLP

RTI

Purpose:    Return from non-maskable interupt
Syntax:     RTI

TAX

Purpose:    Transfers 'A' into 'X'
Syntax:     TAX

TAY

Purpose:    Transfers 'A' into 'Y'
Syntax:     TAY

TSX

Purpose:    Transfers stack pointer into 'X'
Syntax:     TSX

TXA

Purpose:    Transfers 'X' into 'A'
Syntax:     TXA

TXS

Purpose:    Transfers 'X' into stack pointer
Syntax:     TXS

TYA

Purpose:    Transfers 'Y' into 'A'
Syntax:     TYA

Compiler Directives

;

Purpose:    To place comments within the program
Syntax:     ;Any characters
This directive will enable you to place comments within your source program. These comments will be ignored when the program is compiled, and will not be included in the object code.

.LIST

Purpose:    To enable listing during compilation
Syntax:     .LIST
This directive tells the compiler to generate a listing. If a list device is specified in the COMPILE statement. This is the default condition.

.NOLIST

Purpose:    To stop a listing from being produced.
Syntax:     .NOLIST
This directive stops the listing from being produced. It can be turned back on by using the .LIST directive.

.MAP

Purpose:    To produce a memory map of program
Syntax:     .MAP
This directive tells the compiler to produce a memory map. A memory map will list the names of global variables, functions, procedures and line labels together with the address in memory. The labels will be listed in the order they where defined.

.NOMAP

Purpose:    To stop the memory map from being produced.
Syntax:     .NOMAP
This command will stop the memory map from being produced at the end of the compilation. The option can be switched back on by a .MAP instruction anywhere else up to the end of the program.

Compiler Expressions

An expression is a valid combination of operands and operators which the compiled object code will evaluate to a 16 bit unsigned integer number. No error detection is made for an overflow. Since each variable is a 2 byte word (16 bits) each variable can hold a number from 0 to 65535 inclusive.

Operator: ( )

These operators will force everything inside the brackets to be evaluated before anything outside them. This will enable you to force the expressions into being evaluated in a different order.

Operator: [ ]

These operators will force everything in the brackets to be executed in the order they are given. The brackets may not be nested, and there may only be the '+' and '-' operator's included in the brackets, along with constants and variables, in addition there are no function calls allowed. These operators where added to provide a facility for very fast addition and subtraction of numbers. The stack is not used at all resulting in very fast code.

Operators: * / MOD + -

These operators are the normal arithmetic operators.
'*'   Multiplication 
'/'   Division
'MOD' Returns remainder
'+'   Addition
'-'   Subtraction)
They perform 16-bit unsigned integer arithmetic, and will ignore overflows.

Operators: = =< < <> > >=

These operators are used for comparisons and will return one if the result is true, and zero if the result is false.
'='        .EQ.  is equal to.
'=<' '<='  .LE.  is less than or equal to
'<'        .LT.  is less than
'<>'       .NE.  is not equal to
'>'        .GT.  is greater than
'>=' '=>'  .GE.  is greater than or equal to
Operators: AND OR EOR

AND will return a value of 1 if both operators are not equal to zero. OR will return a value of 1 if either of the operators is not zero. EOR will return a value of 1 if only one of the operators is not zero
Example:    0 AND 0     0
            0 AND 1     0
            1 AND 0     0
            1 AND 1     1

            0 OR 0      0
            0 OR 1      1
            1 OR 1      1
            1 OR 1      1

            0 EOR 0     0
            0 EOR 1     1
            1 EOR 0     1
            1 EOR 1     0
Operators: .AND. .OR. .EOR.

These operators work in the same way as AND OR & EOR but they work on each bit in the operands.
Example:   %0011 AND %0101   %0001
           %0011 OR  %0101   %0111
           %0011 EOR %0101   %0110
Note that the % means that the numbers following are in binary. The compiler does NOT support binary.

Order of precedence

The following are the precedence levels of each of the opperators. These are used to decide which operator should be executed first.
( ) [ ]
* / MOD
+ -
= =< < <> >= > etc.
AND OR EOR
.AND. .OR. .EOR.

Memory Usage

This compiler generates a non relocatable object file, the code is also generated in a way where the variables are embeded within the object program, therefore it will not be possible to place the code into a ROM or EPROM. The first thing the compiler will do is to write a 1.8K run time package to the file before the object code for the program is generated. The following tables will give a description of memory usage at run time.
Page Zero

$0000  to  $007F    Used by Operating system
$0080  to  $0097    Used by Compiled program
$0098  to  $00AF    Used if Every or After is used
$00BO  to  $00C2    Free memory ( COMPILE MODE )
$00C0  to  $00C2    Free memory ( RUN MODE )
$00C3               Last error number
$00C4  to  $00FF    Free memory
$0100  to  $01FF    Stack for everything ( Return addresses & arguments etc )
$0200  to  $05FF    Used by Operating system
$0600  to  $06FF    Free memory ( COMPILE MODE )
$0680  to  $06FF    Free memory ( RUN MODE )
$0700  to  APPMHI   DOS & Compiled program
APPMHI to  MEMTOP   Screen displays
Note that if you use the resident floating point package, some extra page zero addresses will be used (See Atari's Operating System manuals for more details).

Limitations

Depth of Stack

Since this program uses the 6502 hardware stack for virtualy all data movements and control transfers, it is advisable not to nest procedures and functions to deep as the stack will quickly fill up. If the stack does overflow, the program cannot detect it. Therefore it is VERY important that if you jump out of a subroutine you pop off the return address or addresses.

The stack is used for evaluation of expression, passing parameters to procedures or functions & holding return addresses, as well as any data you may have PUSHed on. In general if you don't jump out of a subroutine, procedure or function you should not have any problems.

WRITE command

In this commands the arguments may not be an expression. They may only be constants or variables.

AFTER & EVERY

Although you may use any of the predefined procedures in this language within the portion of code called by the EVERY and AFTER commands, you should not use any that are not resident, unless you can be sure that the called function or procedure was not in use when the interrupt occured.

If you use a FUNCTION in both the main code and in the EVERY or AFTER routine, then the FUNCTION will probably return incorrect results. This is because the functions use statically allocated variables. When the interrupt routine calls the FUNCTION, the FUNCTION will lose all its previous values that it was in the middle of calculating.

Some Useful Functions

DPEEK

Purpose:    To look at a word address (2 bytes)
External:   PEEK Function
Syntax:     var = DPEEK (adr)
This function will return the value of the memory address. The value will be the 16 bits found in the specified address and the following address. Address holds low byte and address+1 holds high byte.
     LOCAL
     VARIABLE ?ADR
     FUNCTION DPEEK (?ADR)
       DPEEK = PEEK(?ADR)+256*PEEK(?ADR+1)
     RETURN

LOCATE

Purpose:    To return contents of screen location
External:   None
Syntax:     var = LOCATE (exp1,exp2)
This function will return the contents of the screen location specified by exp1 and exp2. Exp1 is the 'X' position and exp2 is the 'Y' position
     LOCAL
     VARIABLE ?XPOS,?YPOS
     FUNCTION LOCATE (?XPOS,?YPOS)
       PUSH (?XPOS,?YPOS)
       CODE 686885546885
       CODE 56688555A260
       CODE A9009D48039D
       CODE 4903A9079D42
       CODE 032056E448A9
       CODE 0048
       PULL (LOCATE)
     END

NOT

Purpose:    To return the logical NOT of an expression.
Syntax:     var = NOT (exp)
This function returns the logical NOT of exp, (ie. non zero returns TRUE (1) and zero returns FALSE (0)).
      LOCAL
      VARIABLE ?NUM
      FUNCTION NOT (?NUM)
        NOT=1*(?NUM<>0)
      END

PADDLE

Purpose:    To return the position of a paddle
External:   PEEK Function
Syntax:     var = PADDLE (exp)
This function will return the value of one of the paddles specified by the lowest 3 bits of exp.
     LOCAL
     VARIABLE ?NUM
     FUNCTION PADDLE (?NUM)
       PADDLE = PEEK(624+(?NUM .AND. 7))
     END

PEEK

Purpose:    To look at a byte address
External:   None
Syntax:     var = PEEK (adr)
This function will return the 8 bit value that is stored at memory location specified by adr.
     LOCAL
     FUNCTION PEEK (?ADR)
       CODE AD
       VARIABLE ?ADR
       PHA
       CODE A900
       PHA
       PULL (PEEK)
     END
Note the trick used by defining the variable after the LDA opcode. The variable is assigned before the LDA instruction which then loads the value from the address specified by the variable.

PTRIG

Purpose:    To return the status of a paddle trigger
External:   PEEK Function
Syntax:     var = PTRIG (exp)
This function will return a 0 if the specified trigger is pressed and a 1 if it is not pressed. The required trigger is specified by the lower 3 bits of exp.
     LOCAL
     VARIABLE ?NUM
     FUNCTION PTRIG (?NUM)
       PTRIG = PEEK(636+(?NUM .AND. 7))
     END

RND

Purpose:    To generate a random number
External:   None
Syntax:     var = RND (exp)
This function will return a random number between 0 and the value of exp-1.
     LOCAL
     VARIABLE ?NUM,53770=?RANDOM
     FUNCTION RND (?NUM)
       RND=(?RANDOM*256+(?RANDOM .AND. 255)) MOD ?NUM
     END

STICK

Purpose:    Return joystick position
External:   PEEK Function
Syntax:     var = STICK (exp)
This function will read the position of one of the joysticks. The joystick to be read is specified by the lowest 2 bits of exp.
     LOCAL
     VARIABLE ?NUM
     FUNCTION STICK (?NUM)
       STICK = PEEK(632+(?NUM .AND. 3))
     END

STRIG

Purpose:    To return the status of a joystick trigger
External:   PEEK Function
Syntax:     var = STRIG (exp)
This function will return the status of the specified joystick trigger, 0 means trigger is pressed and 1 means trigger is not pressed. The trigger number is specified by the lower 2 bits of exp.
     LOCAL
     VARIABLE ?NUM
     FUNCTION STRIG (?NUM)
       STRIG = PEEK(644+(?NUM .AND. 3))
     END

VAL

Purpose:    Returns numeric value of text data
External:   None
Syntax:     var = VAL (adr)
This function returns the numeric value of the characters pointed to by adr.
     LOCAL
     VARIABLE ?ADR
     FUNCTION VAL (?ADR)
       PUSH (?ADR)
       CODE 6885F46885F3
       CODE A90085F22000
       CODE D8B00520D2D9
       CODE 9006A90085D4
       CODE 85D5A5D448A5
       CODE D548
       PULL (VAL)
     END

Example:    POINTER NUMBER
            ASCII "45"
            CODE 9B
            VARIABLE A
            BEGIN
            A=VAL(NUMBER)
            WRITE (A)
            RETURN
This would set the variable 'A' equal to 45 and then write it out onto the screen.

Floating point support procedures

Since the language does not have any inbuilt floating point procedures, here is a short program that will allow you to do limited calculations with floating point numbers. The number can only be operated on by one opperation at a time using the following procedures. If an error is detected by the floating point routines then an error number of 1 will be issued. Note that FR1 & FR2 are both pointers to a floating point numbers, these numbers are printed out by using the 'FWRITE' command.

ADD

Purpose:    To add 2 floating point numbers together
Syntax:     ADD (FR1,FR2)
This procedure will add FR2 to FR1 and store the result in FR1.

DIV

Purpose:    To divide 2 floating point numbers
Syntax:     DIV (FR1,FR2)
This procedure will divide FR1 by FR2 and store the result in FR1.

EQUALS

Purpose:    To set a floating point number equal to another
Syntax:     EQUALS (FR1,FR2)
This procedure will set FR1 equal to the value of FR2.

EXP

Purpose:    To return the base 10 exponential
Syntax:     EXP (FR1)
This procedure will return the base 10 exponential and store the result in FR1.

EXPe

Purpose:    To return the natural exponential
Syntax:     EXPe (FR1)
This procedure will return the natural exponential and store the result in FR1.

LOG

Purpose:    To return the base 10 logarithm
Syntax:     LOG (FR1)
This procedure will take the base 10 logarithm of FR1 and store the result back into FR1.

LOGe

Purpose:    To return the natural logarithm.
Syntax:     LOGe (FR1)
This procedure will take the natural logarithm of FR1 and store the result back into FR1.

MULT

Purpose:    To multiply 2 floating point numbers together
Syntax:     MULT (FR1,FR2)
This procedure will multiply FR1 by FR2 and store the result in FR1.

SUB

Purpose:    To subtract 2 floating point numbers
Syntax:     SUB (FR1,FR2)
This procedure will subtract FR2 from FR1 and store the result in FR1.

Listing of floating point support package

            ;
            ; ================
            ;  Floating point
            ; support routines
            ; (c) 8th May 1986
            ; ================
            ;
            LOCAL
            VARIABLE ?FP1,?FP2,2=?ADR,?NUM,?STATUS
            ;
            ; =======================
            ; Floating point addition
            ; =======================
            ;
            PROCEDURE ADD (?FP1,?FP2)
              FP (2,55910)
            END
            ;
            ; ==========================
            ; Floating point subtraction
            ; ==========================
            ;
            PROCEDURE SUB (?FP1,?FP2)
              FP (2,55904)
            END
            ;
            ; =============================
            ; Floating point multiplication
            ; =============================
            ;
            PROCEDURE MULT (?FP1,?FP2)
              FP (2,56027)
            END
            ;
            ; =======================
            ; Floating point division
            ; =======================
            ;
            PROCEDURE DIV (?FP1,?FP2)
              FP (2,56104)
            END
            ;
            ; =========
            ; FP1 = FP2
            ; =========
            ;
            PROCEDURE EQUALS (?FP1,?FP2)
              MOVE (?FP2,?FP1,6)
            END
            ;
            ; ===================
            ; Floating point LOGe
            ; ===================
            ;
            PROCEDURE LOGe (?FP1)
              FP (1,57037)
            END
            ;
            ; ==================
            ; Floating point LOG
            ; ==================
            ;
            PROCEDURE LOG (?FP1)
              FP (1,57041)
            END
            ;
            ; ===================
            ; Floating point EXPe
            ; ===================
            ;
            PROCEDURE EXPe (?FP1)
              FP (1,56768)
            END
            ;
            ; ===================
            ; Floating point EXPe
            ; ===================
            ;
            PROCEDURE EXP (?FP1)
              FP (1,56780)
            END
            ;
            ; ===========================
            ; Call floating point package
            ; ===========================
            ;
            PROCEDURE FP (?NUM,?ADR)
              MOVE (?FP1,212,6)
              IF (?NUM<>1) THEN
                MOVE (?FP2,224,6)
              END IF
              GOSUB 65020
              PHP
              PHP
              PULL (?STATUS)
              IF (?STATUS .AND. 1)<>0 THEN
                ERROR 1
              END IF
              MOVE (212,?FP1,6)
            END
      65020 CODE 6C0200

Error Codes

 1 - Start of program (BEGIN) not defined
 2 - Out of memory
 3 - Number out of range (less than 0 or greater than 65535)
 4 - Label not defined
 5 - Variable not defined
 6 - Incorrect number of parameters
 7 - Quatation marks missing
 8 - Error in expression
 9 - Invalid expression
10 - Invalid character
11 - Constant expected
12 - Requested line number missing
13 - Syntax error in line
14 - Procedure not defined
15 - Duplicate label
16 - Construct nested to deep
17 - To many local regions ( greater than 250)
18 - Nested INCLUDE requested
19 - Begin already defined
20 - Duplicate label number
21 - Function not defined
22 - Operators expected
23 - Variable or Constant expected
24 - Invalid nesting of IF and WHILE commands. eg IF exp THEN ... END WHILE

Known Bugs

No checking is made for running out of memory when building symbol tables, if characters start to appear on screen this has probably occured. In this case save the source program to disk and write a small routine to INCLUDE it in. This will give more memory for use as a symbol table.

No checking is made for passing the correct number of arguments to a function or procedure, and if these are incorrect it could crash the program from either filling the stack up or pulling the return address off stack.
Author: David Firth: david@signus.demon.co.uk