CPT (CP/m Transfer) is a system for archiving and restoring complete
CP/M disk to and from image files on a PC. It consists of a PC program
which controls the transfer, and a small "client" program which runs
on the CP/M system to read and write physical tracks in response to
commands over a serial connection.

Files in this archive:
----------------------
CPT.TXT     = This file
CPT.COM     = PC side tansfer program program
CPT.ASM     = CP/M side client program
MKCPT.BAT   = Batch file to assembly CPT.ASM to CPT.BIN
ASM80.TXT   = Documentation for my 8080 assembler
ASM80.EXE   = My 8080 cross assembler
MACRO.EXE   = Macro preprocessor for ASM80
HEXFMT.COM  = Hex file manipilation utility
APN0014.TXT = Notes on running under DOS programs under Windows


CP/M Transfer utility - Jun 14 2005 - Dave Dunfield.

Use:    CPT     filename[.CPT] options

Command options (You must specify ONE of these):

  /Q      Query disk information
    Displays information about the selected disk drive
    including #tracks, #sectors/track, #system tracks
    and dumps the BIOS Disk Parameter Block
    - No file is read or written

  /R      Read disk into file
    Reads a diskette into a disk image file.
    By default, reads user area only. Use S=0 to attempt to
    read the system tracks.

  /T      TTY/upload mode
    Connects to target with the TTY mode. Mainly to allow for
    loading of the Client Loader program.
    NOTE: This is the only case where TTY mode is entered that
          is NOT an error condtion. In this case, the F2 (Retry)
          and F3 (Continue) functions will simply exit.

  /W      Write disk from file
    Writes a diskette from a disk image file.
    Normally writes all tracks which were recorded in the image
    FILE. Use S=2 to skip the system tracks.

If none of /Q, /R, /T or /W is specified, CPT will display information
about the image file, but will not perform any other action.

Command modifier options:

  /X      Access ALL tracks with XLT (even system tracks)
    Causes CPT to use the BIOS XLT table (if available) for reading
    and writing ALL tracks. By default (if neither /X or /Y) is
    specified, CPT reads SYSTEM tracks WITHOUT XLT, and USER tracks
    WITH XLT. (See X=)

  /Y      Access NO  tracks with XLT (even if available)
    Causes CPT to read all tracks without XLT. (See X=)

  B=n     Specify baudrate                        [9600]
    Set PC serial port baudrate. Must match Loader Client

  C=1-4   Specify COM port                        [1]
    Set PC COM port.

  D=A-P   Set disk drive to access                [A]
    Set target disk drive to access. Defaults to A:

  K=file  Komment file                            [none]
    Set file to read for image comments when creating (/R) a
    disk image file. Assumes .TXT if no extension is provided.
    If K= is not specified, CPT will prompt for the comment at
    the PC console.

  L=file  Loader file                             [CPT.BIN]
    Sets the name of the Loader Client file which us accessed by
    CPT for the TTY/F6 (Upload) function. File must contain binary
    code image origined at 0100.

  M=xxxx  Set track Memory buffer                 [0800]
    Sets the memory address within the target system used for
    the track data buffer. You shouldn't have to move this unless
    you make the Loader Client really BIG!

  N=n     Override # sectors/track                [BIOS/FILE]
    When creating an image, overrides the sectors/track as reported
    by the BIOS.

  S=n     Override starting track                 [BIOS/FILE]
    When creating an image, sets the first track to read. This
    defaults to the value of OFF from the DPB, which means start
    at the first user track.

    You can TRY using S=0 to include the system tracks, however be
    aware that some CP/M systems format the system tracks differently,
    and you may not be able to read them. If this is the case, there
    is no reliable way to read the system tracks, because CP/M does not
    provide any general functions for accessing the system tracks.

    When writing an image, this option controls the first track
    written. Normally this defaults to the first track which is
    provided in the image file, however if you are restoring an
    image containing the system tracks and you would like to NOT
    restore the system tracks, you can use S=2 to begin writing
    at track 2.

T=n     Override # tracks                       [BIOS/FILE]
    When creating an image this controls the maximum track which
    will be saved. This defaults to the number of tracks on the drive
    as determined by the disk parameter block.

    When writing an image, this controls the maximum track which
    will be written. This defaults to the highest track which is
    contained within the image.

X=n     Sector offset for non-XLT               [XLT/FILE]
    CP/M internally uses sector numbering of 0-(n-1) where n is the
    number of sectors on the track. Most standard floppy disk formats
    use sector numbering 1-n. Exactly where the translation from CP/M's
    0-(n-1) and the disks 1-n numbering happens is up to the particular
    BIOS in question. Many systems provide this translation along with
    sector interleave in the XLT table. In order to enable these systems
    to work without XLT, the X=n option allows you to specify an offset
    which is added to CP/M's 0-(n-1) sector number when XLT is NOT being
    used.

    The default setting for X= is 1 if an XLT table is provided in the
    BIOS, and 0 if not.


What is XLT:
------------
XLT is an internal translate table provided by the BIOS which
provides "Sector interleave". Sector interleave allows time for
processing between adjcent sector reads by spreading them out.
Example, assume a track with only 5 sectors 1-5. When you logically
read 1 2 3 4 5, an interleaved disk might actually read physical
sectors 1 3 5 2 4. This allows an extra sector "gap" between each
sector read, so that the system can take longer to process the data
without "missing" the next sector and have to wait for it to come
around again. A different system might provide two sectors worth of
gap, in which case the physical read order would be: 1 4 2 5 3

CP/M performs sector interleaving with a translation table called
XLT. In order to read sectors in sequential order, CP/M takes the
logical sector number passed by the application, and looks up the
actual physical sector number to use in the XLT table. By making
the XLT entries go 1-n, the table provides both the interleave and
0-(n-1) to 1-n translation functions.

Note that not all systems use XLT. If no XLT table is defined for
the drive, CP/M will call the driver directly with the logical sector
numbers. In this case, the driver must adjust the sector number to
1-n if required by the disk format.

System tracks are normally NOT read by the standard CP/M BIOS, but
instead are read by a very simple loader. For this reason, most CP/M
systems do NOT use XLT when writing the system tracks. This is why
CPT provides several options for handling XLT.


Configuring the Loader Client:
------------------------------
CPT uses a resident client in the target system to perform disk
access under control of the PC serial port. This client requires
an 8-bit binary communications channel with the PC. Since many
CP/M serial port drivers do not provide a "raw" 8-bit path, the
CPT client provides it own serial drivers.

CPT provides three driver functions:

INIT  - Used to provide any required initialization of the
        serial port.
PUTC  - Writes character in A to serial port
        No other registers should be modified.
GETC  - Get character from serial port.
        On exit:    CY=1 means no char received (timeout)
                    CY=0 means character received in A
        No other registers should be modified.

If your system does not automatically initialize the serial port
for 8-bit operation, you will need to add code to the INIT function
which does this. You may also wish to increase the serial speed
(if possible) to reduce disk image transfer time.

For most systems using polled serial I/O, the example GETC and
PUTC can be used without modification by setting the symbols near
the top of the CPT.ASM file:

USTAT   = I/O address of UART status port
UDATA   = I/O address of UART data port
RMASK   = Bit mask for RX ready bit in USTAT
RJMP    = 'JNZ' if (USTAT & RMASK) is NOT 00 when character is ready.
          'JZ'  if (USTAT & RMASK) is 00 when character is ready.
TMASK   = Bit mask for TX ready bit in USTAT
TJMP    = 'JZ'  if (USTAT & TMASK) is NOT 00 when transmitter is ready.
          'JNZ' if (USTAT & TMASK) is 00 when transmitter is ready.


If you do not know how to perform serial I/O on your CP/M system:
-----------------------------------------------------------------
First, determine which serial UART chips are installed in your
system. If you are lucky, this information is contained in your
system documentation. If not:

For S-100 and other bus oriented systems, determine which board
is the serial board by tracing the wires from the serial ports
to determine which board they go to. If your system is all on a
single board, then you will have to look over the whole board.

Look for UART chips. These are usually more than 24 pins.
Common UART chips are:
    24 pin: 6850
    28 pin: 6551
    40 pin: Z80-DART    Z80-SIO     8250        6402        6552
            AY-5-1013   AY-5-1015   TMS6011
The following chips are NOT UART chips (look no further):
    24 pin: 8212        27xx        51xx        61xx
            8253        8254
    28 pin: 27xx        27xxx       62xxx       6840        8259
            Z80-CTC     
    40 pin: 8080        8085        17xx        27xx        765
            8272        Z80-CPU     Z80-PIO     Z80-DMA
If you still can identify the UART chips, try tracing the signals
from the serial ports. These normally go to an RS-232 interface
chip which is connected to the UART. These are smaller devices,
14-16 pins is most common, although there are some 8-pin ones.
Common RS-232 interface chips:
            1488        1489        MAX-232

Once you know what kind of UART is in your system, see if you can
find the datasheet, programming information and I/O port addresses
in your system documenation. If not, you can probably find the
datasheet on the internet.

You can also learn a lot about how your system I/O works by looking
at the code with DDT. Run DDT and enter the command: L0
The very first line displayed should show something like:
    0000  JMP  xx03

The 'xx' gives you the address of the BIOS jump table. Lets assume
that the first line reads:
    0000  JMP  F303
This means that the BIOS jump table is at address F300. Now enter
the command: LF300
You should see something like:
    F300  JMP  xxxx
    F303  JMP  xxxx
    F306  JMP  xxxx     <= Console status (A=FF if char ready)
    F309  JMP  xxxx     <= Console input
    F30C  JMP  xxxx     <= Console output
    F30F  JMP  xxxx     <= List   device output
    F312  JMP  xxxx     <= Punch  device output
    F315  JMP  xxxx     <= Reader device input
    F318  JMP  xxxx
    F319  JMP  xxxx
    F31B  JMP  xxxx
    F31E  JMP  xxxx
    F321  JMP  xxxx
    F324  JMP  xxxx
    F327  JMP  xxxx
    F32A  JMP  xxxx
    F32D  JMP  xxxx     <= List device status

By using the DDT 'Lxxxx' command, you can disassemble each of these
I/O functions to gain insight into how the device operates:
Note1:  Often the first JMP xxxx points to another JMP xxxx - just
        keep following the xxxx address until you find the code.
Note2:  Often the I/O functions use Z80 relative JR instructions
        which DDTs disassembler does not understand. You may need
        to refer to the Z80 instruction set. You may also need to
        use another 'Lxxxx' command to "sync up" disassembler to
        see the instruction right after the Z80 one.


Assembling and Transferring the client:
---------------------------------------
Once you have the client modified to work on your system, you
can assemble it on the PC with my ASM80 cross assembler:
    MACRO CPT.ASM >CPT.ASM
    ASM80 CPT -IT                 <= Assemble to Intel format HEX
    HEXFMT CPT.HEX -bt w=CPT.BIN  <= Create CTP.BIN

I have provided a batch file called: MKCPT.BAT
which performs the above steps.

To get this file to a CP/M system with a serial console, connect
your PC to the system console, and run the PC command: CPT /T
This will put you in a terminal mode to communicate with the
CP/M system. Boot up the system and run: DDT
At the '-' prompt, enter the command: S100
At the prompt, press F6
CPT will upload the CPT.BIN image into memory by "typing" it
in to the DDT memory editor. When if finished, enter '.' to
return to the DDT prompt.
At this point, you can simply launch the client with 'G100',
or you can save it to a disk with: ^C (wait for system prompt)
and then type: SAVE 3 CPT.COM
NOTE: If you have made CPT.BIN substantally larger than the
      standard one, adjust the save size accordingly.

If your system does not have a serial console, then you will have
to transfer the program via the READER port:
  Use PIP to copy RDR: into CPT.HEX
  Use LOAD CPT.HEX to read the Intel format records into memory
  Use SAVE 3 CPT.COM to save the binary program
The exact procedure may vary depending on how your system I/O
devices are configured.



TTY Error Recovery mode
-----------------------
CP/M has a nasty habit of stopping everything and prompting on
the console when certain errors occur. This can prevent CPT from
automatically recovering in those conditions.

When an error occurs which cannot be recovered by a simple retry
(or too many retries occur), CPT will activate an "error recovery
TTY" mode, allowing you to communicate with the target system.

Once you arrive in this mode, you must correct the problem, and
restart the CPT client (if necessary) to continue with the transfer.

The following special keys are available:

F1  = Display a short summary of the key functions
F2  = Exit TTY mode and retry the failed operation
F3  = Exit TTY mode and ignore the failed operation
      (This may/will cause corruption of some data)
F4  = View the last 256 characters which were received on the
      serial port before TTY was entered. This can often reveal
      CP/M error messages which were "eaten" during CPTs detection
      of the error and attempts at retry.
F5  = Reselect the disk Drive and Track
      If you have had to restart the CPT client, then you should
      perform this operation to reactivate the correct drive, and
      reseek to the correct track before you retry or continue.
      Use SPACE to reselect the options that were in effect when
      the error occured.
      You can also use it to switch to a different drive when an
      unrecoverable error occurs.
F6  = Upload client
      Used to transmit CPT.BIN client image into DDT 'S' command
      (See above)
F10 = Exit CPT completely.


Image File Format
-----------------
The .CPT image file is in the following format:

1)  Up to 4K of comment text.
    this provides an ASCII description of the disk image,
    and is for reference/record-keeping only.
    + The comment BLOCK *MUST* begin with the characters: CPT:
    + CPT automatically writes the first line as: CPT: month day,year

2)  The byte value 1A  - this is an ASCII file EOF marker for
    MS-DOS. What this does it allow you to simply TYPE the .CPT
    file to view the comment.
    NOTE: Do NOT edit the .CPT file with a text editor, or copy it
    as a text file. All information beyond this EOF (1A) character
    will be lost!!!

3)  CP/M Drive Parameter Header from source drive (16 bytes)
    For reference only.

3)  CP/M Drive Parameter block from source drive (15 bytes)
    When you recreate the image, CPT will compare the DPB from the
    image file with the DPB of the target drive and warn you if
    they are different (which means the image will likely not work).

4)  XLT table from source drive (if present)
    The exact format of XLT is determined by BIOS SELTRK, but normally
    it is just a list of bytes/words, one for each sector within a track.
    CPT simply saves a number of words equal to sectors/track.
    Not included in file if dph.XLT is 0000 (XLT not used).
    For reference only.

5)  Number of sectors/track actually saved in image (2 bytes)

6)  Starting track saved in image (2 bytes)

7)  Last track saved in image (last track on source drive-1) (2 bytes)

8)  X= value (raw sector offset adjust) when image created.

9)  Flag byte:
    00 = XLT used for ALL  tracks
    55 = XLT used for NO   tracks
    FF = XLT used for USER tracks only (not system)

10  Diskette image data
    128 bytes for each sector, times number of sectors/track,
    times number of tracks recorded in image.
