Appendix V | Index | Appendix VII |
This appendix describes the CP/M Plus implementation on the Spectrum +3, with particular reference on how to use the extensive facilities available in the BIOS extended jumpblock. This is not a tutorial, the reader should have some knowledge of CP/M Plus and its structure.
Note: The term "bank" will only be used in the CP/M Plus sense in which bank 0 is the BDOS bank, bank 1 is the TPA bank etc.
Hexadecimal numbers are preceded by a #. All other numbers are in decimal.
Three character devices are supported:
The keyboard can be in one of four shift states for each of which there is a separate user programmable translation table. These shifts are:
normal | which produces lower case letters |
CAPS | which produces upper case letters |
SYMB | which produces the symbol characters marked on many keys. |
EXTEND | which produces "control" values in the range 0..31. Note that CAPS+SYMB is exactly the same as EXTEND. |
There is a software settable "Num Lock". If num lock is set then all the translations tables are scanned for a "numeric" character "0123456789+-.," otherwise the key is translated according to the current shift state. The tables are scanned in the order normal, Caps, Symb, Extend.
There is also a software settable "Shift Lock", which if asserted has exactly the same effect as if the CAPS SHIFT key was permanently held down.
There is also a CAPS LOCK key, next to the lefthand CAPS SHIFT key. If this has been toggled on, characters in the range #61..#7A (a..z) and #E0 .. #FB (accented lower case letters) are upshifted.
Note that the Shift Lock and Num Lock are software settable in that they can only be set by an application program which uses KM KT PUT. They are included mainly for compatibility with other CP/M Plus implementations.
The CRT device drives the Spectrum screen via a terminal emulator. This provides a machine independent screen environment which can be preserved across a range of machines and should facilitate the installation of standard application programs.
The emulator does not attempt to simulate precisely a particular terminal but is similar to many. The emulator is almost the same as that implemented by Digital Research for their 16bit operating systems.
The emulator is highly compatible with the terminal emulators within the CP/M Plus systems implemented on the CPC6128 and PCW machines. Details of the terminal's character handling and of the screen control codes are given in Appendix III.
The terminal emulator restricts its operation to within a viewport. The viewport may be all, or part, of the screen aligned on character boundaries. The size and shape of the viewport is changed by the ESC 3 or ESC X sequences or by selecting 24 x 80 mode or by enabling or disabling the status line. There is only one viewport. Character cells to the left and right of the viewport are affected by scrolling the viewport. Character cells above and below the viewport are not affected.
The Spectrum +3 has eight colours corresponding to the eight possible combinations in which the three colour "guns" (Red, Green and Blue) can be on or off. It also allows an 8x8 pixel area of the screen to be bright (high intensity) or flash (alternate foreground and background colours).
ESC b and ESC c require a colour parameter. This has #20 subtracted and then is masked with #3F. The resulting value is treated as three 2 bit numbers each specifying the intensity of one of the three primary colours. Bits 0,1 for blue, bits 2,3 for red and bits 4,5 for green. The bit value is then treated as follows:
0 | gun off |
1 or 2 | gun on, normal intensity |
3 | gun on, high intensity provided both foreground and background are high intensity! |
Colours can also (via TE SET INK) be set to flash. Only if both foreground and background colours are set to two different values will flashing actually take place.
Note that the Spectrum hardware restricts colour information so that it has to apply to a whole 8x8 pixel area. These areas only correspond exactly to screen characters in the 32 column mode.
ESC 2 requires a language parameter. This is masked to give a value in the range 0..7. The screen character set is then altered so as to be suitable for the particular language chosen by swapping character matrices within the normal ASCII range (#20..#7F) with characters in the extended range (#A0..#FF).
Some application programs may require a "standard" 24 x 80 screen. Sending ESC x will enable 24 x 80 mode regardless of the actual size of the screen. ESC y will restore the screen to its normal size, ie. 24 x 51. Both ESC x and ESC y will clear the entire screen. Turning 24 x 80 on and off has no effect on whether the status line is enabled.
The screen may be put into "Page Mode". This affects the action of vertical movement commands. These no longer scroll the whole screen up and down, but instead "wrap around" at the top and bottom of the screen. This can be useful when it would take too long to scroll the whole screen - such as is often the case in "Comms" programs.
In Page mode the following commands are respecified:
Page mode has no effect on cursoring up and down, direct cursor movements or clearing areas of the screen.
To prevent unsightly cursor flashing whilst outputting text to the screen the cursor is not turned on until 1/10 second after the last character was written. If the system is in 80 column mode when the cursor is turned on then the half of the screen which contains the cursor is displayed - unless this action has been disabled (using ESC 5).
The bottom line of the screen may be used by the BIOS as a status line. On it are displayed disc error messages and, on single drive systems, instructions to change the disc and whether the drive is A: or B:. The status line can be disabled in which case the CRT device may use the bottom line and BIOS messages are displayed on the CONOUT: device.
If CONOUT: is not attached to the CRT device then status messages are sent to the CONOUT: message channel, and will not appear on the status line. (See Section VI.5 for details).
In 24x80 mode, messages will appear on the bottom line provided the status line is enabled.
A standard 8 bit Centronics interface (without an ACK signal).
The device SIO drives the built-in serial channel. Because of the primitive nature of the serial interface it is not recommended that the input be driven in anything other than handshake mode. Even then, problems may occur with some devices if they are tardy in noticing changes in control signals.
The following parameters can be set by software:
Note that setting 1.5 stop bits is treated as if 2 were requested.
Note that it is not possible to set 8 data bits plus parity.
The receiver and transmitter baud rates can be set independently.
CP/M Plus expresses baud rates as a number in the range 1..15, the encoded baud rate. The table overleaf gives the encoded baud rate, and the baud rate.
1 | 50 | Note: this speed is not implemented | |
2 | 75 | ||
3 | 110 | ||
4 | 134.5 | 10 | 2400 |
5 | 150 | 11 | 3600 |
6 | 300 | 12 | 4800 |
7 | 600 | 13 | 7200 |
8 | 1200 | 14 | 9600 |
9 | 1800 | 15 | 19200 |
The software wait loop is some 6.5 microseconds long - giving a maximum theoretical error of 6% at 9600 baud. Thus slower speeds are more likely to work than faster speeds..
The SIO can be operated in one of two modes, handshake or non-handshake.
A problem arises when one attempts to output to a device which either does not exist or is permanently busy - the system could wait forever. This typically occurs if the user accidentally types control P on a system without a printer. To solve this if an output device fails to respond within 30 seconds (approx) then the following message is displayed:
device not ready - Retry, Ignore or Cancel?where device is the actual name of the device, LPT, SIO etc.
Typing R for retry will try the operation again. Typing I for ignore will throw the character away. Typing C for cancel will set up a sink by removing the offending physical device from all of the output logical devices (CONOUT: AUXOUT: and LST:).
Thus in the above case of accidently typing Control-P the user should respond to the message with C for cancel, all further output to the printer will be thrown away. When a printer is actually available the user can redirect output there by using DEVICE in the normal manner.
Timeouts can be permanently disabled by using the program TIMEOUT.COM. This uses the 'spare' BIT 7 of the character device table mode byte to record the current state.
The disc driver supports one or two floppy disc drives. Three disc formats are supported: "system format" and "data only format" as per CP/M 2.2 on other AMSTRAD machines and the PCW format. The PCW8256 format is actually a family of formats since the precise details of the format are recorded on the boot sector as the "disc specification". "Spectrum +3" discs are one member of the PCW family of formats. Full details of the PCW family of formats can be found in the Spectrum +3 User Guide.
The Spectrum +3 can only be booted from a Spectrum +3 format disc. Once booted any sort of acceptable disc can be used.
If a second drive is fitted then it can be either single or double track, single or double sided. However, DISCKIT assumes that the second drive will be a standard single sided, single track unit.
Many of the disc driver routines are available to an application program via the extended BIOS jumpblock; for example the DISCKIT utility program has to use these routines since there is no standard CP/M Plus facility for formatting discs.
On single drive systems two "logical" drives (A: and B:) are both mapped on to the one physical drive. The number of physical drives fitted is detected during cold boot.
The BIOS routine SELDSK deals with the logical to physical drive mapping. Whenever it is called it checks that the logical drive being selected is currently mapped onto the physical drive. If not a BIOS message is displayed to prompt the user to change the disc.
This enables disc to disc copying using a single drive with standard utilities such as PIP.
The current assignment of logical to physical is displayed on the status line (provided it is enabled) as "Drive is A:" or "Drive is B:".
The disc driver routine interfaces refer to the drives as "unit 0" and "unit 1". This terminology is introduced for reasons of upwards compatability with other products which may have to make a clear distinction between physical drives (units) and logical drives (drives A: B: C: ... P:).
The disc driver routines require "logical" tracks and sectors. These are used to hide information concerning the number of sides and the actual sector numbers from CP/M Plus, which knows nothing about them.
Logical track numbers on a single sided disc are the same as physical track numbers.
For double sided discs two options are available:
Flip sides | side 0 track 0 | = logical track | 0 |
side 1 track 0 | 1 | ||
side 0 track 1 | 2 | ||
side 1 track 1 | 3 | ||
... | |||
side 1 last track | |||
Up and over | side 0 track 0 | = logical track | 0 |
side 0 track 1 | 1 | ||
... | |||
side 0 last track | |||
side 1 last track | |||
side 1 last track - 1 | |||
... | |||
side track 0 |
Logical sectors hide the actual physical sector numbers. Logical sector numbers always start from 0.
Logical sector = physical sector - first physical sector.
BIOS disc error messages are in terms of logical track and sector numbers. All this information is held in an eXtended Disc Parameter Block.
Associated with each (logical) drive is an extended disc parameter block. This contains a standard DPB as required by CP/M Plus and information required by the BIOS to support the different formats. It may be patched in order to use different format discs provided that the restrictions below are obeyed.
The structure of an XDPB is identical to that used for +3DOS, and is documented in the Spectrum +3 User Guide.
To find the XDPB for a particular drive use BDOS function 31.
The restriction on patching an XDPB is that the resulting disc structure must lie within the following maximum sizes:
Maximum 2 bit allocation vector | = 91 bytes |
Maximum checksum vector | = 64 bytes |
Maximum hash table size | = 1024 bytes |
Maximum sector size | = 512 bytes |
This corresponds to a disc of 160 tracks, 9 sectors per track, 512 bytes per sector, 1 reserved track, 256 directory entries, 2K block size. This is the recommended structure for a double sided, double track, double density disc.
CP/M 2.2 and AMSDOS system format and data only format discs from the CPC6128 can be used under CP/M Plus with no further ado.
CP/M Plus discs and be freely used under CP/M 2.2 or AMSDOS provided that:
This is the normal state of a CP/M Plus disc, and will remain as such unless the user explicitly enables any of the above features using INITDIR.COM and/or SET.COM.
If any of the above exist then both CP/M 2.2 and AMSDOS will become confused as to the amount of free space on the disc. Files may still be read but it is recommended that such discs are not written to under CP/M 2.2 or AMSDOS.
INITDIR.COM is used to reformat the directory for time and date stamping. SET.COM is used to create disc labels and enable and create passwords.
The Spectrum's memory is organised into three banks:
Bank 0 is the BDOS bank which contains the banked portions of the BIOS (Basic Input Output System) and BDOS (Basic Disc Operating System). It also contains the screen memory, some disc buffers and the extended BIOS jumpblock.
Bank 1 is the TPA bank in which all application programs are run.
Bank 2 contains a copy of the CCP (Console Command Processor), screen memory, the disc hash tables and data buffers.
The top 16K of memory is common to all banks; it contains the resident portions of the BIOS and BDOS and part of the TPA.
Bank 0 - BDOS | Bank 1 - TPA | Bank 2 - Extra | |||||||||||||||||
|
|
|
|
The character matrix RAM is at #3000 in bank 0. It remains visible at #3000 when bank 2 is selected.
The BIOS uses the restart instructions and their locations as follows:
RST 0 | used by CP/M |
RST 1..RST 5 | not used - reserved |
RST 6 | used by SID |
RST 7 | used for interrupts |
The SID program supplied has been modified to use RST6 instead of the usual RST7.
An application program may use the Z80 alternate and index instructions without further ado. All BDOS and standard BIOS calls preserve these registers. Extended BIOS routines preserve the alternate register set but may use the index registers for passing parameters. See the routine definitions for details.
Note that using Z80 only instructions and/or registers will prevent an application from running on an 8080 or 8085 based machine.
The term "cold boot" means invoking CP/M for the first time after the machine has been switched on or reset.
The boot program loads the first file it finds with type .EMS, this file should contain the CP/M Plus system.
The .EMS file replaces the CPM3.SYS file which is usually found on CP/M Plus implementations. The .EMS file contains CPM3.SYS, CCP.COM together with a loader and the BIOS.
The term "warm boot" means reloading CP/M after a transient program has run or after the use has typed Control-C in order to change a disc.
A warm boot is invoked immediately after initialisation and thereafter by a jump to location zero, or by calling the BDOS System Reset function. The primary function of the warm boot is to load CCP into memory and then to enter the CCP. A copy of the CCP is stored in bank 2 so a warm boot does not require any disc access.
The warm boot routine initialises the jumps at #0000 and #0005
The CP/M Plus time and date clock in the System Control Block (SCB) is updated every second. Hardware limitations mean that the clock will not be found to be very accurate if the machine is used heavily, or the disc accessed a lot.
All BIOS messages are displayed on the status line, if enabled, otherwise they are sent to the CONOUT: device.
Some BIOS messages are followed by the question Retry, Ignore or Cancel?. The system then discards any outstanding characters, turns on the cursor and waits for the user to type R, I or C; anything else will cause a bleep.
In the standard CP/M Plus BIOS jumpblock function 30 "USERF" is reserved for the system implementor. On the Spectrum +3 this function is used for calling the extended BIOS routines in bank 0.
To find USERF fetch the contents of locations 1 and 2, this contains the address of function 1 "WBOOT" in the BIOS jumpblock. Add 87 to give the address of the JMP USERF entry. It is a good idea to copy the USERF jumpblock entry into a fixed location and then call this fixed location.
Note that neither USERF nor the rest of the BIOS jumpblock is at the same address as on the PCW machines.
USERF takes the address of the required routine in bank 0 as an inline parameter, ie. as the two bytes following the CALL instruction. The registers AF BC DE HL IX IY are all passed to the routine and returned back to the caller as set by the routine. The alternate register set is preserved throughout the call, it can neither be used to pass parameters nor to return results.
The BIOS has two jumpblocks: the standard CP/M Plus jumpblock and an extended jumpblock. The word at location #0001 contains the address of the WBOOT entry in the standard BIOS jumpblock, function 1. The extended jumpblock starts at #0080 in bank 0 and contains jumps for additional facilities such as physical sector reading and writing.
Since the extended BIOS jumpblock is in bank 0 whereas the user program is in bank 1 it is not possible for an application program to call routines in the extended jumpblock directly, instead the BIOS function USERF must be used.
This jumpblock is almost the same as those on the CPC6128 and PCW CP/M Plus implementations. Differences are noted where appropriate. It has the format:
Disc Driver | ||
---|---|---|
#0080 | JMP DD INIT | ;initialise disc driver |
#0083 | JMP DD SETUP | ;set disc parameters |
#0086 | JMP DD READ SECTOR | ;read a sector |
#0089 | JMP DD WRITE | ;write a sector |
#008C | JMP DD CHECK SECTOR | ;check a sector |
#008F | JMP DD FORMAT | ;format a track |
#0092 | JMP DD LOGIN | ;login a disc |
#0095 | JMP DD SEL FORMAT | ;select a standard format |
#0098 | JMP DD DRIVE STATUS | ;fetch drive status |
#009B | JMP DD READ ID | ;read a sector ID |
#009E | JMP DD L DPB | ;initialise a DPB |
#00A1 | JMP DD L XDPB | ;initialise an XDPB |
#00A4 | JMP DD L ON MOTOR | ;turn motor on, wait for timeout |
#00A7 | JMP DD L T OFF MOTOR | ;set motor off timeout |
#00AA | JMP DD OFF MOTOR | ;turn motor off |
#00AD | JMP DD L READ | ;read type µPD765A command |
#00B0 | JMP DD L WRITE | ;write type µPD765A command |
#00B3 | JMP DD L SEEK | ;seek command |
SIO Driver | ||
#00B6 | JMP CD SA INIT | ;initialise SIO channel A |
#00B9 | JMP CD SA BAUD | ;set SIO channel A baud rates |
#00BC | JMP CD SA PARAMS | ;fetch SIO channel A parameters |
Terminal Emulator | ||
#00BF | JMP TE ASK | ;where is the cursor, what screen size |
#00C2 | JMP TE RESET | ;re-initialise the screen |
#00C5 | JMP TE STL ASK | ;is the status line enabled? |
#00C8 | JMP TE STL ON OFF | ;enable/disable the status line |
#00CB | JMP TE SET INK | ;set the colour(s) for an ink |
#00CE | JMP TE SET BORDER | ;set the colour(s) for the border |
#00D1 | JMP TE SET SPEED | ;set the ink flash speed |
Keyboard | ||
#00D4 | JMP KM SET EXPAND | ;set the ink flash speed |
#00D7 | JMP KM SET KEY | ;set entry(s) for key translation |
#00DA | JMP KM KT GET | ;get a key token |
#00DD | JMP KM KT PUT | ;put a key token |
#00E0 | JMP KM SET SPEED | ;set key repeat speed |
Miscellaneous | ||
#00E3 | JMP CD VERSION | ;get version numbers |
#00E6 | JMP CD INFO | ;get BIOS system information |
#00E9 | JMP SCR RUN ROUTINE | ;run a routine in screen environment |
#00EC | JMP FIND FID | ;find a FID |
All other entries in the jumpblock are reserved and must not be used. They can differ markedly from one version to the next.
The action performed by each entry in the extended jumpblock is detailed below, along with the entry and exit conditions of each.
0 DD INIT | #0080 |
Initialise the disc driver.
Initialises the disc driver, resets all disc parameters to their default values. Turns the motor off.
The default disc parameters are:
Motor on timeout | 1 second |
Motor off timeout | 5 seconds |
Write current off time | 1.75 milliseconds |
Head settle time | 30 milliseconds |
Step rate | 12 milliseconds |
Head unload time | 480 milliseconds |
Head load time | 4 millisecond |
Non-DMA mode |
DD SETUP
1 DD SETUP | #0083 |
Reset various disc parameters.
Sets the values for the motor on, motor off, write current off and head settle times. Sends a SPECIFY command to the floppy disc controller.
byte 0 | motor on timeout in 100 millisecond units |
byte 1 | motor off timeout in 100 millisecond units |
byte 2 | write current off time in 10 millisecond units |
byte 3 | head settle time in 1 millisecond units |
byte 4 | step rate time in 1 millisecond units |
byte 5 | head unload delay 32..480 ms in 32 millisecond units |
byte 6 | bits 7..1: head load dely 4...508ms in units of 4ms; |
bit 0: non-DMA mode (as per µPD765A SPECIFY command). |
The values given are used for both drives. When using two differing drives use the slower of the two times.
A motor off time of zero will never turn the motor off.
The default values are:
Motor on timeout | 10 |
Motor off timeout | 50 |
Write current off time | 175 |
Head settle time | 30 |
Step rate | 12 |
Head unload time | 15 |
Head load time + non DMA | 3 |
Non-DMA mode |
2 DD READ SECTOR | #0086 |
Read a sector from disc.
Reads a sector from disc into any bank.
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
The "media changed" error means that the sector numbers on the disc are different from those specified in the XDPB.
DD WRITE SECTOR, DD CHECK SECTOR
3 DD WRITE SECTOR | #0089 |
Write a sector to disc.
Writes a sector to disc from any bank.
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
The "media changed" error means that the sector numbers on the disc are different from those specified in the XDPB.
DD READ SECTOR, DD CHECK SECTOR
4 DD CHECK SECTOR | #008C |
Check that a sector on disc is the same as one in memory.
Compares a sector on disc with a store copy.
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
The "media changed" error means that the sector numbers on the disc are different from those specified in the XDPB.
DD READ SECTOR, DD WRITE SECTOR
5 DD FORMAT | #008F |
Format a track.
Formats a track using a header information buffer in any bank.
Format of header information:
Sector entry format:
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
The "media changed" error means that the sector numbers on the disc are different from those specified in the XDPB.
6 DD LOGIN | #0092 |
Login a disc.
Attempts to determine the format of a disc. If successful initialises an XDPB. Does not affect or consider the freeze flag.
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
DD SEL FORMAT
7 DD SEL FORMAT | #0095 |
Select a standard disc format.
Initialises an XDPB for the required format regardless of the actual disc format. Normally the BIOS automatically determines the format of a disc when it is logged in, but for programs such as disc formatters it is necessary to pre-set the format. Does not affect or consider the freeze flag.
This routine will only fail if an illegal disc type is given.
DD LOGIN
8 DD DRIVE STATUS | #0098 |
Fetch the drive status.
Fetch the drive status: ready, write protected etc.
For unit 1 if bit 6 = 0 and bit 5 = 0 then the drive is not fitted.
9 DD READ ID | #009B |
Read a sector ID.
Reads the ID from the first sector found.
In the event of errors this routine trys and retrys a total of 15 times as follows:
T T T R T T T T I T T T T R T T T Twhere T means try, R realign, I move to innermost track.
10 DD L DPB | #009E |
Initialise a standard DPB.
This routine initialises a standard CP/M Plus Disc Parameter Block for a given disc format.
The disc format is specified as follows:
DD L XDPB
11 DD L XDPB | #00A1 |
Initialise an XDPB.
This routine initialises an eXtended Disc Parameter Block for a given disc format.
See DD L DPB for a description of the disc format specification.
DD L DDPB
12 DD L ON MOTOR | #00A4 |
Turn the motor on.
If the motor is off then turn it on, wait for the motor on timeout.
DD L T OFF MOTOR
DD L OFF MOTOR
13 DD L T OFF MOTOR | #00A7 |
Start the motor off timeout.
Starts the motor off timeout, after which the motor will be turned off. Returns immediately, does not wait for the timeout.
DD L ON MOTOR
DD L OFF MOTOR
14 DD L ON MOTOR | #00AA |
Turn the motor off.
Turns the motor off, kills the motor timeout if any.
DD L ON MOTOR
DD L T OFF MOTOR
15 DD L READ | #00AD |
µPD765A read type command driver.
Low level interface for the µPD765A floppy disc driver. Use for "READ DATA", "READ DELETED DATA", "READ A TRACK".
Sends required commands to the µPD765A, deals with bank switching, fetches results.
Motor must be running.
Detailed knowledge of the µPD765A is required in order to use this routine.
DD L WRITE
16 DD L WRITE | #00B0 |
µPD765A write type command driver.
Low level interface for the µPD765A floppy disc driver. Use for "WRITE DATA", "WRITE DELETED DATA", "FORMAT A TRACK", "SCAN EQUAL", "SCAN LOW OR EQUAL", "SCAN HIGH OR EQUAL".
Sends required commands to the µPD765A, deals with bank switching, fetches results.
Motor must be running.
Detailed knowledge of the µPD765A is required in order to use this routine.
DD L READ
17 DD L SEEK | #00B3 |
Seek to required track.
Realigns if required, seeks to given track.
Motor must be running.
Will try 10 times to seek or realign before returning an error.
This routine is not normally required since "DD READ SECTOR", "DD WRITE SECTOR" "DD CHECK SECTOR" and "DD FORMAT" all perform their own seeks.
18 CD SA INIT | #00B6 |
Initialise SIO
Initialise SIO channel A.
#00 | no handshake |
#FF | handshake |
#FE | "interrupt", no handshake (treated as #FE) |
#FD | "interrupt", handshake (treated as #FF) |
#80 | drop DTR |
#7F | raise DTR |
#7E | "drop RTS" - ignored |
#7D | "raise RTS" - ignored |
The parameters are not validated, silly values will give silly results.
It is not possible to select a mode with 8 data bits and odd or even parity as well.
19 CD SA BAUD | #00B9 |
Set the baud rates for the SIO.
Sets the receiver and transmitter baud rates for SIO.
The parameters are not validated, silly values will give silly results.
The encoded baud rates are given in Section VI.1.
Does not affect the CP/M Plus character I/O table.
20 CD SA PARAMS | #00BC |
Get the current parameters for the SIO
Fetches the current mode, parity, baud rates etc for SIO.
The values returned reflect current settings, which may not be quite the same as those requested!
21 TE ASK | #00BF |
Get the current viewport position and size and cursor position.
Fetches the current viewport position and size and cursor position.
The top row is row 0, the left column is column 0.
22 TE RESET | #00C2 |
Re-initialise the terminal emulator.
Re-initialise the terminal emulator: clears the screen, homes and enables the cursor. For use by programs which have written to the screen by means other than using the CRT device.
23 TE STL ASK | #00C5 |
Is the status line enabled?
Asks if the status line is enabled. It will be enabled if it is not disabled and the screen is not in 24x80 mode.
TE STL ON OFF
24 TE STL ON OFF | #00C8 |
Enable / disable the status line.
Enables or disables the status line. Disabling the status line gives an extra line to the terminal emulator. When disabled status line messages are sent to the CONOUT: device.
TE STL ASK
25 TE SET INK | #00CB |
Set the colours in which to display an ink
Set which colour will be used to display an ink. If the flashing parameter in C is the same value as the colour in B then the ink will remain a steady colour. If the value in C is different then the ink may alternate between the foreground and background colours.
Ink 0 is used for the background (which includes the border); ink 1 is used for the foreground. Inks > 1 are ignored.
The colour is masked with #3F and the resulting value is treated as three 2 bit numbers each specifying the intensity of one of the three primary colours. Bits 0,1 for blue, bits 2,3 for red and bits 4,5 for green. This bit value is then interpreted as follows:
Note that the colour values given in Appendix III have had #20 added to them, whereas the values for this routine should not.
The value in C is masked with #3F before comparing it with B for equality. If the values differ, the ink is flashing.
If both inks 0 and 1 are high intensity then the colours will be set to be bright (over the whole 8x8 pixel cell). If both inks 0 and 1 are flashing then the colour will be set to flash (which makes the whole cell alternate between foreground and background colours).
Setting the colour of an ink does not affect the colour of the screen. It affects how characters will be written in the future.
26 TE SET BORDER | #00CE |
Set the colour of the screen border
Set which colour will be used to display the border.
The border can also be changed by using TE SET INK to set ink 0.
The colour parameter is interpreted as described above for TE SET INK, except that it cannot be set bright or flashing.
27 TE SET SPEED | #00D1 |
Set the flash period.
This routine has no effect on a Spectrum +3 because all flashing is done by hardware.
28 KM SET EXPAND | #00D4 |
Set an expansion string
Set the expansion string associated with an expansion token.
The characters in the string are not expanded (or otherwise dealt with). It is therefore possible to put any character into an expansion string.
If there is insufficient room in the expansion buffer for the new string then no change is made to the expansions.
If the string is currently being used to generate characters then the unread portion of the string is discarded. The next character will be read from the key buffer.
29 KM SET KEY | #00D7 |
Set entry(s) in key translation table(s)
Set what character or token a key will be translated to when Caps, Symb, Extend or none of these is pressed.
If the key number is invalid then no action is taken.
Most values in the table are treated as characters and are passed back to the user. However, there are certain special values:
30 KM KT GET | #00DA |
Get a key token.
Try to fetch a key token from the keyboard.
The shift state defines which locks and/or shift keys were pressed. The repeat bit indicates that the key was generated by a repeat.
31 KM KT PUT | #00DD |
Put a key token.
Insert a key token into the keyboard buffer so that the next "KM KT GET" will fetch it.
More than one key token may be put, however, buffer overflow is not reported and will result in key tokens being lost. The buffer is at least 10 tokens long. If a great deal of text is to be generated by KM KT PUT the use of expansion tokens is recommended.
To change any of the lock states call "KM KT PUT" with the required state with an innocuous key number then call "KM KT GET" to remove it.
32 KM SET SPEED | #00E0 |
Set key start up delay and repeat speed.
Set the time before keys first repeat (start up delay) and the time between repeats (repeat speed).
Both delays are given in scans of the keyboard. The keyboard is scanned every fiftieth of a second.
A start up delay or repeat speed of 0 is taken to mean 256.
The default start up delay is 30 scans (0.6 seconds) and the default repeat speed is 2 scans (0.04 seconds or 25 characters a second).
Note that a key is prevented from repeating (by the key scanner) if the key buffer is not empty. Thus the actual repeat speed is the slower of the supplied repeat speed and the rate at which characters are removed from the buffer. This is intended to prevent the user from getting too far ahead of a program that is running sluggishly.
The start up delay and repeat speed apply to all keys on the keyboard that are set to repeat.
33 CD VERSION | #00E3 |
Get version numbers.
Fetches machine type, BIOS version numbers and machine specific version numbers.
34 CD INFO | #00E3 |
Get BIOS system information.
Fetches BIOS system information, number of disc drivers, address of buffer table, number of memory blocks etc.
The buffer table gives details of where the data and directory buffer areas are.
35 SCR RUN ROUTINE | #00E9 |
Runs a routine in the screen environment
Ths routine is provided for compatability with the PCW implementation of CP/M Plus. This routine is not implemented on the CPC6128. The main screen exists in CP/M bank 0, and the second screen (used for the right hand side of the 80 column mode) exists in CP/M bank 2. It is therefore possible to access them using standard bank switching routines.
The screen is laid out in the normal Spectrum way, except that both screens live at address #4000 in their respective banks, with their attribute RAM at #5B00.
The eight bit character matrices used for the 32 column mode can be found at #3000, and the five bit character matrices used for the other modes can be found at #3800. In each case:
Each character entry has the following format:
The 5x8 matrices are left aligned, ie. bits 7..2 contain the character shape.
It is permissible to alter the screen or matrix tables as required - but note that there is no mechanism for restoring the original contents.
36 FIND FID | #00EC |
Find the address of a particular FID
This routine is not generally available on CPC6128 and PCW versions of CP/M Plus.
This section describes the structure and interface of Field Installable Device Drivers (FIDs), for the Spectrum +3 computer running under CP/M Plus. It assumes you are familiar with the internals of CP/M Plus. Writing FIDs is an unlikely occupation for most CP/M Plus users and software developers. This information will mainly be of use to the developers of Spectrum +3 hardware add-ons who want their hardware to be supported by CP/M Plus in an integrated way.
Hex numbers are preceded by #, all other numbers are in decimal.
CAUTION: If you use unpublished information about the implementation of CP/M Plus on the Spectrum +3 (such as might be obtained by disassembling existing software) you run the risk that your software will not work with software (or hardware) revisions. Only interfaces documented by Locomotive Software will necessarily be supported in the future!
During cold boot drive A: user 0 will be searched for FIDs, that is any file with a type part of .FID and a suitable file header. Each FID file is in Page ReLocatable (PRL) format and is loaded into memory somewhere in CP/M bank 0. The FID's Early Morning Start (FID_EMS) routine is then called. The FID can now hook itself into the BIOS in a number of different ways, for example: as one or more disc drives, as one or more character devices, as a non CP/M device such as a mouse, or as a combination of these. The FID is now a part of the BIOS and will remain as such until the next cold boot.
There is no explicit limit on the number of FIDs, however the number is limited by available resources, particularly memory. After loading and initialising all FIDs any remaining memory is used for CP/M's disc cache.
A FID may use the operating system facilities by means of SuperVisor Calls (SVCs). A FID may NOT call the CP/M BDOS or BIOS directly, however an application program may do so on a FID's behalf. The BIOS calls a FID through jumpblocks, the addresses of which are passed to the BIOS during EMS.
If required a CP/M application program or Resident System eXtension (RSX) running in the Transient Program Area (TPA) can communicate directly with a FID. Each FID is named uniquely by its filename, which is stored in the FID header. The application program calls "FIND_FID", in the extended BIOS jumpblock, with a pointer to the FID's filename in common memory. If found the address of the FID in bank 0 is returned, from which any absolute address in the FID can be calculated. Routines in a FID can then be called from the TPA by using USERF.
On the Spectrum +3 there are over 12K bytes available in bank 0 and 1.5K bytes in bank 2 for FIDs and their disc data structures and about 128 bytes in common memory for their character device table and DPBs.
A FID should not rely on these figures since firstly other FIDs may be loaded and, secondly, any future enhancements to the BIOS may alter these figures. In order to minimise the risk of running out of memory, a FID should be as small as possible and only use the resources it requires. Since FIDs use memory which would otherwise be used to cache floppy disc sectors, FIDs will tend to adversely affect floppy disc performance.
The FID program may be regarded as having an origin of #0100, of length P bytes followed by an uninitialised variable area of length V bytes:
#0100 | First byte of program |
#0100 + P - 1 | Last byte of program |
#0100 + P | First byte of uninitialised variable area |
#0100 + P + V - 1 | Last byte of uninitialised variable area |
Whilst loading the FID program is relocated onto a 256 byte boundary and all addresses are changed accordingly.
All relocatable bytes value #FF are assumed to be the most significant byte of a SVC. Both it and the preceding byte are replaced by the actual address of the SVC. A list of SVCs is given below.
It is strongly recommended that all uninitialised variables, buffers etc are placed in the uninitialised variable area rather than in the program file image itself. This can drastically reduce the file size.
Throughout this section, all routines whose names start FID_ are provided by the FID itself, all other routines and variables are system provided by SVCs.
Each routine is documented with its register entry and exit conditions. These must be followed exactly. In particular the phrase "All other registers preserved" means any register that is not explicitly mentioned as returning a value or being corrupt (ie. indeterminate) must be preserved.
All FID routines will be called using a stack in common memory, a local stack should not be necessary.
Interrupts should not be disabled unless absolutely necessary, and then only for short periods, i.e. tens of microseconds. If you cannot avoid disabling interrupts then you will cause the system clock to run slow, and the keyboard to be scanned erratically. A FID can go some way to alleviating this by using the routine SVC_CATCHUP.
FIDs may bank switch if they require to do so, but must restore the calling environment before returning, or allowing interrupt code to run. When a FID is called the memory arrangement is 4-5-6-3. The stack is in bank 3. The FID must arrange to be totally contained within bank 5 by setting its loading bound values correctly (see below). Thus if a FID requires to switch in a ROM it will have to change to the environment R-5-2-3. In order to restore this environment the FID may make use of the system variables SVC_BANK_68 and SVC_BANK_05 which contain the current contents of the hardware latches on channels #1FFD and #7FFD respectively. If the FID wishes to allow normal interrupt code to run it should first write to these variables to reflect the new state of the latches... which must be for the 4-5-6-3 memory arrangement. FIDs cannot rely upon the contents of these latches or variables being maintained from one call of the FID to the next.
The first 32 bytes of a FID is the FID header and must have the following standard form:
#0100..#0102 | JMP FID_EMS | ;jump to EMS routine |
#0103..#010A | 'SPECTRUM' | ;FID identity, overwritten by actual filename |
#010B..#010D | 'FID' | ;type extension |
#010E..#010F | ;version number (user specific) | |
#0110..#0111 | ;checksum | |
#0112 | ;lower bound on loading | |
#0113 | ;upper bound on loading | |
#0114..#011F | ;reserved for Locomotive, initialise to 0 |
The version number field is reserved for use by the user. It is recommended that it is incremented for each new issue of the FID.
The checksum field is the sum of all bytes in the FID file from byte 0 to the last byte in the PRL relocation map, excluding the checksum field, modulo #10000. The Mallard BASIC program FIDCSUM.BAS will plant the correct checksum into a FID file.
The lower bound on loading is the most significant byte of the first address which will be considered for loading the FID. The upper bound on loading is the most significant byte of the first address which cannot be allocated to this FID. Thus a FID which wishes to bank switch should set these values to #40 and #80 respectively; this will guarantee that it will be loaded somewhere between #4000 and #7FFF.
The FID loader will check the checksum and that the name and type of the file are as above, if not then it is assumed that the file is not a FID, otherwise the name and type fields are overwritten by the actual name and type of the file (including any attribute bits). The name field is used by the routine FIND_FID to locate a particular FID in memory.
A FID which requires more memory than is available, or which cannot be loaded into its requested area will not be loaded at all.
Bytes #0114..#011F are reserved for use by the BIOS and must not be written to by the FID.
Subject to availability, the FID_EMS routine may allocate the FID some extra memory over and above the area which was automatically allocated when the FID was loaded. The routine SVC_ALLOCATE will allocate a fixed size area and SVC_MAX_ALLOCATE will allocate the largest available area. It is not possible to restrict the allocation to, for example, the area #4000..#7FFF. FIDs should use SVC_ALLOCATE whenever possible, in preference to SVC_MAX_ALLOCATE.
The FID_EMS routine can also return any memory which it does not require by using the routine SVC_DEALLOCATE. This memory MUST BE an area or part of an area which has been allocated by SVC_ALLOCATE or SVC_MAX_ALLOCATE. It is also permissible to return part of the area which was allocated when the FID was loaded PROVIDED that the FID_EMS routine is not going to return with carry false - in which case the entire area will be automatically deallocated anyway. Please note that deallocating memory which does not belong to a FID is very likely to cause CP/M Plus to behave incorrectly.
Early morning start.
If this routine returns with carry false then the FID is discarded and the memory allocated when it was loaded will be re-used. This routine must NOT return with carry false once it has successfully called FID_C_HOOK or FID_D_HOOK, since the FID is now part of the BIOS and will be called upon to drive the hooked-in devices. If this routine is to return carry false then it must first use SVC_DEALLOCATE to return any memory which it has specially acquired using SVC_ALLOCATE or SVC_MAX_ALLOCATE.
The environment version number is to allow for future exapnsion of the FID system. The FID can choose whether or not to proceed in the given environment. The most significant byte is the major version number, currently #00. This is incremented with each non-upwards compatible change to the FID environment (although none are envisaged). A FID should refuse to run unless it recognises the major version number. The least significant byte is the minor version number, currently #00. This is incremented with each upwards compatible release of the FID environment. A FID should check that the minor version number is sufficiently high to provide the facilities which it requires.
The returned messages are displayed on the screen and should be in the language of the country specified. The country codes are:
0: | U.S.A. | 6: | Italy |
1: | France | 7: | Spain |
2: | Germany | 20: | Holland |
3: | U.K. | 21: | Finland |
4: | Denmark and Norway | 23: | Wales |
5: | Sweden | 24: | Portugal |
For neatness, messages should be designed to fit on one line, but they may use escape sequences if they wish to do otherwise. Since more than one FID may be loaded, a FID should avoid clearing the screen, or assuming that a particular area of the screen has not yet been written to.
Allocate fixed amount of extra memory.
This routine allocates the FID a fixed size area of memory.
This routine must only be called from FID_EMS.
Return unwanted memory.
This routine returns an area of memory to the free pool.
This routine must only be called from FID_EMS.
Note that the data structures recording the locations of free memory are of limited size. FIDs should avoid fragmenting free memory unnecessarily.
Allocate maximum possible area of extra memory.
This routine allocates the FID the maximum currently available area of memory.
This routine must only be called from FID_EMS.
CP/M Plus supports up to 13 character devices, numbered 0..12. Each device is identified by its number and a six character name. Associated with each evice is an entry in the CP/M character device table. This entry gives the name of the device together with its mode and baudrate. The CP/M DEVICE utility can display and change a device's mode and baudrate.
Character device table entry format:
bytes 0..5 | name | upper case, left justified, space filled |
byte 6 | mode | device's characteristics |
byte 7 | baudrate | encoded baudrate |
The mode byte defines the device's characteristics, it is bit significant:
bit 0 | input | can get bytes from the device |
bit 1 | output | can put bytes to the device |
bit 2 | soft baud | supports software selectable baudrates |
bit 3 | serial | may use XON/XOFF protocol |
bit 4 | xon xoff | enables XON/XOFF protocol |
bits 5..6 | reserved | set to 0 |
bit 7 | timeout | set to 1 to disable the timeout for this device. |
The baudrate is encoded as:
0 | no baudrate |
1 | 50 baud |
2 | 75 baud |
3 | 110 baud |
4 | 134.5 baud |
5 | 150 baud |
6 | 300 baud |
7 | 600 baud |
8 | 1200 baud |
9 | 1800 baud |
10 | 2400 baud |
11 | 3600 baud |
12 | 4800 baud |
13 | 7200 baud |
14 | 9600 baud |
15 | 19200 baud |
CP/M offers no support for parity, control line handshaking etc. To support these non-CP/M characteristics the user must supply their onw .COM program which communicates directly with the FID. For example the SETSIO.COM program is used to set the parity and handshaking of the SIO device.
For each new character device required the FID calls SVC_C_HOOK passing the address of a jumpblock and the address of a copy of the character device table entry. SVC_C_HOOK will allocate the next available character device and return its number and a pointer to its CP/M character device table entry.
A FID may not use the names of the resident device drivers. These are:
CRT | screen and keyboard |
LPT | printer |
SIO | serial port |
System messages have special support. This is to allow devices such as alternative screens to separate out system messages from program messages - much as the built-in screen is prepared to place them onto the rotating status line.
If CRT is one of the devices which is currently attached to CONOUT: then the system will attempt to place its messages onto the rotating status line. If the rotating status line is disabled or CRT is not attached to CONOUT: then the system message will be sent to the special message output routines of all CONOUT: devices.
Devices (such as serial port drivers) which do not wish to distinguish between system messages and other messages should arrange for FID_C_M_STATUS to be the same as FID_C_O_STATUS, and FID_C_MESSAGE to be the same as FID_C_OUTPUT.
A character device may use routines provided by other character devices. This allows a FID to be written as a "filter" to edit characters before passing them on to another character device FID or to a standard built-in device. One could for example build a FID to discard LF characters before passing them on to the standard LPT device. This avoids having to build duplicate hardware device driving code within the FID. The FID should use the routine SVC_C_FIND in order to locate other character device jumpblocks.
Hook in a new character device.
Returns the address of the character device table entry.
This routine must only be called from FID_EMS.
+0 | JMP FID_C_INIT | ;initialise |
+3 | JMP FID_C_I_STATUS | ;input status |
+6 | JMP FID_C_INPUT | ;input a character |
+9 | JMP FID_C_O_STATUS | ;output status |
+12 | JMP FID_C_OUTPUT | ;output a character |
+15 | JMP FID_C_M_STATUS | ;system message output status |
+18 | JMP FID_C_MESSAGE | ;output a system message character |
Initialise character device according to character device table entry, (eg. baud rate). This routine is called once when the device is first being hooked in, then again every time the device's baudrate is changed.
Is there a character available for input?
Input a character, if none available wait until there is.
Is the character device ready for output?
Output a character, if not ready wait until it is.
Is the character device ready for system message output?
Output a system message character, if not ready wait until it is.
Find the character device jumpblock of another character device.
Returns the address of the character device jumpblock. It is then possible to call the jumpblock entries and thus use the facilities of another character device. It should not be assumed that the jumpblock consists of entries of the form JMP <routine> and the routine address extracted; instead control should be transferred to the relevant offset within the jumpblock.
This routine must only be called from FID_EMS. The jumpblock routines may be called at any time when the FID has been called via its own character device jumpblock.
For each new disc device required the FID calls SVC_D_HOOK passing the drive required, the maximum sizes of allocation vector, checksum vector and hash table and the address of a jumpblock. SVC_D_HOOK will allocate a DPB, DPH, allocation vector, checksum vector and hash table. If there is not enough room for the hash table then hashing is disabled.
During EMS a number of separate pools of available memory are maintained. The required disc data structures are allocated from the most suitable pool subject to the CP/M restrictions that a DPB must be in common, allocation vectors and checksum vectors must be in common or bank 0. Hash tables can be in any bank except bank 1.
The logical sector size must be 512 bytes. If the actual disc has a physical sector size greater than 512 bytes then the FID must perform the necessary blocking and deblocking. This is not recommended.
Logical sector numbers are 0 based. Logical to physical sector mapping must be performed by the FID itself. Logical track numbers are also 0 based, and again logical track to physical cylinder/head/track mapping must be performed by the FID itself..
A FID may request a particular drive letter or use the next one available. A FID cannot use a drive letter that has already been allocated. The resident disc drivers will have allocated drives A: and B: before any FID is called, therefore a FID cannot use these letters. It is recommended that a FID uses the next available drive letter rather than specifying a particular one.
The FID may not access the drive table, DPH, allocation vector, checksum vector or hash table, this is because with bank switching they may not be visible to the FID_D_ routines.
All bank switching will be performed before the FID_D_READ or FID_D_WRITE routines are called so these routines need not concern themselves with bank switching.
When a routine returns an error code the BIOS will, if required, issue an error message on the status line followed by Retry, Ignore or Cancel? (or the local language equivalent). The BIOS will also deal with the user's response (and the language variations of that). The error message if fetched via FID_D_MESS using message numbers returned by the FID, these message numbers may take any value in the range #00..#FF. They will not clash with internal message numbers or with those used by other FIDs. The status line message is not issued if the BDOS is in error return mode.
The error message should be at most 50 characters long and must not contain any control codes. For example:
Drive C: track 5, sector 7 read failThis will be displayed as:
Drive C: track 5, sector 7 read fail - Retry, Ignore or Cancel?
Hook in a new disc device.
Hooks in a new disc device. The DPB can be initialised now or left until FID_D_LOGIN is called.
This routine must only be called from FID_EMS.
+0 | JMP FID_D_LOGON | ;logon disc |
+3 | JMP FID_D_READ | ;read a sector |
+6 | JMP FID_D_WRITE | ;write a sector |
+9 | JMP FID_D_FLUSH | ;flush buffers |
+12 | JMP FID_D_MESS | ;get a disc error message string |
Logon a drive and initialise the DPB as required. The required sizes of allocation vector, checksum vector and hash table must not exceed those allocated by SVC_D_HOOK.
Read a 512 byte sector.
Write a 512 byte sector.
Flush any internal buffers; ie write to disc such things as deblocking buffers whose write has been delayed.
Return a message string in the language of the country specified to FID_EMS.
If the disc driver supoprts removable media then the following routine can be called to flag that the media has changed. This routine can be called from within interrupt code if required.
Flag that the disc has changed.
Flags that the disc has changed
May be called from within interrupt code
This section summarises the format of the Disc Parameter Block and the various sizes of the disc drive data structures.
Floor(x) | = largest integer <= x. |
Ceiling(x) | = smallest integer >= x. |
Log2(x) | = logarithm to the base 2 of x. |
High(x) | = Floor(x/256), i.e. most significant byte of 16 bits. |
Low(x) | = x - 256 * High(x), i.e. least significant byte of 16 bits. |
Let
BLOCK_SIZE | = allocation block size in bytes 1K,2K,4K,8K or 16K |
OFF | = number of reserved tracks |
NUM_TRACKS | = total number of tracks |
NUM_SECTORS | = number of sectors per track |
DIR_BLOCKS | = number of directory blocks 1..16 |
SEC_SIZE | = 512, sector size in bytes |
REC_SIZE | = 128, record size in bytes |
DIR_ENTRY_SIZE | = 32, directory entry size |
Records per track
SPT = NUM_SECTORS * SEC_SIZE / REC_SIZE
Block shift
BLS = Log2 (BLOCK_SIZE / REC_SIZE)
Block mask
BLM = (BLOCK_SIZE / REC_SIZE) - 1
Highest block number
DSM = Floor((NUM_TRACKS - OFF) * NUM_SECTORS * SEC_SIZE / BLOCK_SIZE) - 1
Highest directory entry number
DRM = (DIR_BLOCKS * BLOCK_SIZE / DIR_ENTRY_SIZE) - 1
Directory allocation map, least significant
AL0 = High (216 - 2(16 - DIR_BLOCKS))
Directory allocation map, most significant
AL1 = Low (216 - 2(16 - DIR_BLOCKS))
Extent mask
EXM = if DSM < 256
Checksum vector size
CKS = (DRM + 1) / 4
Physical sector shift
PSH = Log2 (SEC_SIZE / REC_SIZE)
Physical sector mask
PHM = (SEC_SIZE / REC_SIZE) - 1
Allocation vector size
ALS = Floor(DSM / 4) + 2
Hash table size size
HASH = 4 * (DRM + 1)
DPB format:
bytes | 0..1 | SPT | records per track |
byte | 2 | BSH | block shift |
byte | 3 | BLM | block mask |
byte | 4 | EXM | extent mask |
bytes | 5..6 | DSM | last block number |
bytes | 7..8 | DRM | last directory entry number |
byte | 9 | AL0 | directory allocation |
byte | 10 | AL1 | directory allocation |
bytes | 11..12 | CKS | checksum vector size, set bit 15 if fixed disc |
bytes | 13..14 | OFF | reserved tracks |
byte | 15 | PSH | physical sector shift |
byte | 16 | PHM | physical sector mask |
Note for a fixed disc set CKS = bit 15, this disabled directory checksumming and indicates that the disc cannot be removed.
If hashing is not required set the hash table size to 0.
A FID is not obliged to be a character device and/or a disc device although these are the most likely applications.
A FID may not call the BIOS or BDOS directly. A FID may call the documented SVCs, see list below.
The following routines are available to a FID. The most significant byte of their addresses is #FF and must be marked as relocatable in the PRL file. Both bytes of the address are replaced by the FID loader.
Bank Switching Support
#FF00 | SVC_BANK_05 | ;last value sent to channel #7FFD |
#FF01 | SVC_BANK_68 | ;last value sent to channel #1FFD |
#FF02 | SVC_CATCHUP | ;execute (some) interrupt actions |
The System Control Block
#FF03 | SVC_SCB | ;address of SCB |
Hook routines, only available to FID_EMS
#FF04 | SVC_C_HOOK | ;hook character device |
#FF05 | SVC_D_HOOK | ;hook disc device |
Disc Device Support Routines
#FF06 | SVC_D_CHANGED | ;flag that a disc has changed |
EMS Memory allocation and Deallocation
#FF07 | SVC_ALLOCATE | ;allocate fixed size of extra memory |
#FF08 | SVC_MAX_ALLOCATE | ;allocate max. area of extra memory |
#FF09 | SVC_DEALLOCATE | ;return unwanted memory |
Filter support
#FF0A | SVC_C_FIND | ;locate character device jumpblock |
Perform actions as if a timer interrupt has just occurred.
This routine should be used when interrupts have been disabled for a considerable time and it is very likely that some timer interrupts have been missed. It can cause the cursor to flash, the keyboard to be scanned and the system time to be advanced.
PRL is a standard CP/M file format and is supported by the CP/M linker LINK-80. The switch [op] generates a .PRL file, the switch [Mxxxx] specifies the size of the uninitialised variable area (hex xxxx bytes).
Let H = #0100, size of the PRL header in bytes
Let P = size of the program in bytes
Let M = ceiling (P/8), size of the relocation map in bytes
Let V = size of uninitialised variable area in bytes
bytes 0 .. H - 1 | PRL header |
bytes 1 .. 2 | program size in bytes = P |
bytes 3 .. 4 | uninitialised variable area size in bytes = V |
bytes H .. H + P - 1 | program binary image |
bytes H + P .. H + P + M - 1 | relocation map |
The program binary image has an origin of #0100.
The relocation map contains one bit per byte of program.
Map | Program |
byte 0 bit 7 | byte 0 |
byte 0 bit 6 | byte 1 |
... | ... |
byte 0 bit 0 | byte 7 |
byte 1 bit 7 | byte 8 |
... | ... |
The uninitialised variable area is allocated immediately after the program, ie. at relocatable address #0100 + P .. #0100 + P + V - 1.
The source for the operating system extensions RAMDISC.FID and SERIAL.FID are supplied in
the two files, RAMDISC.ASM and SERIAL.ASM on Side 2 of the disc. These source files provide
useful examples on which to base further FID files. RAMDISC.ASM provides an example of a Disc
Device FID; SERIAL.ASM provides an example of a Character Device FID.
Note: These files are set up for tabs every eight characters: however, if you edit them using RPED, this layout will be thrown away. |
Appendix V | Index | Appendix VII |