CP/M
pages
Home -> CP/M -> Amstrad XBIOS
Internals

Amstrad Extended BIOS Internals

Any Amstrad CP/M Plus system (meaning those created by Locomotive Software
for the CPC, PCW and Spectrum +3) has an XBIOS, which lives at 80h in CP/M bank
0. It exposes a number of functions for things
like reading, writing and formatting floppy discs, reassigning keys on the
keyboard, setting options for the serial port, and so on.

In a conventional banked CP/M Plus system, bank 0 holds only the banked BDOS,
a BIOS to manage the hardware, and possibly some disc buffers. In an
Amstrad/Locomotive CP/M Plus system, the banked BIOS is small and pretty much
hardware-independent; all it does is wrap the XBIOS calls in CP/M character and
disc devices.

Internally, the XBIOS is divided into modules (this is why some functions in
the jumpblock have names starting DD, some starting CD, some starting TE and so
on). I have given these modules names based on the functions in them, on other
sources where available, and invented my own names if necessary. When
disassembling, it's often quite easy to tell where one module stops and another
starts (at least in early versions) because the modules are aligned on 8- or 16-
byte boundaries.

Sources

I have derived the information in this document from the following CP/M boot
files:

System file

Machine

Version

C10CPM3.EMS

CPC

1.0

S10CPM3.EMS

Spectrum +3

1.0

J11CPM3.EMS

PCW 8000

1.1

J12SCPM3.EMS

PCW 8000

1.2 (Spanish)

J14CPM3.EMS

PCW 8000

1.4

J14SCPM3.EMS

PCW 8000

1.4 (Spanish)

J14GCPM3.EMS

PCW 8000

1.4 (German)

J17CPM3.EMS

PCW 8000

1.7H

J11CPM3.EMT

PCW 8000, 9256, 10

1.11

J12CPM3.EMS

PCW 8000, 9256, 10

1.12

J14CPM3.EMT

PCW 8000, 9256, 10

1.14

J15CPM3.EMT

PCW 8000, 9256, 10

1.15

J21CPM3.EMS

PCW 9512

2.1

J29CPM3.EMS

PCW 9512

2.9

J21CPM3.EMT

PCW 9512, 9512+

2.11

J22CPM3.EMS

PCW 9512, 9512+

2.12

J25CPM3.EMS

PCW 9512, 9512+

2.15

J25CPM3.EMT

If you have any other versions of the system file, feel free to share them
with me.

The CPC

On the CPC, CP/M Plus runs as an application under the CPC's ROM firmware.
This is the memory layout of bank 0 (with areas owned by the XBIOS shown thus):

0000-007F

Used by CPC firmware

0080-01FF

The XBIOS
jumpblock.

Also contains initialisation code and displays the sign-on
message.

0200-03FF

CD: Character Devices (code segment)

Routes character I/O to/from the screen, keyboard, printer and serial
interface. Drives the serial interface at the hardware level; the printer
and keyboard are handled by the firmware, and the screen by TE
below.

0400-0AEF

TE: Terminal Emulator (code segment)

Interprets ESCape sequences sent to the screen device and converts them
into SCR_* calls to the CPC firmware.

0AD0-0EFF

DD: Disk Devices (code segment)
All floppy access, including
reading, writing and formatting discs.

0F00-3CFF

CP/M banked BDOS

3D00-3FFF

CP/M banked BIOS

4000-7FFF

Video RAM

8000-87FF

Font

8800-89FF

System message table.

8A00-B0CF

CP/M disc buffers

B0D0-B0FF

DD data segment.

B100-BE3F

Used by CPC firmware.

BE40-BEEF

CD and TE data segments.

BEF0-BFFF

Used by CPC firmware.

C000-F5FF

The top of the TPA.

F600-FBFF

CP/M resident BDOS.

FC00-FF9F

CP/M resident BIOS.

FFA0-FFDF

Floppy transfer code.

Used when reading and writing floppy data. This code has to be in
common memory because the data may be coming from or going to any CP/M
bank.

FFE0-FFFF

XBIOS data transfer area.

Used by XBIOS calls to return data structures to code that might be in
different banks. Used to return floppy results (for DD_L_*
calls), addresses of data buffers (for CD_INFO call) and so
on.

Also contains a flag to say whether keyboard input is ready. This
allows a fast check by the resident BIOS, without needing to do a bank
switch.

The PCW (Old World)

The original versions of CP/M supplied with the PCW8256 (versions 1.2, 1.4)
have a similar layout to the CPC version (give or take the constraints of
hardware, such as the position and size of video RAM). However, the PCW doesn't
have a firmware ROM, so it has to provide modules of its own to do the same
job.

The addresses in this table come from BIOS 1.2. Those in the more common 1.4
are slightly different, but the arrangement of modules is the same.

0000-007F

Zero Page (see below).

Contains the Z80 Restart vectors, which on the PCW are used to call
code in other memory banks. Also contains current memory paging status and
memory size.

0080-022F

XBIOS jumpblock and initialisation code.

0230-043F

CD: Character Devices

0440-08CF

TE: Terminal Emulator

08D0-0ACF

MSG: Displays system messages.

In the CPC version, this is found about halfway through TE rather than
being a separate module.

0AD0-100F

DD: Disk Devices

1010-13EF

KM: Keyboard Manager

This handles scanning the PCW's memory-mapped keyboard, allows keys to
be redefined, and provides the required KM_* functions that
(on a CPC) would be provided by the firmware.

13F0-168F

SCR: Screen

As with KM, this performs screen access (drawing characters, scrolling
or blanking areas, and so on) that on the CPC would have been provided by
the firmware.

1690-182F

Default keyboard layout.

1830-1B2F

System messages. As for the CPC, but also adds all the printer status
messages.

1B30-1D3F

NMI: Non-Maskable Interrupt handler

The PCW uses the Z80 Non-Maskable Interrupt to handle floppy disc reads
and writes. This module contains the NMI handlers, and code to notify the
rest of the system when disc access is about to begin or end.

1D40-203F

KL: Kernel (Part 1)

2040-261F

KL: Kernel (Part 2)

As with SCR_ and KM_ functions, the KL module
provides the kernel functions used by CP/M. In fact, it provides more than
are used by CP/M; CPC functions such as KL_TIME_PLEASE and
KL_TIME_SET are present even though CP/M doesn't use
them.

The kernel is divided into two modules. The first one handles
interrupts, processes and semaphores; the second one manages events,
tickers and kernel memory allocation.

2620-286F

Data segments, in the order KL, CD, TE, MSG, NMI, DD, KM, SCR.

2870-58FF

CP/M disc buffers

5900-5903

Buffer control block linked list: head pointers.

5904-592F

Unused

5930-7FFF

Video RAM.

Though the screen can display 32 lines of text, the XBIOS allocates
memory for 33. The extra line is used to display the printer status bar;
using the Roller-RAM system, it gets swapped in/out instead of the bottom
line of the screen.

Not all the video RAM is visible in bank 0. The remainder, plus the
font, are only visible in the 'screen environment' memory
configuration.

8000-8BFF

CP/M disc buffers

8C00-B9FF

CP/M banked BDOS

BA00-BFEF

CP/M banked BIOS

BFF0-BFFF

Memory-mapped keyboard.

C000-F5FF

The top of the TPA.

F600-FBFF

CP/M resident BDOS.

FC00-FF9F

CP/M resident BIOS.

FFE0-FFFF

XBIOS data transfer area.

The process and semaphore features in the kernel are used for dot-matrix
printer support. Semaphores are used to block disc access while the printer is
active (or vice versa), while processes manage different aspects of the printer.
In a PCW8256 CP/M system, four processes will be in existence, at different
priority levels:

Priority 32: CP/M
Priority 48: Printer control state
Priority 56: Screen dump
Priority 60: Printer hardware driver

Normally, the three printer processes will be blocked on semaphores. If they
are invoked (eg, by the right key combination, or by sending output to the
printer) the appropriate semaphore will be raised. The corresponding process
will then have a higher priority than CP/M, and so will run until it next
becomes blocked.

The PCW (New World)

By the time of 8512 CP/M version 1.7H, the XBIOS memory map had been
rearranged to support loadable drivers. This organisation was subsequently used
by BIOS 2.1 on the PCW 9512 and all subsequent releases.

Oddly, version 2.1 on the PCW 9512 can't load drivers, whereas 1.7H (which
looks, to me, as if it came first) can. On absolutely no evidence, I theorise
that at this time, the BIOS could be build in two versions -- normal, which
didn't load drivers, and 'H', which did. So 2.1H, if it existed, would have been
able to load drivers.

The addresses in this table come from BIOS 2.9. Other versions differ.

0000-007F

Zero Page (see below).

0080-01D7

XBIOS jumpblock and initialisation code.

01D8-024F

Helper code for the daisywheel printer.

0250-067F

System messages.

On a daisywheel system, the message area is 256 bytes larger than on a
dot-matrix system. So NMI is at 0680h in version 2.9, but at 0580h in
version 1.9.

0680-08BF

NMI code segment

08C0-114F

KL code segment

1150-1213

Data segments for KL and NMI

1214-3D7F

Available for loadable drivers or disc buffers.

3D80-3F4F

CD: General character device management.

3F50-41A7

CD: CPS8256 serial port driver

41A8-4567

KM: Keyboard Manager

4568-485F

SCR: Screen functions

4860-49FF

Default keyboard layout

4A00-4ECF

TE: Terminal emulator

4ED0-5137

MSG: System message display

5138-56FF

DD: Disk Devices

5700-58DF

Data segments for the internal device drivers, in the order MSG, KM,
SCR, TE, DD, CD

58E0-5907

Device driver tables

5904-592F

Unused

5930-7FFF

Video RAM.

8000-8BFF

Available for loadable drivers or disc buffers.

8C00-B9FF

CP/M banked BDOS

BA00-BEFF

CP/M banked BIOS

BFF0-BFFF

Memory-mapped keyboard.

C000-F5FF

The top of the TPA.

F600-FBFF

CP/M resident BDOS.

FC00-FF50

CP/M resident BIOS.

FF51-FFDF

Available for loadable drivers: additional disc DPBs.

FFE0-FFFF

XBIOS data transfer area.

The new layout keeps the kernel in the bottom 16k (where it needs to be in
order to access other memory banks) but pushes all the hardware drivers up so
that they grow down from 58E0h — and, importantly, come down below 4000h. This
is because, when disc transfers are done, the area from 4000h-7FFFh contains the
source/target memory. Since any bank could be present in that area when the
driver is called, the driver itself can't be allowed to occupy that space.
Having the built-in CP/M drivers live there gets round the problem nicely.

(Note that NMI, which handles data transfers for the built-in floppy driver,
is not in that area. It's down at the bottom of memory with the kernel).

Loadable device drivers cause a big change to the undocumented areas of the
XBIOS jumpblock. Previously, the BIOS would do character I/O by calling the
jumpblock with a device number. Now, it looks up the device's character device
jumpblock in the table of character devices at 58E0h, and jumps straight to
it.

At boot time, a loadable device manager is present in memory (for BIOS 2.9,
at 0EDA0h; this varies depending on version). The device manager searches the
boot disc for files ending in .FID. If any are found, it loads them into memory
and allows them to add themselves to the BIOS as a character or disc device. The
XBIOS registers its built-in character devices (screen, keyboard etc.) with this
manager at boot time.

The Spectrum +3

Spectrum +3 CP/M appears to have branched off the PCW tree at about version
2.8 (with a few fragments, such as scrolling error messages, coming from CPC
CP/M).

Like the 'new-world' PCW XBIOS, the Spectrum XBIOS comes in two parts, with
the first half containing the jumpblock and messages, and the second half
holding device drivers. Though the two parts are stored separately in the EMS
file, they end up in a contiguous block of memory.

The major difference in +3 CP/M is that there is no KL (kernel) module.
Rather than individual modules registering timers, event blocks, interrupt
handlers and so forth, the 50Hz ticker interrupt handler is hardwired to perform
the necessary functions.

0000-007F

Zero Page (see below).

Contains the hard-wired timer interrupt handler.

0080-016F

XBIOS jumpblock and initialisation code.

0170-01EF

The same library of helper routines as on the PCW9512. This despite
the fact that they're only used by the 9512 daisywheel printer driver,
which the Spectrum doesn't have.

01F0-039F

System messages.

03A0-04CF

CD: General character device management.

04D0-05AF

CD: RS232 serial port driver

05B0-08FF

KM: Keyboard Manager

0900-0F5F

SCR: Screen functions

0F60-100F

Default keyboard layout

1010-1517

TE: Terminal emulator

1518-178F

MSG: System message display

1790-1DDF

DD: Disk Devices

1DE0-21C7

Data segments for the internal device drivers, in the order MSG, KM,
SCR, TE, DD, CD

21C8-21ED

Device driver tables

21EE-2417

Unknown

2418-2FFF

Available for loadable drivers or disc buffers.

3000-3FFF

Fonts

4000-5AFF

Video RAM.

There is a second page of video RAM in CP/M bank 2 for the right-hand
half of the 24×80 video mode.

5B00-8BFF

Available for loadable drivers or disc buffers.

8C00-B9FF

CP/M banked BDOS

BA00-BFFF

CP/M banked BIOS

C000-F3FF

The top of the TPA.

F400-F9FF

CP/M resident BDOS.

FA00-FD4C

CP/M resident BIOS.

FD4D-FDDB

Available for loadable drivers: additional disc DPBs.

FDDC-FF53

Serial port driver routines. These are timing-critical and need to run
in uncontended memory.

FF54-FFDF

Floppy transfer code.

FFE0-FFFF

XBIOS data transfer area. On the +3 this contains, inter alia, the
BANKM and BANK678 variables.

Zero Page

In PCW CP/M, the first 128 bytes of bank 0 are laid out like this:

0000

RST 0: Jump to a function in the bank 2 environment. Takes the address
as an inline parameter.

0003

(2.9+) Jump to the address in BC

0005

(2.9+) Jump to the address in DE

0007

(2.9+) Jump to the address in HL

0008

RST 8: Jump to a function in the screen environment. Takes the address
as an inline parameter.

000B

(2.9+) Jump to the address in IX

000D

(2.9+) Jump to the address in IY

0010

(2.1+) RST 10. Does nothing.

0018

(2.1+) RST 18. Does nothing.

0020

RST 20. Jump to code in an arbitrary memory environment. Takes a word
as an inline parameter, which points to a 4-byte structure:
DEFW address
DEFB bank to page in at 4000h
DEFB bank to page in at 8000h

0028

RST 28. As RST 20, but the 4-byte structure directly follows the
RST.

002B

As RST 20, but the address of the 4-byte structure is passed in
HL.

0030

(1.4+) RST 30: Kernel panic. Disables interrupts and enters a tight
loop. Presumably used when debugging new versions.

0033

Ascii 'BREAK'

0038

RST 38: Z80 mode 1 interrupt handler.

003B

Ascii 'Patch'

0040

(2.1+) Hardware bitflags (returned in L by CD
INFO)

0042

(2.1+) 0FFh if second drive present, otherwise 0. In version 1.7H
(only) this is at 40h.

004C

(2.11+) Bit 5 set if Shift+Extra+Relay pressed.

0060

Memory bank paged in at 0000h

0061

Memory bank paged in at 4000h

0062

Memory bank paged in at 8000h

0063

Memory bank paged in at C000h

0064

Frame flyback counter

0065

Frame flyback maximum (6 on a UK PCW, 5 on a US model)

0066

NMI handler

007F

Number of 16k memory banks in system

For comparison, the same area of memory in Spectrum +3 CP/M looks like
this:

0000

RST 0: Default timer interrupt handler.

0020

RST 20: SVC_CATCHUP
— perform a subset of timer interrupt functions.

0030

RST 30: Kernel panic

0038

IM 1 interrupt handler.

003B

Step down the 50Hz system clock to a 1Hz ticker for CP/M.

0054

Set the border colour to A.

0075

0FFh if a second floppy drive is present, else 0.

A rough outline of development

Based on the CP/M versions I have, here are my best guesses at the order of
the versions, and what changed when:

CPC 1.0

The original.

PCW 1.1

The first version I have for the PCW, though presumably version 1.0
existed as well.

PCW 1.2

Most of the changes appear to be to support the creation of
foreign-language CP/M versions:

The keystrokes used for Retry, Ignore and Cancel
can now be localised; in 1.1 they were hardcoded.

The default screen language and the default matrix printer language are
localised, rather than hardcoded.

System messages can contain accented characters.

Some changes to the keyboard layout. Shift+STOP now generates expansion
token 80h, not a literal Control-C; and Alt+STOP is ignored, rather than
generating ESCape.

Some tweaks to paper feeds in the dot-matrix printer driver.

PCW 1.4

The most common version for the 8256/8512, supplied with many of the
machines, and was used to provide illustrations for the manual.

Change to the dot-matrix printer font: The " and ' characters are
chisel-like, not curly.

The CPS8256 can now be driven in interrupt mode.

The floppy driver uses a semaphore to signal completion, not a simple
on/off flag.

There is a kernel panic (RST 30h) which is invoked if the kernel runs
out of memory or a process descriptor gets corrupted.

PCW 1.7H

Supplied with the ASD HD20 hard drive.

New World memory layout.

Will now load external device drivers (*.FID)

New escape code in the terminal emulator: ESC @ (insert
character)

PCW 2.1

Supplied with the PCW9512.

Support added for the PCW9512 and its daisywheel printer.

FIDs do not load; the code to load them has been removed.

Floppy drive support altered to support a system with a 720k drive A:.
Also some tweaks made to floppy interrupt handling, perhaps to cope with
slight hardware differences.

Spectrum 1.0

My best guess is that +3 CP/M was derived from the PCW CP/M codebase
somewhere around here.

PCW 2.9

Now supports the PCW9512 sheet feeder.

FIDs now enabled again.

The "Drive is A:" message moves four characters to the left (!)

New ESC 4 1 / ESC 4 0 sequences to disable /
enable screen scrolling.

PCW 1.11 / 2.11

Supplied with the PcW 9256 (1.11) and the PcW 9512+ (2.11).

Somewhere between 1.7 and 1.11, the 1.x and 2.x version numbers were
synchronised. This probably means some 2.x versions were skipped. My guess
is that 1.7 corresponds to 2.0, 1.8 to 2.1, and the sync was done at 1.9 =
2.9.

The dot-matrix printer driver allows redefinition of arbitrary
characters, using jumps at FFF9h and FFFCh.

Support added for second-generation PCWs: 9256, 9512+.

Support added for booting the LocoScript installer (insert the boot
floppy and press SHIFT+EXTRA+RELAY. Only applies to second-generation
PCWs).

Allows the floppy drives to be stepped at different rates.

PCW 1.12 / 2.12

Support added for the standalone Centronics port accessory.

PCW 1.14 / 2.14

Support for loading drive parameters from *.FIB files.

Improved Centronics port detection.

If the memory test reports 256k, reset the memory read/write register
and try again.

SHIFT+EXTRA+RELAY now works on first-generation PCWs as
well.

PCW 1.15 / 2.15

A single change: When doing a SHIFT+EXTRA+RELAY reboot, takes all
devices out of interrupt mode so that they don't interrupt at an awkward
moment.

The modules in other systems

At least some of the modules are shared between CP/M and other Amstrad /
Locomotive operating systems. LocoScript 1.20, for example, has its own versions
of NMI, KL and DD, and so does the LocoLink server for the PCW. The main
difference is that another module or set of modules (probably called "DOS")
handles file access. The code in this module resembles +3DOS on the Spectrum +3
(give or take certain register usage conventions) — or, more probably, +3DOS was
created from DOS, DD, and a few bits of MSG.

I suspect that SCR is also shared with LocoScript, since it has at least one
feature (right-to-left text output) which is completely unused in CP/M.

John Elliott, 26 October 2009