The Master 512 is put together in quite a different way from a true IBM PC or 100% compatible machine, and so its "low level" software is also different. This has made it possible for extra facilities, unique to the 512, to be built into the system by Acorn and Digital Research. Naturally, programs written for genuine PC-compatibles are not going to use these. However, there may be a few people around who would like to write programs specifically for the Master 512, and they might well want to use all that is available to them. This article describes some of these facilities and how to use them.
The "lowest level" part of DOS-Plus on the 512 is known as the XIOS (abbreviation for "Extended Input and Output System"). It is possible for programs to call the XIOS directly. Most of the functions available this way are better accessed through "higher level" DOS calls. However a number of the functions which are specific to the Master 512 can only be used by making a direct call to the XIOS. These are the functions described here.
There are other functions found only on the 512 and called as DOS-Plus interrupts. These are not listed again here.
The information in this article is only likely to be useful to those programming in assembly language. The document assumes a basic understanding of the architecture of the 80186 processor, as well as a familiarity with its assembly language and the use of DOS interrupts.
As with all the documents in this collection, this article is not intended to duplicate information available elsewhere. Further information can be found in the books listed in the Bibliography especially Robin Burton's Master 512 Technical Guide.
DOS-Plus stores much of its own internal data in a memory segment known as the System Data Segment (or SYSDAT). You can read the segment address of SYSDAT in one of two ways. The official way is to issue an INT E0h with CL=9Ah. This returns with the SYSDAT address in ES. The slightly quicker, though undocumented, way is to issue INT FEh (no entry parameters) which returns with the address in AX. (See again the article on DOS-Plus Interrupts.)
If your program is going to use any of the facilities listed below it will need to know the value of this segment address, so at some early stage it should use one of these calls and record the result. The address of SYSDAT will not change during a session, so it only needs to be read once.
|There are those with low function numbers (less than 80h). These are standard DOS-Plus calls to the BIOS (mostly inherited from CP/M). I have not described these here since the information is available elsewhere, but I strongly advise you not to use these functions. All that they do can be done through standard DOS calls which, for these activities, are safer.|
|The second category of XIOS functions are those with function numbers greater than or equal to 80h. These are the "Acorn specials" and are the main subject of this article. In practice some are more useful than others, but for completeness they are all described below.|
There are two methods of making direct calls to the XIOS:
First set up a 5-byte parameter block. Byte 0 of the block must contain the function number. Further parameters should be placed in Bytes 1 to 4 (if required). Point DS:DX to this parameter block, set CL=32h and issue an INT E0h.
Set up 80186 registers as follows:
AL Function number DS SYSDAT segment address CX Parameter DX Parameter BX,SI Possible further parameters
Now issue a far call through the main XIOS entry vector, which is a 4-byte vector located at offset 28h in the SYSDAT segment. (The syntax of this call may vary a little depending on the assembler in use. Set DS equal to SYSDAT and then issue:
if you are using the A86 assembler, for instance.)
For the "Acorn special" calls these two methods are generally equivalent. For these:
|Byte 0 of the parameter
block (function number)
|The value in AL|
|Bytes 1 and 2 of
the parameter block
|The parameter in CX|
|Bytes 3 and 4 of
the parameter block
|The parameter in DX|
However a number of the functions can only be called by Method (b) because they require further parameters in BX and SI. There is no way of passing these to the function by Method (a). Furthermore, Method (a) is slightly slower than Method (b). Because of these considerations, Method (b) is normally the best one to use (but do remember to set DS). All of the calls are described according to the Method (b) usage.
(Note that these two methods of calling the XIOS are not equivalent for the low-numbered functions mentioned above, but that need not concern us here.)
Several functions return a value, and this will normally be in AX. BX is always set equal to AX on return. Occasionally values may be returned in other registers. Calls not supported by the system always return with AX=BX=FFFFh (with a couple of exceptions).
These functions make no attempt to preserve the processor's registers. Anything (including ES) may be corrupted. The only registers you can rely on to be preserved are DS (which will still contain the SYSDAT segment value on exit), and of course the program flow control registers CS, SS and SP.
The XIOS identity string is an ASCII string terminated with 0. (Such strings are often known as ASCIIZ.) The string resides in the SYSDAT segment. This function returns in BX=AX a pointer to the start of the string within this segment (ie it returns the offset value).
The function always returns the value 2 in CH. This signifies that the operating system is DOS-Plus, but you already knew that!
This call must be issued before making any direct use of the Tube. After using it your program "owns" the Tube, and the standard Tube protocols apply. This means you can access the host's MOS functions, either by using Interrupts 40h to 4Ch or else by writing and reading control bytes directly across Tube Registers 1 and 2. (See Chapter 12 of Watford's Advanced Reference Manual for the BBC Master, for the necessary protocols for functions handled by the MOS. For the Master 512's dedicated OSWORDs, you can deduce the protocols from the discussion in Chapter 5 of Robin Burton's Master 512 Technical Guide, especially if you read it in conjunction with the disassemblies in Appendix E and Appendix F.)
If you attempt to use the Tube without first claiming it through this call then you will almost certainly crash the system.
No harm will be done by claiming the Tube again, provided that you remember to release it once for every time it is claimed. DOS-Plus maintains a counter of how many times the Tube has been claimed. This is incremented by a claim and decremented by a release. Only when it is zero can other processes use the Tube.
Note that this action is quite different from the "Claim Tube" action within the BBC host. Those claims will happen automatically when needed, and DOS programs in the Master 512 do not need to worry about them.
This should be issued to release the Tube at the end of the action for which it was claimed with Function 81h. This allows other processes to use it (such as background programs, or certain aspects of the system like screen updating). If you fail to release the Tube, then no other process will be able to use it. This will effectively be a crash, because all screen updates will stop.
Note that a call to this function must be made for every time that Function 81h has been issued. Tube claims and releases can safely be nested, provided only that there is a release for every claim.
This is used to set up the screen in the host or to read the current host screen type. Five types of host screen are supported by the system (up to a point). These are:
|Type 0||BBC Mode 3, used for DOS Mode 7.|
|Type 1||BBC Mode 0, used for standard (2-colour) GEM.|
|Type 2||BBC Mode 1, used for 4-colour GEM.|
|Type 3||A 25-line, 4-colour, 40-column mode. It is used by DOS Screen Modes 0/1 and 4/5.|
|Type 4||The 25-line, 2-colour, 80-column mode without gaps between the lines, used by DOS Modes 2/3 and 6. (This is the screen type entered by DOS-Plus on system boot.)|
The function takes one or two parameters. The main parameter is in CL.
If it is called with CL between 0 and 4, then the corresponding screen type will be set up in the host. Note that If CL=1 or 2 (GEM screens) then BX is used as a second parameter. In this case BX must contain the segment value (in the 512) which is to be used for the screen memory. (The screen memory position for DOS screens is not user-definable, but that for GEM screens is. Normally, of course, it is defined by GEM itself.)
If CL=FFh on entry, then the current screen type is read but not changed. The value is returned in AX. If the screen was of Type 1 or 2, then the screen segment value is returned in CX=DX. Types 0, 3 and 4 return with CX=DX=0.
Values of CL other than 0 to 4 or FFh return with AX=FFFFh (unsupported call).
Note the following:
|This function only affects the host screen. What it does is to issue the equivalent of a BBC MODE command, adjust the CRTC and video ULA registers if necessary, and write the palette. It does not clear the 512 copy of the screen nor make any adjustment to the 512 screen variables, except those directly relating to the host screen (namely the screen type and the address in host memory of the screen start).|
|On the host's side of the Tube the screen for DOS Mode 0/1 is identical to that for Mode 4/5. The memory maps in the 512 for these modes are very different, but since this function applies only to host screens the same screen type number is used for both of them. The same applies to DOS Modes 2/3 and 6.|
See the Screen Operation document for more details of how the screen system works on the Master 512.
This updates a rectangular section of the monochrome GEM screen. Data is written across the Tube from the 512's copy of the screen to the host screen memory (at which point, of course, it becomes visible). The section concerned must be made up of whole-character cell blocks, and it is specified in terms of character positions. ([0,0] is top left of the screen.)
Entry values are:
|BX||Segment address value of Master 512 copy of screen|
|CX||Top left of section to be written (CL column, CH row)|
|DX||Bottom right of section (DL column, DH row)|
Note that this function relates only to GEM screens. Screen corruption (or worse) may occur if it is called when a standard DOS screen is active. Function 8Ch is the equivalent for 4-colour GEM screens.
This does nothing, though it returns with AX=0 rather than the usual value of FFFFh for an unsupported call. (This was originally to be used for the colour version of Function 84h. For some reason it was abandonned and replaced with Function 8Ch.)
The Master 512's software support for the mouse is very limited (apart from GEM). However this function makes it possible to implement a mouse driver without having to go into all the complexities of trying to handle the User Port across the Tube, or interrogating the Tube directly.
The 512's version of DOS-Plus does keep a updated record of the current mouse position (in arbitrary, absolute units) and button state. It can also be caused to inform a user program of these at regular intervals. This is the limit of the system's mouse support, though. Any display or movement of a pointer, for example, must be provided by the program.
If you wish to write a program which uses the mouse you should do it like this. Load into memory your own "mouse handler" code. After this use Subfunction 0 (see below) to request the system regularly to inform your handler of the current mouse state. After doing this your code will be entered 50 times per second (usually). On entry to your routine, the processor's registers will be set up as follows:
|AX||Button state (Bit 0 - LH button, bit 1 - middle button (if present), bit 2 - RH button, the bit is set if the corresponding button is pressed.)|
Your code should be a Far Procedure (exiting with a RET FAR, RETF, or equivalent instruction). It does not need to preserve any registers (apart from the stack position). It will be entered with interrupts enabled.
Your code will normally be entered 50 times per second (on the V-sync event). However, the system will make sure that your code is not called in "unsafe" situations. This includes when another process is using the Tube, and in this case your code will be entered as soon as the Tube is released. It also means that you do not need to worry about any complications like re-entrancy. A further consequence is that your code will not normally be entered if you are working at the DOS command line, or are in a .CMD program.
Note that starting a background program can prevent your mouse handler being entered at all. If you want to start a background program, switch the mouse off first (use Subfunction 1 – see below), start the other program, and then re-initialize the mouse.
Your routine can use the Tube if you like (for example, using OSWORD FFh to write a pointer to the host screen if you are in DOS screen mode 7). If you do this, make sure you claim and release the Tube correctly. Because of the safety checks conducted by the system you can be certain that no-one else is using the Tube and you will not hold up the system. Note that in DOS screen modes 0 to 6 the host screen is updated from the 512's copy on every fifth V-sync event, and on these occasions the screen update takes place after the mouse handler has completed its action.
XIOS call 86h has two subfunctions:
|CL=0||Initialize mouse. This function will cause the system to enter your routine at frequent intervals (as outlined above). On entry to the function, BX:DX must point to your code. (It will be entered at this address.)|
|CL=1||Release mouse. After this the handler is no longer entered. This call must be issued if the program of which the handler forms a part is terminated and the memory containing it is to be returned to the DOS pool.|
Other subfunctions are not supported and (except for CL=2) return with AX=FFFFh.
If an action takes place which causes an error to be generated in the BBC Micro host (according to the normal BBC Micro error system), then the 512 is informed of this error and stores the error number and message. This function allows you to read the details of the most recently occurring host error.
The function returns in BX (=AX) a pointer to an "error information block". (Once again this is in the SYSDAT segment and the returned value is the offset.) The byte at [BX] is an error flag. This will be set to FFh if an error has occurred. It will be 0 otherwise. If [BX]=FFh then the host error number will be in [BX+1] and the error message (an ASCIIZ string, as usual) will start at [BX+2].
Note that this function does more than simply return a value. It also sets up the error flag, including preparing for "next time's call". If you use it twice, then the error flag will only be non-zero after the second call if a host error occurred between the two calls.
This means that you can use it to detect whether a host error has occurred during a particular routine. The sequence is like this:
|First issue XIOS Function 87h to clear the error flag for next time (ignore the value of BX at this point).|
|Second, perform the action which might possibly generate a host error.|
Now issue XIOS Function 87h again, and check the value of the byte at [BX].
You will find that you have to make both of the calls to Function 87h. If you omit the first one, then you will not know when the error occurred. If you try to omit the second (and simply use the value you know BX will be given) then the error flag will not be set up.
The Function 89h will "prime" the error system for itself, so if you are using this you do not need a call to Function 87h in preparation. It is enough to call the function once after the OSBYTE to find out whether an error was generated during the call.
In actual fact this does not normally do anything, and neither is it ever called by the system. However, there is nothing useful you can do with it.
This performs an OSBYTE call to the host. This might be used for activities such as selecting a serial printer, setting screen flash rates, changing details of the beep (for ASCII 7), etc. Entry registers correspond as follows:
Values are returned in AL (X) and AH (Y) with the C setting in CF. Note that these correspondences are totally different from those used by Interrupt 4Bh.
This function is much easier to use than Interrupt 4Bh for the following two reasons:
|The XIOS function includes all the necessary Tube claims and releases. You just need to set up the registers and call the function.|
|It handles errors correctly. If a host error occurs while using XIOS Function 89h, then the function will exit as normal. Using Function 87h (above) after the call will tell you whether there has actually been an error and what it was if so. (Function 89h sets up the error flag, so you do not need a preliminary call to Function 87h.) By contrast, If an error were to occur while using Interrupt 4Bh then the machine would hang up.|
Note that OSBYTE functions 82h to 84h are not passed across the Tube to the host. Rather the 512 returns its own values (X=Y=0 in each case).
This performs a standard host OSWORD call. It might be used for defining envelopes, producing sounds, etc. On entry, CL should contain the OSWORD function number (6502 A-register value). DX:SI must point to the parameter block. Note that this is quite different from Interrupt 4Ah. Note also that only non-zero OSWORDs are actioned. If CL=0 on entry, then the function returns having done nothing.
The function can be used to issue OSWORD FAh (though note the bug – see Appendix F of the Master 512 Technical Guide). On the other hand, it does not produce the correct protocols for the "DOS-Plus special" OSWORDs FBh to FFh, and it cannot be used with these. To use them you must "manually" write the required bytes across the Tube. You can work out the necessary byte sequences from the discussion in Chapter 5 of the Technical Guide.
XIOS Function 8Ah is easier to use than Interrupt 4Ah because the Tube claim and release is handled for you. However, unlike Function 89h, it is not protected against errors. The machine would crash if an error happened in the host while it was processing the OSWORD call. In practice this is unlikely to be a problem since very few OSWORD calls can produce errors. None of the MOS calls ever do, and nor do any of the calls to ADFS. (These are OSWORDs 70h to 73h – if something is found to be wrong during an OSWORD 72h then the call is completed and an error code is handed back in the parameter block.) Similarly, OSWORD 7Fh (which reads or writes a DFS disk) will not produce a system error.
However, there are OSWORD calls which can generate errors. The DFS OSWORDs 7Dh and 7Eh may, for instance, if a disk error is found. A decent program should not crash in these circumstances. One possible solution is outlined in the discussion of Interrupts 40h to 4Ch. In practice, though, it is probably easier to handle such OSWORDs by direct Tube manipulation. Watford's Advanced Reference Manual for the BBC Master gives the sequence of actions necessary. Your program should first issue XIOS Function 87h to clear the error flag. After this it should write the necessary control and data bytes across Tube Register 2. Then it should check for errors by alternately issuing XIOS Function 87h and testing whether any data is being returned from the host in Tube Register 2. Data returned means no error has occurred. The program can then complete the process as appropriate.
This function issues a series of short beeps (in two pitches) as a signal to the user. It can also be made to display a message at the bottom of the screen.
The important thing to observe is that the function will only cause the message to be displayed if the machine is running in CP/M Mode. If it was originally in PC Mode, then you can use Interrupt 16h, Function FFh to swap to CP/M Mode before issuing the call (and then swap back afterwards).
Assuming the machine is in CP/M Mode, the message must be an ASCIIZ string, pointed to by SI:DX. (SI and DX are the opposite way round from their usage in Function 8Ah!) The message will be displayed on the bottom line of the screen (the CP/M status line) for as long as the beeps continue. It will then disappear, and the cursor will return to where it was before.
The number, duration and pitch of the beeps are all fixed. The volume is that currently set for the bell character (ASCII 7), and you can change it by using Function 89h to issue the equivalent of a *FX 212.
This function may seem to be rather an oddity, but its real significance is that it can be called by programs running in the background. (The program ALARM.CMD on the boot disk uses it, for example.) Other than this, background programs may not use the screen or the keyboard.
This is the equivalent for the 4-colour GEM screen driver of Function 84h above. It works in exactly the same way.