*The CCS 7710A card is the preferred card of type 2 as it supports
hardware handshaking and variable baud rates from 110 to 19200 baud.
The Apple Communications Card requires hardware modification for use
with baud rates other than 110 or 300 baud.

As a general rule, any card directly compatible with Apple Pascal
without requiring software modifications will probably be directly
compatible with Apple CP/M as well. Other peripheral cards may be
used if software supplied by the card manufacturer is bound to your
Apple CP/M system using the CONFIGIO utility program.

Disk controller for drives E: and F:
Z80 Softcard may be installed here if no disk controller here.

5

1

Disk controller dir drives C: and D:

6

1

Disk controller dir drives A: and B:, must be present.

7

any type

No assigned purpose. The Z-80 SoftCard may be installed here.*

* European Apple II's in PAL mode: only a PAL color card may be inserted here!

If you do have an external terminal interface with a terminal interface card
in slot 3, it is recommended to remove it and to use the normal Apple screen
and keyboard until you have configured Apple CP/M for use with your terminal
with the CONFIGIO utility.

Apple Disk Drives

CP/M name

Slot #

Drive #

1st drive:

A:

6

1

2nd drive:

B:

6

2

3rd drive:

C:

5

1

4th drive:

D:

5

2

5th drive:

E:

4

1

6th drive:

F:

4

2

Note: SoftCard CP/M up to 2.20B allows up to 6 drives, while versions
2.23, 2.25 and 2.26 allows only up to 4 drives. Generic CP/M allows
up to 16 drives.

Installing the Softcard

Make sure the four small DIP switches all are switched to the OFF position.
This is the standard operating position for Apple CP/M.

Turn off your Apple II, insert the SoftCard into any unused slot except slot 0.
The standard slot for the SoftCard is slot 4. If slot 4 is occupied by a
disk controller card, choose some other slot.

Insert the other peripheral cards according to the list above which you
want to use.

Turn on your Apple II.

DIP Switches

The four DIP switches are normally OFF for CP/M operation. Their functions are:

Switch

Function when ON

1-1

Disable address translation.

1-2

Higher priority DMA devices cause SoftCard to relinguish bus.

1-3

Pass NMI line to Z80.

1-4

Pass IRQ line to Z80.

Apple Softcard CP/M specific programs

FORMAT <drive>

Examples:

FORMAT A:

Format disk in drive A:

The Apple CP/M disk formatter
(Apple CP/M ver 2.23 and later has no FORMAT program, instead
disk formatting is integrated into the COPY program)

COPY <dest drive>=<source drive>[/S]

Examples:

COPY B:=A:

Copy disk in A: to disk in B:

COPY A:=A:

Single-drive copy

COPY A:=A:/S

Copy only the CP/M system tracks

COPY

Prompts user for source and dest. drives

The Apple CP/M disk copy program. Copies the entire disk, overwriting
the whole destination disk. Can copy on a single drive too (PIP
requires two drives to copy from one disk to another)

CPM56 <drive>

Example:

CPM56 A:

Updates the CP/M system from 44K CP/M to 56K CP/M. 56K CP/M requires
a Language Card to work. CPM56 is preset only on the 16-sector Apple
CP/M disk.

CONFIGIO

An MBASIC program used to:

Redefine keyboard characters

Load User I/O Software

Configure Apple CP/M for use with an External Terminal

APDOS

Transfers data (files) from your Apple DOS disks to CP/M disks.
May be used to transfer text and binary files only. Does not
transfer files from CP/M disks to Apple DOS disks – use the
Apple DOS utility CPMXFER for that.

DOWNLOAD

DOWNLOAD and UPLOAD enable the user to transfer CP/M files from
another CP/M machine to the Apple by means of an RS-232 serial
data link. UPLOAD is not included on either of the Apple CP/M
disks but should be typed in and assembled on the other CP/M
machine. Using these programs requires a working knowledge of
8080 assembly language programming.

RW13

Allows 16-sector Apple CP/M to access files on a 13-sector Apple
CP/M disk. Requires at least two Disk II drives to work.
RW13 is present only on the 16-sector Apple CP/M disk.

Max number of concurrently open files (default=3)
Each file requires 166+128 bytes extra

/M:<max_mem>

Highest mem location used by MBASIC (default all TPA)

/S:<max_recsize>

Max record size allowed by random files (default 128)

The <no_files> and <max_mem> may be given as <decimal>, &O<octal> or &H<hexadecimal>.

These are Microsofts MBASIC interpreter, adapted for Apple CP/M.
It comes in two flavors: GBASIC supports Apple hires graphics while
MBASIC does not. Both basic's support Apple's lo-res graphics plus
a few other Apple specific things. GBASIC is present only on the
16-sector Apple CP/M disk.

Typing at the Apple Softcard CP/M Keyboard

Key

Action

←Ctrl+H

Backspaces one character, deleting the char under the cursor

Ctrl+X

Backspaces to the beginning of the line, deleting the line

Ctrl+R

Retypes the current line

Ctrl+J

Terminates input - same as RETURN key

Ctrl+E

Physical end-of-line. Cursor moved to the beginning of next line, but line is not terminated until RETURN is typed.

RUBOUT

Deletes and “echoes” (reprints) the last character typed.
Also referred to as DEL or DELETE (ASCII 7Fh). Type Ctrl+@ to get RUBOUT on the Apple ][/][+ keyboard

A few characters normally unavailable on the Apple ][/][+ keyboard have been
assigned to certain control characters, making them available:

Type:

To get:

Ctrl+K

[

Ctrl+@

RUBOUT

Ctrl+B

\

Ctrl+U

TAB (Ctrl+I)

These control characters can be redefined with the CONFIGIO program

Output Control

Key

Action

Ctrl+Shift

Temporarily stops character output to TTY: Output is resumed when any character is typed

Ctrl+P

Sends all character output to LPT: as well as to TTY:
This “printer echo” mode remains in effect until another Ctrl+P is typed.

CP/M Warm Boot: Ctrl-C

When Ctrl+C is typed as the first character on a line, CP/M performs a
“warm boot”, causing CP/M to be reloaded from disk to insure that it is
in working order. You should ALWAYS type Ctrl+C whenever you change
disks.

Hitting the RESET Key

On a system having the Autostart ROM hitting the RESET key while in
CP/M will cause CP/M to warm boot, returning to CP/M. Hitting the
RESET key while in MBASIC/GBASIC will result in a “Reset error”,
which can be trapped using “ON ERROR GOTO”.

On a system having the older Monitor ROM, hitting the RESET key will
land you in the Apple Monitor. You can recover by typing Ctrl+Y RETURN,
after which the behavior will be the same as for the Autostart ROM.

Changing CP/M Disks

Unlike Apple DOS you cannot indiscriminately change disks in drives
with CP/M. When you change disks, you must let CP/M know that you
have done so, because certain disk directory information is stored in
memory at all times and used to allocate space on the disk. When you
change disks, this information must be replaced by the corresponding
information for the new disk.

To let CP/M know you have changed disks, type Ctrl+C to execute a CP/M
“warm boot”. Do so AFTER you have changed the disks. You should get
used to typing Ctrl+C often.

If you don't type Ctrl+C after having changed disks, and a WRITE is
attempted to the changed disk, CP/M will display:

BDOS ERR ON x:Disk R/O

(where x: is a disk drive A:-F:)

(R/O means Read Only). When you receive this message, hit RETURN.
This will perform a CP/M warm boot and return you to CP/M, terminating
any application you may have been running.

The above error will apply only to changed disks which are to be WRITTEN.
No error will result if you attempt to READ from the changed disk without
having typed Ctrl+C first.

6502/Z-80 Address Translation

The SoftCard performs address translation from the Z-80 to the Apple II
address bus. Below Z-80 addresses are written with a trailing 'H' while
6502 addresses are written with a leading '$':

Z-80 addr

6502 addr

Notes

0000H-00FFFH

$1000-$1FFF

Z-80 address zero

1000H-10FFH

$2000-$2FFF

2000H-20FFH

$3000-$3FFF

3000H-30FFH

$4000-$4FFF

4000H-40FFH

$5000-$5FFF

5000H-50FFH

$6000-$6FFF

6000H-60FFH

$7000-$7FFF

7000H-70FFH

$8000-$8FFF

8000H-80FFH

$9000-$9FFF

9000H-90FFH

$A000-$AFFF

0A000H-0AFFFH

$B000-$BFFF

0B000H-0BFFFH

$D000-$DFFF

0C000H-0CFFFH

$E000-$EFFF

0D000H-0DFFFH

$F000-$FFFF

6502 RESET, NMI, BREAK vectors

0E000H-0EFFFH

$C000-$CFFF

6502 memory mapped I/O

0F000H-0FFFFH

$0000-$0FFF

6502 zero page, stack, Apple screen, CP/M RWTS

This translation may be turned off by setting DIP switch S1-1 to ON.

Apple II Softcard CP/M Memory Usage

6502 address

Z-80 address

Use

$0800-$0FFF

0F800H-0FFFFH

Apple CP/M disk drivers and buffers (“RWTS”)

$0400-$07FF

0F400H-0F7FFH

Apple screen memory

$0200-$03FF

0F200H-0F3FFH

I/O config block, device drivers

$0000-$01FF

0F000H-0F1FFH

Reserved area:6502 page zero and 6502 stack

$C000-$CFFF

0E000H-0EFFFH

Apple memory mapped I/O

$FFFA-$FFFF

0DFFAH-0DFFFH

6502 RESET, NMI and BREAK vectors

$D400-$FFF9

0C400H-0DFF9H

56K Language Card CP/M (if Lang. Card installed)

$D000-$D3FF

0C000H-0C3FFH

Top 1K of free RAM with 56K CP/M

$A400-$BFFF

9400H-0AFFFH

44K CP/M (free memory with 56K CP/M)

$1100-$A3FF

0100H-93FFH

Free RAM

$1000-$10FF

0000H-00FFH

CP/M page zero

Apple II Softcard CP/M Memory Map

CP/M Size

Language Card Usage

44K CP/M

does not use Language Card

56K CP/M

uses Language Card, bank 2 only (TPA)

60K CP/M

uses Language Card: bank 2 for TPA, bank 1 for parts of BDOS+BIOS

Note that the Apple II hi-res graphics screens are situated right in
the middle of the Softcard CP/M TPA. Hi-res graphics programming on
SoftCard CP/M therefore requires special precautions. Microsoft
GBASIC solves this by reserving an 8K large memory area, right in the
middle of the Basic interpreter, for hi-res graphics.

Interrupt handling

Interrupts on the Z80 side are normally disabled. Setting DIP switches 1-3 and 1-4
to the ON position passes the NMI and IQR lines, respectively, to the Z-80

Because of the way the 6502 is “put to sleep” by the Z-80 SoftCard using the
DMA line on the Apple bus, ALL interrupt processing must be handled by the
6502. An interrupt can occur at two times: while in Z-80 mode and while in
6502 mode:

Handling the interrupt in 6502 mode: handle the interrupt in the usual way:
simply end the interrupt processing routine with an RTI instruction.

Handling the interrupt in Z-80 mode: both processors are interrupted
when an interrupt occurs in Z-80 mode. Here is a step-by-step process
for handling an interrupt while in Z-80 mode:

Save any registers that are destroyed on the stack

Save the contents of the 6502 subroutine call address (see Calling of 6502 subroutines below) in case an interrupt has occurred during a 6502 subroutine call.

Set up the 6502 subroutine call address to FF58, which is the address of a 6502 RTS instruction in the Apple Monitor ROM.

Return control to the 6502 by performing a write to the address of the Z-80 card (again see Calling of 6502 Subroutines).

When control is returned to the Z-80, restore the previous 6502 subroutine call address.

Restore all used Z-80 registers from the stack.

Enable interrupts with an EI instruction.

Return with a RET instruction.

Console Cursor Addressing and Screen Control

There are nine screen functions supported by Apple CP/M

Clear Screen

Clear to End of Page

Clear to End of Line

Set Normal (lolite) Text Mode

Set Inverse (hilite) Text Mode

Home Cursor

Address Cursor

Move Cursor Up

Non-destructively Move Cursor Forward

The Backspace character (Ctrl-H, ASCII 8) is assumed to move the cursor
backwards, and the Line Feed character (Ctrl-J, ASCII 10) is assumed to
move the cursor down one line.

Screen function character sequences supported by Apple CP/M may be of
two forms:

A single control character, or

Any ACII characters preceded by a single character lead-in

Screen function sequences longer than two characters are not supported

The internal format of each of the two 11-byte tables are identical. Below
are listed the function number, the hexadecimal address and a description
of each table entry.

Funct #

Software

Hardware

Description

0F396H

0F3A1H

Cursor addr coordinate offset. Range 0-127. If hi bit is 0, the X/Y coordinates are expected to be transmitted Y first, X last. If high bit is 1, X first Y last is expected.

0F397H

0F3A2H

Lead-in character, zero if no lead-in

Note: the following rules apply to the screen function table entries below: if the table entry is zero, the function is not implemented. If the entry has the high bit order set, the function requires a lead-in. An entry with the high order bit clear means the function does not require a lead-in.

1

0F398H

0F3A3H

Clear Screen

2

0F399H

0F3A4H

Clear to End of Page

3

0F39AH

0F3A5H

Clear to End of Line

4

0F39BH

0F3A6H

Set Normal (lo-line) Text Mode

5

0F39CH

0F3A7H

Set Inverse (hi-lite) Text Mode

6

0F39DH

0F3A8H

Home Cursor

7

0F39EH

0F3A9H

Address Cursor (see above)

8

0F39FH

0F3AAH

Move Cursor Up One Line

9

0F3A0H

0F3ABH

Non-destructively Move Cursor Forward

The standard 24×40 Apple screen supports all nine function independent
of the Hardware Screen Function Table. However if a Software Screen
Function Table entry is zero, that function will be disabled.

The Hardware and Software Screen Function Tables can be examined and
modified with the CONFIGIO program.

It is possible to write programs that use the information contained in
these tables to perform screen functions. These programs would then
work with ANY terminal, as long as the Hardware Screen Function Table
was set up correctly - however such a program would work only on
Apple SoftCard CP/M and not on any other CP/M system.

Keyboard redefinition

Keyboard redefinition take place only during input from the TTY: and
CRT: devices. The Keyboard Character Redefinition Table will support
up to six character redefinitions. The table is located at 0F3ACH
from the Z-80. Entries in the table are two bytes: the first is the
ASCII value of the character to be redefined, and the second is the
redefined ASCII character. Both bytes must have their high bits cleared.

If there are less than six entries in this table, end end of the table
is denoted by a byte with the high order bit set.

Modifications of the Keyboard Character Redefinition Table may be made
using the CONFIGIO program.

Support of Non-Standard Peripherals and I/O Software

The I/O Info Block also provides for support of non-standard Apple
peripherals and I/O software. All the primitive character I/O
functions are vectored through the I/O Vector Table within the
I/O Config Block. These vectors normally point to the standard I/O
routine located in the CP/M BIOS, but they can be altered by the user
to point to his own drivers. Three blocks of 128 bytes each are
provided within the I/O Config block for user I/O driver software:

Address

Assigned Slot

Assigned Logical Device

0F200H-0F27FH

1

LST: - line printer device

0F280H-0FF7FH

2

PUN: and RDR: - general purpose I/O

0F300H-0F37FH

3

TTY: - the console device

Most Apple I/O interface cards have 6502 ROM drivers on the card.
The easiest way to interface these types of cards to Apple CP/M is to
write Z-80 code to call the 6502 subroutine on the ROM.

If no card is installed in a particular slot, its allocated 128-byte
space can be used for other purposes relating to its assigned logical
device. These include lower-case input drivers for Apple keyboard,
cassette tape interface, etc.

I/O driver subroutines are patched to Apple CP/M by patching the
appropriate I/O vector to point to the subroutine. A table of vector
locations and their purposes is shown below:

Vec #

Addr

Vector Name

Description

1

0F380H

Console Status

Return 0FFH in A if char ready, 00H if not

2

0F382H

Console Input #1

Return char from console into A with

3

0F384H

Console Input #2

hi bit clear

4

0F386H

Console Output #1

Send ASCII char in C to

5

0F388H

Console Output #2

console device

6

0F38AH

Reader Input #1

Read char from “Paper Tape Reader”

7

0F38CH

Reader Input #2

device into A

8

0F38EH

Punch Output #1

Send char in C to “Paper Tape Punch”

9

0F390H

Punch Output #2

device

10

0F392H

List Output #1

Send char in C to

11

0F394H

List Output #2

“Line Printer” device

Vec #

Addr
SS BIOS

Addr
PS IIe BIOS

Device

1

0F380H

0F3C0H

Console status (no CP/M device)

2

0F382H

0F3C2H

Input TTY: = CRT:

3

0F384H

0F3C4H

Input UC1:

4

0F386H

0F3C6H

Output TTY: = CRT:

5

0F388H

0F3C8H

Output UC1:

6

0F38AH

0F3CAH

Input PTR:

7

0F38CH

0F3CCH

Input UR1: = UR2:

8

0F38EH

0F3CEH

Output PTP:

9

0F390H

0F3D0H

Output UP1: = UP2:

10

0F392H

0F3D2H

Output LPT:

11

0F394H

0F3D4H

Output UL1:

Note: during console output, the B register contains a number corresponding
to one of the nine supported screen functions during output of a screen
function. B contains zero during normal character output. B is also
non-zero during the output of the Cursor Address X/Y coords after
executing screen function #7.

Assigning logical to physical I/O devices: the IOBYTE

IOBYTE at 0003H:

LIST

PUNCH

READER

CONSOLE

bits:

7

6

5

4

3

2

1

0

The value of each field can be in the range 0-3:

CONSOLE field (bits 0,1):

0

TTY: device

1

CRT: device

2

BAT:

batch mode, uses RDR: for input and LST: for output

3

UC1:

User defined CONSOLE device

READER field (bits 2,3):

0

TTY: device

1

PTR: device

(“paper tape reader”)

2

UR1:

User defined READER device #1

3

UR2:

User defined READER device #2

PUNCH field (bits 4,5):

0

TTY: device

1

PTP: device

(“paper tape punch”)

2

UP1:

User defined PUNCH #1

3

UP2:

User defined PUNCH #2

LIST field (bits 6,7):

0

TTY: device

1

CRT: device

2

LPT: device

(“line printer”)

3

UL1:

User defined LIST device

Default device assignments are:

CON: = CRT:RDR: = PTR:PUN: = PTP:LST: = LPT:

TTY: Either the standard Apple screen/keyboard or an external
terminal installed in slot 3. This routine vectors through Console
Input #1 and Console Output #1. The Console status is always vectored
through the Console Status vector.

PTR: A standard Apple interface capable of doing INPUT installed into
slot 2. If no card is plugged into slot 2, the PTR: device always returns
a 1Ah end-of-file character. Input from the PTR: device is vectored
through Reader Input vector #1. Characters are returned in the A register.

UR1: User defined reader #1. A character read from this device is returned
in the A register.

UR2: User defined reader #2. This device is physically the same as UR1:.

PTP: Any standard Apple interface capable of doing OUTPUT installed into
slot 2. If no card is plugged into slot 2, the PTP: device does nothing.
Output to the PTP: device is vectored through Punch Output vector #1.

The IOBYTE can be changed with the STAT program, or it may be modified
from an assembly language program using the CP/M Get IOBYTE
and Set IOBYTE (#7 & #8) functions.

Patching User Software Via the I/O Vector Table

User subroutines can be patched into the I/O Configuration Block with
the CONFIGIO program. Any patches made can also be permanently saved
onto a CP/M system disk as well with CONFIGIO.

To create a code file, use ASM to write the driver software,
and then use LOAD to create a COM file.

The code file loaded by CONFIGIO must be of certain internal format.
Only one code segment may be patched into the I/O Configuration Block
per code file. However, as many vectors in the I/O Vector Table may be
patched as desired.

Below is outlined the format of a disk code file to be loaded with
CONFIGIO and patched to the I/O Configuration Block:

First byte:

Number of patches to I/O Vector Table to be made

Next 2 bytes:

Destination address of program code

Next 2 bytes:

Length of program code

Repeat for each I/O vector patch to be made:

Next byte:

Vector Patch type - either 1 or 2

If Vector Patch type = 1:

Next byte:

Vector number to be patched, 1-11

Next 2 bytes:

Address to be patched into the vector

If Vector Patch type = 2:

Next byte: Vector number to be patched, 1-11

Next 2 bytes: Address in which to place the current contents of the vector (may be the address field of a JMP, etc)

Next 2 bytes:

New address to be placed in the specified vector

Next:

The actual program code is located after the patch information above. Convention restricts the size of the program code to 128 bytes per slot-dependent block. Use the block appropriate for your application and slot use.

Calling of 6502 Subroutine

The 6502 is enabled from the Z-80 by a WRITE to the slot-dependent
location 0EN00H, where N is the slot location of the Z-80 card. Z-80
mode is selected from 6502 mode with a WRITE to the same slot
dependent location, which is addressed as $CN00 in 6502 mode. The
location of the SoftCard will vary from system to system.

When the system is booted, the location of the SoftCard is determined
by Apple CP/M and its address is stored in the I/O Configuration Block.
This address is thus available to CP/M software for calling 6502
subroutines.

Calling the 6502 subroutine is a simple matter. Set up the address
of the subroutine to be called, and then write to the address of the
Z-80 SoftCard. One can also pass parameters to and from 6502
subroutines through the 6502 A, X, Y, P (Status) registers. The 6502
stack pointer is also available after a 6502 subroutine call.

Z-80 addr

6502 addr

Purpose

0F045H

$45

6502 A register pass area

0F046H

$46

6502 X register pass area

0F047H

$47

6502 Y register pass area

0F048H

$48

6502 P register pass area

0F049H

$49

Contains 6502 stack pointer on exit

0F3DEH

Address of Z-80 Softcard here as 0EN00H

0F3D0H

Address of 6502 subroutine to be called stored here

$3C0

Start address of 6502-to-Z80 mode switching routine. 6502 RESET, NMI and BREAK vectors point here. A JMP to this address puts the 6502 on “hold” and returns to Z-80 mode.

Note: Locations $800-$FFF are used by the Apple CP/M disk drivers and
buffers (“RWTS”) and are NOT available for use by a 6502 subroutine.

Language Card Users: When in Z-80 mode, the Language Card RAM is both
read- and write-enabled. When a 6502 subroutine is called, the Apple
on-board ROM is automatically enabled, making the Apple Monitor
available to the 6502 subroutine. However the Language Card RAM is
write-enabled during a 6502 call, i.e. a write to any location above
$D000 will write in the Language Card RAM.

A side effect of read-enabling the on-board Apple ROM's is that the
Z80 memory from 0C000H to 0EFFFH ($D000-$FFFF on 6502) cannot be
READ by the 6502, unless the appropriate Language Card addresses can be
accessed.

The first of the two available 4K banks in the Language Card is not used
by 56K Apple CP/M.

Presence and Location of Peripheral Cards

The Card Type Table is located at 0F3B9H, and the entry for a given slot
is located at 0F3B8H + S where S is an integer from 1 to 7. The contents
are:

The Disk Count Byte, located at 0F3B8H, is a single byte equal to the
number of disk controller cards in the system times two. This value does
not reflect an odd number of disk drives.

Each peripheral card has signature bytes at:

$Cn05

$Cn07

$Cn0B

$Cn0C

Where n is the slot number. Apple CP/M looks at $Cn05 and $Cn07
only. Versions 2.23 and later also inspects $Cn0B.

Card type

Signature Bytes

$Cn05

$Cn07

$Cn0B

Parallel Card

$48

$48

Communications Card

$18

$38

Super Serial Card

$38

$18

Disk Controller Card

$03

$3C

Firmware Card

$01

Microsoft SoftCard Version 2.20B BIOS

The BIOS for the Microsoft Softcard 56K CP/M version 2.20B extends
intp the Apple Language Card area but uses only bank 2 of the Language
Card. The Language Card bank 1 is left unused.

All the logical device routines use the IOCB. The IOBYTE is used to
determine which physical device is to be used. The address for that
device is taken from the IOCB and a jump is made to that address.

PUNCH The logical PUN: device, checks IOBYTE then goes to the selected routine

DB87H

DB95H

READER The logical RDR: device, checks IOBYTE then goes to the selected routine

DB96H

DBB7H

A routine for 80-column cards. Conditions the memory locations and looks to see if an escape sequence is coming. Control is passed to routines to perform specific functions depending on how the output is to be performed.

DBB8H

DBDFH

Routine to position the cursor in the GOTOXY sequence

DBE0H

DBF4H

Routine that checks to see if there was a terminal lead-in character sent and calls routines as requires

DBF5H

DC3DH

Routine that considers all the possible combinations and finally prints the character to the console via physical devices TTY: or UC1: as required

DC3EH

DC43H

Physical TTY: device. This is the general console output routine. THe jump address to the specific output routine is patched during the cold boot. Since the output routines are slot-dependent, the slot number of the console is supplied in location DC3FH. The slot number here is 3.

DC44H

DCDEH

Screen output routine for the standard 40-column Apple screen. This is the routine patched into the former routine if no serial or 80-column card is found in slot 3.

DCDFH

DCE9H

The comm card output routine. A status loop runs, and when ACIA is ready, character in C register is transmitted.

DCEEH

DD03H

Preparatory routine for setting up a serial card for either input or output.

Physical LPT: device output function. Jump is made to card driver routine. Jump address is loaded during cold boot and depends on card type in slot 1. Since the card routines are slot dependent, this routine supplies the slot number in location DD2CH

DD31H

DD3EH

Parallell card output routine

DD3FH

DD44H

Physical PTP: device output function. Jump is made to card driver routine. Jump address is loaded during cold boot and depends on card type found in slot 2.

A computational routine used by the peripheral card drivers and disk I/O routines to get needed slot and memory addresses and the numbers passed to them from the physical device routines

DD6DH

DD88H

SELDSK Select the disk drive and set flags to notify the disk I/O routines if the drive has been changed or a nonexistent drive was called

DD89H

DD8DH

SETSEC Select the 128-byte CP/M sector

DD8EH

DD92H

SETDMA Select the disk I/O buffer accress

DD93H

DDA2H

READ Set up the disk read operation according to all the CP/M protocols

DDA3H

DDF1H

WRITE Perform the disk write operation using CP/M protocols

DDF2H

DE72H

Used by both READ and WRITE to make sure the CP/M protocols are met. A sector skew is done with the CP/M sector skew table. The data is moved to or from the CP/M RWTS buffer at $800. The read or write operation is then called.

DE73H

DE91H

Do the actual read or write by calling the 6502 CP/M RWTS

DE92H

DEA1H

The CP/M logical sector skew table, which relates the 256-byte sector number to the logical 128-byte sector number used by CP/M.

F200H

F37FH

The I/O Patch area: space for user provided routines required for special I/O situations. The IOCB must be patched to vector the device I/O to the routines in this area.

F380H

F395H

IOCB containing the vectors to the CP/M physical devices

F396H

F3AAH

Table used by the console routines to perform console functions. Can be adapted to a variety of terminals.

F3C0H

F3FFH

Space used by the Apple Monitor ROM to vector the interrupts and resets. The vectors under CP/M all points to $3C0, so the Z-80 never loses control of the Apple.

F800H

F900H

The data buffer used by the CP/M RWTS

FA00H

FFFCH

The CP/M RWTS routines, written in 6502 assembly

The CPM56.COM map

On Apple II SoftCard CP/M systems, the Standard CP/M utilities MOVCPM
and SYSGEN are missing. Instead we have CPM56.COM on 56K CP/M
systems. Patches are most easily stored on the system tracks by
patching a copy of CPM56.COM and then running it to store the patched
system on the system tracks.

The program CPM56.COM contains the entire 56K CP/M system image. It's
easiest to modify the BIOS by making modifications to CPM56.COM and
then running it to put the image on the system tracks of a disk.
Below is a mapping of the CPM56.COM program when loaded in memory by
DDT

Start

End

Use

100H

2FFH

The command portion of CPM56.COM

300H

3FFH

The boot 1 portion: loads from track 0 sector 0 and is responsible for loading the CP/M RWTS sectors into the memory range $A000-$FFF and the boot 2 portion into the range $1000-$13FF.

400H

9FFH

The CP/M RWTS

A00H

BFFH

The boot 2

C00H

D7FH

The I/O Patch area, which gets moved by boot 2 to F200H-F37FH

D80H

The IOCB console status vector

D82H

The IOCB console input vector 1, or the TTY: device

D84H

The IOCB console input vector 2, or the UC1: device

D86H

The IOCB console output vector 1, or the TTY: device

D88H

The IOCB console output vector 1, or the UC1: device

D8AH

The IOCB reader vector 1, or the PTR: device

D8CH

The IOCB reader vector 2, or the UR1: device

D8EH

The IOCB punch vector 1, or the PTP: device

D90H

The IOCB punch vector 2, or the UP1: device

D92H

The IOCB list vector 1, or the LST: device

D94H

The IOCB list vector 2, or the UL1: device

D96H

DFFH

The console hardware and software definition tables and the remainder of page 3 routines and vectors. The data in the range D80H-DFFH gets moved by boot 2 to F380H-F3FFH

E00H

15FFH

The CCP

1600H

23FFH

The BDOS

2400H

29A7H

The BIOS

29A8H

29E7H

The cold boot routine

29E8H

29FFH

Patches required for 2.20B to run a turnkey and correct a disk read/write problem

The CPM56 Diskette Map

The Apple CP/M diskette system tracks are mapped as follows:

Start

End

Trk

Sec

Trk

Sec

Use

00H

00H

Boot 1 sector

00H

01H

00H

06H

CP/M RWTS

00H

07H

00H

08H

Boot 2 routine

00H

09H

00H

0AH

I/O Patch Area, page F300H routines+tables

00H

0BH

01H

02H

CCP

01H

03H

02H

00H

BDOS

02H

01H

02H

06H

BIOS

CP/M RWTS sectors are used in this table

CPM56 Card Driver Entry Points

A list of entry points to the peripheral card drivers is useful for
BIOS patching:

Addr

Entry Point

DCDFH

Communications Card output routine

DD04H

Serial Card output routine

DD12H

Communications Card input routine

DD1CH

Serial Card input routine

DD31H

Parallel Card output routine

ALl these enty points require that DE contains the card slot
number upon entry. The A and C registers are used as required by
the CP/M protocols.

Microsoft SoftCard Version 2.23 BIOS

THe Microsoft 2.20B BIOS uses some ungainly fixes to correct a few
problems, but still a few problems remain in the area of hardware
interfacing. Most of these problems are corrected in the SoftCard
2.23 BIOS.

The hardware interfacing is greatly improved because version 2.23
uses Apple Computer's protocols for operating what Apple calls
Firmware Cards. Most of the cards that can operate a host of
peripheral devices and have them do all sorts of neat tricks are
Firmware Cards. Version 2.20B could not identify Firmware Cards and
would often use the wrong I/O drives. This caused a grinding of
teeth by those unfortunates who invested in expensive equipment and
could not get it to operate under CP/M. Version 2.23 will operate
the Firmware Cards, if the card manufacturer followed the Apple
protocols.

Another improvement in 2.23 is that the BIOS Comm Card driver uses
the 6502 instead of the Z-80 to access the ACIA. The Z-80 has a
memory refresh provision, which causes the address to be accessed
to be preread before the actual reading or writing occurs. Reading
the data port on an ACIA clears the ACIA status flags, which means
the data can disappear before a second read is made. You can lose
data when the ACIA is read by the Z-80; using the 6502 instead
eliminates this problem.

The 60K 2.23 BIOS has a bigger TPA than the 56K 2.20B verison because
both 4K banked memories in the Language Card are used. Version 2.23
uses bank 1 to store the BIOS disk-handling routines, which include
the 6502 CP/M RWTS, the Z-80 BIOS routines, and two-thirds of the BDOS,
which leaves bank 2 available for program memory.

Start

End

Use

F200H

F37FH

The I/O Patch area: space for user provided routines required for special I/O situations. The IOCB must be patched to vector the device I/O to the routines in this area.

F380H

F395H

IOCB containing the vectors to the CP/M physical devices

F396H

F3AAH

Table used by the console routines to perform console functions. Can be adapted to a variety of terminals.

$3C0

$3DA

Routine which calls the 6502 microprocessor

$3F0

$3FF

Space used by the Apple Monitor ROM to vector the interrupts and resets. The vectors under CP/M all points to $3C0, so the Z-80 never loses control of the Apple.

PUNCH The logical PUN: device, checks IOBYTE then goes to the selected routine

FB91H

FB9FH

READER The logical RDR: device, checks IOBYTE then goes to the selected routine

FBA0H

FBCAH

A routine for 80-column cards. Conditions the memory locations and looks to see if an escape sequence is coming. Control is passed to routines to perform specific functions depending on how the output is to be performed.

FBCBH

FBF1H

Routine to position the cursor in the GOTOXY sequence. The routine jumps to FCA4H. Routines required for the functioning of the routine at FBA0H are also placed out of sequence compared to ver 2.20B and start at address FC56H. This displacement is required so that room for a nibble buffer used by the RWTS can be located at $C00

FBF4H

FBF8H

SETSEC Select the 128-byte CP/M sector

FBF9H

FBFDH

SETDMA Select the disk I/O buffer accress

$C00

$C55

One of the CP/M RWTS nibble buffers

FC56H

FC6AH

Routine that checks to see if there was a terminal lead-in character sent and calls routines as requires

FC6BH

FCB4H

Routine that considers all the possible combinations and finally prints the character to the console via physical devices TTY: or UC1: as required

FC5BH

FCBAH

Physical TTY: device. This is the general console output routine. The jump address to the specific output routine is patched during the cold boot. Since the output routines are slot-dependent, the slot number of the console is supplied in location DC3FH. The slot number here is 3.

FCBBH

FD0DH

Screen output routine for the standard 40-column Apple screen. This is the routine patched into the former routine if no serial or 80-column card is found in slot 3.

FD0EH

FD27H

The comm card output routine, using 6502 code. A status loop runs; when ACIA is ready, character in C register is transmitted.

FD28H

FD70H

Screen function routines, located in the BIOS out of sequence compared to version 2.20B

FD71H

FD82H

The serial card output routine, performs the output by calling the 6502

FD83H

FD98H

Preparatory routine for setting up a serial card for either input or output.

FD99H

FDA8H

Console status routine for a Firmware Card, which calls a 6502 routine for operation

FDA9H

FDB6H

Firmware Card output routine, calls a 6502 routine for operation

FDB7H

FDC0H

Firmware Card input routine, calls 6502 code at $E0F

FDC1H

FDCFH

Serial card input routine.

$DD0

$DE0

Firmware Card initialization routine, followed by a routine that uses the Apple protocol for firmware I/O

$DE1

$DEE

Firmware Card output routine

$DEF

$DFA

Firmware Card routine which waits for card to accept I/O

$E00

$E02

CP/M entry to the warm loader routine

$E03

$E08

Entry to CP/M RWTS routine on Language Card bank 1

$E09

$E0E

Second entry to warm loader routine on bank 1 of Lang Card

$E0F

$E1C

Firmware Card input routine

$E1D

$E25

Firmware Card routine to obtain the card's I/O status

$E26

$E3E

Sets up all parameters used by the Firmware Card protocol and set up the coresident ROM area at $C800 to be ready for the Firmware Card's requirements

$E3F

$E4A

Called by the routine at $3C0 to set all the 6502 registers and flags from their respective memory areas. The 6502 interrupt is also enabled

Physical LPT: device output function. Jump is made to card driver routine. Jump address is loaded during cold boot and depends on card type in slot 1. Since the card routines are slot dependent, this routine supplies the slot number in location DD2CH

FE5BH

FE68H

Parallell card output routine

FE69H

FE6EH

Physical PTP: device output function. Jump is made to card driver routine. Jump address is loaded during cold boot and depends on card type found in slot 2.

A computational routine used by the peripheral card drivers and disk I/O routines to get needed slot and memory addresses and the numbers passed to them from the physical device routines

FE97H

FEC5H

SELDSK Select the disk drive and set flags to notify the disk I/O routines if the drive has been changed or a nonexistent drive was called

FEC6H

FECBH

READ Entry point to the disk read routine found on bank 1 of the Language Card

FECCH

FED1H

WRITE Entry point to the disk write routine found on bank 1 of the Language Card

FED2H

FED8H

Called when the 6502 must be called by code on bank 1

FED9H

FEDFH

Called when a disk I/O error is encountered by disk-handling code on bank 1. Bank 2 is sswitched back on, and the BDOS error routine is called

FEE0H

FEE3H

Bank 1 routines returns here, bank 2 is turned back on

$FFAC

$FFE8

CP/M RWTS prenibblizing routines, located above BDOS in memory and doesn't neatly fit into this memory map. Microsoft had to put it here to fit the second segment of BDOS on bank 1 of the Language Card. Version 2.23 gets choppy from here on.

The following are located on bank 1 of the Langauge Card

Start

End

Use

$D000

$D246

The first segment of the CP/M RWTS. The RWTS is split into two segments for reasons known only to Microsoft.

B247H

B256H

The disk read operation, set up according to the CP/M protocols

B257H

B270H

The disk write operation, performed according to CP/M protocols

B271H

B333H

Used by both READ and WRITE to make sure the CP/M protocols are met. A sector skew is done with the CP/M sector skew table. The data is moved to or from the CP/M RWTS buffer at $800. The read or write operation is then called.

B334H

B358H

Do the actual read or write by calling the 6502 CP/M RWTS

B359H

B368H

The CP/M logical sector skew table, which relates the 256-byte sector number to the logical 128-byte sector number used by CP/M.

$D369

$D5BC

The second segment of the CP/M RWTS

B5C0H

BFFFH

The second BDOS segment. This is not the BIOS, but is included for completeness.

The CPM60.COM map

On Apple II SoftCard CP/M systems, the Standard CP/M utilities MOVCPM
and SYSGEN are missing. Instead we have CPM60.COM on 60K CP/M
systems. Patches are most easily stored on the system tracks by
patching a copy of CPM60.COM and then running it to store the patched
system on the system tracks.

The program CPM60.COM contains the entire 60K CP/M system image. It's
easiest to modify the BIOS by making modifications to CPM60.COM and
then running it to put the image on the system tracks of a disk.
Below is a mapping of the CPM60.COM program when loaded in memory by
DDT

Start

End

Use

100H

3FFH

The command portion of CPM60.COM

400H

4FFH

The boot 1 portion: loads from track 0 sector 0 and is responsible for loading the CP/M RWTS sectors into the memory range $A000-$FFF, loading boot 2 into $1000-$12FF, and loading the $300-page area into $1300-$13FF

500H

746H

The first segment of the CP/M RWTS

747H

858H

The BIOS read/write portions of the disk handling routines

859H

AFFH

The second segment of the CP/M RWTS

B00H

CFFH

The boot 2

D00H

E7FH

The I/O Patch area, which gets moved by boot 2 to F200H-F37FH

E80H

The IOCB console status vector

E82H

The IOCB console input vector 1, or the TTY: device

E84H

The IOCB console input vector 2, or the UC1: device

E86H

The IOCB console output vector 1, or the TTY: device

E88H

The IOCB console output vector 1, or the UC1: device

E8AH

The IOCB reader vector 1, or the PTR: device

E8CH

The IOCB reader vector 2, or the UR1: device

E8EH

The IOCB punch vector 1, or the PTP: device

E90H

The IOCB punch vector 2, or the UP1: device

E92H

The IOCB list vector 1, or the LST: device

E94H

The IOCB list vector 2, or the UL1: device

E96H

EFFH

The console hardware and software definition tables and the remainder of page 3 routines and vectors. The data in the range D80H-DFFH gets moved by boot 2 to F380H-F3FFH

The CP/M RWTS

Written in 6502 code, resides at $800 - $FFF including buffers.
Entry point at $E03 (for BIOS ver 2.20B and 2.23) – before entry
these addresses below must be filled with appropriate data. The CP/M
RWTS use a 256-byte data buffer at $800 by default.

To call the CP/M RWTS from your own code, init the following memory
areas before calling $E03:

$3E0

Place track to be accessed here

$3E1

Place CP/M physical sector to be accessed here. The Apple sector numbers range from $0 to $F. The sector skew for CP/M physical sectors is used

$3E1-$3E3

Holdovers from the DOS 3.3 RWTS and were used for volume numbers. CP/M RWTS doesn't use volume numbers, so put $00 here

CP/M version 2.23 always reinitializes the I/O buffer address to $800
before using the CP/M RWTS. CP/M version 2.20B doesn't reinitialize
the I/O buffer address, so the programmer must restore it to $800
if needed after having called the CP/M RWTS.

The first 3 tracks, tracks $00 to $02, are reserved for the boot
routine, the CCP, BDOS and BIOS. Track $03 contain the CP/M
directory, where only 6 physical sectors contains the directory (CP/M
logical sectors 00H through 0BH).

SoftCard CP/M ver 2.23 and higher uses a trick to allow the system
tracks for data storage: a file called cp/m.sys is created in user
area 31 as a dummy file allocated to the system tracks. It is
inaccessible from the CCP and unseen by the user. The BIOS is
written to recognize the system tracks as accessible data areas.
COPY.COM has an option to create a “data diskette” where cp/m.sys is
absent, which creates 3 more tracks for data storage. Such a
diskette cannot be warm booted, bit it is safe to use it in any other
drive than A:

Sectors

CP/M
Logical

CP/M
Physical

DOS 3.3

Apple
Physical

00,01

0

0

0

02,03

9

6

3

04,05

3

C

6

06,07

C

3

9

08,09

6

9

C

0A,0B

F

F

F

0C,0D

1

E

2

0E,0F

A

5

5

10,11

4

B

8

12,13

D

2

B

14,15

7

8

E

16,17

8

7

1

18,19

2

D

4

1A,1B

B

4

7

1C,1D

5

A

A

1E,1F

E

1

D

Apple CP/M has double sector skewing: the system tracks use CP/M
physical sector skew while the data tracks uses the logical sector
skew. The CP/M physical sector skew is fastest for reading sectors,
while the logical sector skew is a compromise for getting the
fastest sector read skew in conjunction with the fastest sector write
skew.

The Apple CP/M Disk Parameter Tables

The CP/M BIOS contains several Disk Parameter Tables:

DPH - Disk Parameter Header: a pointer to the DPH for a specific disk
is obtained by loading C with the disk drive (0=A:, 1=B:, etc) and
then call the BIOS function SELDSK (entry point at xx1BH, where xx00H
is your BIOS base where xx is found at address 0002H of your CP/M
system). The disk drive need not have any disk inserted, since the
BIOS SELDSK function only locates the tables but does not attempt to
access the disk. When SELDSK returns, HL points to the DPH, which
contains:

Offset

Contents

Use

00H

XLT

Addr of logical-to-physical sector translation vector.
On Apple CP/M, XLT is 0000H, which means that the CP/M BIOS does no such translation - instead sector skewing is implemented in the CP/M RWTS, which is written in 6502 code.

02H

0000H

Scratchpad values for use within BDOS

04H

0000H

Scratchpad values for use within BDOS

06H

0000H

Scratchpad values for use within BDOS

08H

DIRBUF

Addr of scratchpad 128-byte directory buffer.

0AH

DPB

Addr of Disk Parameter Block for this drive, see below.

0CH

CSV

Addr of scratchpad area to check for changed disks

0EH

ALV

Addr of scratchpad area for disk allocation info

DPB - Disk Parameter Block. The address of the DPB can be found in
either the DPH (see above), or by calling BDOS function 31 (=1FH)
“Get addr disk params”, which will return the address of the DPB for
the current drive in HL. If you want the DPB for a specific drive,
first call BDOS function 14 (=0EH) “Select disk”, with the drive to
select in E on entry (0=A:, 1=B:, etc) - note that the drive must
have a valid CP/M disk inserted for this to work.

DSM = maximum data block number supported by this particular drive, measured
in BLS (Block Size) units, or simply “number of allocation blocks on drive”.
Blocks are counted from 0 to DSM, and thus BLS*(DSM+1) = the number of bytes
on the drive (excluding the system tracks). If DSM<256, the disk map in
the directory entry of the file will be 1 byte/block. If DSM>=256 it will
be 2 bytes/block.

DRM = total number of directory entries minus one.

AL0/AL1 = the directory allocation vector. Consider it a bit map of
bits 16 bits, bit 0-15, where 0=hi bit of AL0, 7=lo bit of AL0, 8=hi
bit of AL1, 15=lo bit of AL1. Bits are assigned starting at bit 0 up
until bit 15. Suppose nbits is the number of bits set to 1:

OFF = number of reserved tracks. This value is automatically added
whenever SETTRK is called. It can be used to skip reserved system
tracks, or for partitioning a large disk into smaller segmented
sections.

Several DPH's can address the same DPB if the drive characteristics
are identical. The DPB can be dynamically changed when a new drive
is addressed by simply changing the pointer in the DPH since the BDOS
copies the DPB values to a local area whenever the SELDKS function
is invoked.

The size of the CSV (scratchpad area to check changed disks) is CKS
bytes. If CKS=(DRM+1)/4, this area must be reserved. If CKS=0, no
storage is reserved.

The size of the ALV (scratchpad area for disk storage allocation info)
is (DSM/8)+1 bytes where DSM is the disk size in allocation blocks.

Below DPB parameters are given for three different kinds of Apple CP/M
formats, plus the Standard CP/M 8“ SSSD disk format as a comparison:

A: The SoftCard 13-sector Apple CP/M format, used only briefly on
early SoftCard CP/M systems. No other Apple CP/M card ever used
the 13-sector format. This format yielded 104K of data per
diskette, excluding the system tracks.

B: The 16-sector Apple CP/M format. This was THE Apple CP/M disk
format, introduced by the SoftCard and subsequently used by all
other Apple CP/M systems (Appli-Card, CP/M Card, Premium SoftCard).
This format yields 128K of data per diskette, excluding the system
tracks.

The Apple CP/M disk formats were really too small, since the Standard
CP/M 8” SSSD disk format yielded 243K of data per diskette, and many
CP/M programs assumed a disk at least this big. One enhancement was
to use 40 tracks instead of 35 tracks on the diskette, which would
yield 148K of data per diskette, excluding the system tracks. Later,
when 80-track double-sided disk drives became available, CP/M could
fairly easily be modified to accept these drives. The hardest parts
were to hook up the hardware, and modify the CP/M RWTS program to
access all 80 tracks on both sides, and the formatter program to
format 80 tracks on both sides. But once this was accomplished, it
was fairly straight-forward to modify the BIOS DPH so that CP/M could
access the entire 80-track double-sided disk as one disk, yielding
628K of data per diskette, making virtually any CP/M program
comfortably fitting on one diskette.

C: This disk format is 16 sectors/track, 80 tracks double sided, where
the tracks and sides are mapped within the modified CP/M RWTS so they
appear as 160 tracks to the CP/M Z-80 BIOS (which knew nothing about
double-sided disks). This format yields 628K of data per diskette,
excluding the system tracks.

D: As a comparison, the DPB parameters for the Standard CP/M 8“ SSSD
format is given. This disk format had 128 bytes/sector on the disk.