    Disk Driver Routines
	        for 
	OSI's Disk Basic
	        in RAM
			
	
	Commented by Chris McIntosh May, 1980		
	    


   
    The following is a brief description of how the chips used to
    read and write to the disc drives are initialized and programmed.
    Only the options used by OSI will be explained here although the
    chips can be programmed for many other options.
    
    The chip used by OSI (6820 PIO chip) to read and write to the
    disk drive has two ports with three registers for each port,
    making six registers in the chip in total. Only four of these
    resisters can be specified, however, which means that some extra
    Programming has to be done. The six registers are listed below:

    CRA       - controls interrupt handling and handshaking, Bit 2
              selects DRA or DDRA as follows:
    
                0 selects DDRA
                1 selects DRA
    
    DRA       - if Port A set for input (normally the case)
              indicates status of disk drive.
    DDRA      - controls whether data on the data bus is to be
              input or output (A normally set for input).
    
    CRB       - same as CRA. Bit 2 selects DRB or DDRB in the
              manner described above for CRA.
    
    DRB       - if Port B set for output (normally the     
              case) used to control the disk drive.
    
    DDRB      -controls whether data on the data bus is to      
              be input or output (B normally set for            
              output).
    
    The addresses of the above registers are listed below:
    
    CRA  -C001
    DRA  -C000 (if bit 2 of C001 is set)
    DDRA -C000 (if bit 2 of C001 is clear)
    CRB  -C003 
    DRB  -C002 (if bit 2 of C003 is set) 
    DDRB -C002 (if bit 2 of C003 is clear)
    
    When the BREAK and D keys are hit, code in ROM is executed to
    initialize port A for input and port B for output. This can be
    done with the following code:
    
    LDA #0
    STA $C001     ;select DDRA.
    STA $C000     ;0's in DDRA indicate input.
    LDA #4
    STA $C001     ;select DRA. Any LDA's from $COOO
                  ;will read data from DRA.
    LDA #0
    STA $C003     ;select DDRB.
    LDA #$FF
    STA $CO02     ;1's in DDRB indicate output.
    LDA #4        ;select DRB, Any STA's to $C002
                  ;will write data to DRB.
    
  

       After DRA has been initialized for input with code similar
       to that above, the status of the disk drive can be
       determined reading from location C000. The following
       table can be used to determine what the various bits in this
       location mean, Only the bits used by OSI are explained.

        BIT          OFF (CLEAR)                            ON (SET)
        ----         ------------                           --------

           0         drive 1 reads                          drive 1 not ready
           1         head above track 0                     not above track 0
           4         drive 2 reads                          drive 2 not ready
           5         disk write protected                   disk is read/write
           6         select drive 2                         select drive 1
           7         above index hole                       not above index hole

      After DRB has been initialized for output with code similar
      to that above, the disk drive can be controlled by writing
      to location C002. The following  table indicates what bits the various
      bits in this location control

        BIT          OFF (CLEAR)                            ON (SET)
        ----         ------------                           --------
           0         write to disk                          read from disk
           1                                                erase enable; keep on        
           2         direction = to track 39                direction = to track 0
           3         move a track (movement                 get ready to move
                     occurs when this bit is
                     changed from 1 to 0)
           4                                                fault reset; keep on
           5         turn drive off                         turn drive on
           6                                                low current; keep on
           7         put head on disk                       lift head from disk

     The other two addresses used are the address of the disk status and the data
     registers. These are:

      C010  -            disk status location. Only two numbers are                                                                                                                                                                                                                                                                                                disk status location. Only two numbers are
                         written to this location by OSI.
                         $03     master reset; resets the whole chip.
                         $58     selects 8 bits, even parity, 1 stop bit.
                                 Disables transmit interrupt logic
                                 disables receive interrupt logic.

                        The only bits read are bits 0, 1 and 6:
                        bit  0 set - read buffer full; data reads
                                     to be read from data register.
                        bit  1 set - write buffer empty; data can
                                     be written to data register.
                        bit  6 set - a parity error occurred when
                                     the last byte was read from C011
                        

       C011  -          this location is the disk data register. A
                        byte is read from disk by 'LDA C001' when
                        bit 0 of COlO is set; a byte is written to
                        disk by `STA CO1l' when bit 1 of C010 is set.
            
            Below follows a disassembled and commented copy of OSI's
            Floppy Disk Driver routines, The code starts at. location
            2663, The comments above will hopefully make some of what
            follows more understandable.
            
	    ;--------------------------------------------
            ; START OF DISK DRIVERS.
            ;--------------------------------------------
            ;
            ;--------------------------------------------            
            ; ROUTINE TO GO TO TRACK 0
            ;--------------------------------------------
            
            2663 208A26 JSR $268A ;move 1 track towards track 39
            ;
            2666 207826 JSR  $2678   ;wait loop subroutine
            ;
            2669 8C5D26 STY  $265D   ;$265D=track head is above. Set to 0.
            ;
            266C A902   LDA  #$02    ;if on track 0, go into
            266E 2C00C0 BIT  $C000   ;wait loop, then return
            2671 F005   BEQ  $2678   ;to calling program
            ;
            2673 208326 JSR  $2683   ;if not, set direction for track 0,
            2676 F0F4   BED  $266C   ;move a track, wait, and loop back
            ;
            2678 A2OC   LDX  #$0C    ;wait loop subroutine. A JSR $2678
            267A A0C7   LDY  #$C7    ;will set both X (outer decrement)
            267C 88     DEY          ;and Y (inner decrement). If a
            267D D0FD   BNE  $267C   ;longer or shorter wait is wanted
            267F CA     DEX          ;the user can set X themselves
            2680 D0F8   BNE  $267A   ;and JSR $267A
            2682 60     RTS
            ;
            2683 AD02C0 LDA  $C002   ;set direction towards track 0,
            2686 0904   ORA  #$04    ;jump to store & wait routines
            2688 D005   BNE  $268F
            ;
            268A A9FB   LDA  $$FB    ;set direction towards track 39,
            268C 2D02C0 AND  $C002   ;store head direction below
            ;
            268F 8D02C0 STA  $C002   ;store head direction
            2692 208226 JSR  $2682   ;short wait
            ;
            2695 29F7   AND  #$F7    ;move over one track
            2697 8D02C0 STA  $C002
            269A 208226 JSR  $2682   ;short wait loop
            269D 0908   ORA  #$08    ;reset bit 3 to 1. ready for
            269F 8D02C0 STA  $C002   ;next move when it changes to a 0
            ;
            26A2 A208   LDX  #$08    ;set `outer' decrement value and
            26A4 D0D4   BNE $267A    ;jump to wait routine, then return
            
            ;--------------------------------------------
            ; MOVE DISK HEAD TO DECIMAL TRACK NUMBER 
            ; STORED IN LOCATION $2662
            ;--------------------------------------------                                        
            26A6 AD6226 LDA $2662    ;Load track no. for USR(X) routine
            ;
            26A9 38     SEC          ;convert decimal track number
            26AA A2FF   LDX #$FF     ;in accumulator into BCD,
            26AC ES     INX          ;store in location IFA
            26AD E9OA   SBC #$0A     ;and put on the stack
            26AF BOFB   BCS $26AC
            26B1 690A   ADC #$0A
            26B3 85FA   STA $FA
            26B5 BA     TXA
            26B6 0A     ASL A
            26B7 0A     ASL A
            26B8 0A     ASL A
            26B9 0A     ASL A
            26BA 05FA   ORA $FA
            26BC B5FA   STA $FA
            26BE 48     PHA
            ;
            26BF 2C9E26 BIT $269E    ; if low digit less than 8,
            26C2 F004   BEQ $26C8    ;perform next validity check
            ;					    
            26C4 2906   AND #$06     ;it low digit treater than 9 (ie. a
            26C6 D005   BNE $26CD    ;hex digit), loto ERROR #8 routine
            ;					    
            26C8 68     PLA          ; if track # less than 40, OK
            26C9 C940   CMP #$40
            26CB 9004   BCC $26D1   
            ;					    
            26CD A908   LDA #$08     ;load return code (B in this case)
            26CF D00D   BNE $26DE    ; and Jump to ERROR routine
            ;					    
            26D1 AD5C26 LDA $265C    ; load disk drive number
            26D4 2901   AND $#01     ;( 0=drive 1, 2=drive 2)
            ;					    
            26D6 A8     TAY          ;see if disk is ready
            26D7 20DA29 JSR $29DA   
            ;					    
            26DA 9005   BCC $26E1    ;it ready, continue at $26E1
            ;					    
            26DC A906   LDA #$06     ;not ready, load return code (6=disk
            26DE 4C4B2A JMP $2A4B    ;not ready), Jump to ERROR routine
            ;					    
            26E1 F8     SED          ;compare $FA (track you want) with
            26E2 A6FA   LDX $FA      ;$265D (track head is above).
            2614 ECSD26 CPX $265D    ;if equal, clean up and return
            26E7 F01C   BED $2705   
            ;					    
            26E9 B00D   BCS $26F8    ;if low, move towards track 39
            ;					    
            26EB A999   LDA #$99     ;track you are above is too high,
            26ED 6D5D26 ADC $265D    ;subtract 1 from $265D (points to
            26F0 8D5D26 STA $265D    ;track head is above) and move
            26F3 208326 JSR $2683    ;one more track towards track 0
            ;					    
            26F6 FOE9   BEQ $26E1    ;loop to see if above correct track
            ;					    
            26F8 A900   LDA #$00     ;track you are above is too low,
            26FA 6D5D26 ADC $265D    ;add 1 (carry is set) to $265D (points
            26FD 8D5D26 STA $265D    ;to track head is above) and move
            2700 208A26 JSR $268A    ;one more track towards track 39
            ;
            2703 FODC   BEQ $26E1    ;loop to see if above correct track
            ;					    
            2705 D8     CLD          ;finished. Clear decimal mode,
            2706 4C7826 JMP $2678    ;go to wait loop, and return.
            ;
            ;--------------------------------------------------; 
            ;  SELECT CORRECT CURRENT (HIGH OR LOW)            ;
            ;  DEPENDING ON WHETHER DISK HEAD OVER A           ;
            ;  TRACK <= TRACK 42 OR A TRACK > TRACK 42.        ;
            ;---------------------------------------------------
            ;                                                    
            2709 ADO2CO LDA $C002
            270C A242   LDX #$42
            270E EC5D26 CPX $265D    ;see if disk head on a track
            2711 9004   BCC $2717    ;less than or Greater than 42
            2713 0940   ORA #$40     ;head <= track 42, set current bit
            2715 D002   BNE $2719    ;store current bit
            ;					    
            2717 29EF   AND #$BF     ;head > track 42, clear current bit
            2719 8D02C0 STA $C002    ;store correct current
            271C 60     RTS          ;and return
            ;
            ;-------------------------------------------------; 
            ; ROUTINE TO WAIT FOR DISKETTE TO REVOLVE TO      ;
            ; FIRST BYTE PAST THE INDEX HOLE.                 ;
            ;-------------------------------------------------;                                                   
            271D AD00C0 LDA $C000    ;load status of disk drive
            2720 3OFB   BMI $271D    ;if not above index hole, loop
            2722 AD00C0 LDA $C000    ;above index hole, load disk status
            2725 1OFB   BPL $2722    ;loop until past index hole
            2727 60     RTS          ;then return
            
            ;-------------------------------------------------;                                                   
            ; ROUTINE TO PUT HEAD ON DISK, FIND FIRST BYTE    ;
            ; OF DATA, AND INITIALIZE PlO CHIP.               ;
            ;-------------------------------------------------;  
            2728 205427 JSR $2754    ;subroutine to put disk head on disk
            2720 201D27 JSR $2710    ;subroutine to ,find 1st byte of data
            272E A903   LDA #$03     ;reset the chip
            2730 8D10C0 STA $C010  
            ;					   
            2733 A958   LDA #$58     ;select 8 bits, even parity, 1 stop
            2735 8D1OCO STA $C010    ;bit, disable interrupt logic
            2738 60     RTS          ;return
            
            ;-------------------------------------------------;                                                   
            ; READ A TRACK INTO THE MEMORY LOCATIONS          ;
            ; POINTED TO BY LOCATIONS (FE,FF) (low,high),     ;
            ;-------------------------------------------------;                                                   
            2739 202827 JSR $2728    ;routine gets ready to read 1st bwte
            ;					      
            273C AD00C0 LDA $C000    ;if over index hole, clean
            273F 1020   BPL $2761    ;up and return
            ;					    
            2741 AD10C0 LDA $C010    ;if not reads to read a byte,
            2744 4A     LSR A        ;loop to check position anin
            2745 90F5   BCC $273C   
            					    
            2747 AD11CO LDA $C011    ;read a byte from disk
            274A 91FE   STA ($FE),Y  ;store in memory
            274C C8     INY          ;increment index V
            274D DOED   BNE $273C    ;if Y=0 (256 bytes stored), then
            274F E6FF   INC $FF      ;inc FF (high byte of mem. pointer)
            ;					    
            2751 4C3C27 JMP $273C    ;loop to check position again
            ;
            ;--------------------------------------------
            ; ROUTINE TO PLACE DISK HEAD ON DISKETTE,   ;
            ; JUMP TO WAIT LOOP, AND RETURN.            ;
            ;--------------------------------------------
            2754 A97F   LDA #$7F     ;turn off bit 7 of C002
            2756 2D02C0 AND $C002    ;to put head on diskette
            2759 8D02C0 STA $C002
            ;
            275C A228   LDX #$28     ;set X (outer decrement) to hex 28
            275E 4C7A26 JMP $267A    ;and Jump to wait loop, then return
            ;
            ;----------------------------------------------
            ; ROUTINE TO LIFT DISK HEAD FROM DISKETTE,    ;
            ; JUMP TO WAIT LOOP, THEN RETURN              ;
            ; TIME, THEN RETURN.                          ;
            ;----------------------------------------------
            2761 A980   LDA  #$80    ;turn on bit 7 of C002
            2763 0D02C0 ORA  $C002
            ;
            2766 DOF1   BNE  $2759   ;store value in C002, wait, return
            ;
            ;----------------------------------------------
            ; INITIALIZATION ROUTINE. WRITES HEADER        ;
            ; INFORMATION ON TO ALL 39 TRACKS OF DISKETTE. ;
            ;----------------------------------------------;
            2768 A939   LDA #$39    ;store hex 39 at $E5
            276A 85E5   STA $E5 
            ;
            276C 206326 JSR $2663   ;move to track 0
            ;
            276F 20832C JSR $2C83   ;move to the next track
            ;
            2772 207D27 JSR $277D   ;write track header information
            ;
            2775 AD5D26 LDA $265D   ;load track no. head is above
            ;
            2778 C939   CMP #$39    ;if not equal to 39, rereat
            277A DOF3   BNE $276F   ;code from $276F again
            ;
            277C 60     RTS         ;disk initialized, return
            ;
            ;---------------------------------------------
            ; ROUTINE TO WRITE TRACK HEADER INFORMATION  ;
            ; ON A TRACK OF DISKETTE.                    ;
            ;---------------------------------------------
            277D A902   LDA #$02    ;check to see if head above
            277F 2COOCO BIT $C000   ;track 0. If not, continue
            2782 D004   BNE $2788
            ;
            2784 A903   LDA #$03    ;on track 0, load error code of 3.
            2786 D009   BNE $2791   ;(can't write header on track 0)
            ;
            2788 A920   LDA #$20    ;check to see if disk is write
            278A 2COOCO BIT $C000   ;protected. If not, continue
            278D D005   BNE $2794
            ;
            278F A904   LDA #$04    ;write protected disk, load error
            2791 4C4B2A JMP $2A4B   ;code of 4, Jump to error routine
            ;
            2794 202827 JSR $2728   ;get ready to read 1st bwte of data
            ;
            2797 A9FC   LDA #$FC    ;enable write circuits
            2799 2002C0 AND $C002
            279C 8D02C0 STA $C002
            ;
            279F A2OA   LDX #$0A    ;store outer decrement of 10 in X,
            27A1 207A26 JSR $267A   ;Jump to wait loop (1 millisecond)
            ;
            27A4 A243   LDX #$43    ;write the two byte start code
            27A6 20C227 JSR $27C2   ;of $43, $57
            27A9 A257   LDX #$57
            27AB 20C227 JSR $27C2
            ;
            27AE AE5D26 LDX $265D   ;load BCD track number disk head is
            27B1 20C227 JSR $27C2   ;initializing, write it to disk
            ;
            27B4 A258   LDX #$58    ;write the track type code to disk
            27B6 20C227 JSR $27C2   ; (always a hex 58)
            ;
            27B9 AD00C0 LDA $C000   ;wait until index hole found
            27BC 3OFB   BMI $27B9
            ;
            27BE A983   LDA #$83    ;lift head, disable write, set erase
            27C0 D0A1   BNE $2763   ;enable to 1, store, wait & return
            ;
            ;-------------------------------------------------------                 
            ; ROUTINE TO WRITE A BYTE TO DISK.                     ;
            ;-------------------------------------------------------
            27C2 AD10C0 LDA $C010   ;loop to wait until write
            27C5 4A     LSR A       ;buffer is empty
            27C6 4A     LSR A
            27C7 90F9   BCC $27C2
            ;
            27C9 8E11C0 STX $C011   ;write the byte in X reg to disk
            ;
            27CC 60     RTS         ;return
            ;					    
            ;-------------------------------------------------------
            ; ROUTINE TO READ A BYTE FROM DISK.
            ;-------------------------------------------------------
            27CD AD10C0 LDA $C010   ;loop to wait until read
            27D0 4A     LSR A       ;buffer is full
            27D1 90FA   BCC $27CD
            27D3 AD11C0 LDA $C011   ;load acc. with byte from disk
            ;
            27D6 60     RTS         ;return
            ;
            ;---------------------------------------------;
            ; WRITE A SECTOR TO DISK WITH ERROR CHECK     ; 
            ;---------------------------------------------;             
            27D7 AD6026 LDA $2660   ;load ($FE,$FF) with buffer
            27DA 85FE   STA $FE     ;address for read/write operation
            27DC AD6126 LDA $2661   
            27DF 85FF   STA $FF	    
            ;					    
            27E1 AD5F26 LDA $265F   ;load page count
            ;					    
            27E4 F002   BEQ $27E8   ;if 0, load error routine code
            27E6 1004   BPL $27EC   ;of B (bad sector length value)
            27E8 A9OB   LDA #$OB    ;and Jump to ERROR routine
            27EA D0A5   BNE $2791   
            ;					    
            27EC C969   CMP #$09    ;if sector length >= 9, Jump to
            27EE 10F8   BPL $27E8   ;ERROR routine with code of B
            ;					    
            27F0 A902   LDA #$02    ;if on track 0, return
            27F2 2COOCO BIT $C000   ;(can't write a sector to track 0
            27F5 FODF   BEQ $27D6   ;without special utilitw)
            ;					    
            27F7 4A     LSR A       ;store a 1 in memory
            27F8 85FA   STA $FA     ;location $FA
            ;					    
            27FA A920   LDA  #$20   ;if disk not write protected,
            27FC 2C00C0 BIT  $C000  ;then continue
            27FF D004   BNE  $2805  
            ;					    
            2801 A904   LDA #$04    ;disk. write protected, load error
            2803 D0E5   BNE $27EA   ;code of 4 and Jump to ERROR routine
            ;					    
            2805 A901   LDA #$01    ;initialize $F6 and $F8 with
            2807 85F6   STA $F6     ;number of tries to read data back
            2809 A903   LDA #$03    ;after writing before jumping
            280B 85F8   STA $F8     ;to ERROR *2 routine
            ;					    
            280D 20C428 JSR $28C4   ;position head above correct sector
            ;					    
            2810 209F28 JSR $289F   ;wait 400 us X last sector lenflh
            ;					    
            2813 A9FE   LDA #$FE    ;enable write circuits
            2815 2D02C0 AND $C002   
            2818 8D02C0 STA $C002   
            ;					    
            28lB A225   LDX #$25    ;short wait loop
            281D CA     DEX		    
            281E DOFD   BNE $281D   
            ;					    
            2820 A9FF   LDA #$FF    ;do nothing, wait loop (?)
            2822 2D02C0 AND $C002   
            2825 8D02C0 STA $C002   
            ;					    
            2828 209F28 JSR $289F   ;wait 400 us X last sector length
            ;
            282B A276    LDX #$76   ;write sector start code to disk
            282D 20C227  JSR $27C2
            ;
            2830 AE5E26  LDX $265E  ;write sector number to disk
            2833 20C227  JSR $27C2
            ;
            2836 AE5F26  LDX $265F  ;store sector length in
            2839 86FD    STX $FD    ;memorv location $FD
            283B 20C227  JSR $27C2  ;write sector length to disk
            ;
            283E A000    LDY #$00   ;init Y, index register
            ;
            2840 B1FE    LDA ($FE),Y
            2843 20C227  JSR $27C2  ;write correct number of
            2846 C8      INY        ;pages to disk
            2847 D0F7    BNE $2840
            2849 E6FF    INC $FF
            284B C6FD    DEC $FD
            284D D0F1    BNE $2240
            ;
            284F A247    LDX #$47   ;write a hex 47 to disk
            2851 20C227  JSR $27C2
            ;
            2854 A253    LDX #$53   ;write a hex 53 to disk
            2856 20C227  JSR $27C2
            ;
            2859 AD5F26  LDA $265F  ;calculate 6 times the
            285C 0A      ASL A      ;page count (sector length)
            285D 85FD    STA $FD
            285F 0A      ASL A
            2860 18      CLC
            2861 65FD    ADC $FD
            ;
            2863 20A428  JSR $28A4  ;wait 300 us X page count
            ;					    
            2866 AD02C0  LDA $C002  ;enable read circuits
            2869 0901    ORA #$01
            286B 8D02C0  STA $C002
            ;
            286E A269    LDX #$69   ;short wait loop
            2870 CA      DEX
            2871 DOFD    BNE $2870
            ;
            2873 0902    ORA #$02   ;set erase enable bit on
            2875 8D02C0  STA $C002
            ;
            2878 18      CLC        ;reset memory location $FF
            2879 8A      TXA        ;to point back to the beginning
            287A 65FF    ADC $FF    ;of memorw buffer Just written
            287C 38      SEC        ;to disk
            287D ED5F26  SBC $265F
            2880 85FF    STA $FF
            ;
            2882 200529  JSR $2905  ;verify that data written to disk OK
            ;
            2885 B013    BCS $289A  ;if carry set; data written OK
            ;
            2887 C6F8    DEC $F8    ;data not read back OK. Try
            2889 D0ED    BNE $2878  ;again if RETRY counter not < 0
            ;
            288B C6F6   DEC $F6      ;if all RETRIES exhausted, go to
            288D 300C   BMI $289B    ;ERROR #2 routine
            288F BA     TXA          ;reset memory location $FF to point
            2890 65FF   ADC $FF      ;to buffer written to disk
            2892 38     SEC
            2893 EDSF26 SBC $265F
            2896 85FF   STA $FF
            ;
                                     ;NOTE: Code below incorrect,
                                     ;Stack will be incorrect, as
                                     ;code at $2909 causes one byte
                                     ;to be pulled from the stack
                                     ;which has been pushed at $2905.
            ;
            2898 DO6F   BNE $2909    ;one more try. (See above note)
            289A 60     RTS          ;return
            2898 A9O2   LDA #$02     ;load return code (2=can't write
            289D DO22   BNE $28C1    ;sector) and Jump to ERROR routine
            ;
            ;------------------------------------------------
            ;  ROUTINE TO WAIT 400 MICROSECONDS OF DELAY    ;
            ;  TIMES THE NUMBER STORED IN MEMORY LOCATION   ;
            ;  $FA (USUALLY THE LENGTH OF THE SECTOR JUST   ;
            ;  READ FROM DISK OR JUST SPACED OVER ON DISK). ;
            ;  (NOTE: THIS IS HALF OF THE DELAY WAITED IN   ;
            ;  BETWEEN WRITING DIFFERENT SECTORS TO DISK.)  ;
            ;------------------------------------------------          
            289F A5FA   LDA $FA      ;load previous sector lensth
            ;
            28A1 0A     ASL A        ;multiply by 8
            28A2 0A     ASL A
            28A3 0A     ASL A
            ;
            28A4 A8     TAY          ;store in Y (outer decrement)
            28A5 A212   LDX   #$12   ;loop to wait 50 microseconds of
            28A7 CA     DEX          ;delay times the number stored
            28A8 D0FD   BNE  $28A7   ;in the Y resister
            28AA EA     NOP
            28AB EA     NOP
            28AC 88     DEY
            28AD D0F6   BNE  $28A5
            ;
            28AF 60     RTS         ;return
            ;
            ;------------------------------------------------
            ; READ A BYTE FROM DISK WITH ERROR CHECKING.     ;
            ; FOR USE IN SEARCHING FOR TRACK HEADERS.        ;
            ;------------------------------------------------
            28B0 AD00C0 LDA $C000   ;if index found, go to
            28B3 100A   BPL $28BF   ;ERROR *9 routine
            
            28B5 AD10C0 LDA $C010   ;wait until read buffer full
            2BB8 4A     LSR A
            28B9 90F5   BCC $28B0
            ;
            28BB AD11C0 LDA $C011   ;read a byte from disk
            28BE 60     RTS         ;return
            ;
            28BF A909   LDA #$09    ;load return code of 9 (can't find
            28C1 4C4B2A JMP $2A4B   ;track header), Jump to ERROR routine
            ;
            ;------------------------------------------------ 
            ; ROUTINE TO POSITION HEAD ABOVE SECTOR NUMBER  ;
            ; STORED IN LOCATION $265E ON THE TRACK YOU ARE ;
            ; CURRENTLY ON.                                 ;
            ;------------------------------------------------ 
            28C4 202B27 JSR  $272B  ;get ready to read 1st bwte of data
            28C7 20B028 JSR  $28B0  ;search for two byte
            2BCA C943   CMP  #$43   ;track start code of $43, $57
            28CC DOF9   BNE  $28C7
            28CE 20B028 JSR  $28B0
            28D1 C957   CMP  #$57
            28D3 D0F5   BNE  $28CA
            ;
            20D5 20CD27 JSR $27CD   ;read BCD track number from disk
            ;
            28DB CD5D26 CMP $265D   ;see if it matches track number
            28DB F004   BEQ $28E1   ;disk head is above. If so, continue
            28DD A905   LDA #$05    ;track no. from disk <> track no.
            28DF D0E0   BNE $28C1   ;disk head is above. ERROR #5
            ;
            28E1 20CD27 JSR $27CD   ;read track type code
            ;
            28E4 CE5E26 DEC $265E   ;if sector 1 wanted, return
            28E7 F014   BED $28FD
            ;
            28E9 A900   LDA #$00    ;init $F9 (sector counter)
            28EB 85F9   STA $F9     ;to 0.
            ;
            28ED 209829 JSR $2998   ;read east a sector
            28F0 900F   BCC $2901   ;if carry clear, ERROR #A occurred
            ;
            28F2 AD5E26 LDA $265E   ;if not on correct sector,
            28F5 C5F9   CMP $F9     ;loop to read past another sector
            28F7 DOF4   BNE $28ED
            ;
            28F9 C5FB   CMP $FB     ;if last sector read had the wrong
            28FB D004   BNE $2901   ;sector number, ERROR #A occurred
            28FD EE5E26 INC $265E   ;inc $265E (decremented earlier)
            ;
            2900 60     RTS         ;return
            ;
            2901 A9OA   LDA #$0A    ;load return code (A=can't find sector
            2903 DOBC   BNE $28C1   ;before one requested), go to ERROR
            ;
            ;-----------------------------------------------
            ; RE-READ SECTOR JUST WRITTEN TO MAKE SURF IT   ;
            ; COMPARES WITH WHAT WAS SUPPOSED TO HAVE BEEN  ;
            ; WRITTEN TO DISK.                              ;
            ;------------------------------------------------
            2905 48     PHA         ;acc has high byte of buffer address
            ;
            2906 20C428 JSR  $28C4  ;position head on correct sector
            ;
            2909 20B028 JSR  $28B0  ;loop until sector start
            290C C976   CMP  #$76   ;code found on disk
            290E D0F9   BNE  $2909
            ;
            2910 20CD27 JSR  $27CD  ;read sector number from disk, if
            2913 CD5E26 CMP  $265E  ;it equals sector no. Just written,
            2916 F003   BEQ  $291B  ;then continue at $291B
            ;
            2918 68     PLA         ;pull ace. stored at $2905,
            2919 18     CLC         ;carry clear indicates error
            ;
            291A 60     RTS         ;return
            ;
            291B 20CD27 JSR  $27CD  ;read page count written to disk
            291E AA     TAX         ;store in X reg and at $265F
            291F 8D5F26 STA  $265F
            ;
            2922 A000   LDY  #$00   ;init Y index reg to 0
            ;
            2924 68     PLA         ;stack=f lag. 0.=read from disk into
            2925 F01C   BEO  $2943  ;buffer, NOT 0=compare disk with buffer
            ;
            2927 AD10C0 LDA  $C010  ;wait until read buffer full
            292A 4A     LSR  A
            292B 90FA   BCC  $2927
            ;
            292D AD11C0 LDA  $C011  ;read a byte from disk
            ;
            2930 2C10C0 BIT  $C010  ;if parity error, set error flag
            2933 70E4   BVS  $2919  ;and return
            ;
            2935 D1FE   CMP  ($FE),Y ;compare buffer with disk data
            2937 DOEO   BNE  $2919  ;if not eeual, set error, return
            ;
            2939 C8     INY         ;increment index register V
            293A DOEB   BNE  $2927  ;and if necessary
            293C E6FF   INC  $FF    ;high byte of buffer pointer
            ;
            293E CA     DEX         ;if not done, loop to continue
            293F DOE6   BNE $2927   ;checking until sector verified
            ;
            2941 38     SEC         ;carry set means all OK.
            ;
            2942 60     RTS         ;return
            ;
            ;------------------------------------------------    
            ; READ THE SECTOR YOU ARE ON INTO MEMORY
            ; LOCATIONS POINTED TO BY ($FE,FF) WITH
            ; ERROR CHECKING. PAGE COUNT IS IN REG. X.
            ;------------------------------------------------
            2943 AD10C0 LDA $C010   ;wait until read buffer is full
            2946 4A     LSR A
            2947 9OFA   BCC $2943
            ;
            2949 AD11CO LDA $C011   ;read a byte from disk
            294C 2C1OCO BIT $C010   ;if paritry errors set error fin
            294F 70C8   BVS $2919   ;and return
            ;
            2951 91FE   STA ($FE),Y ;store byte read in correct iocation
            ;
            2953 C8     INY         ;increment index reg Y
            2954 D0ED   BNE $2943   ;and if necessary
            2956 E6FF   INC $FF     ;high byte of buffer pointer
            ;
            2958 CA     DEX         ;bit not done, read some
            2959 D0E8   BNE $2943   ;more data from sector
            295B 38     SEC         ;carry set means all OK
            295C 60     RTS         ;return
            ;
            ;-------------------------------------------------
            ; READ SECTOR WITH ERROR CHECKING AND RETRIES    ;
            ; IF FIRST READ NOT SUCCESSFUL.                  ;
            ;-------------------------------------------------
            295D AD6026 LDA $2660   ;store buffer address where data
            2960 85FE   STA $FE     ;is to go in iocations ($FE,$FF)
            2962 AD6126 LDA $2661
            2965 85FF   STA $FF 
            ;
            2967 A903   LDA #$03    ;initiaiize $F7 and $F8 with
            2969 85F7   STA $F7     ;the number of times to try to
            296B A907   LDA #$07    ;read sector before giving up
            296D 85F8   STA $F8     ;on parity error
            ;
            296F A900   LDA #$00    ;0=flag indicating read from disk
            ;
            2971 200529 JSR $2905   ;Jump to read/compare routine
            ;
            2974 9004   BCC $297A   ;if carry ciear,Y error occurred
            ;
            2976 60     RTS         ;return
            ;
            2977 C6FF   DEC $FF     ;error occurred trying to read
            2979 E8     INX         ;sector from disk. Restore buffer
            297A EC5F26 CPX $265F   ;pointer in location $FF
            297D D0F8   BNE $2977
            ;
            297F C6F8   DEC $F8     ;if inner NO OF RETRIES <> 0
            2981 DOEC   BNE $296F   ;then ioop back to try again
            ;
            2983 208326 JSR $2683   ;move one track towards track 0
            2986 207826 JSR $2678   ;wait loop
            ;
            2989 208A26 JSR $268A   ;move one track towards track 39
            298C 207826 JSR $2678   ;wait ioop
            ;
            298F C6F7   DEC $F7     ;if outer NO OF RETRIES <> 0
            2991 10D8   BPL $296B   ;then ioop back to try again
            ;
            2993 A901   LDA #$01    ;couldn't read data, set return code
            2995 4C4B2A JMP $2A4B   ;to 1 (parity error); go to ERROR
            ;
            ;----------------------------------------------------
            ; READS PAST A SECTOR. CARRY SET TO 1 IF READ       ;
            ; SUCCESSFUL, SET TO 0 IF NOT SUCCESSFUL.           ;
            ;----------------------------------------------------
            2998 AD00C0 LDA $C000   ;if above index hole, clear
            299B 1027   BPL $29C4   ;carry and return
            ;
            299D AD10C0 LDA $C010   ;wait until read buffer full
            29A0 4A     LSR A
            29A1 90F5   BCC $2998
            ;
            29A3 AD11C0 LDA $C011   ;read a byte from disk
            ;
            29A6 C976   CMP #$76    ;if not a sector start code,
            29A8 DOEE   BNE $2998   ;keep reading
            ;
            29AA 20CD27 JSR $27CD   ;read sector number, store in
            29AD 85FB   STA $FB     ;memory location $FB
            ;
            29AF 20CD27 JSR $27CD   ;read sector length, store in
            29B2 85FA   STA $FA     ;memory location $FA
            ;
            29B4 E6F9   INC $F9     ;increment sector number counter
            ;
            29B6 A8     TAY         ;init reg V to sector length,
            29B7 A200   LDX #$00    ;and reg X to 0
            ;
            29B9 20CD27 JSR $27CD   ; read past this sector
            29BC CA     DEX
            29BD DOFA   BNE $29B9
            29BF 88     DEY
            29C0 DOF7   BNE $29B9
            ;
            29C2 38     SEC          ;carry set means read successful
            ;
            29C3 60     RTS          ; return
            ;
            29C4 18     CLC          ;carry clear means error
            ;
            29C5 60     RTS          ; return
            ;
            ;---------------------------------------------------
            ; ROUTINE TO SELECT DISK DRIVE AND SEE IF IT       ;
            ; IS READY TO BE USED.                             ;
            ;---------------------------------------------------
            29C6 8D5C26 STA $265C    ;store disk drive # in $265C
            ;
            29C9 0A     ASL A        ;X=drive number times 2
            29CA AA     TAX
            ;
            29CB 2902   AND #$02     ;drive=1, Y=2. drive=2, Y=0
            29CD A8     TAY
            ;
            29CE BDE929 LDA $29E9,X  ;load old status of the disk drive
            29D1 8DOOCO STA $C000    ;you are selecting
            29D4 BDEA29 LDA $29EA,X
            29D7 8DO2CO STA $C002
            ;
            29DA ADOOCO  LDA $C000   ;put DISK READY bit in carry
            29DD 4A      LSR A       ;bit (1=not ready)
            ;
            29DE 08      PHP         ;save status bits
            ;
            29DF C000    CPY #$00    ;if drive 1 selected, return
            29E1 D006    BNE $29E9
            ;
            29E3 28      PLP         ;restore status and stack
            ;
            29E4 4A      LSR A       ;disk drive 2 selected, so use
            29E5 4A      LSR A       ;bit 4 as DISK READY bit
            29E6 4A      LSR A       ;instead of bit 0
            29E7 4A      LSR A
            ;
            29E8 60      RTS         ;return
            ;
            29E9 28      PLP         ;drive 1 selected. Restore status
            ;                               
            29EA 60      RTS         ;return
            
            Below is listed some code that can be used to accomplish
            various tasks.
            
            
            To place disk head above track 0.
            
              JSR $2663
            
            
            To move disk head of a specific disk drive to a specific
            track. TRCKNO is the track number you want to move the disk
            head to, and DRIVNO is the drive you want to move the head
            of,
            
              LDA #TRCKNO
              STA $2662
              LDA #DRIVNO
              STA $265C
              JSR $26A6
            
            
            To wait for first byte past index hole.
            
              JSR $271D
            
            
            To put head on disk, initialize PIO chip, and wait until
            diskette revolves to first byte of data. (After executing
            this routine, a LDA $C011 (after making sure the read buffer
            is full) will read the first byte of data on a track.)
            
              JSR $2728
            
            
            Read the track you are on into memory, (MEMLO and MEMHI
            point to the memory locations the track is to be read into.)
            
              LDA #MEMLO
              STA $FE
              LDA #MEMHI
              STA $FF
              LDY #0
              JSR $2739
            
            
            Routine to place disk head on diskette.
            
              JSR $2754
            
            
            Routine to lift disk head from diskette.
            
              JSR $2761
            
            
            To initialize a new disk by writing track header information
            on all 39 tracks of diskette.
                                           
              JSR $2768
            
            
            To initialize the track disk head is above.
              JSR $277D                            .
            
            
            To write a byte to disk.
            
              LDX #BYTE
              JSR $27C2
            
            
            To read a byte from disk.
            
              JSR $27CD ;byte is returned in accumulator
            
            
            To write a sector to disk with error checking. MEMHI and
            MEMLO point to the memory locations that are to be written
            to disk, NSECTR is the number of the sector you want to
            write to disk, and NPAGES is the number of pages you want to
            write to disk.
            
              LDA #MEMLO
              STA $2660
              LDA #MEMHI
              STA $2661
              LDA #NSECTR
              STA $265E
              LDA #NPAGES
              STA $265F
              JSR $27D7
            
            To place disk head above sector NSECT on the track disk head
            is above.
            
              LDA #NSECT
              STA $265E
              JSR $28C4
            
            
            To read a sector from the track you are on into memorw.
            MEMHI and MEMLO point to where the data is to go, and NSECT
            is the sector that is to be read. If the carry is set on
            return from this routines it means the read was successful.
            If the carry is clears it means a parity error occurred and
            all data maw not have been read or maw be in error.
            
              LDA #MEMLO
              STA $2660
              LDA #MEMHI
              STA $2661
              LDA INSECT
              STA $265E
              JSR $2943
                                          
            
            
            
            
            To read a sector from the track wou are on into memory.
            MEMHI and MEMLO point to where the data is to go, and NSECT
            is the sector that is to be read. This routine will perform
            retries if the first attempt to read the data is not
            successful.
            
              LDA #MEMLO
              STA $2660
              LDA #MEMHI
              STA $2661
              LDA INSECT
              STA $265E
              JSR $295D
            