.........1.........2.........3.........4.........5.........6.........7.........8 HISOFT Presents The Colt FAST BASIC COMPILER COLT ZX BASIC Compiler Manual Copyright Threlfall and Hodgson 1985 Published by Hisoft 180 High Street Dunstable LU6 1AT First Edition August 1985 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = CONTENTS -------- Page 1 Introduction Page 1 The compilation process Page 2 Getting started with COLT Page 4 COLT in detail Page 5 Loading the compiler Page 5 COLT statements Page 9 Strings and arrays Page 9 Error messages during compilation Page 10 Run-time errors Page 10 Saving compiled code Page 11 Re-loading compiled code Page 11 Trace facilities Page 12 Compiling up to 32K Page 12 Returning to Basic Page 13 Fetching variables from Basic Page 13 Taking COLT variables back to Basic Page 14 Floating point? Page 15 LOAD commands Page 15 Speed Page 16 Strange Errors Page 16 COLT in Detail Page 18 Changing these space allocations - some useful addresses Page 18 Calls between Basic and COLT Page 19 Compiling subroutines Page 19 Re-entering code Page 21 The Executive Page 22 Using the Executive Page 22 Quick access commands Page 23 User-definable "soft" (function) keys Page 24 Enhanced Basic Commands Page 24 Window commands Page 26 Sprite commands Page 27 Reading the keyboard Page 28 Other commands Page 31 User-defined Basic Page 32 Executive error messages Page 33 Other disc/wafer interfaces = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Introduction ------------ Welcome to the world of fast programs and easy development given to you and your ZX Spectrum with Hisoft's COLT Basic compiler. COLT is a totally new product which transforms your Spectrum Basic programs into pure z80 machine code, making them run between 2 and 800 times faster! COLT is easy to use and is small enough to allow most programs to be compiled. Before we start to use it, we'll look into the process of compilation to see why having a program such as COLT is so handy. The compilation process ----------------------- When you write a Basic program on your Spectrum, you're taking advantage of the machine's in-built "interactive" features. This means that you can write part of a program, run it and correct any errors. This can be done because the Basic system used by the Spectrum is known as an "interpreter". It takes each line of Basic which you type in, and if the line makes sense it is added to the Basic program in memory. The "syntax checker", which prints a flashing '?' whenever you attempt to enter an incorrect line, can detect only what is known as a "syntax error". A syntax error is a programming error which cannot form part of a Basic program because it does not conform to the "syntax rules" of the language. For example, just as we cannot sensibly say "Time four half past is the" in English, we cannot assign a string to a numeric variable in Spectrum Basic: 10 LET a="This will cause a syntax error" The syntax checker cannot detect "algorithmic" errors, which are programming errors that, although perfectly valid Basic, do not really do what you expect or require. You may have a line which adds 10 to a variable, for instance, when in fact you are supposed to be adding 5. These are always the hardest errors to find! Once you have a valid Basic program in the Spectrum's memory, you can execute the program by typing 'RUN' and pressing the ENTER key. Errors can still occur, of course, if you miss out lines or perform incorrect calculations. The program will then stop with an "error report", telling you at which line the error occurred. This is why the system is known as "interactive", as it allows you to correct errors as they occur, rather than having to run the program, find all the errors, and correct them all before running the program again. Interaction is a feature of interpreters, as they run programs in a particular way. When you RUN a program, the interpreter finds the first line of the program, which is stored in the computer as Basic, and works out what it is supposed to do with the line. This may involve continuing on to other lines, it may involve calling subroutines, or it may just print something on the screen and finish. It doesn't matter what it does, but how it does it. Interpreted programs are automatically much slower than the computer is truly capable of because each individual line has to be examined by the interpreter program every time it is met. A FOR ... NEXT loop is not automatically converted into a machine code loop which ends after a certain number of iterations, but is examined each time the line containing the NEXT is encountered, and a check is made to see if the end of the loop has been reached. The Spectrum Basic interpreter lives in the ROM (read- only memory) inside the machine and cannot easily be removed. COLT supplants this interpreter with a program known as a "compiler". A compiler is a program which converts another program written in a particular language to machine code (in this case), so that the computer can run this program directly rather than having to go through an interpreter. In the case of the COLT compiler, the language which it converts from is Spectrum Basic. The end result is a comparatively short machine code program which will do exactly what the Basic program does, but considerably faster. As it is now in machine code, we cannot run our program by typing 'RUN', as this is an interpreter command. Instead, we need to "call" it using an address given to us by the compiler. We can call machine code programs with the RANDOMIZE USR
statement, where
is the address which we want to call. There are a very few Basic features which the COLT compiler cannot handle, but we needn't consider them until later. To see how the whole system works, let's start from the beginning. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Getting started with COLT ------------------------- The COLT compiler is supplied on a cassette tape which incorporates a short BASIC loader to get the compiler into memory and initialise it. Make sure that this cassette is fully rewound and then place it in your cassette player ready to be loaded. Type: LOAD "" (ENTER> (press the 'J' key followed by two presses of the SYMBOL-SHIFT 'P' combination) and press PLAY on your cassette recorder. After a few seconds the familiar tape loading stripes should appear on the screen and the program name will be printed: Program: COLT If this doesn't happen, rewind the cassette recorder and try again. If, after numerous attempts, you still cannot get the tape to load, return it to Hisoft when we will be pleased to send you a free replacement. Eventually, the BASIC program will have loaded and started running. The first thing it does is to automatically load the compiler machine code into the computer. When the whole process has finished, you will be asked if you want to make a backup (working) copy of the compiler. If this is the first time that you have used the compiler, we strongly recommend that you answer 'Y' to this question. Hisoft licences you to make one working copy of the compiler on either cassette tape or microdrive cartridge. If you do answer 'Y', you will then be asked if you want to save the copy to cassette tape or microdrive. If you have a microdrive it is obviously sensible to save your working copy on a cartridge as it will subsequently load much faster. Next you are asked whether you want to change the start address of the compiled program from 40000. Answer 'N' to this at the moment, as you won't need to do this until you are compiling large programs. You'll see the screen clear and a clock appear in the top right of the screen, ticking away happily. This clock is part of the "Executive" program, which we'll be examining in greater detail later. Now type in this program in the normal way: 10 LET h$="0123456789ABCDEF" 20 FOR a=0 TO 255 30 LET d$=" " : REM TWO spaces inside the string 40 GO SUB 100 50 POKE 23692,255 60 PRINT a;" = ";d$ 70 NEXT a 80 STOP 100 LET x=INT (a/16): LET y=a-16*x 110 LET d$(1)=h$(x+1) 120 LET d$(2)=h$(y+1) 130 RETURN When you run this program, you will see the numbers from 0 to 255 printed out along with their hexadecimal (base 16) equivalents. The "POKE 23692,255" statement on line 50 simply stops the computer asking "Scroll?" each time the screen is filled up. If you time this program, you'll find that it takes just over 30 seconds to complete. To compile the program type RANDOMIZE USR 60000 and press ENTER. After a very short time, you should see this information printed on the screen: 00:00:00:0 HISOFT COLT Integer Compiler 1.0 (c) 1985 THRELFALL and HODGSON Compiling Line 140 Compiled OK Begin End Vars Lines 40000 40384 51517 51999 Names Nmtop Ctop Nvars 52059 52191 52460 80 To run RANDOMIZE USR 40000 (some of the numbers and messages may be different, but don't worry) All these numbers will be useful to advanced programmers, but the rest of us can ignore them. All we need to know is that the "Compiled OK" message appeared. If a line cannot be compiled (either because it doesn't make sense or because it is one of the things which COLT cannot deal with) then the dubious line is reproduced on the screen with a flashing '?' mark next to the offending part of the line. This program, if typed in correctly, will not cause any errors. When the screen display above appears, run the compiled program by typing: RANDOMIZE USR 40000 (and press ENTER) you can see the difference immediately! Although our example turns out only to be about twice as fast as interpreted Basic, other programs can achieve as much as 70 times greater execution speed. When the compiled program finishes, you can type LIST and find that the original program is still there, ready to be altered and re-compiled at once. By allowing us to do this, the COLT compiler maintains the interactivity provided by the standard Basic interpreter. Now we can look at each feature of COLT and describe its operation in more detail. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - COLT in detail -------------- COLT is a fully microdrive and Interface 1 compatible integer Basic compiler for the ZX Spectrum and Spectrum+. It will compile nearly all ZX Basic code including strings, all the microdrive commands, tape commands, RS232 commands, networking commands and finally the commands associated with the EXECUTIVE. COLT is an "Integer" Basic, which means that it can deal only with whole numbers between -32768 and 32767. This has been done so that the maximum speed can be attained, making COLT ideal for writing high-quality arcade-style games. COLT has been written to not use floating point arithmetic as the increase in speed over the Spectrum's own interpreter would be negligible. COLT includes many special features to maintain compatibility with Spectrum Basic. There are no special commands which cannot be tested in the normal interactive environment. Here is a list of some of the features of COLT: Full string handling Up to 26 one-dimensional arrays and 26 one-dimensional string arrays. Fully microdrive / Interface 1 compatible All microdrive commands except DATA can be compiled Full variable names Access to Basic variables Basic access to COLT variables INPUT with full line editing Computed GOTOs VAL and VAL$ may be used Break key can be permanently enabled Compiles up to 32K of Basic, producing very fast code Very fast compilation (maximum 2 seconds per 1K of Basic) with precise error reporting - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Loading the compiler -------------------- You should load the compiler by typing the command LOAD "". This will load a Basic program which gives some information on the compiler. You will be offered the opportunity of making a working copy to tape or microdrive. This will enable you to treat the copy you have just received as a MASTER BACKUP. In addition, you will be given the chance to change the point at which the compiler places the compiled code. This is RAMTOP, and for the compiler alone may be between 26000 and 59000. If you use the Executive as well then the upper limit is 52000. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - COLT statements --------------- Variable names may be of any length but may contain only the characters 'A' to 'Z', 'a' to 'z' and '0' to '9' (but a digit cannot be the first character of a variable's name). As in Basic, upper and lower case are treated as being the same. There must not be any colour codes embedded in the name or the compiler will object. In the list below: 'e' represents an arbitrary expression 'N' represents a positive integer 'a$' represents any string variable or sliced string expression (as in "x$(1 TO 4)") 'a' represents any simple or loop variable 'a(e)' represents any one-dimensional array or array element Colour codes and other control codes must not appear in the middle of lines, except within quotes. When 'x', 'y' and 'z' are given as arguments to a function then floating point evaluation is possible. The expression 'n/m' may replace 'x', 'y' or 'z' and 'n/m' is calculated to give a floating point result. 'n' and 'm' may be integer variables or integer bracketed expressions, e.g. "BEEP 1/3,5" sounds the beeper for 1/3 of a second. "BEEP (1+2)/(3+4),5" sounds it for 3/7ths of a second. A division sign is the only operator which is allowed outside of brackets, and there may be one only per argument (x, y or z). String expressions should not contain brackets (e.g. a$=(b$+c$)) as they are unnecessary and tend to confuse the compiler. In PRINT statements string comparisons must be in parentheses (brackets); e.g. use "PRINT ("x"<"y")" rather than "PRINT "x"<"y"". Unless otherwise stated, the functions below work exactly as in Basic (remembering that all arithmetic is done in integer form). This table should be examined in conjunction with the Spectrum manual. AND Boolean 'AND'. Cannot be used to mix strings and numbers: e.g. "b$=a$ AND 2" will not compile. ABS e Ar e,e ATTR(e,e) BEEP x,y See comments about floating point above. BIN e BORDER e BRIGHT e CIRCLE x,y,z CHR$ e CLS Both this and the special Interface 1 form CLS# are handled. CAT All forms are supported. CLEAR Clear compiled code variables only. The Interface 1 form "CLEAR#" to reset the channels is supported. The form "CLEAR 12345" is NOT supported. CLOSE All forms are supported. CODE a$ CONTINUE This is not useful in a program and may be compiled. It must be the first sub-statement in a multiple statement line. COPY DATA list 'list' must be a list of integers or strings in quotes and may not contain expressions. It must be the first and only statement in a line. DEF FN User-defined functions are NOT supported! DIM a(v) Only one-dimensional arrays are available in COLT. DIM a$(v) The storage of both arrays and strings is discussed later. Run-time array bound checking is minimal to make the speed of execution as high as possible. All arrays, strings and variables are erased when you re-enter a COLT program. DRAW x,y DRAW x,y,z ERASE FLASH e FN User-defined functions are NOT supported! FORMAT All forms supported. FOR a=u TO v STEP w 'STEP' is optional. Note that the difference between 'u' and 'v' cannot exceed 32767 and the loop is always traversed at least once. GOSUB n 'n' is a positive integer. The fast form of GO SUB. GOSUB e The expression must begin with a non-numeric (i.e. not a digit) and this is then evaluated at run-time. This option is relatively slow and should be used only when absolutely necessary. GOTO n as GOSUB GOTO e as GOSUB IF e THEN IN e INK e INKEY$ INKEY$ #e for Interface 1 INPUT a Editing exactly as in Basic. Colour operations and all three forms of INPUT may INPUT a(v) be intermixed. The suffix #e is allowed to INPUT a$ enable reading from the RS232 or from microdrive files. INT e Helps testing within the interactive environment. INVERSE e LEN a$ a$ cannot be sliced. LET a=e LET a$=a$ LINE LOAD All forms including the microdrive derivatives may be used with the exception of "LOAD ... DATA". See "LOAD commands" below. LPRINT With or without the addition of #e. MERGE MOVE All forms are supported. NEW NEXT a See 'FOR'. Note that COLT expects that the 'NEXT' will follow the 'FOR' when the code is read from top to bottom. OPEN All forms supported. OR OUT e,e OVER e PAPER e PAUSE e PEEK e PLOT e,e POKE e,e POINT(e,e) PRINT With or without #e. RANDOMIZE RANDOMIZE e READ a Reads a list of integers from DATA statements. Only minimal checking is performed to ensure that types are correct. READ a$ As for 'READ a', except that the data read are strings. REM See special type below. Used for testing BREAK key. RESTORE e Restores the data pointer to line e. Line e must exist and be a DATA statement. RESTORE Initialises the DATA pointer to the start of the program. RETURN RND Returns a random integer between 0 and 32767 (this is not quite the same as Basic). To obtain the same effect under Basic use USR 59997. SAVE All forms, including microdrive versions (except "LOAD ... DATA") are allowed. SCREEN$(e,e) SGN e STOP STR$ e See comments on strings and the section called "Floating Point?" below. TAB e TO All forms a$(m TO n), a$( TO n) and a$(m TO ) are allowed. USR e USR "string" VAL a$ If a$ contains a reference to a variable then the Basic variable of that name is used. See "Fetching from Basic" below. VAL$ a$ see VAL VERIFY All forms except "VERIFY ... DATA" allowed. All Executive commands of this form are compiled. Note, however, that "*fx Goto e" always returns to Basic line 'e', not compiled line 'e'. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Strings and arrays ------------------ Strings and arrays are stored within the Basic variable space (i.e. in the space pointed to by the system variable 'VARS' (location 23627)) and are at the front of this space. The space needed for strings and arrays is allocated dynamically as the need arises at run-time, just as in Sinclair Basic. There is one minor difference: if a string or array gets smaller, the space allocated to it does not decrease. This results in code which is about 5 times faster than that which would result if strings were made exactly the correct size. In general, string handling is roughly 20 to 25 times faster than Basic. The fact that the space is not handed back is invisible to the user as an enquiry like "LEN a$" will give the expected result. One side effect is that you may run out of space slightly earlier than usual. However, this process results in faster code for string handling than any other Spectrum Basic compiler. Arrays work in an exactly analogous fashion and get longer, but not shorter, if they are re-allocated. The old array space is reused. The only space used between 'STKEND' and 'RAMTOP' (Basic system variables) at run-time is temporary space used in forming string expressions and is built up from 256 bytes above STKEND (the end of normal Basic space). Note that as this gap is only 256 bytes long, no string should change in length by more than 255 bytes (characters) in one go. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Error messages during compilation --------------------------------- Any error will result in the offending line becoming the current (editing) line. Simply press EDIT (CAPS-SHIFT and 1 simultaneously) to bring the line down to the bottom of the screen ready to be edited. Error reports: 1 Next without For A 'NEXT' statement uses a variable which has not been seen so far in a 'FOR' statement. 2 Variable not found The maximum number of variables (255) has been exceeded. There is no cure except to use fewer variables. 4 Out of memory The table length for the variable names is not long enough (change locations 59991 and 2 - see "Technical Information" below). 8 End of file No code to compile. C Nonsense in Basic This means that the compiler can't compile this particular statement. G No room for line The space allocated to code is too small; try decreasing RAMTOP with a "CLEAR n" with n less than 40000. M RAMTOP no good No room for tables. There must be enough room for the names, lines and variables above RAMTOP for compilation to begin, even when compiling 32K of code. N Statement not found Using GOTO or GOSUB to go to a line number greater than 32767. This can occur at run-time with computed GOTOs and GOSUBs. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Run-time errors --------------- 3 Subscript wrong Only very rudimentary array bound checking is performed to speed up the code. 6 Number too big Usually due to dividing by zero. B Integer out of range A number greater than 32767 or less than -32768 has been used. D and L BREAK into program The BREAK key has been pressed. E Out of data A READ has been attempted after all the DATA statements have been exhausted. H STOP in INPUT The keyword 'STOP' was entered in response to an INPUT statement. P FN without DEF An EXECUTIVE routine has been called but the Executive is not present. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Saving compiled code -------------------- If you wish to save your compiled code you must save both the compiled code and the compiler. It is easiest to save from RAMTOP (usually 40000) to 65535 (the physical top of RAM) as this will also save any user-defined graphics. "E!k" in the EXECUTIVE will do this automatically, otherwise the command is: LET rt=USR 59200: SAVE "name" CODE rt,65535-rt: LET rt=USR 59200 Do not BREAK into this SAVE or the compiler will be corrupted. To minimise the amount of code to be saved try to make "Vars" only just larger than "End" (see "Technical information"). This may be accomplished by the following action: CLEAR (PEEK 23730+256*PEEK 23731)+(Vars-End-5) where "Vars" and "End" are read from the screen at the end of a compilation. The code must then be recompiled and the new entry point noted. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Re-loading compiled code ------------------------ It is extremely important that before re-loading compiled code into a "clean" machine you should "CLEAR n", where 'n' is the address to which your code was compiled (normally 40000). Failure to do this will usually crash the machine. If the compiled code which you re-load contains Executive commands, then the Executive must be re-started with RANDOMIZE USR 55020. This is not necessary for sprite or window functions. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Trace facilities ---------------- A very helpful feature of COLT is that you can use it with or without the BREAK key enabled, and, in addition, in association with the Executive, a trace of each line being executed can be seen. This is achieved by three different 'REM' statements, each of the form "REM #n": REM #0 BREAK is disabled except at "Scroll?", INPUT and during tape and microdrive commands. This results in the fastest, smallest and most secure code. Programs can be broken in to with the Executive. REM #1 BREAK enabled. This produces longer code than REM #0, but BREAK works as usual. REM #2 When used in association with the Executive "*fx line" command, the current line number is displayed every 50th of a second. This clearly is a very powerful feature when debugging. It will cause the line number (but not the statement number) to be printed if there is an error. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Compiling up to to 32K ---------------------- Usually, it is possible only to compile about 16K or so of Basic in a 48K machine (a little less if you are using the Executive). This is because the machine must hold both your source code (i.e. the Basic program) and the resulting compiled code. The latter is much the same size as the former. When working to and from cassette tape this is clearly a good method, as you still have the Basic present to try again if your code does not work as intended. With the advent of the microdrives the position has changed. Provided that you have saved your Basic code, you are unlikely to mind if the compiler removes it from memory during the compilation process. This fact is used in COLT to allow you to compile 30 to 34K of Basic, as follows: 1) SAVE your Basic code 2) With a "CLEAR n" set RAMTOP so that there is room for the area from 'Vars' to 'Ctop' (see "Technical information"). For a 32K program this will need to be about 5K, so use CLEAR 55000. 3) POKE the COLT variable at 59987 (a two-byte integer) with the final RAMTOP address at which you wish the code to be compiled. For example, to make it 32767 (= 127 * 256 + 255), you should: POKE 59987,255: POKE 59988,127 4) Compile. If the compilation is successful then the Basic area will be empty. If any compilation error occurs, the Basic should still be there. Error messages are produced as usual. 5) During compilation, the machine stack has been moved from your original choice to location 65535 (so over-writing the last few UDGs) and then to your new chosen value. 6) Before re-loading any files you should re-execute step 2 above or there will not be room for the Basic. 7) Note that if you have the Executive present then about 25K only of Basic can be compiled, and the first CLEAR (step 2) should be to about 48000. To turn off the Executive to make more space, type: RANDOMIZE USR 59190 and press ENTER. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Returning to Basic ------------------ A section of compiled code will return automatically to Basic when it finishes. STOP will cause a normal error 9 report. If the compiled code was called by an immediate mode command (typed at the bottom), then no statements after the "RANDOMIZE USR n" will be executed. If the code is called by a line in another program then it will return to the next statement. This is carried out by the compiled code executing a CONTINUE, so if you wish to return to some other point in Basic, you should POKE 'OLDPPC' (location 23662) with the line number and 'OSPPC' (location 23664) with the statement number. This will over-ride the values put there by the compiler and must be in the compiled code. This method may also be used to chain programs. If the compiled code contains a line "LOAD "fred"", and the compiled code is invoked from line 10, first statement, then the compiler will return to the second statement in line 10 (if it exists) or the next line in "fred". Hence, you may chain Basic and compiled code. Note however that the LOAD command will destroy the compiled code's arrays and strings. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Fetching variables from Basic ----------------------------- There will be many occasions when you wish to pick up the value of a Basic variable for use in a COLT program. For this reason, if the argument to the VAL function contains a reference to a variable, it uses the Basic variable rather than the COLT variable. This allows you to write statements like LET fred=VAL "fred" which would take the Basic variable 'fred' and transfer its value into the COLT variable 'fred'. The same applies to members of an array: LET b(10)=VAL "b(10)" The 'VAL$' function may be used to get Basic strings into COLT, like this: LET a$=VAL$ "a$" which gets the Basic string variable 'a$' into the COLT string variable 'a$'. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Taking COLT variables back to Basic ----------------------------------- This is not quite as easy as the converse, so a special function has been provided to help: LET fred=USR 59227: PRINT "john" will set Basic variable 'fred' to be equal to COLT variable 'john'. This can be extended to arrays and strings: LET point=USR 59227: PRINT "b(n)" will set 'point' to be an integer pointer to the FIRST member of the COLT array 'b'. 'n' may take any value but the pointer is always to the first member. To access the first element of the array 'b', a Basic line like LET b(1)=PEEK point + 256*PEEK(point+1) would suffice. To get at the 'nth' member, use: LET b(n)=PEEK (point+2*(n-1)) + 256*PEEK (point+2*(n-1)+1) the factor of two allows for the fact that there are 2 bytes per array member. To access a string we would type: LET point=USR 59227: PRINT "a$" where 'point' points to the first member of the COLT string 'a$', (i.e. a$(1)), 'point+1' points to the second member (a$(2)), and so on. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Floating point? --------------- We said at the beginning that COLT used only integer arithmetic, as floating point mathematics is prohibitively expensive in computer time. Exceptions to this rule have been seen already in the DRAW and BEEP commands. The VAL and STR$ functions give access to full floating point arithmetic. Try: PRINT STR$ VAL "SQR 3" You will see that a floating point number is printed out. The VAL function can be used to make available all the floating point functions, such as SIN, COS and TAN. Using the function VAL by itself always returns the result of the floating point operation as an integer. For example: LET a=VAL "100*SQR 20" will set 'a' to be 447. However, "STR$ VAL" has been set to return the floating point result into the string: LET a$=STR$ VAL "100/3" will set a$ to be the string "33.333333". This string can then be manipulated further by repeated use of these functions: LET b$=a$+"*2" LET c$=STR$ VAL b$ Sets c$ to be two times the value of the number held in a$: "66.666666". This process can be continued indefinitely. Note also that any variables used in quotes, like "a*b", refer to the Basic variables 'a' and 'b', not the COLT ones. This form of arithmetic is useful but will run at much the same speed as Basic. Here are a few examples: 10 LET a=VAL "SIN(.523598775)*100+100*.01" 20 PRINT a gives 51 both in Basic and compiled code. Note that the expression did not contain any variables. This may be accomplished like this: 10 LET b=100 20 LET a=VAL ("SIN(.523598775)*100+0.01*"+STR$ b) 30 PRINT b which uses the compiled variable 'b'. However, if line 20 was replaced by: 20 LET a=VAL("SIN(.523598775)*100+0.01*b") the Basic variable 'b' would be used. All the above return integer values, but by using strings we may obtain floating point ones: 10 LET a$="100/LN 12+ EXP 2" 20 LET b$="SIN 1+COS 2+TAN 3+0.01" 30 LET c$=VAL(a$+"2.34973+"+b$) 40 PRINT c$ which gives 300 both in Basic and compiled code. It must be admitted that it is rather cumbersome, but it works! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LOAD commands ------------- If you wish to compile these a word of warning is necessary: "LOAD CODE" will work correctly, but loading Basic is dangerous. It will work successfully, but in doing so will wipe out all the COLT arrays and strings from the 'VARS' area of Basic. If you are not using any, then this won't matter, but otherwise strange results will ensue. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Speed ----- Speed is the main reason that most people buy a compiler, and COLT produces very fast code. Although some functions, such as DRAW, CIRCLE and tape commands are no faster than Basic, others are very fast indeed. A FOR ... NEXT loop at the bottom of a 16K program takes nearly 800 times longer in Basic than when compiled under COLT. In general, though, an improvement of about 50 times is to be expected, the ratio improving with larger programs. Executive commands vary considerably in the amount they are speeded up. A simple command will be much faster, while a typical sprite MOVE command may be only 2 to 4 times faster as the Executive commands are already very efficient. On the standard "KILOBAUD" tests as used in most magazines, the average improvement over Spectrum Basic is about 75 times. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Strange Errors On most occasions when COLT appears to give strange results the problem can be attributed usually to problems with integers. Remember that a calculation which would normally yield a fractional result will be rounded to an integer with COLT, and that the maximum range of numbers which can be operated on is -32768 to 32767. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - COLT in Detail -------------- This Section gives details of the more advanced operations of COLT, together with the internal workings of the system and ways to enhance it. The compiler is invoked with the command: RANDOMIZE USR 60000 If any Basic command is found which cannot be compiled, the line up to that point followed by a flashing cursor will be shown. A return to Basic will be made with the offending line being made the "current line" (it will have the '>' listing marker after its line number). After an initial pass of the code during which any errors should show up, a second pass is made immediately. During both passes the message: Compiling line xxxx will appear. This is followed immediately by a table of useful information about the layout of your compiled code in the machine. The table appears as shown over the page: Begin End Vars Lines xxxxx xxxxx xxxxx xxxxx Names Nmtop Ctop Nvars xxxxx xxxxx xxxxx xx To run type RANDOMIZE USR xxxxx To explain these numbers, we'll use a diagram: ----------------------------------------------------------------------- Basic | Spare | Compiled Code | Unused | Vars | Lines | Names | | COLT ---------------------------------------|------|-------|-------|-|------ | | | | | STKEND RAMTOP End Vars Lines Names | | = Begin | Ctop Nmtop 'STKEND' A Basic system variable (address 23653 and 4) which marks the end of the space occupied by Basic. 'RAMTOP' A Basic system variable which marks the highest point that Basic is allowed to reach. This is set by "CLEAR n" in Basic, and defaults to 40000 under COLT. 'Begin' Usually this is the same as the original RAMTOP, but when compiling 32K, it changes (see below). 'End' Marks the end of the compiled code. From here to 'Vars' is free for more program. 'Vars' The variables used by COLT are not the same as similarly-named Basic variables. They are stored here. The space needed is 2 bytes per new variable after the initial ones. All variables have an entry in this table. The 26 single-letter variables are first, containing space for the value, the loop end and the step. Strings are next (26 of them), and here the table contains a pointer to the string, its length, and its absolute maximum length. The 26 arrays are last, with similar pointers. 'Lines' In order to compile 'GOTO' and 'GOSUB', etc., a table of line numbers and addresses is built here. It is kept for use in computed GOTOs. This space is four times the number of lines. 'Names' You may have up to 255 variables in COLT. The first two are system variables, the next 78 are the string variables, array variables and FOR-loop variables (single letters). These are pre-defined to make the code as fast as possible. The space from 'Names' to 'Ctop' is reserved for the names of your variables. By default, a few hundred bytes are allocated, but you may change this (see below). 'Nmtop' The last location used between 'Names' and 'Ctop' for variable names. 'Nvars' The number of variable names you have used. This will never be less than 80. 'Ctop' The last space which may be used during the compilation of code. This is normally just before the start of COLT (or the Executive if you are using it). This value may be changed (see below). The bottom of the compiler is at 59200, and the bottom of the Executive is at 52000. -------------------------------------------------------------------- Changing these space allocations - some useful addresses -------------------------------------------------------- All numbers are stored as two-byte integers in normal Z-80 (i.e. reversed) format. The locations of interest are: 59987 Normally this is set to zero, but if it is made non- zero then this is the address of the new RAMTOP to be adopted when the Basic code is erased during a 32K compilation. 59991 The space allocated to variable names. 59993 The address of 'Ctop' above. You may wish to change this if you are compiling subroutines. 59997 Use "RANDOMIZE USR 59997" to access COLT's random number generator from Basic. -------------------------------------------------------------------- Calls between Basic and COLT ---------------------------- When you have finished your program and compiled it, you will usually delete all the Basic code and treat the compiled code as a subroutine (i.e. you will call it with "RANDOMIZE USR xxxxx"). Note that it is a true subroutine and the variables used in COLT are not the same as the Basic ones and vice versa. The easiest way to delete all the Basic code is to type 'NEW'. This clears the machine up to RAMTOP. The compiled code is above RAMTOP, and is safe from deletion. You can now call your compiled code with the simple statement: RANDOMIZE USR n where 'n' is the value of RAMTOP you chose, usually 40000. This Statement may be issued either in immediate mode or in a program line. Note that in either case any further statements on that line will not be executed. Another slight restriction is that while Basic can call as many compiled sections as you wish (see "Compiling subroutines"), you should not call one COLT section from another. This is because entering a compiled section always clears any old COLT arrays and strings from the Basic variables area. In addition, when you reach the end of a section of compiled code, there is not a simple return to Basic but a jump to the next statement of Basic after the one which called the compiled code. This is necessary due to the uncertain state of the machine stack after certain ROM routines. See the section on returning to Basic. For the same reason, you cannot call compiled code from your own machine code. -------------------------------------------------------------------- Compiling subroutines --------------------- It is possible to compile several sections of Basic to be treated as totally independent subroutines. The procedure is as follows: 1) Compile the first section. Now make a note of the variables 'End' and 'Vars', which are given on the screen following compilation. Subtract the smaller from the larger and adjust RAMTOP (by a "CLEAR n") so that it is increased by this amount minus one (i.e. End - Vars - 1). For example, if RAMTOP was 40000 (='Begin'), 'End' was 54000 and 'Vars' was 57000, then you should issue the command: CLEAR 42999 2) Recompile to this new RAMTOP and make a note of the variable 'Begin' which is displayed. This will be the USR call for the first section of code. 3) Modify the COLT variable 'Ctop', which is location 59993, so that the value is the old value of RAMTOP (=old value of 'Begin') minus one. This protects the code you have just generated from being overwritten. 4) Load or type the next section of Basic and issue a "CLEAR n", where 'n' is the location at which you wish the second section of code to be compiled. 5) Now follow the instructions 1 to 4 as many times as required. 6) Save from the last RAMTOP you have used to 65535 (this will include all UDGs as well). You would be well advised to do this step after each section of compilation. 7) Note that while there may be variables in several sections with the same names, they are NOT the same variables. When you re-enter a section at the beginning, all variables are set to zero. -------------------------------------------------------------------- Re-entering code It may occasionally be useful to re-enter a piece of compiled code without resetting all the variables; for example after a trapped error under the Executive. This is possible if you enter the code 19 locations on from the normal entry point. For example, if your code is at 40000, then: RANDOMIZE USR 40019 will enter the compiled code without clearing or destroying arrays, strings or variables. However, there are a few points which should be borne in mind if this process is to be totally successful: 1) You should not re-enter if you have used RUN or CLEAR since the last time the code was entered at the normal entry point. 2) You must enter at the normal point at least once before using the alternative point. 3) You must not alter your Basic area at all between calls, for instance by adding or altering lines of code or by opening or closing streams. 4) You can only re-enter the last section of code you ran. Here is an example of how this might be carried out: 1 IF A=1 THEN GOTO 10 2 DIM A(10) 3 FOR K=1 TO 10: LET A(K)=K 4 NEXT K 10 LET A=1 The first time the program is run, lines 1 to 10 will be executed (use "RANDOMIZE USR n"). If the program is subsequently re-run with "RANDOMIZE USR (n+19)" then only lines 1 and 10 will be executed. -------------------------------------------------------------------- The Executive ------------- The Executive is an integral part of the COLT program which allows numerous extra commands to be used in both standard Spectrum Basic and COLT-compiled programs. The Executive is automatically loaded and activated at the same time as COLT (it's responsible for the clock at the top of the screen), but it can be turned off and even removed if the space it takes up is required for use with COLT. Obviously, de-activating or removing the Executive means that no Executive commands must be issued in either interpreted or compiled Basic programs. Some of the features of the Executive are: * Sprite graphics for sophisticated moving pictures and objects * Window functions, including individual window scrolling and attribute setting * On-screen user-defined graphics generation * Machine code programs and subroutines may be called with parameters * ON ERROR GOTO statement * Two-byte PEEK and POKE * Decimal to binary / hexadecimal and hexadecimal to decimal conversions * Free space calculator to tell you how much memory is available * No 'USR' calls once the Executive is started. Every command looks like Basic and is syntax-checked on entry as usual * All Executive commands may be executed in immediate mode or intermixed with normal Basic commands * All commands will compile under COLT * User-defined Basic commands * Multiple line delete * Fully microdrive compatible * Programmable keys - ideal for those tortuous microdrive commands * On-screen clock with stopwatch facilities * On-screen trace of the line number being executed * Function key command to invoke the COLT compiler * Function key command to run program at RAMTOP (for COLT) * "Repeat last command" key -------------------------------------------------------------------- Using the Executive ------------------- The Executive code starts at address 52470 and finishes at 59200. If you want to save code which includes the Executive you should stop the Executive first, otherwise it will fail to verify on tape. If you do not wish to use the Executive and require the extra space for compiled code then the command: RANDOMIZE USR 59190 will erase it and allow a further 7K of Basic to be compiled. The compiled code must not call any Executive routines if you do this. The Executive uses interrupt mode 2, so it cannot be used with other programs using Interrupts. It is inactivated (but not erased) by 'NEW', so you should use: *fx d 1,9999: CLEAR to have the same effect as 'NEW', but without disabling the Executive. The Executive is started with: RANDOMIZE USR 55020 and can be stopped with: RANDOMIZE USR 55010 Note that with the Executive operating, programs will run about 10% slower than usual, due to the use of interrupts. -------------------------------------------------------------------- Quick access commands --------------------- The quick access commands allow you to use certain Executive commands with a very small number of keystrokes. In the table which follows, the symbols 'E!' mean "press SPACE and the letter, release SPACE then release the letter key". ENTER does not need to be pressed. E!t Switches the clock on. E!l Switches the line trace facility on. E!o Switches the clock or line trace off. E!s Stops clock display but does not switch the clock off. E!z Zero the clock display. E!i Initialize the clock - any key toggles a digit, and ENTER moves on to the next digit in the sequence. E!r Return last command issued to the command line. E!c Call the COLT compiler (this command actually executes a "RANDOMIZE USR 60000" command). E!p Executes the program at RAMTOP+1 (correct for COLT). E!k Save code. This generates the command to KEEP the compiled code plus compiler and UDGs to tape. The command presented may be edited to save to microdrive. The copy saved to tape may be reloaded with "CLEAR n: LOAD "name" CODE" where 'n' is the value of 'RAMTOP' to which the code was compiled. Unless you have changed it, this will be 40000. Note that when the code is reloaded the compiler is disabled, and 'E!c' should not be used. However, this does not mean that you may give copies of your compiled program to your friends. Do not break into the SAVE as the compiler will be disabled. E!x Breaks into and stops (exits) almost any program. Also returns display to normal black ink on white paper. -------------------------------------------------------------------- User-definable "soft" (function) keys ------------------------------------- Now that Sinclair has released the microdrives, the ability to press one or two keys to save or load programs is definitely an advantage. The microdrive commands can only be described as devilish, requiring several shifted characters. The "soft" or "programmable" key function provided by the Executive allows you to have your own special expressions pre- defined for access with only two key strokes. There are nine user-definable keys ('1' to '9'). Execution of the commands they represent is simplicity itself: just press 'E!number'. Here is how you define the keys: You should have a line 1 REM in which you type the command or characters you wish to have inserted in the input area. This may include keywords such as THEN, IF and so on (you may need a ':' before them to be able to enter them). Each definition is separated by either a (SYMBOL SHIFT H) or a '|' (Extended mode then SYMBOL-SHIFT S). If you use '^' then an ENTER character is automatically added on to the end of the function key string. If '|' is used, the machine returns to accept more input. Examples: 1 REM PRINT "Mary had a little lamb"| PRINT "its fleece was white as snow"^ Pressing 'E!1' would add: PRINT "Mary had a little lamb" to the input line, and wait for you to press ENTER or type some more. 'E!2' would print: "its fleece was white as snow" straight away. -------------------------------------------------------------------- Enhanced Basic Commands ----------------------- Executive commands must be entered with the Executive running and are just like Basic commands. They may be freely inter-mixed with Basic commands and are all of the form: *fx token/letter argument 1, argument2 ... Each argument is any valid expression and there may be up to 16 of them. Excess arguments will be ignored, and no error message will be given. Note that all arguments are treated as integers. An upper-case letter plus a bracketed series of letters following '*fx' means that you can type the first letter in upper or lower case. The letters in brackets may be omitted. Words totally in upper-case are Basic 'tokens' and are entered by a single keystroke, such as 'FN', 'FORMAT' and 'ERASE'. The result of an Executive command is in some cases an 8-bit integer (up to a value of 255), and sometimes a 16-bit integer. It should be obvious which is applicable. -------------------------------------------------------------------- Window Commands --------------- The Executive allows you to define a window on the Spectrum screen which is smaller than the normal screen size of 32 columns by 24 lines. Within this window there are many special functions which may be carried out, such as high-resolution scrolling and colour changes. *fx FN a,b,c,d Defines a window (we're using 'FN' to stand for FeNetre!) which has its top left corner at (line a, column b), is c lines deep and d columns wide. The default is the whole screen, and the minimum window size is 2x2. *fx PAPER n Changes the colour of the paper in the window to colour 'n' immediately ('n' is between 0 and 7). No error is reported if 'n' is outside this range, but 'n' is taken modulus 8 (so that 9 becomes 1, 10 is 2 and so on). *fx PAPER n,1 Changes the colour of the paper in the window only for those character locations matching the present attributes exactly in ink, paper, flash and bright. *fx INK n As PAPER but for INK colour. *fx INK n,1 As PAPER but for INK colour. *fx FLASH 0 Turns flashing off over the whole window. *fx FLASH n Where 'n' is greater than 0 turns flashing on over the whole window. *fx FLASH n,1 As for PAPER but for FLASH attribute. *fx BRIGHT 0 As for FLASH but controls the BRIGHT attribute. *fx BRIGHT n As for FLASH but controls the BRIGHT attribute. *fx BRIGHT n,1 As for FLASH but controls the BRIGHT attribute. *fx INVERSE 0 Inverts the window's attributes (the paper colour becomes the ink colour, and the ink colour is used for the paper). *fx INVERSE 0,1 As FLASH. *fx SCREEN$ n,p,q Moves the window ink in the direction 'n' (5, 6, 7 or 8, going in the direction indicated by the arrows on those keys) by 1 pixel 'p' times. 'q' defines the wraparound: q = 2: wrap from one side to the other q = 1: fill side with ink-coloured pixels q = 0: fill side with paper-coloured pixels q = -1: wrap and invert *fx ATTR n Moves window attributes in direction 'n'. This scrolls in the current attributes. *fx LINE n,p,r,q Moves character line 'r' in direction 'n' (5 for left or 8 for right) by 1 pixel 'p' tines. Wraparound is given by 'q' as above in 'SCREEN$'. Line 'r' must be within the current window for predictable results. -------------------------------------------------------------------- Sprite commands --------------- Sprites add a new dimension to Basic graphics on the Spectrum. They are user-defined characters of up to 32 pixels by 24 pixels which may be positioned anywhere on the screen. When a sprite is moved the background which was there before the sprite arrived is re-instated. Try that from ordinary Basic! There are commands which allow you to access the easy-to-use on-screen sprite definer as well as to make sprites visible and invisible at will. You can have up to 16 sprites. There are a few restrictions. You should not scroll the area of the screen containing a sprite if you wish to move it again, as it will be erased from its old home rather than the new one. On some machines (not the Spectrum!), this process is controlled by hardware and is then totally successful. *fx FORMAT n,a,b,c,d,m,e Sprite 'n' (where 'n' may be from 1 to 16) is defined to be at screen position (a,b) and to be 'c' pixels wide and 'd' deep. (Subject to the space limitation given above). The UDGs defining it start at address 'm' and successive bytes read across then down the sprite. The UDGs may be stored wherever you please. A sprite is always made visible after being formatted, its ink colour being that current when the sprite was defined, and the paper colour is 9. Only pixels which are ink are plotted, so if a character is only 2 pixels wide, make bits 0 to 5 zeros. To aid in defining sprites and UDGs in general, an on-screen character definition system is provided. If parameter 'e' is 1 in the *fx FORMAT command, then an 8 times full-size picture of the sprite or UDG will be shown on the screen. The cursor may be moved to change the character using the keys as follows: 0 - clear current pixel 1 - set current pixel 3 - clear the entire grid 4 - set the entire grid 5 - left 6 - down 7 - up 8 - right 9 - restore grid to the last-shown correct size ENTER - return to next command CAPS-SHIFT - show sprite at (a,b) full size For example, to define an ordinary UDG (say UDG letter 'A'), issue a command similar to this: *fx FORMAT 1,100,100,8,8,65368,USR"A" Note that using the sprite definer will turn the clock/trace off. *fx MOVE n,a,b,e Move sprite 'n' to pixel location (a,b). If parameter 'e' is given then the address of the UDG is changed to 'e'. This allows you to alternate UDGs to "animate" a sprite. When a sprite is moved it is always visible (if it is on the screen) afterwards. *fx ERASE n Temporarily remove sprite 'n' but leave defined. *fx ERASE Sets all sprites as erased, although they stay on the screen. You should do this after a 'CLS' command, otherwise the next 'MOVE' will re-draw the background you have just erased!. Colours will become confused if you don't use this instruction. The best advice is to use this at the start of your program and after every CLS. *fx VERIFY n This provides collision detection. It looks to see if sprite 'n' is overlapping any other sprite and sets location 54983 accordingly. If this is 0 after a 'VERIFY' command then sprite 'n' is not touching any other sprite. Otherwise it is set to the highest-numbered sprite it touches. *fx RESTORE n Restore an erased sprite to its last location. To use sprites, first FORMAT each one, using the sprite definer if necessary. This identifies each sprite and gives the initial position. It also gives the sprite its shape and tells it where the bytes defining it are (Don't forget to save the areas where you have stored your characters). Now MOVE, ERASE and RESTORE as desired. -------------------------------------------------------------------- Reading the keyboard -------------------- 'INKEY$' will read the keyboard successfully only if just one key is pressed at a time. As this is no good for a game, it is better to use the 'IN' command. For example, if 'IN 254' does not equal 255 then one or more keys are being pressed. If 'IN 65278' does not equal 255 then one or more of CAPS-SHIFT, Z, X, C or V are being pressed. The full use of 'IN' to read the keyboard can be found in Chapter 23 of the (old) Spectrum manual. -------------------------------------------------------------------- Other commands -------------- *fx T(ime) Turns on the clock. Note that the clock stops during 'BEEP' and tape or microdrive commands. The clock value may be PEEKed from Basic and is held at locations 54986, 7, 8 and 9. *fx L(ine) Line numbers. The number of the line currently being executed is displayed at the top right of the screen. In Basic, the statement is also shown. If you use this command in association with "REM #2" in COLT, the line number of the compiled code being run is shown, but not the statement number. This is updated every 50th of a second. *fx O(ff) Turns off L or T. Does not stop the clock or the Executive. *fx Z(ero) Zero the clock. *fx I(nitialize) Sets the time on the clock. The form "*fx I h,m,s" sets the clock. *fx S(top) Stops display of the clock or line trace, leaving them at their current values (the clock continues internally). *fx F(ree) Prints the amount of free space between 'STKEND' and 'RAMTOP'. *fx P(rog) Run the program at RAMTOP+1 (correct for COLT). *fx LEN Print the end address of Basic (this is equal to the value of the system variable 'STKEND'. *fx USR m,a,b,c... Call location 'm'. The HL register pair points to argument 'a' (2 bytes long). This means that you can take parameters to a machine code routine. *fx BIN n Print 'n' (a decimal number) in 16-bit binary (base 2). *fx CODE n Print hexadecimal value (base 16) of 'n' (a decimal number). *fx H(ex) Goes into input mode to accept a hexadecimal (base 16) number. After ENTER has been pressed, it prints the decimal equivalent. Illegal keys are ignored and deletion is not allowed. *fx D(elete) m,n Delete lines 'm' to 'n'. *fx W(here) n Print location in memory of program line 'n'. The address given is that of the higher byte of the line number. *fx G(oto) n,m If an error occurs which would normally give an error report then execution continues at line 'n'. If 'm' is zero or not given then BREAK (errors 'D' or 'L') still give an error report. If 'm' is 1 then error 'L' is trapped. If 'm' is 2, the errors 'D' and 'L' are both trapped (dangerous as it includes E!E!). If the code is compiled, it transfers command to the Basic line 'n', not that in the compiled code. If 'n' = 0 then the error trapping is turned off. The error number is stored in location 54982 before control is passed to line 'm'. The Interface 1 errors and numbers are as follows: 100 Nonsense in Basic 101 Invalid stream number 102 Invalid device expression 103 Invalid name 104 Invalid drive number 105 Invalid station number 106 Missing name 107 Missing station number 108 Missing drive number 109 Missing baud rate 111 Stream already open 112 Writing to a 'read' file 113 Reading a 'write' file 114 Drive 'write' protected 115 Microdrive full 116 Microdrive not present 117 File not found 118 Hook code error 119 CODE error 120 MERGE error 121 Verification failed 122 Wrong file type Error trapping is turned off once an error occurs (even for BREAK), so if you wish error trapping to continue you should re-enable it. *fx STOP n Stop with error report 'n'. This will be trapped by "*fx GOTO" above unless 'n' is zero. *fx DATA m,n This is a two-byte POKE. The 16-bit integer 'n' is put into locations 'm' and 'm+1' in normal Z-80 fashion. *fx PEEK m This is a two-byte PEEK. The 16-bit (unsigned) integer in memory locations 'm' and 'm+1' is returned. *fx LN m,n,p This provide a "logging" function which enables you to see which part of your program (whether it's Basic or machine code) is absorbing all the program time. This means that you can devote your effort to improving the small percentage of your code which takes longest. The general maxim is that 10% of the code is used for 90% of the time. Now you can find which part that 10% is: Basic ----- The parameters are 'm' (the start line number), 'n' (the increment in 'm') and 'p', which is 2. There are 10 'bins' for the information which is returned. The first holds the use of all lines up to and including 'm'. The next, 'm+1' to 'm+n', the third 'm+n+1' to 'm+2*n' etc. The last bin holds all occurrences greater than 'm+9*n'. For example, *fx LN 100,10,2 would log the activity in the line range starting at 100 with a resolution of 10 lines. Machine Code ------------ As for Basic except that the parameters are now 'm' (the starting address), n (the increment in m), and 'p' is 1. This will report the next location at which code is to be executed. The logging for both Basic and machine code is carried out every 50th of a second, so if too small a number is given for 'n' in machine code logging, very misleading results can be produced from synchronism with the sampling process. If 'p' is made zero the logging process is turned off. A new "*fx LN" always clears the data accumulated from previous runs. *fx LLIST This command causes the logging data started by "*fx LN" to be printed on the screen as a table. The results are self- explanatory. This command does not stop or reset the logging process. -------------------------------------------------------------------- User-defined Basic ------------------ You nay have your own user-defined statements by using or re- defining existing Executive commands. You should put the address of your machine code routine (in the form "JP address") in locations 55001, 2 and 3. 'JP' is 'C3' in hexadecimal. Your routine will be passed the token or first letter after '*fx' in the A register. The HL register pair holds the address of the first two-byte argument. If bit 7 of the system variable 'FLAGS' is zero then you should treat this as syntax checking, and return zero in the A register (and the zero flag reset) if the character or token is yours. Otherwise return without altering anything. If bit 7 of 'FLAGS' is set, Basic is running and you should execute your code, returning zero in the A register. For example, to define a new "*fx SQR" function to print a character on the current stream, you could use code like this: CP 187 ; 187 is the token 'SQR' RET NZ ; return if not SQR XOR A ; clear A and zero flag BIT 7,(IY+1) ; test bit 7 of 'FLAGS' RET Z ; return if in syntax phase LD A,(HL) ; get first argument in A RST 16 ; print on current stream via ROM XOR A ; clear A RET ; and return The Basic code to print the letter 'A' (ASCII value 65) would then be: *fx SQR 65 -------------------------------------------------------------------- Executive error messages A flashing cursor during syntax checking (i.e., when you press the ENTER key to enter a line into a Basic program) means that the syntax of a statement is wrong or something is out of context. The messages reported by the Executive are: Q Parameter error You have used more than 16 parameters. P FN without DF An invalid *fx command has been issued from a compiled piece of code. This shouldn't happen unless the versions of COLT and the Executive are incompatible. A Invalid argument The line numbers used in a DELETE command are not sensible. B Integer out of range All arguments must be in the normal integer range of -32768 to 32767. This error is also caused if you attempt to define too large a window or to manipulate a line which is off the screen. 5 Out of screen This means that the screen is not large enough for the FORMAT command. The Executive uses interrupt mode 2 to maintain the clock, trace, etc., and is called automatically every 50th of a second. The system variable 'FRAMES' (locations 23672, 3 and 4) is modified by this process. The overhead of doing this is that all programs slow down by between 10 and 15%. In addition, the clock will stop during tape, microdrive and certain other operations which cause interrupts temporarily to be disabled. During development, we have experienced problems with the SAGA Emperor keyboard, which would not type the exclamation mark, (SYMBOL-SHIFT 1). SAGA was extremely helpful in sorting out this problem with its product, and the cure is very simple. It should only be attempted if it is necessary. The keyboard is connected to the computer by two cables. One is an 8-way cable and the other is 5-way. At the computer end of the 5-way cable is a small printed circuit board with 5 tracks at one end. You should solder a 10K resistor between the first and fifth tracks to cure the fault. The problem has been experienced on several other programs. If your keyboard does have this fault, but is not manufactured by SAGA, we suggest you contact its manufacturer. -------------------------------------------------------------------- Other disc/wafer interfaces --------------------------- We believe that other storage media interfaces which use the commands FORMAT, CAT, MOVE, ERASE, OPEN, CLOSE, MERGE or VERIFY will function perfectly correctly with COLT due to the unique compilation process used for these statements. Please let us know what success you have. .........1.........2.........3.........4.........5.........6.........7.........8