Classic Computer Magazine Archive COMPUTE! ISSUE 86 / JULY 1987 / PAGE 82

1571 Utility Package

Dick Smit

Among other exciting features, the Commodore 1571 disk drive has the ability to perform high-speed burst mode operations and can read MFM (non-Commodore) disks for CP/M mode. The four programs included with this article let you copy MFM-format disks, read and alter the information on an MFM disk, and access all of the 1571's special features from BASIC. A Commodore 128 with 1571 disk drive and 80-column monitor is required.

The Commodore 1571 is the most versatile disk drive ever offered by Commodore. It can operate as a 1541 drive, giving you access to the huge library of existing Commodore 64 software. With a Commodore 128 in 128 mode, it can also transfer data in burst mode at much higher speeds than a 1541 disk drive. Commodore disks use a recording system known as GCR (Group Code Recording), but CP/M disks for many other computers use a different system known as MFM (Modified Frequency Modulation). Since the 128 can operate as a CP/M computer, the 1571 provides the ability to read and write MFM-format disks. CP/M is one of the most widely used microcomputer operating systems, and vast amounts of public domain CP/M software are available on MFM disks. The IBM PC and compatible computers also use MFM disks.

The 1571's special capabilities are impressive, but using them from BASIC is not always so easy. Some of the most useful 1571 routines aren't designed for use with

Command Descriptions

There are 14 individual routines included in Program 3. Five of these serve as subroutines for the other nine user-callable subroutines. These five subroutines (SENDCMD, SPOUT, SPIN, CLKLO, and CLKHI) are not meant to be called directly from BASIC with SYS.

The following descriptions provide all the information needed to use these routines. The Call address specifies the entry point of the routine; to activate the routine, SYS to this address. The Table address shows the location of that command's data storage area. The Format section of each description details the function of each byte in the command's storage area. Note that some bits are common to all commands; they are detailed only in the description of the first command, Read Sector.

READ SECTOR

Purpose: Reads a sector from the currently logged disk and stores the data in the computer's memory

Call address: $30F8 (12536)

Table address: $3800–$3806 (7 bytes)

Format: $3802: Control byte

bit 7 transfer data (1 = no transfer)

bit 6 error ignore flag (1 = ignore error)

bit 5 buffer transfer (1 = transfer buffer)

bit 4 side select (MFM only—0 = front, 1 = back)

bits 1–3 burst command (000 for Read Sector)

bit 0 drive select (keep at 0 for all commands)

$3803: Track to be read (0–35 for GCR or 0–39 for MFM)

$3804: Sector to be read (range of valid values depends on format and mode)

$3805: Number of sectors (must be more than zero)

$3806: Next track (optional, normally unused)

Explanation: This routine reads a sector from the disk into the memory. Before this routine is called, the correct values should be placed in the instruction table by POKEing into locations $3802–$3806. You must also specify the addresses where the data read from disk is to be stored. Computing the length of this area is not difficult for GCR, since a GCR block always contains exactly 256 bytes. For MFM, however, the block length may vary from 128–1024 bytes. Make sure that the difference between the starting and ending addresses matches the number of bytes you expect the sector to contain. Store the low byte of the starting address in location $FB and the high byte in location $FC. Similarly, locations $FD–$FE must contain the low and high bytes of the ending address. You can calculate the low and high bytes of an address A with the statements HI = INT(A/256) and LO = A-HI*256, where HI is the high byte and LO is the low byte.

Example: None.

BASIC, and cannot be called directly with a SYS command. And the 1571 user's manual offers little information on how to use special features such as burst mode.

This article includes four programs which make the 1571's power easily accessible to BASIC programmers. Program 1 lets you copy MFM-format disks. Program 2 is a comprehensive "disk doctor" that permits you to read and alter any data found on an MFM disk. Program 3 is a machine language utility which makes it possible to access all burst mode routines with BASIC SYS commands. Program 4 is a machine language display routine used by Program 2.

Type in and save all four programs (be sure you have copies of all four on the the same disk). Programs 1 and 2 are ordinary BASIC programs. (To generate the {BELL} character in Program 1, hold down the CONTROL key and type a G.) Programs 3 and 4 are written in machine language and must be typed in with the Commodore 128 version of "MLX," the machine language entry program listed elsewhere in this issue. Be sure to read the MLX instructions carefully before you begin. Here are the addresses required to enter Programs 3 and 4 with MLX:

Program 3: BURST

Starting address:	3000
Ending address:	323F

Program 4: SCREEN

Starting address:	3400
Ending address:	349F

You must save Programs 3 and 4 with the filenames BURST and SCREEN, respectively. It's important to use these filenames because Programs 1 and 2 use them when attempting to load the programs from disk. Again, it's also important that you save-Programs 3 and 4 on the same disk with Programs 1 and 2.

MFM Disk Copier

Program 1 makes copies of MFM-format disks, including both CP/M and IBM PC disks. It will not copy GCR-format Co'mmodore disks, nor can it be used to duplicate copy-protected MFM-format disks. (Note that the master system disk for Commodore 128 CP/M isn't in true

WRITE SECTOR

Purpose: Write a sector from memory to the currently logged disk

Call address: $3153 (12627) in bank 12–15

Table address: $3807–$380D (7 bytes)

Format: $3809: Control byte

bits 4–7 same as Read Sector

bits 1–3 command (001 for write).

bit 0 same as Read Sector

$380A–$380D: same as Read Sector

Explanation: The format of this command is almost identical to that of Read Sector. The only difference is that it writes a block to the current disk.

Example: This program writes the contents of locations $4000–$40FF to track 20, sector 3 in GCR format.

10 B = DEC("3800"):POKE251,0:POKE253,0:POKE252,64:POKE254,65
20 POKE B+3,20:POKE B+4,3:POKE B+5,2
30 OPEN15,8,15:BANK 15:SYS DEC("3153"):END

INQUIRE DISK

Purpose: Log the disk in the drive

Call address: $30E8 (12520) in bank 12–15

Table address: $380E–$3810 (3 bytes)

Format: $3810: Control byte

bits 5–7 not used (can be any value)

bit 4 same as Read Sector

bits 1–3 command (010 for Inquire Disk)

bit 0 same as Read Sector

Explanation: This command logs a disk for use. Disks must be logged in before they are used. Information pertaining to the disk is returned in the status byte. The status byte indicates the disk's format (MFM or GCR), the number of bytes in each sector, and the drive's error status. If you wish to determine the format of the disk, use the command Query Disk Format, which returns more information.

Example: This line logs the disk and prints the status and format on the screen.

10 OPEN15,8,15:BANK 15:SYS DEC("30E8"):PRINT PEEK(250):END

FORMAT MFM

Purpose: Format an MFM disk

Call address: $30EE (12526)

Table address: $3811–$381B (11 bytes)

Format: $3813: Control byte

bit 7 partial format (1 = partial)

bit 6 index mark written (1 = written)

bit 5 double side select (1 = format double side)

bit 4 side select (valid if bit 5 = 0)

bits 1=3 command (011 for MFM)

bit 0 same as Read Sector

$3814: Control byte

bit 7 must be a 1

bit 6 must be a 0

bits 0–5 specify the logical starting sector

$3815: Interleave byte (normally 0)

$3816: Sector size (0 = 128 bytes, 1 = 256, 2 = 512, 3 = 1024)

$3817: Last track (0 to 39, used for partial format)

$3818: Number of sectors per track (standard is 26 for 128-byte sectors, 16 for 256-byte sectors, 9 for 512-byte sectors, and 5 for 1024-byte sectors.)

$3819: Logical starting track (normally 0)

$381A: Starting track offset (normally 0)

$381B: Fill byte (value which to fill all sectors; normal value is $E5)

Explanation: This command formats an MFM disk, which allows great flexibility. You may control the size of the sectors, the number of sectors

MFM format, and cannot be copied with this program.) When you run the program, it checks to see whether the burst utility routine (Program 3) is in memory, and loads it from disk if it is not. Follow the prompts on the screen and swap disks when indicated. The program automatically detects the format of the source disk and creates the same format on the destination disk. An 80-column monitor is required because the program uses the 128's FAST mode.

MFM Disk Utility

Program 2, "MFM Disk Utility," offers a number of useful features for manipulating the information on MFM disks. Note that it requires an 80-column display, since a 40-column screen doesn't have enough room to display the contents of an entire 1024-byte MFM disk sector. When you run the program, it loads both the BURST and SCREEN routines (Programs 3 and 4) from disk, if they aren't already in memory. Line 4 of the program is optional: Its only purpose is to make sure that the drive's read/write head is within the range of a GCR disk (tracks 1–35) before the main program begins.

The program has the standard features found in most disk utilities. With this program, you can examine the contents of any sector on an MFM-format disk, and change the data as desired. The program is self-prompting, so you won't need extensive instructions to use it. Simply respond to the prompts displayed on the screen. Here is a list of the program's functions:

Log in new disk

New block

Rewrite block

Move to next block

Move to previous block

Move to next track

Move to previous track

Change byte under cursor

Text mode

Double side select

You should always perform a log in operation when you insert a new disk in the drive. After logging in a new disk, you should use the New block option to select the first block before using the + or keys to change blocks. The program disper track, and the number of tracks per disk. You need not precede this command with an Inquire Disk or Query Disk Format command.

Example: The following will format an MFM disk with ten 512-byte sectors per track on both sides.

10 OPEN 15, 8, 15 : B = DEC("3800"):POKE B + 19, 102 : POKE B + 22, 2
20 POKE B + 20, 128 : POKE B + 24, 10 : BANK 15 : SYS DEC("30EE"):END

FORMAT GCR

Purpose: Format a GCR disk

Call address: $30E4 (12516) in bank 12–15

Table address: $381C–$3821 (6 bytes)

Format: $381E: Control byte (must be $06)

$381F: Control byte (must be $00)

$3820–$3821: ID characters (can be any value)

Explanation: Formats a disk in Commodore GCR (Group Code Recording) format. This command operates the same as a normal format but does not write a directory to the disk.

Example: Format a GCR disk with an ID of GC

10 OPEN 15, 8, 15 : B = DEC("3800") : POKE B + 32, 71 : POKE B + 33, 67
20 POKE B + 30, 6 : POKE B + 31, 0 : BANK 15 : SYS DEC("30E4") : END

SECTOR INTERLEAVE

Purpose: Read or change the sector interleave factor used for multisector burst read and write

Call address: $30C4 (12484) in bank 12–15

Table address: $3822–$3825 (4 bytes)

Format: $3824: Control byte

bit 7 interleave read or write (0 = write interleave, l=read interleave)

bits 1–4 select command (0100 for sector interleave)

bit 0 same as Read Sector

$3825 Interleave (interleave to be written to the drive; $00 is normal)

Explanation: Reads or sets the interleave byte stored in the drive used for multisector reads or writes. The interleave byte is usually set to zero.

Example: Read and display the sector interleave.

10 OPEN 15, 8, 15 : BANK 15 : B = DEC("3800"):POKE B + 36, 136
20 SYS DEC("30C4") : SI = PEEK(250) : PRINT SI : END

QUERY DISK FORMAT

Purpose: Determine the disk format on the specified track

Call address: $3099 (12441) in bank 12–15

Table address: $3826–$3829 (4 bytes)

Format: $3828 Control byte:

bit 7 step head flag (0 = track 0)

bit 4 same as Read Sector

bits 1–3 select command (101 for Query Disk Format)

bit 0 same as Read Sector

$3829 Track offset (if bit 7 of $3828 is set to 1)

Explanation: Determines the format of any track on the disk. This command also logs in the disk so that it can be used. The status byte in $FA (250) is updated to indicate any errors, the sector size of the disk (128, 256, 512, or 1024), and the disk's format (MFM or GCR). For an MFM disk, the routine returns additional information about the format in locations $3700–$3704 (14080–14084). Location $3700 holds the number of sectors on the track; $3701 holds the logical track number on the track; and $3702 holds the minimum logical sector number (the sector with the lowest value address). Location $3703 holds the maximum logical sector number (the sector with the highest value address); $3704 holds the CP/M hard interleave found on the track. This data can be useful in finding the format of nonstandard MFM disks.

Example: Determine the format of track 10.

plays information about the format of the currently logged disk. The double side select operation lets you access the alternate side of a double-sided disk. You can't access the back side of an MFM disk by simply flipping it over, since that maneuver prevents the drive from finding the disk's index hole.

Burst Mode Utility

In addition to its use with Programs 1 and 2, Program 3 provides full access to the 1571's extra features—including burst mode commands—for anyone wishing to write disk-oriented programs. Although the program itself is written in machine language, you need not be a machine language expert to use it. All of the disk-handling routines can be accessed from BASIC with a SYS command. Of course, the routines can also be accessed from machine language if you wish.

Program 3 occupies memory locations 12288–12860 ($3000–$323C). Each burst utility command is activated by SYSing to a different location. For instance, the SYS address for the Query Disk Format routine is $3099 (12441). To execute this routine, you can perform either SYS 12441 or SYS DEC("3099").

Program 3 also uses a small command table which begins at location $3800 (14336). This table contains the actual commands which are sent to the drive to perform disk operations. To create the command table from BASIC, include the following lines in your program (this routine may be renumbered as needed):

1000 RESTORE : FOR I = DEC("3800") TO DEC("3800") + 16 * 3  1
1010 READ A$ : POKE I, DEC(AS) : NEXT I : RETURN
1020 DATA 55, 30, 00, 00, 01, 02, 01, 55, 30, 02, 00, 01, 02, 01, 55, 30
1030 DATA 04, 55, 30, 06, 81, 00, 02, 27, 0A, 00, 00, E5, 55, 30, 06, 00
1040 DATA 58, 58, 55, 30, 08, 00, 55, 30, 0A, 00, 55, 30, 8C, 00, 00, 00

You can also generate the command table by calling the GEN TABLE routine contained in Program 3 (see below).

Many of the special disk commands require that you pass some information to the drive along with the command itself. For example, when you wish to read the contents

10 OPEN 15, 8, 15 : BANK 15 : B = DEC("3800") : POKE B + 41, 10
20 POKE B + 40, 138 : SYS DEC("3099") : END

INQUIRE STATUS

Purpose: Read or write the status byte in the drive

Call address: $3075 (12405) in bank 12–15

Table address: $382A–$382D (4 bytes)

Format: $382C (14380) Control byte

bits 6–7 00 = write new status

01 = log in disk

10 = read status

11 = has disk been changed? ($FA contains $0B if changed)

bits 1=4 burst command (110 for Inquire Status)

bit 0 same as Read Sector

$382D (14381) New status (status sent to the drive if $382C bit 7 is 0)

Explanation: Reads or writes the status in the drive. The command can also be used to detect whether the disk has been swapped, and if it has, to log it in.

Example: Read and display the status from the drive.

10 OPEN 15, 8, 15 : BANK 15 : B = DEC("3800") : POKE B + 44, 140
20 SYS DEC("3075") : PRINT PEEK(250) : END

SENDCMD

Purpose: Send a command to the disk drive

Call address: $304A (12362) in bank 12–15

Table address: none

Format: none

Explanation: Sends a command to the disk drive. The Y and X registers must contain the high and low byte, respectively, of the address for the character string which comprises the command. The A register must contain the length of the command. This subroutine is called by all the burst utility commands. For the subroutine to function properly, the disk command channel must be open to logical file 15 (OPEN 15,8,15).

Example: Send a Query Disk Format command.

10 OPEN 15, 8, 15 : BANK 15 : SYS DEC("304A"), 4, 38, 56 : END

SPIN

Purpose: Prepares the serial bus for fast serial input

Call address: $3025(12325) in banks where the I/O block is visible (for example, bank 15)

Table address: none

Format: none

Explanation: For standard (slow) data transfers, the 128's serial bus is bidirectional—data is free to flow either in or out. However, the bus has extra circuitry to enforce the direction of data flow for fast (burst mode) transfers. This subroutine, intended for use by other burst utility routines, sets up the serial bus for fast input.

Example: Prepares bus for fast input.

10 SYS DEC("3025") : END

SPOUT

Purpose: Prepares the serial bus for fast serial output

Call address: $3000 (12288) in banks where the I/O block is visible (for example, bank 15)

Table address: none

Format: none

Explanation: See the explanation above for the SPIN routine. This routine sets up the serial bus for fast output.

Example: Prepares bus for fast output.

10 SYS DEC("3000"):END

of a sector, you must tell the drive which sector to read. The command table contains a storage area for each command. Before you activate a command with SYS, you must POKE the data needed by that command into the corresponding storage area for that command. The descriptions at the end of this article contain all the details you need to call the 14 routines provided by Program 3.

To see how this works, let's call the Read Sector routine. The description for this routine indicates that its storage area is at locations $3802–$3086. In addition to placing information in that area, you must indicate the starting and ending addresses of the memory area where you wish to store the data from the disk sector. The addresses are stored in locations $FB–$FC and $FD–FE, respectively, using standard low-byte/high-byte format. The following program segment calls Read Sector to read the contents of track 10, sector 1 into memory at $4000 (it assumes you are reading a GCR disk).

10 B = DEC("3800") : POKE251, 0 : POK E253, 0 : POKE252, 64 : POKE254, 65
20 POKE B + 3, 10 : POKE B + 4, 1 : POKE B + 5, 2
30 OPEN15, 8, 15 : BANK 15 : SYS DEC ("30F8") : END

Program 1: MFM Disk Copier

For instructions on entering this program, please refer to "COMPUTE!s Guide to Typing In Program" elsewhere in this issue.

CLKLO

Purpose: Set the serial bus clock line to a low state

Call Address: $3038 (12344) in banks where the I/O block is visible (for example, bank 15)

Table address: none

Format: none

Explanation: Sets the serial bus clock line output to a low state (0 volts). This subroutine is intended for use by other burst utility routines.

Example: Bus clock line output set to a low state.

10 SYS DEC("3038") : END

CLKHI

Purpose: Set the serial bus clock line to a high state

Call address: $3041 (12353) in banks where the I/O block is visible (for example, bank 15

Table address: none

Format: none

Explanation: Sets the serial bus clock line output to a high state (+5 volts). This subroutine is intended for use by other burst utility routines.

Example: Bus clock line output set to a high state.

10 SYS DEC("3041") : END

GEN TABLE

Purpose: Generates the command table at $3800 required for the other BURST subroutines

Call address: $3200 (12800) in banks with block 0 RAM

Table address: none

Format: none

Explanation: Creates the command table at $3800. The table can also be generated using the BASIC program shown above.

Example: Generates the command table at $3800.

10 SYS DEC("3200") : END