*********************************************************************
*                                 *            Movie:               *
*       ProDOS Hyper-FORMAT       *     ProDOS Hyper-FORMAT II      *
*                                 *           The Return            *
*     created by Jerry Hewett     *   Modified by Gary Desrochers   *
*         copyright  1985         *                                 *
*     Living Legends Software     *        Tryll Software           *
*                                 *                                 *
* A Public Domain disk formatting * A Puplic Domain Disk Formatting *
* routine for the ProDOS Disk Op- * You know the same as -------|   *
* erating System.  These routines *<----------------------------|   *
* can be included within your own * Except it now includes code for *
* software as long as you give us * the 3.5 Disk and the Ram3 Disk. *
* credit for developing them.     *  Please don't use this for any  *
*                                 * SmartPort volumes bigger than   *
*       Updated on: 23Aug85       * 2.1 Meg. Look under Hyper-FORMAT*
*                                 * in you local BB Library for the *
*********************************** original code for Hyper-FORMAT  *
;                                 *                                 *
         Keep   HypeForm          *      Updated on: 22Dec89        *
         65816 off                *                                 *
         65C02 off                ***********************************
Home     gequ  $FC58                    ;Monitor clear screen and home cursor
DevCnt   gequ  $BF31                    ;Prodos device count
DevList  gequ  $BF32                    ;List of devices for ProDOS
DevAdr   gequ  $BF10                    ;Given slot this is the address of driver
Buffer   Gequ  $0                       ;Address pointer for FORMAT data
CH       Gequ  $24                      ;Storage for Horizontal Cursor value
IN       Gequ  $200                     ;Keyboard input buffer
WARMDOS  Gequ  $BE00                    ;BASIC Warm-start vector
MLI      Gequ  $BF00                    ;ProDOS Machine Language Interface
LAST     Gequ  $BF30                    ;Last device accessed by ProDOS
STROUT   Gequ  $DB3A                    ;Applesoft's string printer
WAIT     Gequ  $FCA8                    ;Delay routine
CLRLN    Gequ  $FC9C                    ;Clear Line routine
RDKEY    Gequ  $FD0C                    ;Character input routine  (read keyboard)
PRBYTE   Gequ  $FDDA                    ;Print Byte routine (HEX value)
COUT     Gequ  $FDED                    ;Character output routine (print to screen)
Step0    Gequ  $C080                    ;Drive stepper motor positions
Step1    Gequ  $C081                    ;  |      |      |       |
Step2    Gequ  $C082                    ;  |      |      |       |
Step4    Gequ  $C084                    ;  |      |      |       |
Step6    Gequ  $C086                    ;  |      |      |       |
DiskOFF  Gequ  $C088                    ;Drive OFF  softswitch
DiskON   Gequ  $C089                    ;Drive ON   softswitch
Select   Gequ  $C08A                    ;Starting offset for target device
DiskRD   Gequ  $C08C                    ;Disk READ  softswitch
DiskWR   Gequ  $C08D                    ;Disk WRITE softswitch
ModeRD   Gequ  $C08E                    ;Mode READ  softswitch
ModeWR   Gequ  $C08F                    ;Mode WRITE softswitch
;**********************************************************
; Equates
;**********************************************************
         Org   $5000
HypForm  Start
         tsx
         stx   Stack
         LDA   LAST                     ;Store current slot/drive # in Slot
         STA   QSlot                    ;Save Prodos's last device accessed
         JSR   Home                     ;Clears screen
         jsr   MLI
         .byte $$42'
         .word NetParms'             ;Call for Appletalk which isn't wanted
         bcc   NotError
         cmp   #$01                     ;Even though everyone said that this
         beq   Reentry                  ; should happen I never could get it.
         cmp   #$04                     ;Got this but don't try to change the
         beq   Reentry                  ; parameter count to 1 or #$%@&*^()
NotError anop
         lda   NetDev
         jsr   HexDec
         LDA   #Appletalk               ;Prompt to continue or not
         LDY   #>Appletalk              ;because Appletalk is installed
         JSR   STROUT
         jsr   GetYN
         beq   Reentry
         jmp   MExit
Reentry  anop
         JSR   Home                     ;Clears screen
         LDA   #TargSlt                 ;Prompt for slot
         LDY   #>TargSlt
         JSR   STROUT
LSlot    JSR   RDKEY                    ;Get a keypress
         CMP   #$B0                     ;Less than slot #1?
         BCC   LSlot
         CMP   #$B8                     ;Greater than slot #7?
         BCS   LSlot
         STA   Buffer                   ;Store SLOT number in Buffer
         JSR   COUT                     ;Print it on the screen
         LDA   #TargDrv                 ;Prompt for drive
         LDY   #>TargDrv
         JSR   STROUT
LDrive   JSR   RDKEY                    ;Get a keypress
         CMP   #$B1                     ;Drive #1?
         BEQ   LConvert
         CMP   #$B2                     ;Drive #2?
         BNE   LDrive
LConvert STA   Buffer+1                 ;Store DRIVE number in Buffer+1
         JSR   COUT                     ;Print it on the screen
         JSR   DOTWO                    ;Print two carriage returns
         LDA   Buffer                   ;Fetch the SLOT number
         AND   #$0F                     ;Mask off the upper 4 bits
         rol   a                        ;Move lower 4 bits to upper 4 bits
         rol   a
         rol   a
         rol   a
         STA   Slot                     ;Store result in FORMAT slot
         tax
         LDA   Buffer+1                 ;Fetch the DRIVE number
         CMP   #$B1                     ;Does Slot need conditioning?
         Beq   Jump5                    ;Nope
Jump1    LDA   Slot                     ;Fetch FORMAT slot
         ORA   #$80                     ;Set MSB to indicate drive #2
         sta   Slot
         tax
Jump5    ldy   DevCnt                   ;Load how many devices
FLoop    lda   DevList,y                ; since this isn't a sequential
         sta   ListSlot                 ; list then must go through each one
         and   #$F0                     ; must also store what is there for later
         cmp   Slot
         beq   ItIsNum
         dey
         bpl   FLoop
         jmp   NoUnit                   ;Used to be bmi
ItIsNum  anop
         txa                            ;Make the slot the indexed register
         lsr   a                        ; for getting device drive controller
         lsr   a
         lsr   a
         tay
         lda   DevAdr,y                 ;Get it
         sta   Addr                     ; and save it
         lda   DevAdr+1,y
         sta   Addr+1
         tay
         and   #$F0                     ;Next see if it begins with a C0
         cmp   #$C0
         beq   YesSmart                 ; and if it does is a very smart device
         txa
         cmp   #$B0                     ;If it isn't smart test for /Ram
         beq   YesRam3
         clc
         ror   a
         ror   a
         ror   a
         ror   a
         and   #$07
         ora   #$C0
         sta   Addr+1                   ;if it isn't either then treat it as
         jmp   YesSmart1                ; smart and save what bank it is in.

YesRam3  anop
         lda   Addr+1                   ;If you think it is a /Ram then check
         cmp   #$FF                     ; the bits that tell you so.
         beq   Loop7                    ; Does the Address pointer start with FF
         jmp   NoUnit
Loop7    lda   Addr                     ; And end with 00
         cmp   #$00
         beq   Loop8
         jmp   NoUnit
Loop8    lda   ListSlot
         and   #$F3
         cmp   #$B3
         beq   Loop9
         jmp   NoUnit
Loop9    LDA   #ItIsRam3                ;Tell the preson that you think it is a
         LDY   #>ItIsRam3               ; /Ram and if they want to continue
         JSR   STROUT
         jsr   GetYN
         Bne   Jump2
         jsr   OldName
         jsr   Ram3Form
Jump2    jmp   AGain
YesSmart anop
         tya
         and   #$0F
         rol   a                        ;Move lower 4 bits to upper 4 bits
         rol   a
         rol   a
         rol   a
         STA   Slot                     ;Store result in FORMAT slot
YesSmart1 anop
         lda   Addr+1                   ;Check signiture bytes in the Cn page
         sta   Buffer+1                 ; for a smart device.
         lda   #$00
         sta   Buffer
         ldy   #$01
         lda   (Buffer),y
         cmp   #$20
         bne   NoUnit
         ldy   #$03
         lda   (Buffer),y
         bne   NoUnit
         ldy   #$05
         lda   (Buffer),y
         cmp   #$03
         bne   NoUnit
         ldy   #$FF
         lda   (Buffer),y
         cmp   #$00                     ;Apples DiskII
         beq   DiskII
         cmp   #$FF                     ;Wrong DiskII
         beq   NoUnit                   ; must be a smart device.
         ldy   #$07                     ;Test last signiture byte for the
         lda   (Buffer),y               ; Protocol Converter.
         cmp   #$00
         bne   NoUnit                   ;It isn't so its no device I know.
         LDA   #ItIsSmart               ;Tell them you think it is a SmartPort
         LDY   #>ItIsSmart              ; device. and ask if they want to Format.
         JSR   STROUT
         jsr   GetYN
         Bne   Jump3
         jsr   OldName                  ;Show old name and ask if proper Disk
         jsr   LName                    ;Get New name
         jsr   SmartForm                ;Jump too routine to format Smart Drive
         lda   ListSlot
         and   #$F0
         sta   Slot
         jsr   CodeWr                   ;Jump to routine to produce Bit map
         JMP   CATALOG                  ;Write Directory information to the disk
Jump3    jmp   Again


NoUnit   LDA   #UnitNone                ;Prompt to continue or not Because
         LDY   #>UnitNone               ;There is no unit number like that
         JSR   STROUT
         jsr   GetYN
         Bne   Jump4
         jmp   Reentry
Jump4    jmp   MExit

DiskII   anop
         LDA   #ItsaII                  ;Tell them you think it is a DiskII
         LDY   #>ItsaII
         JSR   STROUT
         jsr   GetYN
         Bne   Jump3
         LDA   #$18                     ;Set VOLblks to 280 ($118)
         LDX   #$01                     ; Just setting default settings
         ldy   #$00
         STA   VOLblks
         STX   VOLblks+1
         STY   VOLblks+2
         jsr   OldName                  ;Prompt for proper disk.
         jsr   LName                    ;Get new name
         jmp   DIIForm                  ;Format DiskII

LName    LDA   #VolName
         LDY   #>VolName
         JSR STROUT
LRdname  LDA   #$0E                     ;Reset CH to 14
         STA   CH
         LDX   #$00
         BEQ   LInput                   ;Always taken
LBackup  CPX   #0                       ;Handle backspaces
         BEQ   LRdname
         DEX
         LDA   #$88                     ;<--
         JSR   COUT
LInput   JSR   RDKEY                    ;Get a keypress
         CMP   #$88                     ;Backspace?
         BEQ   LBackup
         CMP   #$FF                     ;Delete?
         BEQ   LBackup
         CMP   #$8D                     ;C/R is end of input
         BEQ   LFormat
         CMP   #$AE                     ;(periods are ok...)
         BEQ   LStore
         CMP   #$B0                     ;Less than '0'?
         BCC   LInput
         CMP   #$BA                     ;Less than ':'?
         BCC   LStore                   ;Valid. Store the keypress
         AND   #$DF                     ;Force any lower case to upper case
         CMP   #$C0                     ;Less than 'A'?
         BEQ   LInput
         CMP   #$DB                     ;Greater than 'Z'?
         BCS   LInput
LStore   JSR   COUT                     ;Print keypress on the screen
         AND   #$7F                     ;Clear MSB
         STA   VOLnam,X                 ;Store character in VOLnam
         INX
         CPX   #$0E                     ;Have 15 characters been entered?
         BCC   LInput
LFormat  TXA                            ;See if default VOLUME_NAME was taken
         BNE   LSetLEN
WLoop    LDA   Blank,X                  ;Transfer 'BLANK' to VOLnam
         AND   #$7F                     ;Clear MSB
         STA   VOLnam,X
         INX
         CPX   #$05                     ;End of transfer?
         BCC   WLoop
         LDA   #$13                     ;Reset CH to 19
         STA   CH
LSetLEN  JSR   CLRLN                    ;Erase the rest of the line
         CLC
         TXA                            ;Add $F0 to Volume Name length
         ADC   #$F0                     ;Create STORAGE_TYPE, NAME_LENGTH byte
         STA   VOLlen
         rts

DIIForm  JSR   FORMAT                   ;Format the disk
         jsr   CodeWr                   ;Form Bitmap
         LDA   #Verif                   ;Ask if you want to Verify the Disk
         LDY   #>Verif
         JSR   STROUT
         JSR   GetYN                    ;Get a Yes or No answer to 'Verify?'
         Bne   BIIForm1
         jmp   VERIFY                   ;Answer was yes...
BIIForm1 JMP   CATALOG                  ;Write Directory information to the disk

CodeWr   LDA   #$81                     ;Set Opcode to WRITE
         STA   Opcode
**********************************
*                                *
* Write Block0 to disk           *
*                                *
**********************************
AskBlk0  LDA   #BootCode                ;Set MLIbuf to BootCode
         LDY   #>BootCode
         STA   MLIbuf
         STY   MLIbuf+1
         LDA   #$00                     ;Set MLIblk to 0
         STA   MLIblk
         STA   MLIblk+1
         JSR   CallMLI                  ;Write block #0 to target disk
**************************************
*                                    *
* Fill buffer $6800-$69FF with zeros *
* and prepare BitMap and Link blocks *
* for writing to disk                *
*                                    *
**************************************
Fill     anop
         lda   #$05                     ;Block 5 on Disk
         sta   MLIBlk
         LDA   #$00                     ;Set Buffer, MLIbuf to $6800
         LDX   #$68
         STA   MLIbuf
         STA   Buffer
         STX   MLIbuf+1
         STX   Buffer+1
         TAY                            ;Fill $6800-$69FF with zeros
         LDX   #$01                     ;Fill 2 pages of 256 bytes
LZero    STA   (Buffer),Y
         INY
         BNE   LZero
         INC   Buffer+1
         DEX
         BPL   LZero
         LDA   #$68                     ;Reset Buffer to $6800
         STA   Buffer+1
         LDA   #$05                     ;Length of DirTbl
         STA   Count
LLink    LDX   Count
         LDA   DirTbl,X                 ;Move Directory Link values into Buffer
         STA   $6802                    ;Store next Directory block #
         DEX
         LDA   DirTbl,X                 ;Fetch another # from DirTbl
         STA   $6800                    ;Store previous Directory block #
         DEX
         STX   Count
         JSR   CallMLI                  ;Write Directory Link values to disk
LDec     DEC   MLIblk                   ;Decrement MLI block number
         LDA   MLIblk                   ;See if MLIblk = 2
         CMP   #$02
         BNE   LLink                    ;Process another Link block
**********************************
*                                *
* Calculate BitMap Size and cndo *
*                                *
**********************************
BlkCount lda   VolBlks+1                ;Where # of blocks are stored
         ldx   VolBlks
         ldy   VolBlks+2                ;Can't deal with block devices this big
         bne   Jump10
         stx   Count+1                  ;Devide the # of blocks by 8 for bitmap
         lsr   a                        ; calculation
         ror   Count+1
         lsr   a
         ror   Count+1
         lsr   a
         ror   Count+1
         sta   Count+2
         jmp   BitMapCode
Jump10   pla                            ;Remove the address that the routine
         pla                            ; would have returned to
         lda   #$4D                     ;Make error Block size to large
         jmp   Died
BitMapCode anop
         lda   #%00000001               ;Clear first 7 blocks
         sta   (Buffer),y
         ldy   Count+1                  ;Original low block count value
         bne   jump11                   ;if it is 0 then make FF
         dey                            ;Make FF
         dec   Count+2                  ;Make 256 blocks less one
         sty   Count+1                  ;Make FF new low block value
Jump11   anop
         ldx   Count+2                  ;High Block Value
         bne   Jump15                   ;If it isn't equal to 0 then branch
         ldy   Count+1
         jmp   Jump19

Jump15   anop
         lda   #$69                     ;Set the adress of the upper part of
         sta   Buffer+1                 ; Block in bitmap being created
         lda   #%11111111
         ldy   Count+1                  ;Using the low byte count
Jump20   dey
         sta   (Buffer),y               ;Store them
         beq   Jump17
         jmp   Jump20
Jump17   anop
         dey                            ;Fill in first part of block
         lda   #$68
         sta   Buffer+1
Jump19   lda   #%11111111
         dey
         sta   (Buffer),y
         cpy   #$01                     ;Except the first byte.
         beq   Jump18
         jmp   jump19
Jump18   rts


*************************************
*                                   *
* VERIFY - Verify each block on the *
* disk, and flag bad ones in BITMAP *
*                                   *
*************************************
Verify   anop

         LDA   #$80                     ;Set Opcode to $80 (READ)
         STA   Opcode
         LDA   #$60                     ;Change Error to an RTS instruction
         STA   Error
         LDA   #$00                     ;Reset MLIbuf to $1000
         LDX   #$10
         STA   MLIbuf
         STX   MLIbuf+1
         STA   Count                    ;Set Count and Pointer to 0
         STA   Pointer
         STA   LBad                     ;Set bad block counter to 0
         STA   MLIblk                   ;Reset MLIblk to 0
         STA   MLIblk+1
LRead    JSR   CallMLI                  ;Read a block
         BCS   LError                   ;Update BitMap if error occurs
LIncBlk  CLC                            ;Add 1 to MLIblk
         INC   MLIblk
         BNE   LCheck
         INC   MLIblk+1
LCheck   INC   Count                    ;Add 1 to BitMap counter
         LDA   Count                    ;If Count > 7 then add 1 to Pointer
         CMP   #$08
         BCC   MDone
         LDA   #$00                     ;Reset Count to 0
         STA   Count
         INC   Pointer                  ;Add 1 to Pointer offset value
MDone    LDX   MLIblk                   ;See if we've read 280 blocks yet
         LDA   MLIblk+1
         BEQ   LRead
         CPX   #$18                     ;Greater than $118 (280) blocks read?
         BEQ   LResult                  ;Finished. Display results of VERIFY
         BNE   LRead                    ;Go get another block
LError   LDX   Count                    ;Use Count as offset into MapTbl
         LDA   BitTbl,X                 ;Fetch value for bad block number
         LDY   Pointer                  ;Use Pointer as offset into Buffer
         AND   (Buffer),Y               ;Mask value against BitMap value
         STA   (Buffer),Y               ;Store new BitMap value in Buffer
         CLC
         DEC   VOLblks                  ;Decrement # of blocks available
         BNE   LIncBad
         DEC   VOLblks+1
LIncBad  INC   LBad                     ;Add 1 to # of bad blocks found
         JMP   LIncBlk                  ;Get the next block on the disk
LResult  LDA   #$EA                     ;Change Error back to a ANOP instruction
         STA   Error
         LDA   LBad                     ;Find out if there were any bad blocks
         BEQ   LGood
         JSR   HEXDEC                   ;Convert hex number into decimal
         LDX   #$00
BLoop    LDA   IN,X                     ;Print the decimal Gequivalent of LBad
         CMP   #$31                     ;Don't print zeros...
         BCC   MNext
         JSR   COUT
MNext    INX
         CPX   #$03                     ;End of number?
         BCC   BLoop
         LDA   #Bad
         LDY   #>Bad
         JSR   STROUT
         JMP   CATALOG                  ;Write BitMap and Links to the disk
LGood    LDA   #Good
         LDY   #>Good
         JSR   STROUT
         JMP   CATALOG
LBad     .byte $00                        ;Number of bad blocks found
*************************************
*                                   *
* CATALOG - Build a Directory Track *
*                                   *
*************************************
Catalog  anop

         LDA   #$81                     ;Change Opcode to $81 (WRITE)
         STA   Opcode
         LDA   #$00                     ;Reset MLIbuf to $6800
         LDX   #$68
         STA   MLIbuf
         STX   MLIbuf+1
         LDX   #$06                     ;Write Buffer (BitMap) to block #6 on the disk
         STX   MLIblk
         STA   MLIblk+1
         JSR   Call2MLI                  ; Call for time and date
         jsr   MLI
         .byte $$82'
         .word 0'
         lda   $BF90                    Get them and save them into the
         sta   Datime                   ; Directory to be written.
         lda   $BF91
         sta   Datime+1
         lda   $BF92
         sta   Datime+2
         lda   $BF93
         sta   Datime+3
         LDY   #$2A                     ;Move Block2 information to $6800
CLoop    LDA   Block2,Y
         STA   (Buffer),Y
         DEY
         BPL   CLoop
         LDA   #$02                     ;Write block #2 to the disk
         STA   MLIblk
         JSR   Call2MLI
Again    anop
         LDA   #Nuther                  ;Display 'Format another' string
         LDY   #>Nuther
         JSR   STROUT
         JSR   GetYN                    ;Get a Yes or No answer
         BNE   MExit                    ;Answer was No...
         JMP   Reentry                  ;Format another disk
MExit    JSR   DOTWO                    ;Two final carriage returns...
         lda   QSlot
         sta   Last
         ldx   Stack                    ;Just because I am human to and might
         txs                            ;have messed up also.
         JMP   WARMDOS                  ;Exit to BASIC
Call2MLI anop
         jsr   CallMLI
         rts
***************************
*                         *
* GetYN - Get a Yes or No *
* answer from the user    *
*                         *
***************************
GetYN    anop

         JSR   RDKEY                    ;Get a keypress
         AND   #$DF                     ;Mask lowercase
         CMP   #$D9                     ;is it a Y?
         BEQ   LShow
         LDA   #$BE                     ;Otherwise default to "No"
LShow    JSR   COUT                     ;Print char, Z flag contains status
         CMP   #$D9                     ;Condition flag
         RTS
*************************************
*                                   *
* CallMLI - Call the MLI Read/Write *
* routines to transfer blocks to or *
* from memory                       *
*                                   *
*************************************
CallMLI  anop

         JSR   MLI                      ;Call the ProDOS Machine Langauge Interface
Opcode   .byte $$81'                  ;Default MLI opcode = $81 (WRITE)
         .word Parms'
         BCS   Error
         RTS
Error    anop                           ;(this will be changed to RTS by VERIFY)
         pla
         pla
         pla
         pla
         JMP   Died
**************************************
*                                    *
* DOTWO - Print two carriage returns *
*                                    *
**************************************

DOTWO    anop
         LDA   #$8D                     ;(we don't need an explanation, do we?)
         JSR   COUT
         JSR   COUT
         RTS
***********************************
*                                 *
* HEXDEC - Convert HEX to decimal *
*                                 *
***********************************

HEXDEC   anop
         STA   IN+20                    ;Store number in Keyboard Input Buffer
         LDA   #$00
         STA   IN+21
         LDY   #$02                     ;Result will be three digits long
DLoop    LDX   #$11                     ;16 bits to process
         LDA   #$00
         CLC
LDivide  ROL   a
         CMP   #$0A                     ;Value > or = to 10?
         BCC   LPlus
         SBC   #$0A                     ;Subtract 10 from the value
LPlus    ROL   IN+20                    ;Shift values in IN+20, IN+21 one bit left
         ROL   IN+21
         DEX
         BNE   LDivide
         ORA   #$B0                     ;Convert value to high ASCII character
         STA   IN,Y                     ;Store it in the input buffer
         sta   NetNum,y
         DEY
         BPL DLoop
         RTS
***********************************
*                                 *
* FORMAT - Format the target disk *
*                                 *
***********************************

Format   anop
         php
         sei
         LDA   Slot                     ;Fetch target drive SLOTNUM value
         PHA                            ;Store it on the stack
         AND   #$70                     ;Mask off bit 7 and the lower 4 bits
         STA   SlotF                    ;Store result in FORMAT slot storage
         TAX                            ;Assume value of $60 (drive #1)
         PLA                            ;Retrieve value from the stack
         BPL   LDrive1                  ;If < $80 the disk is in drive #1
         INX                            ;Set X offset to $61 (drive #2)
LDrive1  LDA   Select,X                 ;Set softswitch for proper drive
         LDX   SlotF                    ;Set X offset to FORMAT slot/drive
         LDA   DiskON,X                 ;Turn the drive on
         LDA   ModeRD,X                 ;Set Mode softswitch to READ
         LDA   DiskRD,X                 ;Read a byte
         LDA   #$23                     ;Assume head is on track 35
         STA   TRKcur
         LDA   #$00                     ;Destination is track 0
         STA   TRKdes
         JSR   SEEK                     ;Move head to track 0
         LDX   SlotF                    ;Turn off all drive phases
         LDA   Step0,X
         LDA   Step2,X
         LDA   Step4,X
         LDA   Step6,X
         LDA   TRKbeg                   ;Move TRKbeg value (0) to Track
         STA   Track
         JSR   BUILD                    ;Build a track in memory at $6700

*******************************
*                             *
* WRITE - Write track to disk *
*                             *
*******************************
Write    Entry
         JSR   CALC                     ;Calculate new track/sector/checksum values
         JSR   TRANS                    ;Transfer track in memory to disk
         BCS   DiedII                   ;If carry set, something died
MInc     INC   Track                    ;Add 1 to Track value
         LDA   Track                    ;Is Track > ending track # (TRKend)?
         CMP   TRKend
         BEQ   LNext                    ;More tracks to FORMAT
         BCS   DONE                     ;Finished.  Exit FORMAT routine
LNext    STA   TRKdes                   ;Move next track to FORMAT to TRKdes
         JSR   SEEK                     ;Move head to that track
         JMP   WRITE                    ;Write another track
DONE     LDX   SlotF                    ;Turn the drive off
         LDA   DiskOFF,X
         plp
         RTS                            ;FORMAT is finished. Return to calling routine
DiedII   PHA                            ;Save MLI error code on the stack
         JSR   Done
         PLA                            ;Retrieve error code from the stack
         JMP   Died                     ;Prompt for another FORMAT...

**************************************
*                                    *
* Died - Something awful happened to *
* the disk or drive. Die a miserable *
* death...                           *
*                                    *
**************************************
Died     anop
         cmp   #$4D                     ;Save MLI error code on the stack
         beq   RangeError
         cmp   #$27
         beq   DriveOpen
         cmp   #$2F
         beq   DiskError
         cmp   #$2B
         beq   Protected
         jmp   NoDied
RangeError LDA   #TooLarge
         LDY   #>TooLarge
         jmp   DiedOut
DiskError LDA   #NoDisk
         LDY   #>NoDisk
         jmp   DiedOut
DriveOpen LDA   #Dead
         LDY   #>Dead
         jmp   DiedOut
Protected LDA   #Protect
         LDY   #>Protect
         jmp   DiedOut
NoDied   PHA                            ;Save MLI error code on the stack
         LDA   #UnRecog
         LDY   #>UnRecog
         JSR   STROUT
         PLA                            ;Retrieve error code from the stack
         JSR   PRBYTE                   ;Print the MLI error code
         jmp   Again
DiedOut  JSR   STROUT
         JMP   Again                    ;Prompt for another FORMAT...
************************************
*                                  *
* TRANS - Transfer track in memory *
* to target device                 *
*                                  *
************************************

Trans    anop
         LDA   #$00                     ;Set Buffer to $6700
         LDX   #$67
         STA   Buffer
         STX   Buffer+1
         LDY   #$32                     ;Set Y offset to 1st sync byte (max=50)
         LDX   SlotF                    ;Set X offset to FORMAT slot/drive
         SEC                            ;(assum the disk is write protected)
         LDA   DiskWR,X                 ;Write something to the disk
         LDA   ModeRD,X                 ;Reset Mode softswitch to READ
         BMI   LWRprot                  ;If > $7F then disk was write protected
         LDA   #$FF                     ;Write a sync byte to the disk
         STA   ModeWR,X
         CMP   DiskRD,X
         NOP                            ;(kill some time for WRITE sync...)
         JMP   LSync2
LSync1   EOR   #$80                     ;Set MSB, converting $7F to $FF (sync byte)
         NOP                            ;(kill time...)
         NOP
         JMP   MStore
LSync2   PHA                            ;(kill more time... [ sheesh! ])
         PLA
LSync3   LDA   (Buffer),Y               ;Fetch byte to WRITE to disk
         CMP   #$80                     ;Is it a sync byte? ($7F)
         BCC   LSync1                   ;Yep. Turn it into an $FF
         NOP
MStore   STA   DiskWR,X                 ;Write byte to the disk
         CMP   DiskRD,X                 ;Set Read softswitch
         INY                            ;Increment Y offset
         BNE   LSync2
         INC   Buffer+1                 ;Increment Buffer by 255
         BPL   LSync3                   ;If < $8000 get more FORMAT data
         LDA   ModeRD,X                 ;Restore Mode softswitch to READ
         LDA   DiskRD,X                 ;Restore Read softswitch to READ
         CLC
         RTS
LWRprot  CLC                            ;Disk is write protected! (Nerd!)
         JSR   DONE                     ;Turn the drive off
         lda   #$2B
         pla
         pla
         pla
         pla
         JMP   Died                     ;Prompt for another FORMAT...
************************************
*                                  *
* BUILD - Build GAP1 and 16 sector *
* images between $6700 and $8000   *
*                                  *
************************************
Build    anop

         LDA   #$10                     ;Set Buffer to $6710
         LDX   #$67
         STA   Buffer
         STX   Buffer+1
         LDY   #$00                     ;(Y offset always zero)
         LDX   #$F0                     ;Build GAP1 using $7F (sync byte)
         LDA   #$7F
         STA   LByte
         JSR   LFill                    ;Store sync bytes from $6710 to $6800
         LDA   #$10                     ;Set Count for 16 loops
         STA   Count
LImage   LDX   #$00                     ;Build a sector image in the Buffer area
ELoop    LDA   LAddr,X                  ;Store Address header, info & sync bytes
         BEQ   LInfo
         STA   (Buffer),Y
         JSR   LInc                     ;Add 1 to Buffer offset address
         INX
         BNE   ELoop
LInfo    LDX   #$AB                     ;Move 343 bytes into data area
         LDA   #$96                     ;(4&4 encoded version of hex $00)
         STA   LByte
         JSR   LFill
         LDX   #$AC
         JSR   LFill
         LDX   #$00
YLoop    LDA   LData,X                  ;Store Data Trailer and GAP3 sync bytes
         BEQ   LDecCnt
         STA   (Buffer),Y
         JSR   LInc
         INX
         BNE   YLoop
LDecCnt  CLC
         DEC   Count
         BNE   LImage
         RTS                            ;Return to write track to disk (WRITE)
LFill    LDA   LByte
         STA   (Buffer),Y               ;Move A register to Buffer area
         JSR   LInc                     ;Add 1 to Buffer offset address
         DEX
         BNE   LFill
         RTS
LInc     CLC
         INC   Buffer                   ;Add 1 to Buffer address vector
         BNE   LDone
         INC   Buffer+1
LDone    RTS
***********************************
*                                 *
* CALC - Calculate Track, Sector, *
* and Checksum values of the next *
* track using 4&4 encoding        *
*                                 *
***********************************
Calc     anop

         LDA   #$03                     ;Set Buffer to $6803
         LDX   #$68
         STA   Buffer
         STX   Buffer+1
         LDA   #$00                     ;Set Sector to 0
         STA   Sector
ZLoop    LDY   #$00                     ;Reset Y offset to 0
         LDA   #$FE                     ;Set Volume # to 254 in 4&4 encoding
         JSR   LEncode
         LDA   Track                    ;Set Track, Sector to 4&4 encoding
         JSR   LEncode
         LDA   Sector
         JSR   LEncode
         LDA   #$FE                     ;Calculate the Checksum using 254
         EOR   Track
         EOR   Sector
         JSR   LEncode
         CLC                            ;Add 385 ($181) to Buffer address
         LDA   Buffer
         ADC   #$81
         STA   Buffer
         LDA   Buffer+1
         ADC   #$01
         STA   Buffer+1
         INC   Sector                   ;Add 1 to Sector value
         LDA   Sector                   ;If Sector > 16 then quit
         CMP   #$10
         BCC   ZLoop
         RTS                            ;Return to write track to disk (WRITE)
LEncode  PHA                            ;Put value on the stack
         LSR   a                        ;Shift everything right one bit
         ORA   #$AA                     ;OR it with $AA
         STA   (Buffer),Y               ;Store 4&4 result in Buffer area
         INY
         PLA                            ;Retrieve value from the stack
         ORA   #$AA                     ;OR it with $AA
         STA   (Buffer),Y               ;Store 4&4 result in Buffer area
         INY
         RTS
*************************************
*                                   *
* SEEK - Move head to desired track *
*                                   *
*************************************
Seek     anop

         LDA   #$00                     ;Set InOut flag to 0
         STA   LInOut
         LDA   TRKcur                   ;Fetch current track value
         SEC
         SBC   TRKdes                   ;Subtract destination track value
         BEQ   LExit                    ;If = 0 we're done
         BCS   LMove
         EOR   #$FF                     ;Convert resulting value to a positive number
         ADC   #$01
LMove    STA   Count                    ;Store track value in Count
         ROL   LInOut                   ;Condition InOut flag
         LSR   TRKcur                   ;Is track # odd or even?
         ROL   LInOut                   ;Store result in InOut
         ASL   LInOut                   ;Shift left for .Table offset
         LDY   LInOut
ALoop    LDA   LTable,Y                 ;Fetch motor phase to turn on
         JSR   PHASE                    ;Turn on stepper motor
         LDA   LTable+1,Y               ;Fetch next phase
         JSR   PHASE                    ;Turn on stepper motor
         TYA
         EOR   #$02                     ;Adjust Y offset into LTable
         TAY
         DEC   Count                    ;Subtract 1 from track count
         BNE   ALoop
         LDA   TRKdes                   ;Move current track location to TRKcur
         STA   TRKcur
LExit    RTS                            ;Return to calling routine
**********************************
*                                *
* PHASE - Turn the stepper motor *
* on and off to move the head    *
*                                *
**********************************

Phase    anop
         ORA   SlotF                    ;OR Slot value to PHASE
         TAX
         LDA   Step1,X                  ;PHASE on...
         LDA   #$56                     ;20 ms. delay
         JSR   WAIT
         LDA   Step0,X                  ;PHASE off...
         RTS
**********************************
*                                *
* Format a Ram3 device.          *
*                                *
**********************************
Ram3Form anop
         php
         sei
         lda   #3                       ;Format Request number
         sta   $42
         Lda   slot                     ;Slot of /Ram
         sta   $43
         lda   #$00                     ;Buffer space if needed Low byte
         sta   $44
         lda   #$67                     ; and high byte
         sta   $45

         lda   $C08B                    ;Read and write Ram, using Bank 1
         lda   $C08B

         jsr   Ram3Dri
         bit   $C082                    ;Read ROM, use Bank 2(Put back on line)
         bcs   Ram3Err
         plp
         rts

Ram3Dri  jmp   (Addr)
Ram3Err  anop
         tax
         plp
         pla
         pla
         txa
         jmp   Died
**********************************
*                                *
* Format a SmartPort Device      *
*                                *
**********************************
SmartForm anop
         Php
         sei
         lda   #0                       ;Request Protocol converter for a Status
         sta   $42
         Lda   ListSlot                 ;Give it the ProDOS Slot number
         and   #$F0
         sta   $43
         lda   #$00                     ;Give it a buffer may not be needed by
         sta   $44                      ; give it to it anyways
         lda   #$68
         sta   $45
         lda   #$03                     ;The Blocks of Device
         sta   $46
         jsr   SmartDri
         txa                            ;Low in X register
         STA   VOLblks                  ; Save it
         tya                            ; High in Y register
         STa   VOLblks+1                ; Save it
         LDa   #$00
         STa   VOLblks+2
         lda   #3                       ;Give Protocol Converter a Format Request
         sta   $42                      ;Give it Slot number
         Lda   ListSlot
         and   #$F0
         sta   $43
         lda   #$00                     ;Give a buffer which probably won't be
         sta   $44                      ; used.
         lda   #$68
         sta   $45

         jsr   SmartDri
         bcs   SmartErr
         plp
         rts

SmartDri jmp   (Addr)
SmartErr anop
         tax
         plp
         pla
         pla
         txa
         jmp   Died

**********************************
*                                *
* Is there an old name?          *
*                                *
**********************************
OldName  anop
         lda   ListSlot
         and   #$F0
         STA   Info+1
         jsr   MLI
         .byte $$C5'
         .word Info'
         lda   VolLen
         and   #$0F
         bne   OldName1
         lda   VolLen+1
         cmp   #$28
         bne   OldError
         pla
         pla
         jmp   NoUnit
OldName1 sta   VolLen
         LDA   #TheOld1
         LDY   #>TheOld1
         JSR   STROUT
         lda   #VolLen                  ;Get Name Length
         ldy   #>VolLen
         jsr   Strout                   ;Print old name
         LDA   #TheOld2
         LDY   #>TheOld2
         JSR   STROUT
         jsr   GetYN
         beq   OldError
         pla
         pla
         jmp   Again
OldError anop
         rts

*************************
*                       *
* Variable Storage Area *
*                       *
*************************

Info:     .byte $02
          .byte $00
          .word VolLen
Parms:    .byte $03											;Parameter count = 3
Slot:     .byte $60											;Default to S6,D1
MLIbuf:   .word BootCode										;Default buffer address
MLIblk:   .word $0000											;Default block number of 0
QSlot:    .byte $00											;Quit Slot number
ListSlot: .byte $00											;Saving the slot total from the list
Addr:     .byte $00, $00
NetParms: .byte $00
          .byte $2F											;Command for FIListSessions
          .word $0000											;Appletalk Result Code returned here
          .word $100											;Length of string
          .word $6700											;Buffer low word
          .word $0000											;Buffer High word
NetDev:   .byte $00											;Number of entries returned here
LByte:    .byte $00											;Storage for byte value used in Fill
LAddr:    .byte $D5, $AA, $96										;Address header
          .byte $AA, $AA, $AA, $AA, $AA, $AA, $AA, $AA							;Volume #, Track, Sector, Checksum
          .byte $DE, $AA, $EB										;Address trailer
          .byte $7F, $7F, $7F, $7F, $7F, $7F								;GAP2 sync bytes
          .byte $D5, $AA, $AD										;Buffer header
          .byte $00											;End of Address information
LData:    .byte $DE, $AA, $EB										;Data trailer
          .byte $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F, $7F		;GAP3 sync bytes
          .byte $00											;End of Data information

LInOut:   .byte $00											;Inward/Outward phase for stepper motor
LTable:   .byte $02, $04, $06, $00									;Phases for moving head inward
          .byte $06, $04, $02, $00									;   |    |    |      |  outward

TargSlt:  dc    H'8D8D'
          dc    C'Format disk in SLOT ',H'00'
TargDrv:  dc    C' DRIVE ',H'00'
VolName:  dc    H'8D',C'Volume name: /'
Blank:    dc    C'BLANK'
          dc    C'__________',H'00'
Verif:    dc    H'8D 8D',C'Certify disk and mark any bad blocks in '
          dc    C'the Volume BitMap as unusable? (Y/N): ',H'00'
TheOld1:  dc    H'8D',C'Do You Want To Write Over',H'8D A0 AF 00'
TheOld2:  dc    H'A0 BF',C' (Y/N)',H'00'
UnRecog:  dc    H'8D',C'Unrecognisable ERROR = ',H'00'
Dead:     dc    H'8D',C'-- Check disk or drive door --',H'00'
Protect:  dc    H'8D',C'Disk is write protected, you bozo!',H'00'
Bad:      dc    H'8D 8D',C' bad block(s) marked',H'00'
Good:     dc    H'8D 8D',C'Disk is error-free',H'00'
NoDisk:   dc    H'8D',C'No Disk in the drive',H'00'
Nuther:   dc    H'8D 8D',C'Format another disk? (Y/N): ',H'00'
TooLarge: dc    H'8D',C'Unit Size Is To Large For this Program',H'00'
UnitNone: dc    H'8D',C'No Unit in that slot and drive',H'8D'
          dc    C'Format another disk? (Y/N): ',H'00'
ItIsRam3: dc    H'8D',C'This is a Ram3 disk',H'8D'
          dc    C'Continue with Format? (Y/N): ',H'00'
ItsaII:   dc    H'8D',C'This is a Disk II',H'8D'
          dc    C'Continue with Format? (Y/N): ',H'00'
ItIsSmart: dc   H'8D',C'This is a SmartPort device',H'8D'
          dc    C'Continue with Format? (Y/N): ',H'00'
Appletalk: dc    H'8D',C'Number of Appletalk devices is = '
NetNum:   dc    H'00 00 00 8D',C'AppleTalk is installed this Program may',H'8D'
          dc    C'not work properly do you want to',H'8D'
          dc    C'Continue (Y/N)',H'00'
Block2:   dc    H'00 00 03 00'
VOLlen:   .byte $00                        ;$F0 + length of Volume Name
VOLnam:   .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00           28          ;Volume Name, Reserved, Creation, Version
Reserved: .byte $00, $00, $00, $00, $00, $00
UpLowCase: .byte $00, $00
Datime:   .byte $00, $00, $00, $00
Version:  dc    H'01'
          dc    H'00 C3 27 0D'
          dc    H'00 00 06 00'
VOLblks:  .byte $00, $00, $00                        ;Number of blocks available
DirTbl:   dc    H'02 04 03'              ;Link list for directory blocks
          dc    H'05 04 00'
BitTbl:   .byte %01111111              ;BitMap mask for bad blocks
          .byte %10111111
          .byte %11011111
          .byte %11101111
          .byte %11110111
          .byte %11111011
          .byte %11111101
          .byte %11111110
Stack:    .byte $00                        ;Entrance stack pointer
Count:    .byte $00, $00, $00                        ;General purpose counter/storage byte
Pointer:  .byte $00, $00                        ;Storage for track count (8 blocks/track)
Track:    .byte $00, $00                        ;Track number being FORMATted
Sector:   .byte $00, $00                        ;Current sector number (max=16)
SlotF:    .byte $00, $00                        ;Slot/Drive of device to FORMAT
TRKcur:   .byte $00, $00                        ;Current track position
TRKdes:   .byte $00, $00                        ;Destination track position
TRKbeg:   .byte $00                   ;Starting track number
TRKend:   .byte $35                   ;Ending track number
BootCode: .byte $01, $38, $B0, $03, $4C, $32, $A1, $86, $43, $C9, $03, $08, $8A, $29, $70, $4A, $4A, $4A, $4A, $09, $C0, $85, $49, $A0
          .byte $FF, $84, $48, $28, $C8, $B1, $48, $D0, $3A, $B0, $0E, $A9, $03, $8D, $00, $08, $E6, $3D, $A5, $49, $48, $A9, $5B, $48
          .byte $60, $85, $40, $85, $48, $A0, $63, $B1, $48, $99, $94, $09, $C8, $C0, $EB, $D0, $F6, $A2, $06, $BC, $1D, $09, $BD, $24
          .byte $09, $99, $F2, $09, $BD, $2B, $09, $9D, $7F, $0A, $CA, $10, $EE, $A9, $09, $85, $49, $A9, $86, $A0, $00, $C9, $F9, $B0
          .byte $2F, $85, $48, $84, $60, $84, $4A, $84, $4C, $84, $4E, $84, $47, $C8, $84, $42, $C8, $84, $46, $A9, $0C, $85, $61, $85
          .byte $4B, $20, $12, $09, $B0, $68, $E6, $61, $E6, $61, $E6, $46, $A5, $46, $C9, $06, $90, $EF, $AD, $00, $0C, $0D, $01, $0C
          .byte $D0, $6D, $A9, $04, $D0, $02, $A5, $4A, $18, $6D, $23, $0C, $A8, $90, $0D, $E6, $4B, $A5, $4B, $4A, $B0, $06, $C9, $0A
          .byte $F0, $55, $A0, $04, $84, $4A, $AD, $02, $09, $29, $0F, $A8, $B1, $4A, $D9, $02, $09, $D0, $DB, $88, $10, $F6, $29, $F0
          .byte $C9, $20, $D0, $3B, $A0, $10, $B1, $4A, $C9, $FF, $D0, $33, $C8, $B1, $4A, $85, $46, $C8, $B1, $4A, $85, $47, $A9, $00
          .byte $85, $4A, $A0, $1E, $84, $4B, $84, $61, $C8, $84, $4D, $20, $12, $09, $B0, $17, $E6, $61, $E6, $61, $A4, $4E, $E6, $4E
          .byte $B1, $4A, $85, $46, $B1, $4C, $85, $47, $11, $4A, $D0, $E7, $4C, $00, $20, $4C, $3F, $09, $26, $50, $52, $4F, $44, $4F
          .byte $53, $20, $20, $20, $20, $20, $20, $20, $20, $20, $A5, $60, $85, $44, $A5, $61, $85, $45, $6C, $48, $00, $08, $1E, $24
          .byte $3F, $45, $47, $76, $F4, $D7, $D1, $B6, $4B, $B4, $AC, $A6, $2B, $18, $60, $4C, $BC, $09, $A9, $9F, $48, $A9, $FF, $48
          .byte $A9, $01, $A2, $00, $4C, $79, $F4, $20, $58, $FC, $A0, $1C, $B9, $50, $09, $99, $AE, $05, $88, $10, $F7, $4C, $4D, $09
          .byte $AA, $AA, $AA, $A0, $D5, $CE, $C1, $C2, $CC, $C5, $A0, $D4, $CF, $A0, $CC, $CF, $C1, $C4, $A0, $D0, $D2, $CF, $C4, $CF
          .byte $D3, $A0, $AA, $AA, $AA, $A5, $53, $29, $03, $2A, $05, $2B, $AA, $BD, $80, $C0, $A9, $2C, $A2, $11, $CA, $D0, $FD, $E9
          .byte $01, $D0, $F7, $A6, $2B, $60, $A5, $46, $29, $07, $C9, $04, $29, $03, $08, $0A, $28, $2A, $85, $3D, $A5, $47, $4A, $A5
          .byte $46, $6A, $4A, $4A, $85, $41, $0A, $85, $51, $A5, $45, $85, $27, $A6, $2B, $BD, $89, $C0, $20, $BC, $09, $E6, $27, $E6
          .byte $3D, $E6, $3D, $B0, $03, $20, $BC, $09, $BC, $88, $C0, $60, $A5, $40, $0A, $85, $53, $A9, $00, $85, $54, $A5, $53, $85
          .byte $50, $38, $E5, $51, $F0, $14, $B0, $04, $E6, $53, $90, $02, $C6, $53, $38, $20, $6D, $09, $A5, $50, $18, $20, $6F, $09
          .byte $D0, $E3, $A0, $7F, $84, $52, $08, $28, $38, $C6, $52, $F0, $CE, $18, $08, $88, $F0, $F5, $BD, $8C, $C0, $10, $FB, $00
          .byte $00, $00, $00, $00, $00, $00, $00, $00
