OSWORD
OS call specified by contents of A and parameter block
Table of Contents
Function |
Address | Vector | Description |
OSWORD |
FFF1 | 20C | OS call specified by contents of A and parameter block |
The OSWORD routines are very similar in concept to the OSBYTE routines. The major difference arises in the way
of passing parameters. Instead of being passed in the X and Y registers, they are placed in a parameter block,
The address of this parameter block is sent to the routine in the X (for the low byte) and Y (for the high byte)
registers.
Entry parameters
Register |
Value |
A |
OSWORD routine ID |
X |
Low byte of parameter block address |
Y |
High byte of parameter block address |
OSWORD Specification
Only OSWORD 0x00 returns a result in the Y register and the Carry flag.
The registers are preserved for all other calls.
OSWORD calls with numbers 0x15…0x7F must only have a maximum of 16 bytes in the control block.
OSWORD calls with numbers greater than 0x7F must contain the number of parameters to send in the first byte of
the control block and the number of parameters to receive in the second byte.
Both of these must include the first two bytes so their values are in the range of 0x02…0x7f.
Note the first two values in the parameter block are required to instruct the Tube software how big the block
is when the OSWord is issued from a coprocessor.
Due to a limitation in the host side of the Tube software these values cannot exceed 128 bytes in either direction.
OSWORD calls with numbers &E0 to &FF are "available for use by the user" and are passed directly to USERV (0x0200) on the 6502 I/O processor.
This makes them easier to implement as only USERV needs to be hooked into instead of WORDV, and 0xF0/0xF1 is already prepared pointing at the control block.
All other unrecognised OSWORD calls are offered to the paged ROMs.
Although not enforced by the API, the convention for high-numbered OSWORD calls is for the control block contents to be:
XY+ |
On entry |
On exit |
Range |
0 |
send block length, depends on subreason code |
preserved |
0x02…0x7F |
1 |
return block length, depends on subreason code |
preserved |
0x02…0x7F |
2 |
action |
set to zero |
|
3 |
must be zero |
result |
|
4… |
request data |
result data |
|
1 - Read line from input
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
0 |
00 |
Read line from input | x |
x |
x |
This routine takes a specified number of characters from the currently selected input stream.
Input is terminated following a RETURN or an ESCAPE. DELETE (&7F/127) deletes the previous character and CTRL U
(&15/21) deletes the entire line.
If characters are presented after the maximum line length has been reached the characters are ignored and a BEL (ASCII
7) character is output.
OSWORD 0x00 is the only OSWord which return's data in the registers.
Parameter block
XY+ |
Size |
Content |
0 |
2 |
Buffer address for input |
2 |
1 |
Maximum line length |
3 |
1 |
Minimum acceptable ASCII value |
4 |
1 |
Maximum acceptable ASCII value |
Only characters greater or equal to XY+3 and less than or equal to XY+4 will be accepted.
This is useful for forms where you want only digits by setting the minimum to '0' and maximum to '9'
On exit
C=0 |
Carriage return terminate input |
C=1 |
ESCAPE condition terminated input |
Y |
Contains line length, excluding carriage return if used. |
2 - Read/Write system clock
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
1 |
01 |
Read system clock | x |
x |
x |
2 |
02 |
Write system clock | x |
x |
x |
The clock is a five byte clock value is read or written to the address contained in the X and Y registers.
For example the TIME function in BASIC uses OSWORD 0x01.
This clock is incremented every hundredth of a second and is set to 0 by a hard BREAK.
3 - Interval timer
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
3 |
03 |
Read interval timer | x |
x |
x |
4 |
04 |
Write interval timer | x |
x |
x |
This routine may be used to read/write the interval timer, used for events.
For read (OSWord 0x03) the current clock value will be writted to the 5 bytes pointed to by the XY registers.
For write (OSWord 0x04) the new clock value is contained in the 5 bytes pointed to by the XY registers.
4 - Read/Write I/O processor memory
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
5 |
05 |
Read I/O processor memory | x |
x |
x |
6 |
06 |
Write I/O processor memory | x |
x |
x |
A byte of I/O processor memory may be read or written across the Tube using this call.
A 32 bit address should be contained in memory at the address contained in the X and Y registers.
For writes (OSWord 0x06) the value to write should be placed in XY+4
For reads (OSWord 0x05) the value read is placed in XY+4 on exit.
Parameter block
XY+ |
Content |
Read call |
Write call |
0 |
LSB of address in I/O processor |
|
|
1 |
|
|
|
2 |
|
|
|
3 |
MSB of address in I/O processor |
|
|
4 |
|
Byte read by OSWord 0x05 |
Byte to write with OSWord 0x06 |
If the I/O processor uses 16 bit memory addressing only least significant two bytes need to be specified.
5 - Sound command
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
7 |
07 |
Sound command | x |
x |
x |
This routine takes an 8 byte parameter block addressed by the X and Y registers.
The 8 bytes of the parameter block may be considered as the four parameters used for the SOUND command in BASIC.
Parameter block
XY+ |
Length |
Content |
0 |
2 |
Channel |
2 |
2 |
Amplitude |
4 |
2 |
Pitch |
6 |
2 |
Duration |
For example, to perform a
SOUND 1,-15,200,20
then the contents of the table would be:
Parameter block
XY+ |
Content |
Sound Param |
Value |
0 |
Channel |
1 |
0x01 |
1 |
|
|
0x00 |
2 |
Amplitude |
-15 |
0xF1 |
3 |
|
|
0xFF |
4 |
Pitch |
200 |
0xC8 |
5 |
|
|
0x00 |
6 |
Duration |
20 |
0x14 |
7 |
|
|
0x00 |
6 - Define an Envelope
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
8 |
08 |
Define an Envelope | x |
x |
x |
The ENVELOPE parameter block should contain 14 bytes of data which correspond to the 14 parameters described in the ENVELOPE command.
This call should be entered with the parameter block address contained in the X and Y registers.
7 - Read pixel value
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
9 |
09 |
Read pixel value | x |
x |
x |
This routine returns the status of a screen pixel at a given pair of X and Y co-ordinates.
Parameter block
XY+ |
Content |
0 |
LSB of X coordinate |
1 |
MSB of X coordinate |
2 |
LSB of Y coordinate |
3 |
MSB of Y coordinate |
4 |
Logical colour at that point |
On exit,
XY+4 contains the logical colour at the required point
or &FF if the point specified was off the screen.
8 - Read character definition
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
10 |
0A |
Read character definition | x |
x |
x |
This call returns the 8 bytes which define the 8 by 8 matrix of each character.
The call requires a 9 byte parameter block pointed to by the X and Y registers.
The first byte contains the ASCII value of the character definition to be read.
After the call the 8 byte definition is contained in bytes 1 to 8 of the parameter block,
with the top row in byte 1 and the bottom row in byte 8.
9 - Read/Write palette
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
11 |
0B |
Read palette | x |
x |
x |
12 |
0C |
Write palette | x |
x |
x |
These routines read and write the colour palette.
They take a 5 byte parameter block:
Parameter block
XY+ |
Content |
Read call |
Write call |
0 |
Logical colour |
Logial colour |
|
1 |
Physical colour |
Current mapping |
Required mapping |
2 |
Reserved for future expansion |
|
Set to 0 |
3 |
Reserved for future expansion |
|
Set to 0 |
4 |
Reserved for future expansion |
|
Set to 0 |
Write Palette
The OSWORD 12 write palette call performs the same task as a VDU 19 command
which can be used from machine code using OSWRCH.
The advantage of using this OSWORD call rather than the conventional VDU
route is that there is a significant saving in time.
Another advantage is that OSWORD calls can be used in interrupt routines
while VDU routines cannot.
10 - Read last two graphics cursor positions
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
13 |
0D |
Read last two graphics cursor positions | x |
x |
x |
The operating system keeps a record of the last two graphics cursor,
positions in order to perform triangle filling if requested.
These cursor positions may be read using this call. X and Y should
provide the address of 8 bytes of memory into which the data may
be written.
Parameter block
XY+ |
Content |
0 |
LSB Previous X coordinate |
1 |
MSB Previous X coordinate |
2 |
LSB Previous Y coordinate |
3 |
MSB Previous Y coordinate |
4 |
LSB Current X coordinate |
5 |
MSB Current X coordinate |
6 |
LSB Current Y coordinate |
7 |
MSB Current Y coordinate |
11 - Read CMOS clock
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
14 |
0E |
Read CMOS clock | |
x |
|
This routine reads from the onboard CMOS clock.
For systems without a CMOS clock, the MOS passes the calls to sideways ROM's for support.
The first byte of the parameter block is a function code representing the action required.
The rest of the block's content (including its size) depends on that function.
Return clock value as string
On entry:
XY=0
On exit:
XY+ |
Length |
Content |
Value range |
0 |
24 |
Date |
CR-terminated string in form |
"Day,DD Mon Year.HH:MM:SS". |
Return BCD clock value
On entry:
XY=1
On exit:
XY+ |
Length |
Content |
Value range |
0 |
1 |
year |
0x00 |
0x99 |
1 |
1 |
month |
0x01 |
0x12 |
0 |
1 |
day |
0x01 |
0x31 |
0 |
1 |
day of week |
0x01 Sun |
0x07 Sat |
Notes:
- year
- 0x80-0x99 represents 1980-1999. 0x00-0x79 represents 2000-2079.
- day of week
- 0x00 = not returned
Convert BCD to string
On entry:
XY=1
XY+1…7 the BCD value as returned above
On exit:
XY+1…25 CR terminated string
XY+ |
Length |
Content |
Value range |
0 |
1 |
year |
0x00 |
0x99 |
12 - Write CMOS clock
OSWord call |
Action |
Available on: |
(dec) |
(hex) | BBC |
Master |
Electron |
15 |
0F |
Write CMOS clock | |
x |
|
This routine allows the onboard CMOS clock to be set.
For systems without a CMOS clock, the MOS passes the calls to sideways ROM's for support.
The first byte of the parameter block is a function code representing the action required.
The rest of the block's content (including its size) depends on that function.
Function |
Action |
Format of input |
8 |
Set time |
"HH:MM:SS" |
16 |
Set date |
"Day,DD Mon Year" |
24 |
Set date and time |
"Day,DD Mon Year.HH:MM:SS" |
13 - IP Networking and DNS Resolution
OSWord call |
Action |
Available on: |
(dec) |
(hex) | Other |
192 |
C0 |
IP Networking and DNS Resolution | SPROW Ethernet for BBC Master |
This call is supported on the Network API
documentation for the
SPROW Ethernet upgrade for the Master Series
which I happen to have installed in my BBC Master 128.
This call is modelled on the Berkeley Sockets API.
Call format
The control block follows the convention for high-numbered OSWORD calls where the control block contains the
request & response sizes, action and result codes as the first 4 bytes of the block.
XY+ |
On entry |
On exit |
Range |
0 |
send block length, depends on subreason code |
preserved |
0x02…0x7F |
1 |
return block length, depends on subreason code |
preserved |
0x02…0x7F |
2 |
action |
set to zero |
|
3 |
must be zero |
result |
|
4… |
request data |
result data |
|
Actions
To allow for many functions to be performed but without using up lots of OSWord numbers a one byte
action code is included, allowing for up to 256 different pieces of functionality.
The action codes are further split into groups of 64 each:
Action (range) |
Functionality |
0x00…0x3F | Socket operations |
0x40…0x7F | Resolver operations |
0x80…0xBF | Reserved for future use |
0xC0…0xFF | Reserved for future use |
Unused or reserved action codes will return an error number at XY+3.
13.1 - Socket operations
0x00 Socket Create
This function sets up a new socket and returns a handle for its future use.
Only a limited number of sockets can be opened simultaneously.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
Communications domain, 2 for PF_INET |
socket number created or -1 on failure |
8 |
4 |
Socket type:
1=stream 2=datagram 3=raw
|
|
12 |
4 |
Protocol or zero for default for the socket type |
|
0x01 Socket Bind
Bind a socket to a specific local address.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 if the bind fails |
8 |
4 |
Pointer to socket address to bind to |
|
12 |
4 |
Size of socket address, usually 16 |
|
Socket address
sa+ |
Length |
On entry |
On exit |
0 |
1 |
Size of socket address, usually 16 |
1 |
1 |
Address family, 2 for AF_INET |
2 |
2 |
Port number |
4 |
4 |
IPv4 address |
8 |
4 |
Zero |
12 |
4 |
Zero |
Note that the size of the socket address structure is used twice, once in the structure itself, and also as the
third parameter at YX+12.
0x02 Socket Listen
Switch a socket into listening for incoming connection attempts.
Only sockets opened and configured to tbe stream based sockets can be set to listen,
datagram and raw sockets are connectionless and cannot be set to listen.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 if the call fails |
8 |
4 |
Backlog of unaccepted connections to allow before rejecting |
|
0x03 Socket Accept
Switch a socket into listening for incoming connection attempts.
Only sockets opened and configured to tbe stream based sockets can be set to listen,
datagram and raw sockets are connectionless and cannot be set to listen.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 if the bind fails |
8 |
4 |
Pointer to socket address to bind to |
|
12 |
4 |
pointer to an integer describing the size of socket address (usually 16) |
|
Note: XY+12 in the original documentation mentions this is a pointer, but in other calls it's an actual value.
This needs clarifying.
0x04 Socket Connect
Accept an incoming connection on an existing socket.
If there are no pending incoming connections, this call will block until there is one.
On accepting, the address details of the remote computer will be filled in at the block pointed to by YX+8.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 if the connect fails |
8 |
4 |
Pointer to socket address to bind to |
|
12 |
4 |
size of socket address (usually 16) |
|
0x05 Socket Receive
Read data from the given socket.
This function attempts to read data or waits until some is ready.
It is possible that zero bytes are returned, probably indicating that the remote computer has disconnected.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 on failure, otherwise number of bytes received |
8 |
4 |
Pointer to data buffer to receive into |
|
12 |
4 |
Buffer size |
|
16 |
4 |
Flags, usually 0 |
|
0x08 Socket Send
Send out data on the given socket.
For raw and datagram style sockets the message length must fit within one packet otherwise the request will
be rejected, for stream style sockets as much as the message as possible will be queued and sent subject to
available memory.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 on failure, otherwise number of bytes sent |
8 |
4 |
Pointer to data buffer to send |
|
12 |
4 |
Buffer size |
|
16 |
4 |
Flags, usually 0 |
|
0x0B Socket Shutdown
Shutdown part of a socket.
This allows a socket to be partially shut where the TCP/IP stack supports this. Caution should be taken as
this does not actually close the socket, so does not free up any of the resources associated with the socket -
see details of Close for how to do this.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 on failure |
8 |
4 |
Direction to shut 0=receive side 1=transmit side 2=both sides |
|
12 |
4 |
Buffer size |
|
16 |
4 |
Flags, usually 0 |
|
0x10 Socket Close
Close a socket.
As there are fixed number of sockets available it is important to remember to close sockets once any
transactions are complete.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
socket |
-1 on failure |
Unsupported actions
The following actions are defined but are not supported. Using them will return an error.
Action |
Description |
0x06 | Socket Receive From |
0x07 | Socket Receive Message |
0x09 | Socket Send to |
0x0A | Socket Send Message |
0x0C | Socket Set Socket Option |
0x0D | Socket Get Socket Option |
0x0E | Socket Get Peer Name |
0x0F | Socket Get Socket Name |
0x11 | Socket Select |
0x12 | Socket Ioctl |
0x13 | Socket Read |
0x14 | Socket Write |
0x15 | Socket Stat |
0x16 | Socket Readv |
0x17 | Socket Writev |
13.2 - Resolver operations
0x40 Resolver Get Host By Name
Resolves a host name to a network address.
A control terminated name will be passed to the DNS resolver software built into the network module.
This call will then wait for a result, and only return when a match is found or timeout occurs.
The returned block at YX+8 onwards is a 'hostent' structure containing a list of IP addresses amongst other information,
the lists will remain valid until the next resolver request.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
|
Pointer to name looked up |
8 |
4 |
|
Pointer to null terminated list of pointers to aliases |
12 |
4 |
|
IP address type returned, 2 for AF_INET |
16 |
4 |
|
Length of this address type, 4 for IPv4 |
20 |
4 |
|
Pointer to null terminated list of pointers to IP address(es) |
0x41 Resolver Get Host
Resolves a host name to a network address.
This is very similar to GetHostByName except that it returns immediately.
If the name is already in the DNS cache the result will be filled in and YX+3 is zero,
otherwise a request is issued and a 'resolver busy' error returned.
Further calls to GetHost will update YX+3 until either a timeout occurs or the name is found.
This allows the request to be sent and the foreground program continue operating, compare this with
GetHostByName which blocks until the name has been found.
XY+ |
Length |
On entry |
On exit |
4 |
4 |
|
Pointer to name looked up |
8 |
4 |
|
Pointer to null terminated list of pointers to aliases |
12 |
4 |
|
IP address type returned, 2 for AF_INET |
16 |
4 |
|
Length of this address type, 4 for IPv4 |
20 |
4 |
|
Pointer to null terminated list of pointers to IP address(es) |
Unsupported actions
The following actions are defined but do nothing. They do not return an error.
Action |
Description |
0x42 | Resolver Get Cache |
0x43 | Resolver Cache Control |
13.3 - Library functions
The following listing provides BASIC functions with the same names and parameters as the corresponding
function in most libraries for the 'C' programming language as a convenience for use.
This is taken verbatim from the original documentation:
1REM Network functions
2REM (C)2010 SPROW
3:
4DEFFNgethost(name$)
5wordblk?0=8:REM Parameters in
6wordblk?1=24:REM Parameters out
7wordblk?2=&41:REM Resolver_GetHost
8wordblk?3=0:REM No error on entry
9wordblk!4=nameblk
10$nameblk=name$
11A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
12IFwordblk?3<>0 THEN=0
13=wordblk+4:REM Address not value
14:
15DEFFNcreat(pf%,type%,prot%)
16wordblk?0=16:REM Parameters in
17wordblk?1=8:REM Parameters out
18wordblk?2=&00:REM Socket_Creat
19wordblk?3=0:REM No error on entry
20wordblk!4=pf%
21wordblk!8=type%
22wordblk!12=prot%
23A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
24IFwordblk?3<>0 THEN=-1
25=wordblk!4
26:
27DEFFNbind(handle%,addr%,addrlen%)
28wordblk?0=16:REM Parameters in
29wordblk?1=8:REM Parameters out
30wordblk?2=&01:REM Socket_Bind
31wordblk?3=0:REM No error on entry
32wordblk!4=handle%
33wordblk!8=addr%
34wordblk!12=addrlen%
35A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
36IFwordblk?3<>0 THEN=-1
37=wordblk!4
38:
39DEFFNlisten(handle%,count%)
40wordblk?0=12:REM Parameters in
41wordblk?1=8:REM Parameters out
42wordblk?2=&02:REM Socket_Listen
43wordblk?3=0:REM No error on entry
44wordblk!4=handle%
45wordblk!8=count%
46A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
47IFwordblk?3<>0 THEN=-1
48=wordblk!4
49:
50DEFFNaccept(handle%,addr%,addrlenblk%)Network programmer's API
51wordblk?0=16:REM Parameters in
52wordblk?1=8:REM Parameters out
53wordblk?2=&03:REM Socket_Accept
54wordblk?3=0:REM No error on entry
55wordblk!4=handle%
56wordblk!8=addr%
57wordblk!12=addrlenblk%
58A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
59IFwordblk?3<>0 THEN=-1
60=wordblk!4
61:
62DEFFNconnect(handle%,addr%,addrlen%)
63wordblk?0=16:REM Parameters in
64wordblk?1=8:REM Parameters out
65wordblk?2=&04:REM Socket_Connect
66wordblk?3=0:REM No error on entry
67wordblk!4=handle%
68wordblk!8=addr%
69wordblk!12=addrlen%
70A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
71IFwordblk?3<>0 THEN=-1
72=wordblk!4
73:
74DEFFNrecv(handle%,data%,len%,opts%)
75wordblk?0=20:REM Parameters in
76wordblk?1=8:REM Parameters out
77wordblk?2=&05:REM Socket_Recv
78wordblk?3=0:REM No error on entry
79wordblk!4=handle%
80wordblk!8=data%
81wordblk!12=len%
82wordblk!16=opts%
83A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
84IFwordblk?3<>0 THEN=-1
85=wordblk!4
86:
87DEFFNsend(handle%,data%,len%,opts%)
88wordblk?0=20:REM Parameters in
89wordblk?1=8:REM Parameters out
90wordblk?2=&08:REM Socket_Send
91wordblk?3=0:REM No error on entry
92wordblk!4=handle%
93wordblk!8=data%
94wordblk!12=len%
95wordblk!16=opts%
96A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
97IFwordblk?3<>0 THEN=-1
98=wordblk!4
99:
100DEFPROCshutdown(handle%,type%)
101wordblk?0=12:REM Parameters in
102wordblk?1=4:REM Parameters out
103wordblk?2=&0B:REM Socket_Shutdown
104wordblk?3=0:REM No error on entry
105wordblk!4=handle%Network programmer's API
106wordblk!8=type%
107A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
108ENDPROC
109:
110DEFPROCclose(handle%)
111wordblk?0=8:REM Parameters in
112wordblk?1=4:REM Parameters out
113wordblk?2=&10:REM Socket_Close
114wordblk?3=0:REM No error on entry
115wordblk!4=handle%
116A%=192:X%=wordblk:Y%=wordblk DIV256:CALL&FFF1
117ENDPROC