!    S D O S D I S K V A L I D A T E   P A S S   5
!
!    SDOSDISKVAL5.BAS -- SDOS 1.0 DISK VALIDATE, PASS 5
!    Checks that reconstructed DISKMAP.SYS matches actual DISKMAP.SYS,
!        and resolves the differences.  Verifies that DIRECTORY.SYS
!        is only mentioned in the directory once.  Also verifies that BOOT.SYS
!        owns Cluster Zero, and that SDOS.SYS, if it exists, is a contiguous
!        file.
!
!    Revision History:
!
!    EDITED 07/25/79    TO CHECK UNUSED PORTION OF DISKMAP
!                       COMPARE CONSTRUCTED TO DISK MAP TO ACTUAL DISK MAP
!                       RESOLVE ANY CONFLICTS
!    EDITED 12/20/79    TO MAKE THE FIND OWNER ROUTINE
!                       FIGURE OUT THE END OF THE VALID DISKMAP PORTION CORRECTLY
!
!    CONVERTED TO BASIC 1.4 03/06/80
!
!    7/21/80    MOD FOR BASIC1.4G
!    1/30/81    MOD FOR BASIC14H
!               CHECK SIZE OF DISKMAP.SYS FILE AND FIX IF WRONG
!
!    12/26/82   UPDATE TO HANDLE SDOS 1.1G
!               MODIFIED TO HANDLE LARGE DISKMAP.SYS FOR 40Mb DISK DRIVES
!               ADD LOGIC TO CHECK BOOT.SYS OCCUPIES CLUSTER ZERO
!               ADD LOGIC TO CHECK THAT SDOS.SYS IS CONTIGUOUS, IF IT EXISTS
!
!    11/30/83   Changed from 1.1g to 1.1h, to match other modules. (RCW)

!^L
    PROGRAM ORIGIN :4400

    DATA ORIGIN :2E00

    COMMON Q$[34],DEVICE$[20],FNAME$[16],FNAME2$[16],OP$[12],DIR$[32]
    COMMON DIR2$[32],DEVDIR$[30]
    COMMON BYTE$[1],TWOB$[2],MINUS1$[2]
    COMMON NBPS,NLSN,NLCN,NSPC,HEADERBYTE,HCN,HCN2,HCSIC,HCSIC2
    COMMON MODF,MOD2F,DISMOUNT$[4],UNPROT$[4]
    COMMON NSPT,NTPC,NCYL,NOTBADS,NLCNS,NLCNS2,STAT$[23]
    COMMON SETMAP$[8],BUFFER$[20],BUFAD$[2]
    COMMON UNPROT2$[3]
    COMMON MAXFSIZE,GETPOS$[14],HCN$[2],HCSIC$[1],LCNS$[2],FSIZE$[4]
    COMMON PROT$[1],EMPTY$[6],PROT,FSIZE,CKSUM,BYTES,BAD,KILL,POS
    COMMON AZ$[27]
    COMMON PER09$[11]
    COMMON OPTIONS

    COMMON DMAP$[2048]
    ! DMAP$ CONTAINS DISKMAP.SYS IMAGE CONSTRUCTED BY PASS 4

REM LOCAL VARIABLES:
    DIM RDMAP$[2048]
    ! RDMAP$ CONTAINS ACTUAL DISKMAP.SYS AS IT APPEARS ON THE DISK

    DIM DB(8),RDB(8)
    DIM BADSECTS,BDSD/-1/, UNOWNF/0/

    DIM CCSETFILEPROT$/:E,8,0,:11/,WBPROTECT$/:41/,NOPROTECT$/0/,UNPROTECTED/0/

    DEF LSBIT(X1)=X1&:1
    DEF MSB(X2)=INT(X2/256)
    DEF LSB(X3)=X3-MSB(X3)*256
!^L
    PRINT "(500) SDOSDISKVALIDATE Pass 5 V1.1h"

    !D! PRINT "LEN(DMAP$)";LEN(DMAP$)
    !D! FOR I=0 TO LEN(DMAP$)-1
    !D!     IF I&:F=0 THEN PRINT \ PRINT HEX$(I);" ";
    !D!     PRINT HEX$(DMAP$(I+1))[4,2];
    !D! NEXT I

    LEN(RDMAP$)=LEN(DMAP$)

    OPEN #3,DEVICE$ CAT "DIRECTORY.SYS"

    OPEN #2,DEVICE$ \ ! OPEN AFTER DIR.SYS TO ENSURE MAP ALGORITHM IS SET
    SYSCALL UNPROT2$ \ ! ALLOW US TO WRITE INTO HEADER CLUSTERS, IF NECESSARY

CHECKOUTSYSTEMFILES: ! Scan directory for system files
    MustDoPass4Again=False \ ! Assume all the system files are wonderful

    BOOTSYSDIRENTRYLOC=-1 \ ! Remember we haven't seen this guy yet
    SDOSSYSDIRENTRYLOC=-1 \ ! Remember we haven't seen this guy yet
    DIRECTORYSYSDIRENTRYLOC=-1 \ ! Remember we haven't seen this guy yet
    DISKMAPSYSDIRENTRYLOC=-1 \ ! Remember we haven't seen this guy yet

    DIRENTRYLOC=0
SCANDIRECTORYFORSYSTEMFILES: ...
&   REPEAT
        ! Scan Directory for critical system files, and verify rationality
        READ #3@DIRENTRYLOC,DIR$ \ ! Scan next directory entry
        IF EOF(3) THEN EXIT SCANDIRECTORYFORSYSTEMFILES
        ELSEIF DIR$[1,16]="DIRECTORY.SYS   " AND...
&              DIR$[19]<>0 AND DIR$[20]!DIR$[21]<>0
            THEN GOSUB VALIDATEDIRECTORYSYS
        ELSEIF DIR$[1,16]="BOOT.SYS        " AND...
&              DIR$[19]<>0 AND DIR$[20]!DIR$[21]<>0
            THEN GOSUB VALIDATEBOOTSYS
        ELSEIF DIR$[1,16]="SDOS.SYS        " AND...
&              DIR$[19]<>0 AND DIR$[20]!DIR$[21]<>0
            THEN GOSUB VALIDATESDOSSYS
        ELSEIF DIR$[1,16]="DISKMAP.SYS     " AND...
&              DIR$[19]<>0 AND DIR$[20]!DIR$[21]<>0
            THEN GOSUB VALIDATEDISKMAPSYS
        DIRENTRYLOC=DIRENTRYLOC+32 \ ! Advance to next directory entry
    END
    If MustDoPass4Again
    Then
        ! We did something to louse up the diskmap, go rebuild it again
        ! Re-protect the directory if we un-protected it
        IF UNPROTECTED=TRUE
        THEN SYSCALL #3,CCSETFILEPROT$,WBPROTECT$
        Print "(530) Chaining to SDOSDISKVAL.PAS4"
        Chain "SDOSDISKVAL.PAS4"
    Fi
    IF DIRECTORYSYSDIRENTRYLOC<0
    THEN Print "(519) No DIRECTORY.SYS?? Program bug!" \ Error 104
    IF SDOSSYSDIRENTRYLOC<0 THEN ! We don't care in the least...
    IF DISKMAPSYSDIRENTRYLOC<0
    THEN
        ! No DISKMAP.SYS file
        ! This isn't necessarily deadly, but it does make it hard add to files
    FI
    !  Re-protect the directory if necessary
    IF UNPROTECTED=TRUE
    THEN SYSCALL #3,CCSETFILEPROT$,WBPROTECT$
    GOTO VALIDATEDISKMAPCONTENTS
!^L
ALLOWDIRECTORYUPDATE: ! ALLOW US TO MODIFY THE DIRECTORY
    SYSCALL #3,CCSETFILEPROT$,NOPROTECT$
    UNPROTECTED=TRUE \ ! REMEMBER WE MUST RE-PROTECT THE FILE
    RETURN

VALIDATEDIRECTORYSYS: ! CHECK OUT STRUCTURE OF DIRECTORY.SYS FILE
    ! Check that entry is at beginning of sector
    IF DIRENTRYLOC&(NBPS-1)<>0 THEN BADDIRECTORYSYS

    ! Determine where BOOTDIRLSN points; we know it to be correct
    READ #2@:1B,Q$\BOOTDIRLSN=(Q$[1]**8+Q$[2])*256+Q$[3]

    ! Determine if directory entry we just read must be the real DIRECTORY.SYS
    LSN=DIRENTRYLOC/NBPS \ ! Compute offset in sectors; No fractional part possible
    RDCN=INT(LSN/NSPC) \ ! Relative data cluster number
    LET HCN=DIR$[17]**8+DIR$[18]
    READ #2@HCN*NSPC*NBPS+(RDCN+1)*2,TWOB$ \ ! Cluster containing BOOTDIRLSN
    IF BOOTDIRLSN<>(TWOB$[1]**8+TWOB$[2])*NSPC+(LSN-RDCN*NSPC)
    THEN BADDIRECTORYSYS

    ! Remember this location
    DIRECTORYSYSDIRENTRYLOC=DIRENTRYLOC
    Return

BADDIRECTORYSYS:
    Print "(521) Duplicate DIRECTORY.SYS entry found in directory at ";...
&         hex$(DIRENTRYLOC)
    Repeat
        Input "      Delete the duplicate (default=YES)? " Q$
        Gosub 1000
    When InvalidAnswer End
    If Q$<>"N"
    Then
        ! Trash this directory entry; notice this loses us some clusters!
        DIR$[19]=0\DIR$[20]=0\DIR$[21]=0
        Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
        MustDoPass4Again=TRUE \ ! This fixes lost clusters
        Return
    Fi
!^L
VALIDATEBOOTSYS: ! CHECK OUT STRUCTURE OF BOOT.SYS FILE
    REM FOUND BOOT.SYS DIRECTORY ENTRY
    IF BOOTSYSDIRENTRYLOC>=0
    THEN
        Print "(522) Duplicate BOOT.SYS entry found in directory."
        Repeat
            Input "      Delete the duplicate (default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            ! Trash this directory entry; notice this loses us some clusters!
            DIR$[19]=0\DIR$[20]=0\DIR$[21]=0
            Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
            MustDoPass4Again=TRUE \ ! This fixes lost clusters
            Return
        Fi
    ELSE BOOTSYSDIRENTRYLOC=DIRENTRYLOC
    ! Check filesize for proper size
    LET FSIZE=((DIR$[22]**8+DIR$[23])*256+DIR$[24])*256+DIR$[25]
    TEMP=64 \ ! Minimum BOOT.SYS size
    IF FSIZE<TEMP
    THEN
        PRINT "(523) DIR:FILESIZE of BOOT.SYS < ";TEMP
        REPEAT
            INPUT "      Set DIR:FILESIZE of BOOT.SYS to proper size? " Q$
            GOSUB 1000
        WHEN INVALIDANSWER END
        IF Q$<>"N"
        THEN
            REM CHANGE THE FILESIZE
            DIR$[22]=MSB(MSB(MSB(TEMP)))
            DIR$[23]=LSB(MSB(MSB(TEMP)))
            DIR$[24]=LSB(MSB(TEMP))
            DIR$[25]=LSB(TEMP)
            Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
        FI
    FI
    REM MAKE SURE 1ST DATA CLUSTER OF BOOT.SYS IS NOT A DUMMY
    LET HCN=DIR$[17]**8+DIR$[18]
    READ #2@HCN*NSPC*NBPS+2,TWOB$
    LET LCN=TWOB$[1]**8+TWOB$[2]

    REM VERIFY THAT NLCNS ALLOCATED IS >=2
    LET NLCNS=DIR$[20]**8+DIR$[21]
    IF NLCNS<2 OR LCN<>0
    THEN
        PRINT "(524) BOOT.SYS doesn't own LCN 0 as first data cluster!"
        Repeat
            Input "      Change so it owns LCN 0 (default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            ! Make it all better...
            TWOB$[1]=0\TWOB$[2]=0
            WRITE #2@HCN*NSPC*NBPS+2,TWOB$
            MustDoPass4Again=TRUE \ ! Because NSPC could now be wrong, etc.
        Fi
    FI
    Return
!^L
VALIDATESDOSSYS: ! CHECK OUT STRUCTURE OF SDOS.SYS FILE
    REM FOUND SDOS.SYS DIRECTORY ENTRY
    IF SDOSSYSDIRENTRYLOC>=0
    THEN
        Print "(527) Duplicate SDOS.SYS entries found in directory."
        Repeat
            Input "      Delete the duplicate (default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            ! Trash this directory entry; notice this loses us some clusters!
            DIR$[19]=0\DIR$[20]=0\DIR$[21]=0
            Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
            MustDoPass4Again=TRUE \ ! This fixes lost clusters
            Return
        Fi
    ELSE SDOSSYSENTRYLOC=DIRENTRYLOC

    ! SDOS.SYS can legally be any size, so we don't check its size.

    REM MAKE SURE 1ST DATA CLUSTER OF SDOS.SYS IS NOT A DUMMY
    LET HCN=DIR$[17]**8+DIR$[18]
    READ #2@HCN*NSPC*NBPS+2,TWOB$
    LET LCN=TWOB$[1]**8+TWOB$[2]

    REM VERIFY THAT NLCNS ALLOCATED IS >=2
    LET NLCNS=DIR$[20]**8+DIR$[21]
    IF NLCNS<2 OR LCN<>1
    THEN
        PRINT "(526) SDOS.SYS doesn't own LCN 1 as first data cluster!"
        Repeat
            Input "      Change so it owns LCN 1 (default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            ! Make it all better...
            TWOB$[1]=0\TWOB$[2]=1
            WRITE #2@HCN*NSPC*NBPS+2,TWOB$
            MustDoPass4Again=TRUE \ ! Because NSPC could now be wrong, etc.
        Fi
    FI
    ! Now verify that SDOS.SYS allocation is contiguous
    FOR LCN=1 to NLCNS-1
        READ #2@HCN*NSPC*NBPS+LCN*2,TWOB$
        IF LCN<>TWOB$[1]**8+TWOB$[2]
        Then
            Print "(529) SDOS.SYS is not a contiguous file!"
            Repeat
                Input ...
&                 "      Make SDOS.SYS properly contiguous? (default=YES)? " Q$
                Gosub 1000
            When InvalidAnswer End
            If Q$<>"N"
            Then
                ! Set HCSIC to 1, NLCN=2, filesize to 0
                DIR$[19]=1\DIR$[20]=0\DIR$[21]=2
                DIR$[22]=0
                DIR$[23]=0
                DIR$[24]=0
                DIR$[25]=0
                Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
                ! Erase all LCNs except header and 1st data cluster
                TWOB$[1]=:FF\TWOB$[2]=:FF
                For i=2 to NLCNS-1
                    WRITE #2@HCN*NSPC*NBPS+i*2,TWOB$
                Next i
                MustDoPass4Again=TRUE
                Return
            Fi
         Fi
    NEXT LCN
    Return
!^L
VALIDATEDISKMAPSYS: ! CHECK OUT STRUCTURE OF DISKMAP.SYS FILE
    REM FOUND DISKMAP.SYS DIRECTORY ENTRY
    IF DISKMAPSYSDIRENTRYLOC>=0
    THEN
        Print "(520) Duplicate DISKMAP.SYS entry found in directory."
        Repeat
            Input "      Delete the duplicate (default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            DIR$[19]=0\DIR$[20]=0\DIR$[21]=0
            Gosub AllowDirectoryUpdate\Write #3@DIRENTRYLOC,DIR$
            MustDoPass4Again=TRUE
            Return
        Fi
    ELSE DISKMAPSYSENTRYLOC=DIRENTRYLOC
    ! Check filesize for proper size
    LET FSIZE=((DIR$[22]**8+DIR$[23])*256+DIR$[24])*256+DIR$[25]
    TEMP=INT( (INT((NLCN+7)/8)+NBPS-1)/NBPS )*NBPS
    IF FSIZE<>TEMP
    THEN
        PRINT "(518) DIR:FILESIZE of DISKMAP.SYS <> ";TEMP
        REPEAT
            INPUT "      Set DIR:FILESIZE of DISKMAP.SYS to proper size? " Q$
            GOSUB 1000
        WHEN INVALIDANSWER END
        IF Q$<>"N"
        THEN
            REM CHANGE THE FILESIZE
            DIR$[22]=MSB(MSB(MSB(TEMP)))
            DIR$[23]=LSB(MSB(MSB(TEMP)))
            DIR$[24]=LSB(MSB(TEMP))
            DIR$[25]=LSB(TEMP)
            GOSUB ALLOWDIRECTORYUPDATE\WRITE #3@DIRENTRYLOC,DIR$
        FI
    FI
    REM MAKE SURE 1ST DATA CLUSTER OF DISKMAP.SYS IS NOT A DUMMY
    LET HCN=DIR$[17]**8+DIR$[18]
    READ #2@HCN*NSPC*NBPS+2,TWOB$
    LET LCN=TWOB$[1]**8+TWOB$[2]
    REM VERIFY THAT NLCNS ALLOCATED IS >=2
    LET NLCNS=DIR$[20]**8+DIR$[21]
    IF NLCNS<2 OR LCN=:FFFF
    THEN
        PRINT "(516) DISKMAP.SYS doesn't have 1st data cluster!"
        Repeat
            Input "      Choose a cluster from reconstructed map? " Q$
            GOSUB 1000
        When InvalidAnswer End
        If Q$<>"Y"
        Then 5121
        Else
            ! Find a free cluster according to reconstructed bit map
            For LCN=0 To NLCN-1
                If DMAP$[(LCN&:FFF8)/8+1]&(1**(LCN&7))=0 Then Exit LCN
            Next LCN
            If LCN=NLCN Then Error 1015 \ ! Disk Space Exhausted
            ! Mark allocated LCN as busy
            Let DMAP$[(LCN&:FFF8)/8+1]=DMAP$[(LCN&:FFF8)/8+1]!(1**(LCN&7))
            Let TWOB$[1]=MSB(LCN)\TWOB$[2]=LSB(LCN)
            Write #2@HCN*NSPC*NBPS+2,TWOB$
            ! Now, DISKMAP.SYS contents are garbage.
            ! Repair for this will be automatic when constructed diskmap
            ! is checked against actual diskmap contents.
            MustDoPass4Again=TRUE \ ! To get NCLUSTERS in directory entry right
        Fi
    FI
    Return
!^L
VALIDATEDISKMAPCONTENTS:
    IF ERROR WHEN OPEN #1,DEVICE$ CAT "DISKMAP.SYS"
    THEN
        PRINT "(513) Cannot Open DISKMAP.SYS...Bye!" \ Error 104
    FI

    REM READ ACTUAL CONTENTS OF DISKMAP.SYS
    READ #1,RDMAP$[1,LEN(RDMAP$)]

    IF DMAP$=RDMAP$
    THEN
        PRINT "(501) Reconstructed DiskMap matches DISKMAP.SYS contents."
        GOTO CHECKBOOTSYSEXISTENCE
    FI
    PRINT "(514) Reconstructed DiskMap does NOT match DISKMAP.SYS contents!"

    ! Count number of goofs in map
    LET ERCNT=0

    For i=1 to len(RDMAP$)
        T=RDMAP$[i] XOR DMAP$[i]
        IF T<>0
        Then
            For j=1 to 8 Do ERCNT=ERCNT+(T&1)\T=(T&:FE)/2
        Fi
    Next i
    Print     "(531)";ERCNT;"differences encountered."
    Repeat
        Input "      Fix DISKMAP.SYS (F), Display errors (D) or Quit (Q)? " Q$
        Let Q$=UPPERCASE$(Q$)
        If Q$="F" Then RDMAP$=DMAP$\Goto 54
        ElseIf Q$="D" Then DisplayDiskMapErrors
        ElseIf Q$="Q" Then 5121
    End
!^L
DisplayDiskMapErrors: ! Wade thru Diskmaps slowly, and let user see screwups
    LET ERCNT=0
    BADSECTS=0

    FOR I=1 TO LEN(RDMAP$)
53      IF RDMAP$[I]=DMAP$[I] THEN 51
        TEMP=RDMAP$[I]
        FOR J=1 TO 8 DO RDB(J)=LSBIT(TEMP)\TEMP=INT(TEMP/2)
        TEMP=DMAP$[I]
        FOR J=1 TO 8 DO DB(J)=LSBIT(TEMP)\TEMP=INT(TEMP/2)
        MOD2F=0
    FOR J=1 TO 8
        IF DB(J)=RDB(J) THEN 57
        IF DB(J)>RDB(J) THEN 52
535     IF BDSD=-1
        THEN
            INPUT "(502) Free all Unowned clusters? " Q$
            GOSUB 1000\ON INVALIDANSWER GOTO 535
            IF Q$<>"N" THEN LET BDSD=0 ELSE LET BDSD=1
        FI
        IF BDSD<>0 THEN 59
        LET RDB(J)=0
        IF MODF=0 THEN PRINT "(503) Logical Cluster Numbers of freed clusters:"
        IF COL(0)>58 THEN PRINT
        PRINT HEX$((I-1)*8+J-1);" ";
        NOTBADS=NOTBADS+1
        GOTO 56

59      PRINT "(504) Free LCN ";HEX$((I-1)*8+J-1);\INPUT "? " Q$
        GOSUB 1000\ON INVALIDANSWER GOTO 59
        IF Q$="Y"
        THEN LET RDB(J)=0\NOTBADS=NOTBADS+1
        ELSE LET BADSECTS=BADSECTS+1\GOTO 57
56      MOD2F=1\MODF=1\GOTO 57
52      BIT=(I-1)*8+J-1
        IF UNOWNF=0 THEN
            IF COL(0)>1 THEN PRINT
            INPUT "(515) Print the names of files which have unallocated clusters? " Q$
            GOSUB 1000 \ ON INVALIDANSWER GOTO 52
            IF Q$="Y" THEN UNOWNF=2 ELSE UNOWNF=1
        FI
        IF UNOWNF=2
        THEN
            GOSUB 500
            IF COL(0)>1 THEN PRINT
            PRINT "(505) LCN ";HEX$(BIT);" which is owned by file ";FNAME2$
            PRINT "      isn't marked in DISKMAP.SYS as owned!"
        FI
55      RDB(J)=1
        ERCNT=ERCNT+1
        MOD2F=1
57  NEXT J
    IF MOD2F<>1 THEN 51
58  RDMAP$[I]=RDB(8)*128+RDB(7)*64+RDB(6)*32+RDB(5)*16+RDB(4)*8+RDB(3)...
&             *4+RDB(2)*2+RDB(1)
51  NEXT I
    IF COL(0)>1 THEN PRINT
    IF BADSECTS>0 THEN PRINT "(506) A Total of";BADSECTS;"unowned clusters."
    IF NOTBADS>0 THEN PRINT "(507) Freed";NOTBADS;"unowned clusters."
    IF ERCNT=0 THEN PRINT "(508) No DiskMap problems remain."
    IF MODF+ERCNT=0 THEN CHECKBOOTSYSEXISTENCE
    IF ERCNT=0 THEN 54
512 PRINT "(509)";ERCNT;"cases of clusters owned but not allocated were found."
    INPUT "      Update DISKMAP.SYS? " Q$
    GOSUB 1000\ON INVALIDANSWER GOTO 512
    IF Q$="Y" THEN 54
5121 PRINT "(512) DISKMAP.SYS left in DAMAGED state!"\Error 104

54  SYSCALL #1,CCSETFILEPROT$,NOPROTECT$
    WRITE #1@0,RDMAP$
    SYSCALL #1,CCSETFILEPROT$,WBPROTECT$
    READ #1@0,DMAP$[1,LEN(RDMAP$)]
    IF RDMAP$=DMAP$
    THEN PRINT "(511) DISKMAP.SYS is fixed! "\GOTO CHECKBOOTSYSEXISTENCE
    PRINT "(510) DiskMap not written to DISKMAP.SYS correctly, retrying..."
    GOTO 54
!^L
500 ! FIND OUT WHICH FILE CONTAINS LCN GIVEN BY "BIT"
    IF BIT>=NLCN THEN LET FNAME2$="-ILLEGAL LCN-"\RETURN
    ON ERROR GOTO 0
    POSITION #3,0
501 READ #3,DIR2$
    IF EOF(3) THEN FNAME2$="-VALIDATE ERROR-"\RETURN
    IF DIR2$[19]=0 THEN 501
    HCSIC2=DIR2$[19]
    HCN2=DIR2$[17]*256+DIR2$[18]
    RESTORE #2,HCN2*NSPC*NBPS
    FOR HEADERDISPLACEMENT=0 TO HCSIC2*NBPS-2 STEP 2
        READ #2,TWOB$
        !D! Print ">>";DIR2$[1,16];hex$(TWOB$[1]*256+TWOB$[2])
        IF BIT=TWOB$[1]*256+TWOB$[2] THEN FNAME2$=DIR2$[1,16]\RETURN
    NEXT HEADERDISPLACEMENT
    GOTO 501
!^L
CHECKBOOTSYSEXISTENCE: ! Check to ensure that BOOT.SYS exists.
    CLOSE #1
    IF BOOTSYSDIRENTRYLOC<0
    THEN
        ! No BOOT.SYS file!!!!
        Print "(533) No BOOT.SYS file found in directory."
        Repeat
            Input "     Create BOOT.SYS (Default=YES)? " Q$
            Gosub 1000
        When InvalidAnswer End
        If Q$<>"N"
        Then
            Create #4,DEVICE$ CAT "BOOT.SYS" \ ! Fix the problem
            Syscall #4,CCSETFILEPROT$,WBPROTECT$
            Close #4
            Goto CheckOutSystemFiles \ ! To verify Cluster 0 is owned
        Else
             Print "(534) Missing BOOT.SYS"\Error 104
        Fi
    FI
    Exit \ ! The nice way out...

1000 ! IS THAT A GOOD RESPONSE????
    IF Q$=""
    THEN
        INVALIDANSWER=0
        RETURN
    ELSE
        LET Q$=UPPERCASE$(Q$)[1,1] \  REM DON'T CARE ABOUT "ES" OR "O" OR ....
        LET INVALIDANSWER=Q$<>"N" AND Q$<>"Y"
        RETURN
    FI

END
