[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