[Coco] SYSCALL Tutorial

Bob Devries devries.bob at gmail.com
Thu Oct 1 02:29:48 EDT 2009


Using SYSCALL in Basic09

 

While I will concede that using SHELL commands inside Basic09 procedures reduces the code size and may make the code more readable, I abhor its use, since it often poses problems, particularly if the CMDS referred to by SHELL do not exist on the user's disk. This problem is not just apparent in Basic09, but also in C and assembler programming; hence the problem with DELDIR which calls ATTR. This works fine for a stock OS-9 system, but once changes are made, whammo!

 

Basic09 has a perfectly usable method of accessing the system commands through the use of the SYSCALL function. SYSCALL takes two arguments; the callcode, and a pointer to a complex variable containing the CPU registers.

 

The register variable is set up using the TYPE command like this:

 

TYPE registers = cc, a, b, dp:byte; x, y, u:integer

 

After that, using the DIM command creates memory space for it:

 

DIM regs:registers

 

The callcode is also DIMensioned as BYTE:

 

DIM callcode:BYTE

 

The callcode is the byte that's usually associated with the OS9 macro in assembler programming:

 

            OS9 I$SetStt

Or

            OS9 $8E

 

If we want to access the options section (as for instance, to change the TMODE settings), we also need to set aside a 32 byte memory packet:

 

DIM status_packet[32]:BYTE

 

So how do we use all this?

If we are going to make changes to system settings, we should first save a copy of those settings so we can restore them to what they were. Here's how:

 

TYPE registers = cc, a, b, dp: BYTE; x, y, u: INTEGER

DIM regs: registers

DIM callcode: BYTE

DIM status_packet[32]: BYTE

DIM pause:byte

 

callcode = $8D (* I$GetStt System Call *)

regs.a = 1 (* STDOUT *)

regs.b = 0 (* SS.Opt *)

regs.x = ADDR(status_packet) (* get pointer to address packet memory *)

RUN SYSCALL(callcode, regs) (* call the system function *)

 

We now have an unmodified copy of the options packet. 

 

For the purpose of this tutorial, I will only save one byte from the status_packet array. Depending on the usage, you may need to save the whole array. By the way, contents of the status packet is documented on page 6-2 and following of the OS9 Technical Reference Manual. Only bytes at offset $20 to $3F are copied from the path descriptor by the I$GetStt call.

 

pause = status_packet[7] (* offset to the PD.PAU ($27) option *)

 

IF pause = 0 THEN

            PRINT "Page pause is off"

ELSE

            PRINT "Page pause is on"

ENDIF

 

To set page pause to off (assuming it was on to start with), here's what we do:

 

status_packet[7] = 0 (* set IT.PAU to 0 = OFF *)

 

callcode = $8E (* I$SetStt system call *)

 

We can assume that all the settings previously used to call SYSCALL are unchanged.

We can then call the SYSCALL function.

 

RUN SYSCALL (callcode, regs)

 

PRINT "Page pause is now off"

 

Don't forget to return the system to the condition it was in before!

 

status_packet[7] = pause (* return to original state *)

 

RUN SYSCALL(callcode, regs)

 

I hope this helps some people. Any questions may be directed to me via this list. In the even that I've made mistakes, kindly point them out to me!

 

Regards, Bob Devries

 

--
Besides a mathematical inclination, an exceptionally good mastery of one's native tongue is the most vital asset of a competent programmer.

Edsger W.Dijkstra, 18 June 1975



More information about the Coco mailing list