Apple II Technical Notes _____________________________________________________________________________ Developer Technical Support Pascal #12: Disk Formatter Routine Revised by: Cheryl Ewy & Dan Strnad November 1988 Revised by: Cheryl Ewy June 1985 This Technical Note documents the Apple II Pascal 1.3 Disk Formatter routine. _____________________________________________________________________________ Introduction Integrating the Pascal Disk Formatter utility into your application program will free the user from having to format Pascal disks prior to running your program. Error codes that specify any problems encountered during the formatting process are returned. The disk contains the following files: FORMATTER.TEXT is a sample Pascal host program that illustrates the use of the formatter routine. FORMDISK.TEXT is an assembly language function that is linked to your Pascal host program. It contains the code to format disks in ProDOS blocked devices and calls the ASMFORMAT function to format disks in Disk II drives. ASMFORMAT.TEXT is the Disk II formatter, an assembly language procedure that must be specially handled (see below). BOOTTRACKS.DATA is a data file that is used to create the formatter data file. It contains boot blocks for both Disk II drives and ProDOS blocked devices and a blank disk directory. MAKEFMT.TEXT, MAKEFMT.CODE are a Pascal program that will create the required formatter data file. FORMATTER.DATA is a complete formatter data file (identical to that supplied with the Apple II Pascal 1.3 Development System). FORMATTER.CODE is the formatter program supplied with the Apple II Pascal 1.3 Development System. All programs are supplied in source (and where appropriate, as code files) so that you may modify them for your own particular purposes. ASMFORMAT - The Disk II Formatter Routine The file ASMFORMAT.TEXT contains a proprietary subroutine that performs the actual formatting of Disk II disks. It is written in 6502 assembly language suitable for assembly by the Apple II or Apple /// Pascal Assembler. This code requires special handling by the host program to ensure a reliable format. It contains critical timing code, and because of this, it must be located on a page boundary in memory (a location of the form xx00, e.g., 3D00, 2000, etc.). To do this, it must be assembled ABSOLUTE and you must use ORG to place it on particular page boundary. It comes supplied at location 3D00, which is the location used by the formatter routine supplied with the Apple II Pascal 1.3 Development System (FORMATTER.CODE). If you need to move it to another particular location you must change the .ORG statement in the file to the new address. The formatter will not work reliably if it is not on a page boundary. The code itself is 1082 bytes in length. Because of the special nature of this code, it must be loaded by the Pascal host program at the chosen location. The following sample code illustrates how this is done: TYPE MEMARRAY = PACKED ARRAY [0..1535] OF 0..255; MEMPTR = RECORD CASE BOOLEAN OF TRUE: (ADDR: INTEGER); FALSE: (MEM: ^MEMARRAY); END; VAR LOADPTR: MEMPTR; {this is the pointer to the absolute memory location where the Disk II formatter routine will be loaded.} {the following code will load the Disk II formatter routine from the formatter data file into memory at a fixed location} RESET(DATAFILE, '%FORMATTER.DATA'); LOADPTR.ADDR := 15616; {this value is the absolute memory location where the code is to be loaded. In this example, 15316 is the decimal equivalent of the memory address 3D00.} BLOCKSREAD := BLOCKREAD(DATAFILE, LOADPTR.MEM^, 3); {the above line will load three blocks (the Disk II formatter code) from the data file into the memory space specified in LOADPTR} The Disk II formatter routine assumes that the A register has been setup with the slot number and drive number of the disk which is to be formatted. FORMDISK sets up this information before doing a JSR to the Disk II formatter routine. The contents of the A register are defined as follows: Bit 7 Drive number. 0=Drive 1, 1=Drive 2 Bits 6-4 Slot number. 100=4, 101=5, 110=6. No other slots are supported. Bits 3-0 Reserved; must be set to zero. After the Disk II formatter routine is called, it returns an error code in the A register. FORMDISK then returns this error code to the host program. The error codes are listed in the following section. FORMDISK - The Main Formatter Routine The file FORMDISK.TEXT is an assembly language function that is assembled and linked to your Pascal host program. This function determines whether the drive containing the disk to be formatted is a Disk II drive or a ProDOS blocked device. If it is a Disk II drive, FORMDISK invokes the Disk II formatter routine with the required parameters as described in the previous section. If the drive is a ProDOS blocked device, FORMDISK sets up the proper parameters and executes a format call to the device. FORMDISK will return an error code back to the Pascal host after the formatting is complete. The call to this function is shown below: VAR ERRCODE: INTEGER; {the error code returned} VOLNUM: INTEGER; {the volume (unit) number of the disk} ERRCODE := FORMDISK(VOLNUM); {the function call} There are six possible error codes returned by FORMDISK. They indicate problems that may have occurred during the formatting process. They are as follows: Error code Error Possible causes _____________________________________________________________________________ 00 No Error Formatting successfully completed 39 Unable to format the disk No disk in drive; drive door not closed; bad media 43 Disk is write-protected Disk is write-protected; disk is pushed halfway into drive, activating the write-protect switch 47 No disk in drive The disk drive is empty. This error is only reported for ProDOS block devices. If a Disk II drive is empty, error #39 is returned. 51 Drive speed is too slow The drive motor speed requires adjustment, it is too slow. This erroris only reported for Disk IIs. 52 Drive speed is too fast The drive motor speed requires adjustment, it is too fast. This error is only reported for Disk IIs. To use the FORMDISK function requires that you modify one .EQU statement in the source file (FORMDISK.TEXT) to specify the location of the Disk II formatter routine in memory. Currently, the statement reads as follows: DO_FORMAT .EQU 3D00 ;memory address of the Disk II formatter routine If you decide to relocate the Disk II formatter routine, simply change this value to reflect the new memory address, then reassemble FORMDISK. The FORMDISK function does a JSR to this value to invoke the Disk II formatter routine. Note: The value used in the .ORG in ASMFORMAT and the .EQU in FORMDISK must match. Making a Formatter Data File To use the formatter requires a data file that contains three pieces: 1. The Disk II formatter routine code, to be loaded into memory. 2. The boot code that is written to blocks 0 and 1 of the formatted disk. 3. A blank UCSD Pascal directory that is written to block 2 of the formatted disk. The formatter disk comes with the second and third parts in the file BOOTTRACKS.DATA. This four-block file contains the boot blocks for Disk II drives and ProDOS blocked devices and the blank directory. Once the Disk II formatter routine has been assembled (to ASMFORMAT.CODE) it must be concatenated to the BOOTTRACKS.DATA file to make the formatter data file. The Disk II formatter routine code occupies the first 3 blocks of the formatter data file, which is then followed by the contents of the BOOTTRACKS.DATA file. Because the assembler puts special informational content blocks into a code file, a special program is required to copy only the blocks containing the code of the Disk II formatter routine. This is the program MAKEFMT.CODE. This program copies blocks 1, 2, and 3 of ASMFORMAT.CODE to blocks 0, 1, and 2 of the file FORMATTER.DATA. It then copies blocks 0, 1, 2, and 3 of the file BOOTTRACKS.DATA to blocks 3, 4, 5, and 6 of the file FORMATTER.DATA. This makes the required formatter data file (7 blocks in size) that will be used by the Pascal host program. MAKEFMT requires that the files ASMFORMAT.CODE and BOOTTRACKS.DATA be on the prefix volume. Set the Pascal prefix to this volume and X(ecute MAKEFMT. It will create the file FORMATTER.DATA on the same volume. The source for this program is included so that you may modify it as needed. The Pascal Host Program It is up to you to write the Pascal host program. On the disk is a sample program (the Apple II Pascal 1.3 Formatter) that you may study. It illustrates the above techniques. The primary functions of the Pascal host are to: 1. Open the FORMATTER.DATA file. 2. Read blocks 0 - 2 into a memory location that is on a page boundary. 3. Read blocks 3 - 6 into a 2,048 byte buffer. 4. Call the assembly language function FORMDISK with the volume number of the drive containing the disk to be formatted. 5. Examine the error code returned. If there is an error then report it to the user, otherwise continue. 6. Use UNITSTATUS to determine whether the drive is a Disk II or a ProDOS blocked device and how many blocks are on the disk. 7. Use the number of blocks returned by UNITSTATUS to update the maximum block number information in the blank directory. 8. If the drive is a Disk II, use UNITWRITE to write blocks 0 - 2 from the buffer to blocks 0 - 2 on the newly formatted disk. 9. If the drive is a ProDOS blocked device, use UNITWRITE to write block 3 from the buffer to block 0 on the newly formatted disk, then use it again to write block 2 from the buffer to block 2 on the disk. The following code is an example of how to read in the blocks from the FORMATTER.DATA file, determine the drive type, update the directory, and write the boot blocks and directory to the newly formatted disk: TYPE BYTARRAY = PACKED ARRAY [0..1] OF 0..255; VAR BUFFER: PACKED ARRAY [0..2048] OF 0..255; NUMBLOCKS : INTEGER; TRIX : RECORD CASE BOOLEAN OF TRUE : (INT : INTEGER); FALSE : (BYT : BYTARRAY); END; {read in the boot blocks and directory} NUMBLOCKS := BLOCKREAD (DATAFILE, BUFFER, 4, 3); {determine type of disk drive and number of blocks on the disk} UNITSTATUS (VOLNUM, NUMBLOCKS, 1); {update maximum number of blocks in blank directory} TRIX.INT := NUMBLOCKS; BUFFER[1038] := TRIX.BYT[0]; BUFFER[1039] := TRIX.BYT[1]; {write out the boot blocks and directory to a Disk II disk} UNITWRITE (VOLNUM, BUFFER, 1536, 0); {write out the boot block and directory to a ProDOS blocked device disk} UNITWRITE (VOLNUM, BUFFER[1536], 512, 0); UNITWRITE (VOLNUM, BUFFER[1024], 512, 2); A dynamic variable can also be used as the buffer so that your program can reclaim the buffer space for its own use after the formatting is completed: TYPE BUFFER = PACKED ARRAY [0..2048] OF 0..255; VAR BUFPTR : ^BUFFER; OLDPTR : ^INTEGER; {mark the beginning of usable space} MARK (OLDPTR); {allocate space for the buffer} NEW (BUFPTR); {read in the boot blocks and directory} NUMBLOCKS := BLOCKREAD (DATAFILE, BUFPTR^, 4, 3); {write out the boot blocks and directory to a Disk II disk} UNITWRITE (VOLNUM, BUFPTR^, 1536, 0); {release the space used by the buffer} RELEASE (OLDPTR); In Review The following is a step-by-step review of how to use the formatting routine. 1. Determine where in memory you wish to load the Disk II formatter routine. Remember it must be on a page boundary. 2. Edit the file ASMFORMAT.TEXT, and change the value in the .ORG statement to be the memory address chosen. 3. Assemble ASMFORMAT.TEXT to ASMFORMAT.CODE. 4. X(ecute MAKEFMT to make the required FORMATTER.DATA file. 5. Edit the file FORMDISK.TEXT and change the line DO_FORMAT .EQU 3D00 to reflect the new memory location (same value as in the .ORG statement above). 6. Assemble FORMDISK.TEXT to FORMDISK.CODE. 7. Write the Pascal host program using the above techniques for loading the Disk II formatter routine, calling the FORMDISK function, updating the blank directory, and writing the boot blocks and directory. Remember error reporting. 8. Compile the Pascal host. 9. Link the Pascal host to the file FORMDISK.CODE, thus linking the FORMDISK function into your program. 10. With the linked Pascal host program and the FORMATTER.DATA file you can now format disks.