Libraries and Devices

This Chapter deals with the exploitation of the Amiga's operating system, providing a vast range of possibilities for the experienced system programmer. System libraries are dealt with first, and then devices are examined.

Accessing the system libraries

All of the most useful calls to the Amiga's internal system libraries are already built in to AMOS Professional. You are able to call any library directly from an AMOS Professional program, as well as access all devices connected to your computer. If you really need to make contact with these libraries and devices, the following functions are supplied. Please take note that using them without precise knowledge is a recipe for disaster!

AMOS Professional is able to execute commands from any library installed in your Amiga. These options use the standard AMOS Professional channel system to deal with Input/Output structures. Total access to all the standard data structures is also provided via the powerful STRUC function, which automatically senses the type of element to be manipulated.

LIB OPEN

instruction: open a library for use
Lib Open channel number,"name.library",version

The LIB OPEN command calls the OPEN LIBRARY function from EXEC. If the library is external, it will be loaded into memory from the "Libs:" folder of your current start-up disc. If a problem is encountered, you will be helped by the relevant error message from AMOS Professional, and the error can easily be intercepted using a TRAP command.

After the library has been initialised successfully, it remains open until the program is run again from the Editor, or your variables are re-set using a CLEAR command, or a LIB CLOSE command is called.

Three parameters are needed for a LIB OPEN instruction. The number of a new AMOS Professional channel, to be used to refer to this library throughout the AMOS Professional program. Then the name of the library that is to be opened, given in standard Commodore format. Lastly, the minimum version number of the library that is to be installed in memory should be specified. If you are unsure of this parameter, use a value of zero.

LIB CLOSE

instruction: close one or all currently open libraries
Lib Close
Lib Close channel number

Used on its own, the LIB CLOSE command closes all open libraries in a single operation. If an optional Channel number is included, an individual library may be closed. Please note that if a selected library does not exist, no error will be reported!

LIB CALL

function: call a function from a library
result=Lib Call(channel number,function offset)

This important function acts as the gateway to all the functions in the selected library. It calls the required function and returns the result to your AMOS Professional program.

The function offset parameter holds the offset value to the library function that you wish to execute, and if it is entered directly this value must be exact. Any mistakes will crash the computer. Alternatively, you are recommended to use a safer method via the LVO function to call the command by name, which is explained below.

Before calling this function, the appropriate parameter values need to be loaded into the Address and Data registers, using the AREG and DREG commands. The precise format of these parameters depends on the function in question, and should be checked from the appropriate reference manual.

After the function has been successfully executed, any return values will be available for immediate use from the AREG and DREG variables. Note that AREG only allows the registers from A0 to A3 to be accessed. (Registers A4, A5 and A6 are not used by the libraries at all.)

LIB BASE

function: get the base address of the library
address=Lib Base(channel number)

LIB BASE is used to return the base address of the selected library. This can be used in conjunction with the STRUC function to manipulate the internal data structures directly. Obviously, the normal PEEK and POKE functions can be used for this purpose as well.

DOSCALL

function: execute function from DOS library
result=Doscall(function offset)

DOSCALL executes a function directly from the DOS library, with the offset to the appropriate function being specified in brackets. The selected command is executed straight from an AMOS Professional program, without the need to open the DOS library in your program. This is useful for single calls to an important routine.

The offset value can either be a simple number or a named function using the LVO command. As with LIB CALL, the control registers first need to be set up carefully. These values should be placed into D0 to D7 and A0 to A3, with the aid of the AREG and DREG functions. After the command has been executed, the result will be given as the return value in D0. Please note that the contents of the other registers will not be loaded back into AREG and DREG.

EXECALL

function: call EXEC library
result=Execall(function offset)

The EXECALL function performs a call to the Amiga's EXEC library, with the specified offset value. On entry, D0 to D7 and A0 to A2 must be loaded with the control settings required by the function. A value is returned holding the contents of D0.

GFXCALL

function: call Graphics library
result=Gfxcall(function offset)

This executes a function directly from the Graphics library, taking the parameters from the DREG and AREG arrays. The function offset parameter enters the offset to the function you wish to call, and can also be set using the LVO function, if required.

INTCALL

function: call Intuition library
result=Intcall(function offset)

The INTCALL function calls a command directly from the Intuition library. Before using this function, it is vital to load the appropriate control parameters into the registers D0 to D7 and A0 to A3. This can be done with the AREG and DREG variables from an AMOS Professional program. When the function has been executed, the contents of D0 will be returned back to your program as the result. Please note that this function is particularly dangerous, unless you are familiar with the Intuition library.

Equates and Offsets

Experienced programmers of C or Assembler languages will be used to calling most library functions directly, by name. These names are converted invisibly into the appropriate offset values when a program is compiled into machine code. Unfortunately, this technique only works with compiled languages. AMOS Professional in an interpreted language, and so a slightly different system has been adopted.

An "equate" is simply a library function name converted to its internal equivalent. Instead of supplying the usual Include files, equates have been placed in the "AMOSPro.System_Equate" file in your "AMOSProSystem" folder. The first time a program is tested, the names are converted into their internal equivalents by AMOS Professional. Each name is translated into a single value, which is then saved into a permanent memory bank, ready for instant use.

As you would expect from AMOS Professional, the entire process is completely automatic. Simply define a memory bank for your equates, and use the LVO, EQU or STRUC functions (explained below) to return the relevant offset values. Everything else is handled by AMOS Professional.

SET EQUATE BANK

instruction: set up the automatic equate system
Set Equate Bank bank number

This command allocates a memory bank for use by the automatic equate system. It should be called up before the first equate in your program, preferably near the beginning. Specify the bank number to be used for your equates, ranging from 1 to 65535. Any existing bank of the same number will be erased when the equates are installed in memory, without warning, so take care!

LVO

function: get the Library Vector Offset
offset=Lvo("Name_of_the_function")

This function returns the Library Vector Offset associated with a specified function. The function name will be translated automatically when your program is tested for the first time, and it will be placed in a memory bank for future use. Set up the memory bank with a SET EQUATE BANK command first, otherwise an error message will be generated. If the function name does not exist, an "Equate not found error" will be given from the Editor.

The function name is in standard Commodore format, and should be typed in exactly as it appears in your reference manuals. This is especially important regarding the way upper case letters are treated differently from their lower case equivalents. For example, Input, INPUT and input are separate keywords, only the first version will be accepted, and either of the alternatives will generate an error when the program is tested!

Also note that because the function is executed during the testing process, it must be a simple string rather than an expression. For example, if you need to call the FindTask option from Exec, you would use a line like this:

TASK=Execall(Lvo("FindTask"))

EQU

function: get an equate
value=Equ("Name_of_the_equate")

The EQU function returns any standard equate value used by the Amiga system libraries. The equate can represent anything from an offset to a structure, or even the names of various bit- masks. Provided that it is supplied in the standard Amiga include files, it will be available from AMOS Professional immediately. The only exceptions to this rule are the library offsets, and these should be obtained with the LVO function.

The name of the equate should be specified in brackets, and refers to the name as set out in your reference manuals. This name is case sensitive, as explained above, so care should be taken. It is also important to remember that the name string must be a constant, and that expressions are not allowed! In fact, the technique is extremely simple. This example would send a WRITE command to a device:

DEV D0(channel,EQU("CMD_WRITE"))

STRUC

reserved variable: access an internal data structure
value=Struc(address,"Offset Name")
Struc(address,"Offset_Name")=value

The STRUC reserved variable provides a simple way of assigning a value to any one of the elements of a system structure, and it is intelligent!

There can be problems with these structures, because the type of an element varies dramatically from function to function. Depending on the structure, it can be anything from a single byte to a whole string of characters. This means that before an element can be changed, the tedious process of checking its format must be carried out.

STRUC is able to identify the type of the element directly from the equates, and then handle the entire procedure automatically, no matter if the element is a byte, a word or a longword. If the element is a string pointer, an error will obviously be generated, but we have provided a STRUC$ variable to cater for this!

The address parameter holds the address of your structure in memory. This will usually be returned by a LIB BASE or a DEV BASE function. The offset name is the name of the relevant data object as listed in your manuals. The name will be converted into an offset number by AMOS Professional, using the auto-equate system, as explained earlier. This means that a SET EQUATE BANK command needs to be included near the beginning of your program, to initialise this feature. For example:

Struc(Dev Base(1),"I0_LENGTH")=TRACK_SIZE

The same process can be used to read a value from a structure:

Print Struc(Dev Base(1),"I0_LENGTH")

STRUC$

function: read or write a string pointer to a structure
value$=Struc$(address,"Offset_Name")
Struc$(address,"Offset Name")="value"

This is used to read or write a string of characters to the named structure in memory. If the element is a number, an error will be generated when the program is first tested. When used to copy a string in a buffer area, STRUC$ adds a zero to the end, and then LOKEs it. In its alternative use, STRUC$ grabs the string from the relevant structure address, where this address refers to the address of the structure in memory, as returned by the LIB BASE or DEV BASE functions.

In both cases, the offset name refers to the name of the item to be manipulated.

Adding equates to the equates file

If your own non-standard libraries are to be used, equate files can easily be expanded in order to make use of your new routines.

To achieve this, an assembly listing should be produced, containing the equate definitions in standard Devpak format. This listing should then be run through the "Equates_Generator.AMOS" program, which can be found in the root directory of the AMOSPro_System disc.

The Requester Extension

As a default, the AMOS Professional requester routine will be used in preference to hit' Workbench system requester.

REQUEST WB

instruction: use the Workbench system requester
Request Wb

This command is used to switch to the Workbench system requester. As soon as one of the options is selected from it, you will be returned to AMOS Professional. Please note that if the Requester Extension is deleted from the extension list by means of the configuration file, then the standard Workbench requester will be used for displaying messages. This will give the illusion that AMOS Professional has crashed when a requester appears. If this situation occurs, simply press Amiga + A to return to the Workbench, respond to the requester and press Amiga + A again to return to AMOS Professional. There should be no need to delete the Requester extension unless memory is very low.

REQUEST ON

instruction: use the AMOS Professional requester routine
Request On

This is the default setting, and is used to make AMOS Professional employ its own requester routine.

REQUEST OFF

instruction: cancel the requester
Request Off

If this instruction is used, AMOS Professional will automatically select the [CANCEL] button of the requester, and the actual requester will not be displayed. This is ideal for error trapping Within a program.

Control of devices

AmigaDOS supports a wide range of devices for your use. Some devices are provided to control specific items of hardware, such as printers and disc drives, while others offer access to internal facilities like the synthetic speech handler. The following two functions need no expert knowledge to use!

DEV FIRST$

function: get the first device from the current device list
device$=Dev First(path$)

This function is similar to DIR FIRST$. A string is returned identifying the first device that satisfies a chosen search path in the current device list.

DEV FIRST$("**") will list everything, DEV FIRST$("D/**") will only list disks, and DEV FIRST$(A/**") is used if you only want to list assigns.

DEV NEXT$

function: get the next device that satisfies the current search path
device$=Dev Next$

This is used in conjunction with the DEV FIRST$ function to get the next device in the current device list that satisfies the specified search path. Once the last device has been found, an empty string will be returned.

Print Dev First$("**") Do A$=Dev Next$ If A$="" Then End Print A$ Loop

AMOS Professional includes a powerful series of commands to exploit these devices directly from your programs, but they should only be used by experienced programmers, armed with the relevant ROM Kernel manual. You have been warned!

DEV OPEN

instruction: open a device
Dev Open(channel number,"name.device",IOlength,UnitNumber,Flags)

The DEV OPEN command opens a communication port and prepares the device for use by AMOS Professional programs. If this device is not already installed, it will be loaded from the "DEVS" folder of your current start-up disc automatically. Floppy disc users may be requested to swap discs at this point.

The selected device will now remain active during the course of the program, and will only be closed if a DEV CLOSE command is called, or a RUN command is used to clear the variable area, or a CLEAR operation is undertaken.

The specified channel number should be from zero to 4, the "name.device" parameter enters the name of the device to be initialised in normal AmigaDOS format, and IOlength specified the length of the IO structure to be created for the device. If in doubt, use a value of 256, which should be sufficient for most devices. The final flags parameter sets the status of the device flags if applicable. Please refer to your system documentation for details.

DEV OPEN performs the following operations:

DEV CLOSE

instruction: close one or more devices
Dev Close
Dev Close channel

Use this command to close one or more open devices.

Memory used by the IO structure will be returned back to AMOS Professional and the message port is released for subsequent use. If the channel number is omitted, all active devices are closed simultaneously, otherwise the single specified device is closed down. Note that if a specified channel is not already open, no error will be reported.

DEV DO

instruction: call a command using DoI0
Dev Do channel number,command number

The DEV DO instruction executes a DoIO operation via the specified channel. Obviously the correct internal structure parameters must be set using a STRUC command, before this operation is called. The specified channel number refers to a previously opened device channel. The command number holds the number of the IO command you wish to Do. This command may be entered directly by name, using the EQU function explained earlier. You are warned to take great care when using this instruction!

DEV SEND

instruction: call a command using SendIO
Dev Send channel number,command

This calls the SendIO command from Exec, and runs your operation using the Amiga's multi- tasking system. The new process will run invisibly in the background, and your AMOS Professional program will continue from the next instruction immediately.

DEV CHECK

function: check status of a device with a CheckIO
value=Dev Check(channel number)

Use this function to perform a CheckIO on the specified channel. The resulting value is passed back to AMOS Professional.

DEV ABORT

instruction: abort an IO operation
Dev Abort channel number

This instruction executes an AbortIO and a WaitIO command, clearing all pending action from the specified device channel. It can be used to exit directly from a multi-tasking operation, without waiting for it to complete.

DEV BASE

function: get base address of an IO structure
address=Dev Base(channel number)

This function returns the base address of the IO structure assigned to the current device. The structure can now be manipulated directly, using the STRUC commands, as required.