6: DOS Plus MOS Calls

Having seen how the standard Tube host code and the extra facilities provided by 6502.SYS are implemented on the host's side of the Tube, this chapter details the MOS and filing system calls which can be made from within 512 code.

In 512 user programs, any language which includes the ability to load nominated 80186 registers with specified values, directly as in machine code or indirectly as in, for example, BASIC's CALL or USR functions, can access the host's MOS or filing system via these calls. The various facilities of 6502.SYS can likewise be accessed by means of issuing the appropriate unknown OSWORD call.

Note though, that in general applications programming it is neither necessary nor desirable to directly program the host's hardware device controllers or internal software flags, the FDC, perhaps, being the most obvious example. Most languages have specific filing system support commands for loading or saving data and these should be used whenever possible. Screen mapping too should remain transparent in DOS applications code.

If standard DOS Plus or CP/M facilities are used, not only will the resulting programs be easier to write and understand, they will also be more easily maintained or transferred to a different machine or a different language, should the need arise. 512 users, perhaps more than others, should appreciate the penalties of dubious programming techniques or 'illegal' direct hardware device control. Programs which use MOS Tube calls will no more work on a PC than PC programs that used direct PC hardware access do on the 512.

The following information is intended to allow programs to be written for the 512 which must, for particular reasons, gain direct access to the MOS or filing system calls of the host. Readers should note that, as we are now referring to 80186 registers and DOS functions, 86 series conventions apply and hexadecimal values are written according to the normal 86 standards. For example, a value of 127, which in native BBC mode would be written as &7Fh, is shown here as 7Fh.

Calling the MOS

All Operating System functions required by code running in the 512 under DOS Plus are made by calling a DOS interrupt. In fact, unless illegal coding techniques are employed, all program communication with all other software and the machine's hardware should be achieved through these calls. The bottom 1024 bytes of DOS memory is reserved for the interrupt vector table, each entry of which points to the DOS routines designed to handle the particular type of call Each interrupt vector entry is a four-byte segment:offset address, therefore the full range of interrupts number 256(1024/4).

The MOS Operating System calls of the Tube host code detailed in Chapter Four, and the unknown OSWORD giving access to 6502.SYS explained in Chapter Five, can be called from the 512 by means of several (otherwise unused) DOS interrupt numbers appropriated for the purpose. Of the possible total of 256 hardware and software interrupts, the majority are unused in all DOS versions to date. Although more will inevitably be used by succeeding versions of MSDOS or PCDOS and later hardware, even as far as MSDOS version 3.3 only (some of) the interrupt numbers up to 2Fh, plus 33h, 44h and 67h had been allocated.

In the version of DOS Plus supplied for the 512, interrupt numbers between 040h and 04Ch are used for the eleven different MOS call types supported by the 6502's Tube host code, plus two MOS calls which are simulated. Some MOS calls, for example OSBYTE, normally require parameters to be placed in the 6502's registers. When called from DOS the values are placed in the 80186's AL, BH and BL registers. When the call is passed to the host for service through the Tube protocol, these values will be transferred to the 6502's A, X and Y registers respectively.

The following is an outline of the supported call types, but users wishing to employ them should refer to suitable MOS reference texts for the precise details of parameters and how the calls are implemented in the host.

MOS Call Types

The 13 MOS calls supported by the Tube host code are listed in Table 6.1 below in order of ascending interrupt call numbers. Interrupts 7h and 48h are included in the table only for completeness, though these are not supported by the Tube host code, as can be seen from Chapter Three and the host code Source listing.

Interrupts 47h and 48h are actually simulations provided in the XIOS to avoid the need for two more explicit calls in the Tube host code or 6502.SYS. A call to INT 47h, OSASCI, results in the current output character value being tested. If the character is Dh, (CHRS13) then INT 48h is called, if not then it is output directly through a call to INT 49h. A call to INT 48h, OSNEWL, simply loads Character Dh and calls INT 49h, then loads Ah and calls INT 49h.

Routine INT Function
OSFIND  40h Open or close a file for byte access
OSGBPB  41h Multiple byte read or write an open file
OSBPUT  42h Put (write) a byte to an open file
OSBGET  43h Get (read) a byte from an open file
OSARGS  44h Read/write file attributes or read filing system type
OSFILE  45h Read or write a whole file or its attributes
OSRDCH  46h Host operating system read character
OSASCI  47h simulated, if Dh also send Ah through INT 49h
OSNEWL  48h simulated, output Ah and Dh through INT 49h
OSWRCH  49h Host operating system write character
OSWORD  4Ah Host operating system word general function call
OSBYTE  4Bh Host operating system byte general function call
OSCLI   Host operating system command line interpreter

Table 6.1 MOS calls supported by the Tube

The only 'standard' additions to this list are the functions provided by 6502.SYS, explained in the preceding chapter, or routines you may implement yourself by patching an additional 6502 routine into the jump table in 6502.SYS. Such a routine must, of course, be loaded after booting the system.

It should be understood that the following calls, when referencing a disc filing system operation, relate only to ADFS format (that is, bootable DOS 640K or true ADFS) or DFS format discs, not to any of the IBM DOS formats controlled through 6502.SYS. It should also be appreciated that, unless you are accessing a true MOS format disc for a special purpose, many of the host's filing system options are meaningless in DOS.

The same is true for the more general MOS calls which must be used with care. As a dramatic and salutary demonstration, you can prove this very simply by trying this example. While *FX13, 4 in native mode produces no visible effects, (the MOS does not normally use this event itself) the same command issued as STAR FX13, 4 from DOS will instantly and permanently paralyse the system by disabling all 6502.SYS operations.

As can be seen in the preceding chapter, event four is critical to the functioning of 6502.SYS, particularly for keyboard input. While both the MOS and DOS actually continue to function after this 'FX', you will have irreversibly severed their (and your) only means of communication through the Tube. It is not, in fact, just the keyboard you have disabled, all inter-processor communication is triggered by event four, which causes 50 IRQs per second in the 512 and which you have now permanently (until re-booting) disabled.

MOS Call Definitions


Function: Open or close a file for byte access
On entry: AL specifies the operation
DS contains the segment pointer to the filename BX contain the offset pointer to the filename
AL = 0 The file is to be closed
AL = 40h The file to be opened for input
AL = 80h The file to be opened for output
AL = C0h The file to be opened for input/output
The filename must be terminated by Dh (CHR$13).
On exit: AL contains the returned file handle, or 0 if file has been closed or could not be opened.
80186 flags: Undefined


Function: Read/write a block of bytes from / to a specified open file.
On entry: AL specifies the operation type
DS:BX Point to a file control block which may be in either processor,
where bytes contain the following
00 = File handle
01-04 = 4-byte DMA address pointer (low byte first)
05-08 = No of bytes to be transferred (low byte first)
09-0C = Pointer value for transfer (low byte first)
AL = 1 Put bytes using new sequential pointer
AL = 2 Put bytes ignoring sequential pointer
AL = 3 Get bytes using new sequential pointer
AL = 4 Get bytes ignoring sequential pointer
AL = 5 Get media title and boot option
AL = 6 Read current directory and device
AL = 7 Read current library and device
AL = 8 Read filenames from current directory
On exit: AL = 0 Operation was attempted
AL = entry value: Call not supported by current host FS.
80186 flags: CF unset = Call completed succesfully
CF set = Call failed
Others = Undefined


Function: Write a single byte to an open file using the file's sequential pointer
On entry: AL contains the byte to be written
BH contains the file handle (provided by OSFIND)
On exit: Nothing returned
80186 flags: Undefined


Function: Read a single byte from an open file using the file's sequential pointer.
On entry: BH contains the file handle (provided by OSFIND)
On exit: AL contains the byte read from the file
80186 flags: CF is set if an attempt is made to read past the end of the file- others are undefined.


Function: Read/write an open file's arguments or read the current filing system type
On entry:
On entry: AL = operation type
AH = file handle (provided by OSFIND) or 0.
BX points to a 4-byte attribute block, which must have been previously set up in the host's RAM
Operations: If AH = 0 and
AL = 0 Return the current filing system type
AL = 1 Return the address of the rest of the command line in the zero page control block
AL =FFh Update all files to the media (i.e. ensure that all file's buffers are written)
If AH is greater than 0 and
AL = 0 Read sequential pointer of file
AL = 1 Write sequential pointer of file
AL = 2 Read length of file
AL = 3 Write the length of the file
AL = FFh Update the file to the media
On exit: If entered with AH=0 and AL=0, AL contains the filing system number as follows:
0 No filing system
1 1200 baud cassette
2 300 baud cassette

If entered with AH = 0 and AL = 1, then the address of the remainder of the last command line is returned in a four byte zero page control block pointed to by BX.
This address is always in the I/O processor and its data should be read using OSWORD 5.
The remainder of the last command line is always terminated by 13h (CHR$13).
For all other calls no data is returned unless an error is reported via a normal register four IRQ.

80186 flags:  


Function: Read/write a complete file or catalogue information
On entry: AL contains the operation type
DS:BX point to the file's control block
Operations: AL = 0 Save a block of memory as a file
AL = 1 Write the information in the parameter block to the catalogue of an existing file
AL = 2 Write the load address of an existing file
AL = 3 Write the execution address of an existing file
AL = 4 Write the attributes of an existing file
AL = 5 Read a file's catalogue info with the file type returned in AL and the info returned in the parameter block
AL = 6 Delete a named file
AL = 7 Create a named file without transferring data
AL = FFh Load a named file
  The file control block is in the form:
00-01 = Address (lo-hi) of the filename
02-05 = Four byte load address (low byte first)
06-09 = Four byte execution address (low byte first)
0A-0D = Start address of data for save (low byte first) or file length otherwise
0E-11 = End address of data for save (low byte first) or file attributes
  File attributes are stored in 4 bytes. The most significant 3 bytes are filing system specific. The least significant byte indicates the following when a bit is set on:
0 No read access to owner (i.e. filename /WR)
1 No write access to owner (i.e. filename LR/)
2 Not executable by owner (i.e. filename /)
3 Not deletable by owner (i.e. filename L)
4 No public read access
5 No public write access
6 Not executable with public access
7 Not deletable with public access

ADFS Note: The three most significant bytes are undefined, i.e. not used. In the least significant byte, bit 2 is not used and bits 4-7 are always the same as bits 0-3.
In write attribute operations all bits except zero, one and three are therefore ignored.
If the object is a directory, bits zero and one are also ignored.
The other bytes and bits are used by other filing systems, e.g. network.

On exit: AL contains the result code as follows:
0 = File not found
1 = File found
2 = Directory found
FFh= Protected file
80186 flags: Undefined


Function: Read a character from currently selected input stream
On entry: No parameters
On exit: AL contains the character or an error code
80186 flags: CF unset = Valid character read
CF set = Error condition (code in AL)


Function: Write character to the currently selected output stream
but also output character Ah if current character is Dh
On entry: AL contains the character to be written
Operations: IF AL = Dh (CHR$13) THEN call INT 48h ELSE call INT 49h
On exit: No returned information
80186 flags: Undefined


Function: Write carriage return / linefeed to current output stream
On entry: No parameters
Operations: Loads AL with Dh (CHR$13) and calls INT 49h then loads AL with Ah (CHR$10) and calls INT 49h
On exit: No returned information
80186 flags: Undefined


Function: Write a character to the currently selected output stream
On entry: AL contains the character to be written
On exit: No returned information
80186 flags: Undefined


Function: Various functions, with parameters in a memory control block. (See also OSWORD FAh at the end of the chapter).
On entry: AL contains the OSWORD function. DS:BX points to a control block, the size and organisation of which is call dependent. See 6502 MOS reference texts for full call specifications.
On exit: Parameters returned are call dependent and if any, are placed in the control block
80186 flags: Undefined


Function: Various MOS byte operations
On entry: AL = OSBYTE type. See 6502 MOS texts for OSBYTE calls
BL = 6502 X register parameter
BH = 6502 Y register parameter (if required)
On exit: BL contains the returned 6502 X register value
BH contains any returned 6502 Y register value (see note)
Note: For OSBYTE calls that do not require a Y parameter, the Tube host code implements a short OSBYTE routine which neither expects nor transfers the value in BH, which therefore may be safely ignored. However, for all OSBYTE calls, if the value in BH is important it should be preserved by the caller. When a short OSBYTE call is used, the Tube host code does not actually return this value and BH is therefore undefined. For other OSBYTE calls the Y register value is returned, but is not meaningful.
80186 flags: CF value is call dependent but unless significant to the 6502, returned values should be regarded as undefined.


Function: Sends a string to the host's MOS Command Line Interpreter. (* command)
On entry: DS:BX point to the command string
On exit: No returned values
80186 flags: Undefined

Notes: The command string passed does not need a preceeding '*' and may be up to a maximum of 256 characters long.

The string should be terminated by Dh (CHR$13). E.g., setting DS:BX to point to the string cat<CR> would produce a catalogue of the currently selected filing system directory of the chosen drive.

Any variable parameters you wish to pass must be entirely included within the command string length. Unrecognised commands will produce an error which will be reported via the Tube register four error IRQ, ultimately causing a DOS error unless this is trapped by your own code.

Coding of MOS Calls

As a simple example of how the MOS interrupts are called, the following extract of 80186 assembler code shows how OSCLI (interrupt 4Ch) would be called with a fixed string which is the equivalent to '*HELP ADFS' issued in native mode.

; some fxed constant declarations
oscli	equ	04Ch	; OSCLI interrupt
cr	equ	0Dh	; Carriage return 
; the code that does the call
	mov	ds, cs	; just in case it wasn't
	xor	al, al	; clear AL to be neat
	mov bx, offset string_1 ; point BX to the string
	int	oscli	; call INT 04Ch
	ds	"help adfs"
	db	CR

Block Data Transfer

The OSWORD &FA which was removed from 6502.SYS is still available, but has been moved from the host code to the 80186 monitor, which already provides a slinilar facility for manual entry In TFER. It permits transfers to or from the 512.

The OSWORD interrupt code tests for a value of AL = 0FAh and diverts the call if it matches. This OSWORD call requires a control block to be set up in the 512, the location of which is pointed to by DS.BX. The format of the control block is:

0	Number of parameters sent to I/O processor (0Dh or 0Eh)
1	Number or parameters read from I/O processor (01h)
2	LSB of I/O processor address
3	...
4	...
5	MSB of I/O processor address
6	LSB of 512 offset address
7	MSB of 512 offset address
8	LSB of 512 segment address
9	MSB of 512 segment address
A	LSB of length of transfer
B	MSB of length of transfer
C	Operation type (See below)
D	6502 memory access control

The operation type specifies the type of transfer as follows:

0	Write to  6502 at 24 Ás/byte
1	Read from 6502 at 24 Ás/byte
2	Write to  6502 at 26 Ás/pair of bytes
3	Read from 6502 at 26 Ás/pair of bytes
6	Write to  6502 at 10 Ás/byte using 256 byte blocks
7	Read from 6502 at 10 Ás/byte using 256 byte blocks

The memory access control byte allows access to the paged RAMs, paged RAM and shadow RAM in the host machine and is laid out as follows:

7 6 5 4 3 2 1 0
- sm m/s c pr3 pr2 pr1 pr0

where the bits have the following functions.

Bit7	Unused
sm	IF  (I/O address between 3000h and 8000h) AND (sm=SET) 
	THEN use screen memory regardless of state of *SHADOW - overrides bit 5
m/s	0 = Use main memory if screen address specified
	1 = Use shadow memory if screen address specified
C	IF (I/O address between 3000h and 8000h) AND (C=SET) 
	THEN use currently selected ROM
pr3-pr0	Paged ROM number binary value 0 to Fh)

The memory access byte is only used if the first byte of the control block is set to OEh, otherwise it is ignored. Use of the memory access byte allows paged ROM software to be copied and therefore should be restricted to system use. This would prevent access to the shadow RAM, which is not used by the system and could not be legally accessed by other means.

A small example of the call is now given. This assumes that the control block has been set tip correctly and is located in the first 64k segment. A contiguous 36 kbyte area of memory is used as a buffer for data written from 2000:1000 in the 512. The host buffer starts at 3000h and extends to BFFFh. 3000h to 7FFFh is specified as shadow screen memory and 8000h to BFFFh is specified as paged RAM in bank 5.

osword		equ	04Ah
transfer	equ	0FAh
		sub	ax,ax		; nake ax zero
		mov	ds,ax		; point DS at segment 0
		mov	bx,offset_transfer_block
		mov	al,transfe	; set up OSWORD type
		int	osword		; call interrupt 4Ah
		db	0Eh		; number of parameters sent
		db	01h		; number of parameters read
		dw	3000h,0		; base address in 6502
		dw	l000h,2000h	; base address in 512
		dw	9000h		; length = 36K
		db	6		; fast 256 byte type 6 transfer
		db	025h		; use shadow and paged RAM