*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* * * * OPEN function handler * * * *----------------------------------------------------------------* * * * The open function handler (FNOPEN, $AB22) simply tries to * * locate the named file and read in its first T/S list. If the * * file does not already exits and if the calling command can * * legally create a new file, FNOPEN attempts to build a new file * * description and T/S list. * * * * Execution pattern: * * FNOPEN calls the common open routine (COMNOPEN, $AB28) to * * do all the dirty work. COMNOPEN first zeroes out the work * * area and customizes it with volume, drive, slot*16, track, * * sector size and record length values. If necessary, the * * record length is defaulted to value of "$0001". * * GETFNTRY ($B1C9) is called to read in a fresh VTOC and * * search the directory sectors for the file description entry of * * the wanted file. (The links to the first directory sector are * * housed in the VTOC. Each subsequent directory sector contains * * the link to the next directory sector. The link bytes of the * * last directtory sector are zeroed out.) * * Each directory contains up to seven different file * * descriptions. An example of the data contained in a file * * description is shown below: * * FIL1TSTK DS 1 ;Track # of first T/S list for file 1. * * FIL1TSSC DS 1 ;Sector # of first T/S list for file 1. * * FIL1TYPE DS 1 ;File type code for file 1. ($00=Text, * * ;$01=Integer, $02=Applesoft, $04=Binary, * * ;$08=S-type, $10=Relocatable, $20=A-type * * ;and $40=B-type.) The hi bit is set on * * ;locked files. For example, $02=unlocked * * ;Applesoft and $82=locked Applesoft. * * FIL1NAME DS 30 ;Name of file 1. If a file name less than * * ;30 bytes is used, trailing spaces are * * ;added to the name to fill the buffer. * * FIL1SIZE DS 2 ;Size of file 1 in terms of the number of * * ;sectors used. * * (If a file was deleted, the track # of the first T/S list sec * * was copied to the last byte position of the name field. The * * original track # byte (FIL1TSTK) was then overwritten with * * an #$FF.) * * 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 a (non-deleted) description entry containing * * the name of the wanted file is located, execution branches to * * the FILLINWA routine ($ABA6) which is described several * * paragraphs below. If the named can't be located after * * searching all the directories, 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). SCRNSRCH ($B39D) is used to flag which * * search is being done (1=first search, 0=second search). If no * * free space is located, a disk-full error message is printed. * * If an available space is located, NEWDESCRP ($B2C1) 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 attribute bytes (CMDATTRB, $A909) associated * * with the command. If bit 0 of the first attribute byte * * associated with the command is clear, a new file cannot be * * created. The command is subsequently aborted with a file-not- * * found error message. However if bit 0 is set, execution * * branches to the CREATNEW routine ($AB64) to generate a new * * file description and T/S list sector. * * CREATNEW initializes the file size field in the new * * description space with a "$0001". ASGNTKSC ($B244) is then * * called to assign a free sector for the new T/S list sector. * * If no free sector can be found, a disk-full error message is * * generated. * * If a track has not already been assigned to the file, * * execution branches to the PRPNWTRK routine ($B26A). PRPNWTRK * * reads in a fresh VTOC and adds the direction (+1, $01 or -1, * * $FF) to the last used track number. If the resulting track * * number is too large, the direction is reversed. A legal track * * number causes execution to branch to the CHK4FREE routine * * ($B294) to look for a free sector. If no free sector is * * found, GETNWTRK ($B272) is used to find another track to * * search. * * Once a free sector is located, CPYTKMAP ($B2A1) zeroes out * * the corresponding track map and writes the modified VTOC to * * the disk. Unfortunately, this routine is over exuberant. * * Because it zeroes out all the bytes associated with a given * * track map, an entire track is allocated in the VTOC. (The * * unneeded sectors are later released when the file is closed.) * * Eventually, the ASGNTKSC routine is exited at $B264 with * * ASIGNTRK ($B5F1) and ASIGNSEC ($B5F0) containing the track and * * sector values of the new T/S list sector. These values are * * placed in the new file description entry along with the file * * type code. The directory sector containing the new file * * description is then updated on the disk. Next, the T/S list * * buffer is zeored out and written to the disk as the file's * * first T/S list sector. Bit 7 of the update flag (UPDATFLG, * * $B5D5) is cleared to signal that the T/S list is up to date. * * Execution finally branches to the FILLINWA routine ($ABA6) * * which is common to opening a new or pre-exisiting file. * * FILLINWA customizes the work area with information from * * the file description. (The relative sector number of the last * * sector read or written (RELPREV, $B5E0) is set to "$FFFF". If * * the command that called FNOPEN later reads data from, or * * writes data to the disk, this value eventually forces the * * computer to ignore the data sector currently in memory.) * * After filling in the work area, the READTS routine ($AF5E) is * * used to read in a track/sector list sector. Because this * * routine is entered with the carry clear, the first T/S list is * * read. (If a new file was just created, a zeroed out T/S list * * is used. If the calling command later writes information to * * the disk, the zero bytes are used to signal that a new data * * sector must be allocated.) FNOPEN is finally exited through * * the normal file manager exit routine (GOODFMXT, $B37F). * * * *::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::* (AB22) FNOPEN JSR COMNOPEN ;Open pre-exisitng file or make a new file ;if command allows new files to be created. * 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 are 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 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. (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. 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 SECNXD1R ;the very first directory sector. CLC ;(c)=0=signal to read first directory sec. GETDIRSC INC SECNXD1R ;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. (B1EF) 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 search, * 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 SCRNSRCH if branch ;back to do a second search. (B23C) LDY SCRNSRCH ;(1 = search1, 0 = search2) BNE SETSRCH ;Just did search1 so go start seach2. (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. * 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. * 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) ------------ * Create a new file. * - Initialize file size = 1 sector long. * - Assign sectors for data sectors & update file size. * - Write updated VTOC to the disk. * - Put link & update file size in appropriate * file description area contained in the directory sector. * - Write the updated VTOC to the disk. * - Write a new T/S list to the disk. (AB64) CREATNEW LDA #0 ;Initialize the file size = 1 sector long STA FIL1SIZE+1,X ;(cause at first, only starting with a LDA #1 ;a T/S list sector). STA FIL1SIZE,X (AB6E) STX CURDIRNX ;Save byte offset of file description ;into the directory sector. (AB71) JSR ASGNTKSC ;Find trk/sec values for new file. * Asign trk(s)/sec(s) for the new file. * * Note: This routine usually assigns more * sectors than are needed. Each time * a trk with one or more free sectors is * located, the entire track (or at least * all of the free sectors left on that * track) are assigned. The unneeded sectors * are later released by the CLOSE command. * * Note: DOS does not support the allocation * of track 0 for a file. Instead, track 0 is * reserved for storing part of the DOS image. * However, as shown below, track 0 has special * significance for the following flags: * ASIGNTRK = trk # being assigned or, * if it equals 0, then it is a * signal to get the next track * to assign from the VTOC. * TRK0YET = 0 = haven't encountered trk 0 yet. * = 1 = trk 0 has been encountered. * (Track 0 is used as a reference point. The first * time track 0 is encountered, TRK0YET is set to 1. * The next time track 0 is encountered, the entire * disk has been searched.) * Has a track already been assigned for this file? (B244) ASGNTKSC LDA ASIGNTRK (B247) BEQ PRPNWTRK ;Branch if no trk assigned yet. ;(Always take branch the 1rst time we ;"JSR" to here from CREATNEW. However, ;when we later JSR to here, ASIGNTRK = trk ;number for T/S list.) * A track was already assigned, so now * see if there are any free sectors which * we can use on this track. (B249) ANYAVAIL DEC ASIGNSEC ;Next sector to be assigned. (B24C) BMI ASGNWTRK ;If decrement from $00 --> $FF, then there ;aren't any more secs free on this track. * Check if any secs are free. (B24E) CLC ;Roll bits in the 4-bytes of ASIGNMAP as a (B24F) LDX #4 ;unit. Roll them back to their standard (B251) ;position. ADJSTMAP ROL ASIGNMAP-1,X ;If (c) = 1, sector assoc with rolled DEX ;bit position is free to be assigned to BNE ADJSTMAP ;a new file. (B257) BCC ANYAVAIL * Found a free sector. (B259) INC FILENSEC ;Sector was free, so kick file size up by BNE XWITHFRE ;one & return with free sector number in INC FILENSEC+1 ;(a) so it can later be used for the T/S XWITHFRE LDA ASIGNSEC ;list sector. (B264) RTS ;(Actually only good exit available.) ============= * Prepare to assign a new track (cause all * sectors were assigned on the last track). (B265) ASGNWTRK LDA #0 ;Set signal to assign a new trk. (B267) STA ASIGNTRK * Continue preparations to assign a new * track or begin preparations to assign * the first track. (B26A) PRPNWTRK LDA #0 STA TRK0YET ;Signal that not all trks checked yet. (B26F) JSR READVTOC ;Read in the VTOC to find the next trk to use. * 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) * Find & re-assign free sectors for the * next track. Calculate the next trk to * assign. (B272) GETNWTRK CLC LDA NXTRKUSE ;Get next track to assign. ADC DRECTION ;Direction (+1/-1) of assignment. (B279) BEQ CKIFFULL ;If 0, go see if checked all tracks. * Is track number legal? (B27B) CMP TKPERDSK ;Number of tracks on disk (from VTOC). (B27E) BCC CHK4FREE ;Branch if trk number is valid. * Track number is too large, * so reverse direction. (B280) LDA #$FF ;(a) = -1. (B282) BNE SRCH4TRK ;ALWAYS. * At track 0, see if checked all tracks. * If at track 0 for the first time, set * the flag. If this is the second time * at track 0, go issue a disk-full error * message (because we just searched all * tracks and didn't find any free sectors. (B284) CKIFFULL LDA TRK0YET (B287) BNE TODSKFUL ;Second time - disk full. * Start the second search. (B289) LDA #1 ;Set flag to indicate that the pending (B28B) STA TRK0YET ;search will the second one. * Start search at catalog track * plus or minus one. (B28E) SRCH4TRK STA DRECTION ;Set the search direction. CLC ;Begin search one trk away from cat trk. (B292) ADC #$11 * Check trk's TRKMAP for free sectors. (B294) CHK4FREE STA NXTRKUSE STA ASIGNTRK TAY ;Irrevlevant. ASL ;Trk*4 cause 4 bytes/trk in TRKMAP. ASL TAY ;Index from the last byte of TRKMAP0. LDX #4 ;Index to ASIGNMAP. CLC ;(c)=0, assume no free sectors available. CPYTKMAP LDA TRKMAP0+3,Y ;Copy byte from TRKMAP to the assignment map. STA ASIGNMAP-1,X (B2A7) BEQ NXMAPBYT ;0 = sector used. * Found a free sector. (B2A9) SEC ;(c) = 1 = free sector foundl LDA #0 ;Put 0 in TRKMAP to reassign all eight (B2AC) STA TRKMAP0+3,Y ;sectors represented by this byte. ;(Remember, only 2 bytes of TRKMAP actually (B2AF) ;represent secs. The other 2 bytes are duds.) NXMAPBYT DEY ;Reduce indices to maps. DEX (B2B1) BNE CPYTKMAP ;Branch if not done transferring all bytes ;from TRKMAP to ASIGNMAP yet. * Check if found a free sector. (B2B3) BCC GETNWTRK ;If (c) = 0, then no free sectors found yet ;so go back to get a new track. (B2B5) JSR WRITVTOC ;Update the VTOC on the disk. * Write the Volume Table of Contents (VTOC). (AFFB) READVTOC LDA #2 ;Write opcode for RWTS. * 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 WRITE.) . . (RTS) (B2B8) LDA SECPERTK ;Reset ASIGNSEC with # of secs/trk STA ASIGNSEC ;(ie. one greater than highest sector #). (B2BE) BNE ANYAVAIL ;ALWAYS. ----------- * Go issue a disk-full error message. TODSKFUL JMP DISKFULL ;Go handle error. (B2C0) ------------ * Finish setting up parameters * in the file manager's work area. * (Don't confuse with work buffer * located in the chain of DOS buffers.) (AB74) LDX CURDIRNX ;Offset into directory sec for new description entry. STA FIL1TSSC,X ;Put sec val in directory sector. STA FIRTSSEC ;Put sec val of 1rst T/S list sec in FM work area. STA CURTSSEC ;Put current sector val in FM work area. LDA ASIGNTRK ;Do the same for the track value. STA FIL1TSTRK,X STA FIRSTSTK STA CURTSTRK LDA FILTYPFM ;(From FM parm list.) (AB8F) STA FIL1TYPE,X ;Put file type in file description entry. * Write directory sector buffer. (AB92) JSR WRDIRECT ;Write directory sec buf in cat. * Write the directory buffer. (B037) WRDIRECT JSR PT2DIRBF ;Select directory sector buffer. * Designate the directory sector buffer * as I/O buffer in RWTS's IOB. (B045) PT2DIRBF LDA ADRDIRBF ;Get addr of the directory sector buffer STA IBBUFP ;from the FM constants table and designate LDA ADRDIRBF+1 ;it as the I/O buffer. STA IBBUFP+1 (B051) RTS (B03A) LDX CURDIRTK ;Enter RWTS driver with (x)/(y) = trk/sec LDY CURDIRSC ;values of the directory sector. LDA #2 ;Write opcode for RWTS. (B042) JMP RWTSDRVR ;Call RWTS driver to write the directory buffer. ------------- * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using WRITE.) . . (RTS) * Write T/S list sector buffer. (AB95) JSR SELTSBUF ;Get adr of T/S list sec buf from ;the FM parameter list. * 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 (AB98) JSR CURBUF ;Zero out the T/S list sector buffer. * Zero out the current 256-byte buffer. (B7D6) ZCURBUF LDA #0 TAY ZCURBUF1 STA (A4L),Y INY BNE ZCURBUF1 (B7DE) RTS (AB9B) JSR WRITETS ;Write zeroed out T/S list sector buffer. ;NOTE: If the write subfunction is later ;entered to write new data to the disk, the ;zero bytes are detected & used as signals ;that a new data pair should be put in the ;T/S list sector buffer.) * Write the T/S list buffer. (AF3A) WRITETS JSR SETTSIOB ;Prepare RWTS's IOB for WRITING the ;the T/S list buffer. * 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 (AF3D) LDA #2 ;Write opcode for RWTS. (AF3F) JSR RWTSDRVR ;Call RWTS driver to write the T/S list. * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using WRITE.) . . (RTS) (AF42) LDA #$7F ;Clear bit 7 of the update flag to signal AND UPDATFLG ;that the T/S list sector is up to date. STA UPDATFLG (AF4A) RTS (AB9E) LDX CURDIRNX ;Offset to new file descrip in directory sec. LDA #6 ;Default return code value to that for (ABA3) STA RTNCODFM ;a file-not-found error. * 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 a STA RELPREV ;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 ;Dictate 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 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 BMI WRITETS ;If bit 7 set, updating is required. (AF39) RTS =========== * Write the T/S list buffer. (AF3A) WRITETS JSR SETTSIOB ;Prepare RWTS's IOB for WRITING the ;the T/S list buffer. * 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 (AF3D) LDA #2 ;Write opcode for RWTS. (AF3F) JSR RWTSDRVR ;Call RWTS driver to write the T/S list. * Read/Write Track/Sector driver. (B052) RWTSDRVR . . (See dis'mbly of RWTS driver using WRITE.) . . (RTS) (AF42) LDA #$7F ;Clear bit 7 of the update flag to signal AND UPDATFLG ;that the T/S list sector is up to date. STA UPDATFLG (AF4A) 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. ------------ * 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.) . . (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 the (AFC4) STA RELFIRST ;FIRST data sector that can be described in this ;T/S list. (Always equals $00 when called from FNOPEN.) (AFC7) CLC ;Add the maximum # of data secs that can described ADC MXSCURTS ;in this T/S list. STA RELASTP1 ;Store maximum relative sector number (plus 1) of INY ;the last data sector that can be described in list. LDA (A4L),Y STA RELFIRST+1 ADC MXSCURTS+1 STA RELASTP1+1 ;(RELASTP1/+1 is always set to $007A by FNOPEN.) CLC ;Return with "no error" signal. (AFDB) RTS ============ (AB25) JMP GOODFMXT ;Exit 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).)