1030 lines
72 KiB
Plaintext
1030 lines
72 KiB
Plaintext
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*
|
|
* *
|
|
* VERIFY function handler *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
* *
|
|
* The verify function simply opens & then "reads" a file. *
|
|
* Actual verification occurs deep within RWTS. As the data are *
|
|
* read, a checksum is calculated. If the calculated checksum *
|
|
* agrees with the checksum byte read off the disk, the integrity *
|
|
* of the data are verified. Failure to verify yeilds an I/O *
|
|
* error. *
|
|
* *
|
|
* Execution pattern: *
|
|
* FNVERIFY ($AD18) first calls the common open routine *
|
|
* COMNOPEN ($AB28) to locate and then open the named file. *
|
|
* COMNOPEN configures the FM work area, reads in a fresh VTOC *
|
|
* and then searches the directory sectors for the file *
|
|
* description entry of the wanted file. (The links to the first *
|
|
* directory sector are stored as the 2nd and 3rd bytes (offsets *
|
|
* $01 and $02) of the VTOC. The 2nd and 3rd bytes of each *
|
|
* subsequent directory sector contain the trk and sec values of *
|
|
* the next directory sector. The link bytes of the last *
|
|
* directory sector are zeroed out.) *
|
|
* As each directory sector is read in, an attempt is made *
|
|
* to locate a file description which contains the name of the *
|
|
* file wanted. If the name can't be located after searching all *
|
|
* the directories and if the VERIFY command was used by itself, *
|
|
* a second search is made to locate the first available space in *
|
|
* a directory sector where a new file description can be placed *
|
|
* (in case the command can create a new file). If no free space *
|
|
* is located, a disk-full error message is printed. (When the *
|
|
* VERIFY command is accessed via the INIT, SAVE or BSAVE *
|
|
* commands, no second search is done because these previous *
|
|
* commands would have already created a new file entry if *
|
|
* necessary.) *
|
|
* If an available space is located, NWDESCRP ($B21C) copies *
|
|
* the name of the wanted file from the primary file name buffer *
|
|
* (PRIMFNBF, $AA75) into the new entry space. A check is then *
|
|
* made to see if the command can legally create a new file. The *
|
|
* identifying command byte (NDX2CMD, $AA5F) is used to index a *
|
|
* table of command attributes (CMDATTRB, $A909). Because bit 0 *
|
|
* of the first attribute byte associated with the VERIFY command *
|
|
* is clear, a new file cannot legally be created. As a result, *
|
|
* the VERIFY command is exited with a file-not-found message. *
|
|
* If a (non-deleted) description entry containing the name *
|
|
* of the wanted file is located, execution branches to the *
|
|
* FILLINWA routine ($ABA6). FILLINWA uses the information *
|
|
* contained in the description entry to customize the FM work *
|
|
* area. After the carry is cleared execution jumps to the *
|
|
* READTS routine ($AF5E). Because the carry was just cleared, *
|
|
* READTS reads in the file's first T/S list sector. *
|
|
* Execution then returns to the FNVERIFY routine at *
|
|
* VRFYREAD ($AD1B). VRFYREAD in turn calls NXTDATRD ($BOB6) to *
|
|
* read the file's data sectors into the data sector buffer. *
|
|
* The execution patterns associated with NXTDATRD and its *
|
|
* associated subroutines can be difficult to trace because so *
|
|
* many flags are envolved. Unfortunately these flags are an *
|
|
* evil necessity because NXTDATRD is called by almost any DOS *
|
|
* command that reads or writes disk data. A description of the *
|
|
* flags and possible execution patterns that can be taken by *
|
|
* NXTDTRD when called from the VERIFY command are shown below: *
|
|
* *
|
|
* Major decisions and flags used: *
|
|
* Use current data sector? *
|
|
* - yes = FILPTSEC/+1 = RELPREV/+1 *
|
|
* - no = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* - when a file is first opened, the common open *
|
|
* routine (COMNOPEN, $AB28) sets FILPTSEC: $0000 *
|
|
* and RELPREV: $007A. This forces the computer *
|
|
* to try to use the file's first data sector. *
|
|
* - when a data sector is filled by successively *
|
|
* adding data byte, FILPTSEC/+1 > RELPREV/+1. *
|
|
* - if the position function was used to adjust *
|
|
* the filepointer out of the range of RELPREV, *
|
|
* then FILPTSEC/+1 < > RELPREV/+1. *
|
|
* Use current T/S list ? *
|
|
* - yes = FILPTSEC/+1 > RELFIRST/+1 *
|
|
* and FILPTSEC/+1 < RELASTP1/+1. *
|
|
* - no = FILPTSEC/+1 < RELFIRST/+1 *
|
|
* or FILPTSEC/+1 > = RELASTP1/+1. *
|
|
* Update current data or T/S list sectors? *
|
|
* - yes = bit 6 (data) or bit 7 (T/S list) of UPDATFLG *
|
|
* ($B5D5) are set. *
|
|
* - no = bits 6 and 7 of UPDATFLG are clear. *
|
|
* Read first T/S list? *
|
|
* - yes = (c) = 0 - carry cleared if file was just *
|
|
* opened. File pointer was previously *
|
|
* backed up by CALCFPTR ($B300). *
|
|
* - no = (c) = 1 - file is long enough that another T/S *
|
|
* list must be used. *
|
|
* Writing data? *
|
|
* - yes = OPCODEFM ($B105) = 4. *
|
|
* - no = OPCODEFM < > 4. *
|
|
* Any more data pairs listed in current T/S list? *
|
|
* - yes = trk byte portion of data pair < > $00. *
|
|
* - no = trk byte portion of data pair = $00. *
|
|
* Any more T/S lists in file? *
|
|
* - yes = trk byte portion of link < > $00. *
|
|
* - no = trk byte portion of link = $00. *
|
|
* (Link to first T/S list is contained in the first two *
|
|
* bytes of the file description entry in the directory sec. *
|
|
* Link to subsequent T/S lists are contained in 2nd and 3rd *
|
|
* bytes (offsets $01 and $02) of previous T/S lists.) *
|
|
* *
|
|
* Note: RELPREV ($B5E0, $B5E1) *
|
|
* = the relative sector number (in relation to *
|
|
* the entire file) of the last data sector that *
|
|
* was read or written. (Possible values are: *
|
|
* $0000, $007A, 2*$007A, 3*$007A, 4*$007A.) *
|
|
* RELFIRST ($B5DC, $B5DD) *
|
|
* = the relative sector number (in relation to *
|
|
* the entire file) of the first data sector *
|
|
* that is (or can be) listed in the current *
|
|
* T/S list. *
|
|
* RELASTP1 ($B5DE, $B5DF) *
|
|
* = one greater than the maximum relative sector *
|
|
* number (in relation to the entire file) of *
|
|
* the last data sector that can possibly be *
|
|
* listed in the current T/S list. (Possible *
|
|
* values are: $007A, 2*$007A, 3*$007A, 4*$007A *
|
|
* and 5*$007A.) *
|
|
* NXTDATRD execution patterns: *
|
|
* Pattern 1: = FILPTSEC/+1 = RELPREV/+1 *
|
|
* - select the current data sector. *
|
|
* - exit NXTDATRD routine via XITNXDAT. *
|
|
* Pattern 2: = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* = FILPTSEC/+1 > = NDXFIRST/+1 *
|
|
* and FILPTSEC/+1 < RELASTP1/+1 *
|
|
* = trk portion of data pair < > 0 *
|
|
* - update the current data sector if necessary. *
|
|
* 2a: - get valid link byte to the next data sector from *
|
|
* the current T/S list. *
|
|
* - read in the next data sector. *
|
|
* - update RELPREV. *
|
|
* - exit the NXTDATRD routine via XITNXDAT. *
|
|
* Pattern 3: = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* = FILPTSEC/+1 > = RELFIRST/+1 *
|
|
* and FILPTSEC/+1 < RELASTP1/+1 *
|
|
* = trk portion of data pair = 0 *
|
|
* = OPCODEFM < > 4 *
|
|
* - update the current data sector if necessary. *
|
|
* 3a: - detect zeroed out data pair in the current T/S *
|
|
* list. *
|
|
* - test OPCODEFM to determine that we are NOT *
|
|
* writing and set the carry flag to signal just *
|
|
* read all the data. *
|
|
* - exit the NXTDATRD routine via XITNXDAT. *
|
|
* Pattern 4: = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* = FILPTSEC/+1 < = RELFIRST/+1 *
|
|
* = carry clear at $AF69 *
|
|
* = trk portion of link byte to next T/S list < > 0 *
|
|
* - update current data and/or T/S list secs if *
|
|
* necessary. *
|
|
* - get link to file's first T/S list from the file *
|
|
* description entry in the current directory sec. *
|
|
* - read in the first T/S list. *
|
|
* - loop back to do 2a, 3a or 5. *
|
|
* Pattern 5: = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* = FILPTSEC/+1 > = RELASTP1/+1 *
|
|
* = carry set at $AF69 *
|
|
* = trk portion of link to next T/S list < > 0 *
|
|
* - update current data and/or current T/S list *
|
|
* sectors if necessary. *
|
|
* - get valid link bytes to the next T/S list from *
|
|
* the current T/S list. *
|
|
* - loop back to do 2a, 3a or repeat 5. *
|
|
* Pattern 6: = FILPTSEC/+1 < > RELPREV/+1 *
|
|
* = FILPTSEC/+1 > = RELASTP1/+1 *
|
|
* = carry set at $AF69 *
|
|
* = trk portion of link to next T/S list < > 0 *
|
|
* = OPCODEFM < > 4 *
|
|
* - update current data and/or current T/S list *
|
|
* sectors if necessary. *
|
|
* - get zeroed out link bytes to the next T/S list *
|
|
* from the current T/S list. *
|
|
* - test OPCODEFM to determine that we are NOT *
|
|
* writing and set the carry flag to signal that *
|
|
* we have just read all the data. *
|
|
* - exit NXTDATRD the routine via XITNXDAT. *
|
|
* *
|
|
* If no errors are encountered, the NXTDATRD routine *
|
|
* ($B0B6) is exited via XITNXDAT ($B12C). XITNXDAT points the *
|
|
* A4L pointer ($42, $43) at the DOS data sector buffer and sets *
|
|
* (y) to index that buffer. When an "RTS" is encountered, *
|
|
* execution returns to $AD1E in the VRFYREAD routine. *
|
|
* If this return is made with a set carry, all the data *
|
|
* have been read and the verify function is exited via a branch *
|
|
* to the TOOKFMXT ($AD0F). Otherwise, the file pointer is *
|
|
* incremented and execution jumps back to the VRFYREAD routine *
|
|
* ($AD1B) to "read" the next data sector. *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
|
|
|
|
(AD18)
|
|
FNVERIFY JSR COMNOPEN ;Locate file with the same name and open it.
|
|
|
|
* Common open routine.
|
|
(AB28)
|
|
COMNOPEN JSR ZWRKAREA ;Initialize the work area.
|
|
|
|
|
|
* Zero out the FM work area so it can be customized
|
|
* in accordance with the calling function.
|
|
* (Although some work bytes may not be subsequently
|
|
* altered, don't be lulled into thinking that they
|
|
* are not important. Zero values can be just as relevant
|
|
* as non-zero values.)
|
|
* (P.S. Don't confuse FM work area with its image
|
|
* (FM work buffer) that is housed in the chain of
|
|
* DOS buffers.)
|
|
(ABDC)
|
|
ZWRKAREA LDA #0
|
|
TAX ;Initialize the x-index.
|
|
ZEROWRKA STA FMWKAREA,X ;Put a $00 byte in work area.
|
|
INX
|
|
CPX #45 ;Work area is 45 bytes long.
|
|
(ABE5) BNE ZEROWRKA
|
|
|
|
* Begin customizing the work area.
|
|
* Get volume, drive, slot & catalog track
|
|
* values from the FM parameter list. Put
|
|
* drive, slot*16, catalog track and
|
|
* complemented volume number in the work area.
|
|
(ABE7) LDA VOLFM ;Volume number.
|
|
EOR #$FF ;Calculate 1's complement of volume #.
|
|
STA VOLWA
|
|
LDA DRVFM ;Drive #.
|
|
STA DRVWA
|
|
LDA SLOTFM ;Get slot #.
|
|
ASL ;Calculate slot * 16.
|
|
ASL
|
|
ASL
|
|
ASL
|
|
TAX ;Set (x) = slot * 16.
|
|
STX SLOT16WA
|
|
LDA #$11 ;Normal catalog trk = #17.
|
|
STA TRKWA
|
|
(AC05) RTS
|
|
|
|
(AB2B) LDA #1 ;Describe sector length as 256 bytes
|
|
(AB2D) STA SECSIZWA+1 ;(in the FM work area).
|
|
|
|
* Get record length from the FM parameter
|
|
* list & put it in the FM work area.
|
|
* (Don't allow a zero length. If zero,
|
|
* change it to one.)
|
|
(AB30) LDX RECLENFM+1
|
|
LDA RECLENFM
|
|
BNE STRECLEN ;Non-zero record length is ok.
|
|
CPX #0
|
|
BNE STRECLEN
|
|
INX ;Was zero, make it one instead.
|
|
STRECLEN STA RECLENWA ;Put length in FM work area.
|
|
STX RECLENWA+1
|
|
(AB43) JSR GETFNTRY ;Try to find a directory sector for the file.
|
|
|
|
* Locate or create a file entry in the
|
|
* directory buffer.
|
|
* Make two searches if necessary:
|
|
* - Search1 - try to locate entry with same name as file wanted.
|
|
* - Search2 - couldn't locate entry corresponding to file
|
|
* wanted so create a new entry in first available
|
|
* space in the directory sector.
|
|
* Two searches are never required if the VERIFY cmd is
|
|
* accessed via the INIT, SAVE, or BSAVE commands.
|
|
* These calling commands would have previously
|
|
* created a new file description if necessary.
|
|
(B1C9)
|
|
GETFNTRY JSR READVTOC ;Read in the VTOC so we can get the link to
|
|
;TRKMAPS & to the first directory sector.
|
|
|
|
* Read the Volume Table of Contents (VTOC).
|
|
(AFF7)
|
|
READVTOC LDA #1 ;Read opcode for RWTS.
|
|
(AFF9) BNE RDWRVTOC ;ALWAYS.
|
|
|
|
* Code common to read/write VTOC.
|
|
(AFFD)
|
|
RDWRVTOC LDY ADRVTOC ;Get address of VTOC from the
|
|
STY IBBUFP ;FM constants table & designate it
|
|
LDY ADRVTOC+1 ;as the I/O buffer in RWTS's IOB.
|
|
STY IBBUFP+1
|
|
LDX TRKWA ;Enter RWTS driver with (x)/(y) equal
|
|
LDY #0 ;to the trk/sec values of the VTOC.
|
|
(B00E) JMP RWTSDRVR ;Call driver to read/write the VTOC.
|
|
------------
|
|
|
|
* Read/Write Track/Sector driver.
|
|
(B052)
|
|
RWTSDRVR .
|
|
.
|
|
(See dism'bly of RWTS driver using READ.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Point A4L/H at the primary file name buffer.
|
|
(B1CC) LDA FNAMBUFM ;Get address of the name buffer from the
|
|
STA A4L ;FM parameter list & put it in the A4L/H
|
|
LDA FNAMBUFM+1 ;pointer.
|
|
(B1D4) STA A4L+1
|
|
|
|
* Try to find the directory sector with the
|
|
* wanted file name & read it into the directory
|
|
* sector buffer. Make two searches if necessary.
|
|
* On the first search, try to find a matching name.
|
|
* If that doesn't work, do a second search to store
|
|
* the description in the first available file
|
|
* description field in a directory sector.
|
|
(B1D6) LDA #1 ;Initialize the search counter (SCRNSRCH)
|
|
SETSRCH STA SCRNSRCH ;in the FM scratch space for two searches.
|
|
(B1D8) ;(1 = search1, 0 = search2)
|
|
(B1DB) LDA #0 ;Initialize offset of file description from
|
|
STA SECNXDIR ;the very first directory sector.
|
|
CLC ;(c)=0=signal to read first directory sec.
|
|
GETDIRSC INC SECNXDIR ;Kick up offset from first directory.
|
|
(B1E1) ;(On first entry, $00 --> $01.)
|
|
(B1E4) JSR RDDIRECT ;Go read directory sector into buffer.
|
|
|
|
* Read a directory sector.
|
|
(B011)
|
|
RDDIRECT PHP ;Save (c) on stack:
|
|
; (c) = 0 = read 1rst directory sector.
|
|
; (c) = 1 = read next directory sector.
|
|
(B012) JSR PT2DIRBF
|
|
|
|
* Designate the directory sector buffer
|
|
* as I/O buffer in RWTS's IOB.
|
|
(B045)
|
|
PT2DIRBF LDA ADRDIRBF ;Get addr of direc
|
|
STA IBBUFP ;sec buf from the
|
|
LDA ADRDIRBF+1 ;FM constants tbl
|
|
STA IBBUFP+1 ;& designate it as
|
|
(B051) RTS ;as the I/O buffer.
|
|
|
|
(B015) PLP ;Check if 1rst directory sec or not.
|
|
(B016) BCS RDNXTDIR ;Go read next directory sector.
|
|
|
|
* Read the first directory sector.
|
|
* (Carry = 0.)
|
|
(B018)
|
|
RDFIRDIR LDY FIRDIRSC ;(y)/(x) = trk/sec vals of first directory
|
|
LDX FIRDIRTK ;sector (from the VTOC buffer).
|
|
(B01E) BNE DODIRRD ;ALWAYS - go read in directory sector.
|
|
|
|
* Read the next directory sector.
|
|
* (Carry = 1.)
|
|
(B020)
|
|
RDNXTDIR LDX DIRLNKTK ;Get track of next directory sec from the
|
|
;link in the current directory sector.
|
|
(B023) BNE GETDIRLK ;Link not zeroed out.
|
|
SEC ;Link zeroed out - exit with (c) = 1 to
|
|
(B026) RTS ;signal there are no more directory secs.
|
|
============
|
|
|
|
(B027)
|
|
GETDIRLK LDY DIRLNKSC ;Get sector of next directory sec from the
|
|
;link in the current directory sector.
|
|
|
|
* Call to read in the directory sector.
|
|
(B02A)
|
|
DODIRRD STX CURDIRTK ;Save trk/sec vals of directory sec that
|
|
(B02D) STY CURDIRSC ;we are about to read so they will be
|
|
;the current directory sec values for the
|
|
;next time around.
|
|
(B030) LDA #1 ;Read opcode for RWTS.
|
|
(B032) JSR RWTSDRVR ;Call RWTS driver to do the read.
|
|
|
|
* Read/Write Track/Sector driver.
|
|
(B052)
|
|
RWTSDRVR .
|
|
.
|
|
(See dis'mbly of RWTS driver using READ.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(B035) CLC ;Link didn't zero out so signal that there
|
|
(B036) RTS ;are more directory secs to read & exit.
|
|
============
|
|
|
|
(B1E7) BCS CHNGSRCH ;Link zeroed out, no more directory secs,
|
|
;so go switch searches.
|
|
(B1E9) LDX #0
|
|
CKDIRTRK STX CURDIRNX ;Offset of file description into the current
|
|
(B1EB) ;directory sector.
|
|
(B1EE) LDA FIL1TSTK,X ;Get track number of first T/S list
|
|
;for a particular file from the file
|
|
;description entry in the directory sector.
|
|
(B1F1) BEQ CHRSRCHA ;If trk=0, no more files in this direc sec.
|
|
(B1F3) BMI CHRSRCHB ;Skip deleted file. (When a file is
|
|
;deleted, #$FF is put in byte where trk #
|
|
;of first T/S list is usually kept.
|
|
|
|
* Compare the name found in the file
|
|
* description entry portion of the
|
|
* directory sector with the file name
|
|
* wanted. (On entry, A4L/H points at
|
|
* the primary file name buffer.)
|
|
(B1F5) LDY #0 ;Initialize index to file name buffer.
|
|
INX ;Point (x) at the first char position
|
|
INX ;in the name field of description entry.
|
|
CMPNAMES INX
|
|
LDA (A4L),Y ;Get char of name from primary.
|
|
CMP FIL1TSTRK,X ;Compare to char in name of description.
|
|
BNE DONTMTCH ;Chars (and therefore names) don't match.
|
|
INY
|
|
CPY #30 ;Done all chars yet (0 to 29)?
|
|
BNE CMPNAMES ;Chars matched, branch if more to check.
|
|
LDX CURDIRNX ;All chars matched, so names matched.
|
|
CLC ;Return with (x) = index to file
|
|
(B20A) RTS ;description in current directory sector
|
|
============ ;and with (c) = 0 to signal that the
|
|
;correct file description was found.
|
|
|
|
* Advance index to point at the next
|
|
* potential file description entry.
|
|
(B20B)
|
|
DONTMTCH JSR NXPLUS35 ;Names didn't match, so adjust index
|
|
;to point at the next entry.
|
|
|
|
* Add 35 to the offset to point the index
|
|
* at the next file description entry.
|
|
* (Check to make sure that we don't index
|
|
* right off the end of the directory sec.)
|
|
(B230)
|
|
NXPLUS35 CLC
|
|
LDA CURDIRNX
|
|
(B234) ADC #35 ;Add 35 to index. (Each file description
|
|
;entry is 35 bytes long.)
|
|
(B236) TAX ;Check if there is more space for entries
|
|
CPX #245 ;in the current directory sector.
|
|
(B239) RTS ;Exit with (c) conditioned:
|
|
; (c) = 0 = more space in directory.
|
|
; (c) = 1 = ran off end of directory.
|
|
|
|
(B20E) BCC CKDIRTRK ;More potential file descriptions to check
|
|
;in this directory sector.
|
|
(B210) BCS GETDIRSC ;Go get next directory sector.
|
|
------------
|
|
|
|
* If we just completed the first seach,
|
|
* go back to do the second search.
|
|
(B212)
|
|
CHRSRCHA LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
|
(B215) BNE SETSRCH ;Go switch to second search.
|
|
|
|
* If first search, skip deleted files.
|
|
* If second search, fall through to store
|
|
* the description in the first unused
|
|
* space in the directory.
|
|
(B217)
|
|
CHRSRCHB LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
|
(B21A) BNE DONTMTCH
|
|
|
|
* Couldn't locate the named file in the
|
|
* directory description entries, so begin
|
|
* creating a new description in the first available
|
|
* space in a directory (in case command can
|
|
* legally create a new file).
|
|
(B21C)
|
|
NWDESCRP LDY #0 ;Initialize index to primary file name buffer.
|
|
INX ;Set index to first char position in the
|
|
INX ;name field of the file description entry
|
|
SETNWNAM INX ;space in the directory sector.
|
|
LDA (A4L),Y ;Copy char from primary file name buffer
|
|
STA FIL1TSTK,X ;to the directory description space.
|
|
INY
|
|
CPY #30 ;30 chars in name (0 to 29).
|
|
BNE SETNWNAM ;Branch if more chars to copy.
|
|
LDX CURDIRNX ;Return with (x) = index to file
|
|
SEC ;description space in current directory
|
|
(B22F) RTS ;sector & with (c)=1 to signal new entry
|
|
============ ;was just created.
|
|
|
|
* If first search, switch to second search.
|
|
* If second search, link zeroed out because
|
|
* there isn't enough room left on the
|
|
* disk for a new entry. Therefore,
|
|
* exit with a disk-full error message.
|
|
(B23A)
|
|
CHNGSRCH LDA #0 ;Used to reset search counter if
|
|
;we go back to start a second search.
|
|
(B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2)
|
|
BNE SETSRCH ;Just did search1 so go start search2.
|
|
(B241) JMP DISKFULL ;Even second search was unsuccesful
|
|
------------ ;so go handle a disk-full error.
|
|
|
|
(AB46) BCC FILLINWA ;Branch if found a directory sector with
|
|
;name wanted in the file description entry.
|
|
;Will always find name if using verify in association
|
|
;with INIT, SAVE or BSAVE commands because these commands
|
|
;would have previously provided a new name if necessary.
|
|
|
|
* Named file wasn't found in directory,
|
|
* so prepare a new file entry in case
|
|
* command can legally create a new file.
|
|
(AB48) STX CURDIRNX ;Offset to new description entry in
|
|
;case want to create a new file.
|
|
|
|
* Check to see if command can
|
|
* legally create a new file.
|
|
(AB4B) LDX NDX2CMD ;(x) = index representing command.
|
|
(AB4E) LDA CMDATTRB,X ;Get first byte containing description
|
|
;of the given command's attributes.
|
|
(AB51) LDX CURDIRNX ;(x) = index for new file description
|
|
;entry into the directory sector.
|
|
(AB54) LSR ;(c) = bit 0 of 1rst attribute byte.
|
|
(AB55) BCS CREATNEW ;If (c) = 1, command can create a new file.
|
|
;ALWAYS FALL THRU WHEN VERIFYING.
|
|
|
|
* Command can't create a new file.
|
|
* See which language we are using and
|
|
* exit with the appropriate error msg.
|
|
(AB57)
|
|
NEWILLGL LDA CONDNFLG ;$00=warmstart, $01=reading, $40=A(RAM),
|
|
;$80=coldstart & $C0=integer.
|
|
(AB5A) CMP #$C0 ;Integer in ROM?
|
|
BNE TOFILNOT ;No.
|
|
(AB5E) JMP LNGNOTAV ;Yes - handle language-not-available error.
|
|
------------
|
|
TOFILNOT JMP FILENOT ;Handle file-not-found error.
|
|
(AB61) ------------
|
|
|
|
* Fill in the FM work area buffer.
|
|
* (Routine common to opening a new
|
|
* or pre-existing file.)
|
|
(ABA6)
|
|
FILLINWA LDA FIL1TSTK,X ;T/S list trk val (from directory sec).
|
|
STA FIRSTSTK
|
|
LDA FIL1TSSC,X ;T/S list sec val (from directory sec).
|
|
STA FIRTSSEC
|
|
LDA FIL1TYPE,X ;File type (from directory sec).
|
|
STA FILTYPFM
|
|
STA FILTYPWA
|
|
LDA FIL1SIZE,X ;File size (from directory sec).
|
|
STA FILENSEC
|
|
LDA FIL1SIZE+1,X
|
|
STA FILENSEC+1
|
|
STX BYTNXDIR ;Index into directory sec to description.
|
|
LDA #$FF ;Pretend that the last data sector used had
|
|
STA RELPREV ;a relative sector number (in relation to
|
|
(ABCF) STA RELPREV+1 ;the entire file) of $FFFF. NOTE: This
|
|
;value is later used to trick the read and
|
|
;write subfunctions into ignoring the data
|
|
;sector currently in memory.
|
|
(ABD2) LDA MXIN1TSL ;Dicatate that a T/S list can only describe $7A
|
|
(ABD5) STA MXSCURTS ;(#122) data sectors. Note: This value is later
|
|
;used by the read and write subfunctions to decide
|
|
;whether or not the T/S list currently in memory
|
|
;should be used.
|
|
|
|
* Read first T/S list sector
|
|
* to the T/S list buffer.
|
|
(ABD8) CLC ;(c) = 0 = signal 1rst T/S list sector.
|
|
(ABD9) JMP READTS ;Go read in the T/S list sector.
|
|
------------
|
|
|
|
* Read T/S list sector.
|
|
(AF5E)
|
|
READTS .
|
|
.
|
|
(See dis'mbly given below.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(AD1B)
|
|
VRFYREAD JSR NXTDATRD ;Read the next data sector in. (Assume
|
|
;the data sector we want is not presently
|
|
;in memory.)
|
|
|
|
* Check if we need to read the next data
|
|
* sector into the data sector buffer.
|
|
*
|
|
* - Is the data sec we want already in memory?
|
|
* - If so, does it require updating?
|
|
|
|
* If sector offset into file (FILPTSEC) equals
|
|
* the relative sector number of the last sector
|
|
* read or written (RELPREV), then sector we want
|
|
* is presently in memory. If it is not in memory,
|
|
* read in the data sector wanted. However, first
|
|
* check if the data sector has changed since the
|
|
* last read or write. If it has, the disk must
|
|
* be updated before we read in the new data
|
|
* sector so we don't overwrite the data
|
|
* sector buffer and loose information.
|
|
* NOTE: - if this subroutine is called from a
|
|
* write subfunction and FILPTSEC is not
|
|
* equal to RELPREV, then the data sector
|
|
* buffer must be full & therefore should
|
|
* be written to the disk before any more
|
|
* information is read in.
|
|
* - if the file was just opened, the open
|
|
* subfunction set FILPTSEC = $0000 and
|
|
* RELPREV = #$FFFF so always force reading
|
|
* of a new data sector even if the correct
|
|
* sector is already in memory.
|
|
|
|
* NOTE: Not all of the NXTDATRD routine is listed
|
|
* because not all of it applies to the
|
|
* VERIFY function.
|
|
(B0B6)
|
|
NXTDATRD LDA FILPTSEC ;Last sector used versus sector wanted?
|
|
CMP RELPREV
|
|
(B0BC) BNE CKWCURDA ;Not same - will eventually have to read in
|
|
;a new data sector.
|
|
;Note: THIS BRANCH IS ALWAYS TAKEN ON FIRST
|
|
; ENTRY FROM THE VERIFY FUNCTION
|
|
; because RELPREV was set to #$FFFF
|
|
; in the FILLINWA section of the
|
|
; common open routine. In other
|
|
; words, program flow in the VERIFY
|
|
; function is such that a new data
|
|
; read is forced even if the correct
|
|
; data sector is already resident in
|
|
; the data sector buffer.
|
|
(B0BE) LDA FILPTSEC+1 ;Maybe same - check hi bytes.
|
|
CMP RELPREV+1
|
|
(B0C4) BEQ XITNXDAT ;Same, so go exit.
|
|
|
|
* Write the data sector if necessary.
|
|
* Data sector we want is not presently
|
|
* in memory. Check if we need to write
|
|
* the current data sector buffer before
|
|
* we read in the wanted data sector.
|
|
(B0C6)
|
|
CKWCURDA JSR CKDATUP ;Check the update flag to see if the data
|
|
;sector buffer has changed since the last
|
|
;read or write. If it has, write the data
|
|
;sector buffer to the disk.
|
|
|
|
* Check if the data sector has changed
|
|
* since the last read or write was done.
|
|
(AF1D)
|
|
CKDATUP BIT UPDATFLG ;Check bit 6 to see if data sec requires
|
|
;updating or not.
|
|
(AF20) BVS WRITDATA ;Take branch if data requires updating.
|
|
;ALWAYS FALL THRU WHEN USING VERIFY.
|
|
(AF22) RTS
|
|
|
|
* Should current T/S list be used?
|
|
* (That is, should the data sector be listed in
|
|
* the present T/S list sector? If not, then
|
|
* will need to read in the correct T/S list.)
|
|
|
|
* Is the sector offset into the file of the present
|
|
* data sector less than the relative sector number
|
|
* of the FIRST data sector that can be described in
|
|
* the T/S list presently in memory? (If less,
|
|
* then need to read in a different T/S list sector.)
|
|
(B0C9)
|
|
CKCURTS LDA FILPTSEC+1 ;Sector offset in file associated with
|
|
(B0CC) CMP RELFIRST+1 ;the present data sector versus the
|
|
;relative sector number of the first data
|
|
;sector that can be described in the present
|
|
;T/S list.
|
|
(B0CF) BCC NEEDNXTS ;Data sector wanted represents a SMALLER offset
|
|
;into the file so need a different T/S list.
|
|
(B0D1) BNE CKCURTS1 ;Sector offset of wanted data sector is
|
|
;LARGER than that of the first data sector that
|
|
;can be described in the present T/S list so it
|
|
;may still belong to this T/S list.
|
|
(B0D3) LDA FILPTSEC ;Hi bytes same - so compare low bytes.
|
|
CMP RELFIRST
|
|
(B0D9) BCC NEEDNXTS ;Sector offset of wanted files is LESS,
|
|
;so read in a different T/S list.
|
|
;(Start by reading the file's first T/S list.)
|
|
|
|
* Sector offset associated with the data
|
|
* sector we want is either GREATER THAN OR
|
|
* EQUAL TO the relative sector offset
|
|
* associated with the first data sector that can
|
|
* be described in this T/S list. Therefore,
|
|
* compare the sector offset of the sector
|
|
* wanted with the relative sector number
|
|
* (plus 1) of the LAST sector that can be
|
|
* described in the present T/S list.
|
|
(B0DB)
|
|
CKCURTS1 LDA FILPTSEC+1 ;Sector offset associated with data sector
|
|
(B0DE) CMP RELASTP1+1 ;we want versus the relative sector number
|
|
;(plus 1) of the LAST data sector that can possibly
|
|
;be described in the present T/S list.
|
|
(B0E1) BCC GETDATPR ;Sector offset assoc with data sector we
|
|
;wanted IS described in the present T/S list.
|
|
(B0E3) BNE NEEDNXTS ;Sector offset of present data sector is
|
|
;LARGER than that of the LAST data sector
|
|
;(plus 1) that can possibly be described in the
|
|
;present T/S list, so we need a new T/S list sector.
|
|
(B0E5) LDA FILPTSEC ;Hi bytes same - so compare low bytes.
|
|
CMP RELASTP1
|
|
(B0EB) BCC GETDATPR ;Sector offset associated with data sector
|
|
;we want is LESS than the relative sector
|
|
;number (plus 1) of the last data sector that
|
|
;can possibly be listed in the present T/S list.
|
|
;There4, data sector wanted should be described
|
|
;in the present T/S list.
|
|
|
|
* The data sector we want is NOT listed
|
|
* in the present T/S list, so we must
|
|
* read a different T/S list sector.
|
|
* (NOTE: Routine is entered with (c) = 1 if need a
|
|
* higher numbered T/S list. If (c) = 0, then the file
|
|
* pointer was backed up and we need a smaller numbered
|
|
* T/S list.)
|
|
(B0ED)
|
|
NEEDNXTS JSR READTS ;Read in the next (or first) T/S list. However,
|
|
;first check the update flag to see if the T/S list
|
|
;presently in memory requires updating before
|
|
;we read in the next (or first) T/S list sector.
|
|
;If updating is required, write the present
|
|
;T/S list.
|
|
|
|
* Read T/S list sector.
|
|
(AF5E)
|
|
READTS PHP ;Save (c) denoting if 1rst T/S list or not.
|
|
;(c) = 0 = read 1rst T/S list sec.
|
|
;(c) = 1 = read next T/S list sec.
|
|
(AF5F) JSR CKTSUPDT ;Write T/S list sec buf if updating is
|
|
;required. (If T/S list buf has changed
|
|
;since last read or write, then write it
|
|
;back to the disk so don't overwrite buf
|
|
;and lose information when read the new
|
|
;T/S list sector.)
|
|
|
|
* Check if T/S list requires updating.
|
|
* (ie. Has T/S list buf changed since
|
|
* the last read or write?)
|
|
(AF34)
|
|
CKTSUPDT LDA UPDATFLG
|
|
(AF36) BMI WRITETS ;If bit 7 set, updating is required.
|
|
;ALWAYS FALL THRU FOR VERIFY FUNCTION.
|
|
(AF37) RTS
|
|
============
|
|
|
|
(AF62) JSR SETTSIOB ;Prepare RWTS's IOB for READING a T/S list.
|
|
|
|
* Prepare RWTS's IOB for reading
|
|
* or writing the T/S list sector.
|
|
(AF4B)
|
|
SETTSIOB LDA TSBUFFM ;Get adr of the T/S list buf from the FM
|
|
STA IBBUFP ;parameter list & designate T/S list buf
|
|
LDA TSBUFFM+1 ;as the I/O buffer in RWTS's IOB.
|
|
STA IBBUFP+1
|
|
LDX CURTSTRK ;Set (x)/(y) = trk/sec of current T/S list.
|
|
LDY CURTSSEC
|
|
(AF5D) RTS
|
|
|
|
(AF65) JSR SELTSBUF ;Select the T/S list buffer.
|
|
|
|
* Point A4L/H at the T/S list sector buffer.
|
|
(AF0C)
|
|
SELTSBUF LDX #2 ;Index for T/S list buf.
|
|
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
|
|
|
(AF12)
|
|
PT2FMBUF LDA WRKBUFFM,X ;Get address of the desired buffer from
|
|
STA A4L ;the FM parameter list & put it in the
|
|
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(AF68) PLP ;Get saved (c) back from stack.
|
|
(AF69) BCS RDNXTTS ;If (c) = 1, already read first T/S list
|
|
;sec, so go read next one.
|
|
|
|
* Read first T/S list sector.
|
|
* (Carry was clear.)
|
|
(AF6B)
|
|
RDFIRSTS LDX FIRSTSTK ;Set (x)/(y)=trk/sec of first T/S list sec.
|
|
LDY FIRTSSEC
|
|
(AF71) JMP RDTSLST ;Go read T/S list sector into buffer.
|
|
------------
|
|
|
|
* Read next T/S list sector.
|
|
* (Carry was set.)
|
|
(AF74)
|
|
RDNXTTS LDY #1 ;Index into T/S list buffer.
|
|
LDA (A4L),Y ;Trk for link to next T/S list sector.
|
|
(AF78) BEQ TSLNKZRO ;Link zeroed out, so there are no more
|
|
;T/S list sectors for file.
|
|
(AF7A) TAX ;(x) = next T/S list trk.
|
|
INY
|
|
LDA (A4L),Y ;Sector for link to next T/S list sector.
|
|
TAY ;(y) = next T/S list sector.
|
|
(AF7F) JMP RDTSLST ;Go read in next T/S list sector.
|
|
------------
|
|
|
|
* T/S link zeroed out so now must
|
|
* decide if got an error or not.
|
|
(AF82)
|
|
TSLNKZRO LDA OPCODEFM ;Check read/write status to see if want to
|
|
CMP #4 ;add another T/S list or not.
|
|
BEQ UPDATETS ;Writing, so go update link.
|
|
(AF89) SEC ;Set (c) = 1 to signal no more data.
|
|
;(Causes out-of-data error when reading.
|
|
;Signals verification completed when verifying.)
|
|
(AF8A) RTS
|
|
=========
|
|
|
|
* Subroutine to read T/S list sector.
|
|
(AFB5)
|
|
RDTSLST LDA #1 ;READ opcode for RWTS.
|
|
|
|
* Code common to read/write T/S list.
|
|
(AFB7)
|
|
RDWRTS STX CURTSTRK ;New T/S list sector trk/sec values (x)/(y)
|
|
STY CURTSSEC ;become current T/S list trk/sec values.
|
|
(AFBD) JSR RWTSDRVR ;Call RWTS driver to read/write current T/S
|
|
;list.
|
|
|
|
* Read or write the current T/S list.
|
|
(B052)
|
|
RWTSDRVR .
|
|
.
|
|
(See dis'mbly of RWTS driver using READ or WRITE.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Update the FM work area
|
|
* (not in DOS buffer chain).
|
|
(AFC0) LDY #5 ;Offset into current T/S list buffer.
|
|
LDA (A4L),Y ;Get & save the relative sector number of
|
|
(AFC4) STA RELFIRST ;the first data sector that can be
|
|
;described in this T/S list. (Possible
|
|
;values are: $0000, $007A, 2*$007A,
|
|
;3*$007A or 4*$007A.)
|
|
(AFC7) CLC ;Add the maximum number of secs that
|
|
ADC MXSCURTS ;can be described in this T/S list.
|
|
(AFCB) STA RELASTP1 ;Store the maximum relative sector number
|
|
;(plus 1) that can possibly be described
|
|
;in this particular T/S list. (That is,
|
|
;reset RELASTP1.)
|
|
(AFCE) INY
|
|
LDA (A4L),Y
|
|
STA RELFIRST+1
|
|
ADC MXSCURTS+1
|
|
STA RELASTP1+1 ;Value equals $0000, $007A
|
|
CLC ;2*$007A, 3*$007A, 4*$007A or 5*$007A.
|
|
(AFDB) RTS
|
|
============
|
|
|
|
(B0F0) BCC CKCURTS ;Go back and check if this is
|
|
;the correct T/S list.
|
|
(B0F2) RTS ;RETURN WITH (c)=1 TO SIGNAL RAN OUT OF DATA.
|
|
============
|
|
|
|
* We know that the data sector wanted
|
|
* should be described in the present T/S
|
|
* list so now calculate the offset into
|
|
* the T/S list sector where the data
|
|
* sector pair should be described.
|
|
(B0F3)
|
|
GETDATPR SEC ;Calculate offset to the data pair:
|
|
LDA FILPTSEC ; Sector offset of data sector into file
|
|
(B0F7) SBC RELFIRST ; minus the relative index of first data
|
|
; sector pair described in present T/S list.
|
|
(B0FA) ASL ;Times 2, cause 2 bytes used to describe a data pair.
|
|
ADC #12 ;Add 12 cause 1rst data pair is always listed
|
|
TAY ;12 bytes from the start of the T/S list buf.
|
|
(B0FE) JSR SELTSBUF ;Point A4L/H at the T/S list buffer.
|
|
|
|
* Point the A4L/H pointer at the
|
|
* T/S list sector buffer.
|
|
(AF0C)
|
|
SELTSBUF LDX #2 ;Index to select T/S list sector buffer.
|
|
(AF0E) BNE PT2FMBUF ;ALWAYS.
|
|
|
|
(AF12)
|
|
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from
|
|
STA A4L ;the FM parm list & put it in the pointer.
|
|
LDA WRKBUFFM+1,X
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(B101) LDA (A4L),Y ;Get trk number part of data sector pair.
|
|
(B103) BNE RDDATSEC ;Go read in the data sector.
|
|
|
|
* The track number part of the data sector
|
|
* pair listed in the T/S list was zero.
|
|
* Therefore, there are no more data sector
|
|
* pairs described in this T/S list.
|
|
(B105) LDA OPCODEFM ;Check to see if writing or not.
|
|
CMP #4 ;Opcode for write.
|
|
BEQ NEWPAIR ;Branch if writing.
|
|
SEC ;Not writing and ran out of data sector pairs
|
|
(B10D) RTS ;in the present T/S list, so go exit with
|
|
============ ;carry set to signal no more data.
|
|
|
|
* The data sector pair associated with the
|
|
* data sector wanted was contained in the
|
|
* current T/S list, so now read in the data
|
|
* sector wanted.
|
|
(B114)
|
|
RDDATSEC STA CURDATRK ;Save trk/sec values of current data sector
|
|
INY ;in the work area.
|
|
LDA (A4),Y ;Sector number of current data sector.
|
|
STA CURDATSEC
|
|
(B11D) JSR READDATA ;Go read in the data sector.
|
|
|
|
* Read data sector from disk
|
|
* to the data sector buffer.
|
|
(AFDC)
|
|
READDATA JSR PRPDAIOB ;Set up RWTS's IOB to read a data sector.
|
|
|
|
* Prepare RWTS'S IOB to read/write
|
|
* the data sector.
|
|
(AFE4)
|
|
PRPDAIOB LDY DATBUFFM ;Get the addr of the
|
|
LDA DATBUFFM+1 ;data sec buf from
|
|
STY IBBUFP ;the FM parm list and
|
|
(AFED) STA IBBUFP+1 ;designate it as the I/O
|
|
;buffer for RWTS's IOB.
|
|
(AFF0) LDX CURDATRK ;Enter RWTS driver with (x)/(y)
|
|
LDY CURDATSC ;= trk/sec vals corresponding
|
|
(AFF6) RTS ;to the data sector.
|
|
|
|
(AFDF) LDA #1 ;Opcode for RWTS's read command.
|
|
(AFE1) JMP RWTSDRVR ;Call RWTS driver to read the data sec buf.
|
|
------------
|
|
|
|
* Read/Write Track/Sector driver.
|
|
(B052)
|
|
RWTSDRVR .
|
|
.
|
|
(See dis'mbly of RWTSDRVR using READ.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Save sector-offset-into-file value
|
|
* associated with the data sector just read.
|
|
(B120)
|
|
SETPREV LDA FILPTSEC ;Current sector offset into file.
|
|
STA RELPREV ;Offset into file of last data sector read.
|
|
LDA FILPTSEC+1
|
|
(B129) STA RELPREV+1
|
|
|
|
* Exit the read-next-data-sector routine.
|
|
(B12C)
|
|
XITNXDAT JSR SELDABUF ;Select the data sector buffer.
|
|
|
|
* Point A4L/H at the data sector buffer.
|
|
(AF10)
|
|
SELDABUF LDX #4 ;Index to select data sector buffer.
|
|
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from
|
|
STA A4L ;the FM parameter list & put it in the
|
|
LDA WRKBUFFM+1,X ;A4L/H pointer.
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(B12F) LDY FILPTBYT ;(y) = offset into current data sector.
|
|
CLC ;Exit cleanly.
|
|
(B133) RTS
|
|
============
|
|
|
|
(AD1E) BCS TOOKFMXT ;END OF FILE DETECTED - exit file manager.
|
|
INC FILPTSEC ;Kick up the file pointer position and then
|
|
BNE VRFYREAD ;go back to read in the next data sector
|
|
INC FILPTSEC+1 ;until an end-of-file marker is detected.
|
|
(AD28) JMP VRFYREAD
|
|
-------------
|
|
|
|
(AD0F)
|
|
TOOKFMXT JMP GOODFMXT ;Exit the file manager cleanly.
|
|
------------
|
|
|
|
|
|
* Exit the file manager with or without errors.
|
|
(B35F)
|
|
LNGNOTAV LDA #1
|
|
(B361) BNE BADFMXIT ;ALWAYS.
|
|
|
|
(B373)
|
|
FILENOT LDA #6
|
|
(B375) BNE BADFMXIT ;ALWAYS.
|
|
|
|
(B377)
|
|
DISKFULL JMP FULLPTCH ;(See dis'mbly of errors.)
|
|
------------
|
|
|
|
(B37F)
|
|
GOODFMXT LDA RTNCODFM
|
|
CLC ;(c) = 0 to signal good operation.
|
|
BCC FMEXIT
|
|
BADFMXIT SEC ;(c) = 1 to signal unsuccessful.
|
|
FMEXIT PHP ;Save status on stack.
|
|
STA RTNCODFM ;Store return code in FM parameter list.
|
|
LDA #0
|
|
STA STATUS
|
|
(B38E) JSR CPYFMWA ;Copy the work area to the work buffer.
|
|
|
|
* Copy the FM work area (non-chain) to
|
|
* the FM work buffer (in DOS chain).
|
|
(AE7E)
|
|
CPYFMWA JSR SELWKBUF ;Select the FM work buffer (in DOS chain).
|
|
|
|
* Point the A4L/H pointer at the FM work buffer.
|
|
(AF08)
|
|
SELWKBUF LDX #0 ;Set index to select work buffer.
|
|
(AF0A) BEQ PT2FMBUF ;ALWAYS.
|
|
|
|
(AF12)
|
|
PT2FMBUF LDA WRKBUFFM,X ;Get address of selected buffer from the
|
|
STA A4L ;FM parameter list & put it in the pointer.
|
|
LDA WRKBUFFM+1,X
|
|
STA A4L+1
|
|
(AF1C) RTS
|
|
|
|
(AE81) LDY #0 ;Initialize index.
|
|
STORWRK LDA FMWKAREA,Y ;Get byte from the FM work area.
|
|
STA (A4L),Y ;Put it in the work buffer.
|
|
INY
|
|
CPY #45 ;45 bytes to copy (0 to 44).
|
|
BNE STORWRK
|
|
(AE8D) RTS
|
|
|
|
(B391) PLP ;Retrieve status of success of operation
|
|
;from the stack.
|
|
(B392) LDX STKSAV ;Adjust stack pointer to force exit to the
|
|
TXS ;caller of the function (even if we are
|
|
(B396) RTS ;presently several subroutines deeper than
|
|
============ ;the original entry point). (Returns to
|
|
;AFTRFUNC ($A6AB) in the FMDRIVER routine
|
|
;($A6A8).)
|