|★ APPLICATIONS ★ DIVERS ★ RSXs at your command ★|
|RSX (Computing with the Amstrad)||Applications Divers|
ROLAND WADDILOVE introduces Resident System Extensions
AMSTRAD Basic is rather peculiar, being superb in some areas such as the unique ability to handle interrupts, yet falling down badly in others such as the graphics department, where there is a notable absence of commands.
The operating system is quite different however, having a wealth of commands and routines for the machine code programmer, all fully documented in the Complete Operating System Firmware Specification from Amsoft.
One of the most powerful features of the Amstrad is the ability to add commands to the Basic and so overcome any deficiencies. There are few restrictions. The main difference is the syntax of the new commands, which I will describe a bit later on.
Variables and absolute values can be passed so that functions are possible, but you are restricted to passing the result back to a variable. You could not print the value directly - you have to put it in a variable and print that.
These additional commands are written as machine code subroutines which can be located almost anywhere in RAM and be any length.
The names and execution addresses of the routines are stored in a table which the operating system must be informed of so that they can be recognised and used within a Basic program.
Commands such as these are known as Resident System Extensions or RSXs for short and can be recognised by the vertical bar | which must precede them.
Program I adds seven new commands to Amstrad Basic. Their syntax and function is described later. First we will look at how they are actually constructed.
All dialects of Basic have some method of calling a machine code subroutine. On the Amstrad this takes the form of a CALL statement. Not only can a machine code program be run but an optional list of parameters may be passed as well, which can be picked up and used by the routine.
The parameters are placed after the CALL statement and are separated by commas. When the code is called they are placed in a block somewhere in RAM.
Where exactly this block is located is unimportant, as the routine is entered with the A register equal to the number of parameters and the IX register pointing to the start of the block.
The parameters can be obtained using indexed addressing with the IX register, LD B. (IX+0) would load the B register with the first item in the parameter block (low byte only).
Parameters can be either integer expressions, real expressions or the address of a variable. A two byte number is placed in the block for each parameter passed. An integer number, variable or expression is passed directly, a real number, variable or expression is first converted to an integer before being placed in the block.
By placing (« before a variable its address is placed in the parameter block allowing information to be passed back into Basic variables.
CALL &8000,(«a% would pass the address of a% whereas CALL &8000,a% would pass its value. If you know where a variable is stored you can then put the result of the routine back in it.
All strings must be passed in this manner. They cannot be passed directly - the value placed in the block is the address of the string descriptor. Byte 0 of the descriptor is its length and bytes 1 and 2 contain the address at which the string is stored.
For some unknown reason Basic places the values in the parameter block in reverse order. So if you CALL &8000,a,b,c,d the first value in the parameter block is d, followed by c.b and a. two bytes each, low byte/hi byte in normal Z80 fashion.
CALL &AA00 in a program is meaningless to anyone but the programmer who wrote the routine in the first place. In fact if you have several routines it is difficult to keep track of them yourself!
It would be nice if we could give the program a name and use that instead. Screen.dump is far more descriptive than CALL &AA00. This is exactly the facility an RSX gives us.
An RSX is simply a CALL to a machine code subroutine, but instead of having to remember its address we can use its name instead, as if it were a Basic command.
Anything that can be done with CALL can be done with an RSX command. There is no difference. All CALL XXX,... statements can be replaced with COMMAND , ...
In order to do this an external command table must be set up, the operating system must know what the routines are called and where they are located. The table is split into two. which need not reside next to each other. One half is a table of jumps to the execution addresses of the routines and the other contains their names.
The first two bytes of the RSX table contain the address of the list of names. The last letter of each name has &80 added to its Ascii code to mark it and the name list ends with a zero byte. Four bytes of workspace are also required by the operating system.
The RSX command table in Program I is constructed as follows:
The operating system must be informed of the presence of any RSXs by loading the BC registers with the address of the RSX table, the HL registers with the address of the workspace and calling KL LOG EXT which is at &BCD1. The first nine bytes of the code in Program I are:
This is located at &8000, so CALL &8000 enables the RSX command table. A word of warning though. RSX tables are linked so that more than one can be active at the same time. Be careful not to enable the same table twice.
If you do, then the second time it is linked to the first but as they both occupy the same place the operating system gets in a terrible muddle when looking for a command.
The simplest command in Program I is |GRAPER,colour which can be used to set the graphic paper colour. This is a typical example of a simple RSX command:
|GPAPER could be entered as Igpaper - it will be changed to upper case anyway by Amstrad Basic - and must be followed by one parameter which can be anything except a string.
The RSX commands added by Program I are shown in Table I.
Program II demonstrates the use of some of these new commands.
Space has been left for you to add your own routines. If you have a look at Program I you will see quite a few zero bytes - this is where you add your own command names and jumps.
To do this place a JP to the start of the code at &8020. and put the name (upper case, with last letter +& 80) at &8052. The code can be placed anywhere from &81CD onwards.
You might like to try DEEK and DOKE ... a double byte. 16 bit PEEK and POKE for starters. Can anyone add |CIRCLE,x,y,r?
There is room for up to five extra RSX commands, so get cracking.
|RESET Resets computer but retains program.
|SETCLOCK [, low [,high]] Sets the clock to zero if no parameters, to low where low< 65536 if one parameter, to low+65536*high if two parameters.
|GPEN,option,colour Sets the graphic pen colour and the plotting option.
|GPAPER,colour Sets the graphic paper colour.
|GET,@integor_variable% Waits for a key to be pressed then places its code in integer_variable%.
|FLUSH,buffer Flushes sound buffer if parameter=1, flushes keyboard buffer if parameter=0.
|FILL,x,y,colour Simple fill routine, origin must be at 0,0.