*================================= * READ THE VOLUME TABLE * OF CONTENTS (VTOC). *================================= READVTOC LDA #1 ;READ OPCODE FOR RWTS. BNE RDWRVTOC ;ALWAYS. *================================= * WRITE VOLUME TABLE * OF CONTENTS (VTOC). *--------------------------------- WRITVTOC LDA #2 ;WRITE OPCODE FOR RWTS. * COMMON TO READ/WRITE VTOC. RDWRVTOC LDY ADRVTOC ;GET ADR OF VTOC FRM FM CONSTANTS STY IBBUFP ;TABLE & DESIGNATE IT AS THE I/O LDY ADRVTOC+1 ;BUF IN RWTS'S IOB. STY IBBUFP+1 LDX TRKWA ;ENTER RWTS DRIVER WITH (X)/(Y) LDY #0 ;EQUAL TO TRK/SEC VALS OF VTOC. JMP RWTSDRVR ;CALL DRIVER TO READ/WRITE VTOC. *================================= * READ A DIRECTORY SECTOR. *================================= RDDIRECT PHP ;SAVE (C) ON STK: ; (C) = 0 = READ 1RST DIR SEC. ; (C) = 1 = READ NEXT DIR SEC. JSR PT2DIRBF ;DESIGNATE DIR SEC BUF AS I/O BUF ;IN RWTS'S IOB. PLP ;CHK IF DEALING WITH 1RST DIR SEC BCS RDNXTDIR ;NO - GO READ NEXT DIR SEC. * READ THE FIRST DIRECTORY SECTOR. * (C) = 0 RDFIRDIR LDY FIRDIRSC ;(Y)/(X)=TRK/SEC VALS OF 1RST LDX FIRDIRTK ;DIRECTORY SEC (FROM VTOC BUF). BNE DODIRRD ;ALWAYS - GO READ IN DIREC SEC. * READ THE NEXT DIRECTORY SECTOR. * (C) = 1 RDNXTDIR LDX DIRLNKTK ;GET TRK OF NXT DIR SEC FROM LINK ;IN CURRENT DIRECTORY SECTOR. BNE GETDIRLK ;LINK NOT ZEROED OUT. SEC ;LINK ZEROED OUT -EXIT WITH (C)=1 RTS ;TO SIGNAL NO MORE DIREC SECS. * === GETDIRLK LDY DIRLNKSC ;GET SEC OF NEXT DIR SEC FRM LINK ;BYTES IN CURRENT DIRECTORY SEC. * CALL TO READ IN DIRECTORY SECTOR. DODIRRD STX CURDIRTK ;SAV TRK/SEC VALS OF DIRECTORY WE STY CURDIRSC ;ARE ABOUT 2 READ SO THEY WILL BE ;THE CURRENT DIRECTORY SEC VALS ;FOR THE NEXT TIME AROUND. LDA #1 ;READ OPCODE FOR RWTS. JSR RWTSDRVR ;CALL RWTS DRIVER TO DO THE READ. CLC ;LINK DIDN'T ZERO OUT SO SIGNAL RTS ;MORE DIREC SECS EXIST & THEN XIT *================================= * WRITE THE DIRECTORY BUFFER. *================================= WRDIRECT JSR PT2DIRBF ;DESIGNATE DIREC SEC BUF AS I/O ;BUF IN RWTS'S IOB. LDX CURDIRTK ;ENTER RWTS DRIVER WITH (X)/(Y) LDY CURDIRSC ;EQUAL TO THE TRK/SEC VALS OF THE ;DIRECTORY SECTOR. LDA #2 ;WRITE OPCODE FOR RWTS. JMP RWTSDRVR ;CALL DRIVER TO WRITE DIREC SEC. *================================== * DESIGNATE DIRECTORY SECTOR BUFFER * AS I/O BUFFER IN RWTS'S IOB. *================================== PT2DIRBF LDA ADRDIRBF ;GET ADDR OF DIREC SEC BUF FROM STA IBBUFP ;FM CONSTANTS TBL & DESIGNATE IT LDA ADRDIRBF+1 ;AS I/O BUFFER IN RWTS'S IOB. STA IBBUFP+1 RTS *================================== * READ/WRITE TRACK/SECTOR DRIVERS. *================================== RWTSDRVR STX IBTRK ;ENTER WITH (X) = TRK WANTED. STY IBSECT ; (Y) = SEC WANTED. RWTSDRV1 STA IBCMD ; (A) = OPCODE FOR RWTS ;RWTSDRV1 = ENTRY PT USED BY INIT ;FUNCTION HNDLR WHEN FORMATTING. CMP #2 ;IS CMD A WRITE? NOTE: THE "CMP" ;CONDITIONS THE CARRY AS FOLLOWS: ;(C)=0 =SEEK ($00) OR READ ($01) ;(C)=1 =WRITE($02) OR FORMAT($03) BNE SKPWRSET ;BRANCH IF NOT WRITING. ORA UPDATFLG ;CONDITION UPDATE FLG 2 DESIGNATE STA UPDATFLG ;LAST OPERATION WAS A WRITE (FOR ;NEXT TIME AROUND). * FINISH SETTING UP RWTS'S * INPUT/OUTPUT BLOCK (IOB). SKPWRSET LDA VOLWA ;PUT COMPLEMENTED VOL IN IOB. EOR #$FF STA IBVOL LDA SLOT16WA ;PUT SLOT*16 IN IOB. STA IBSLOT LDA DRVWA ;PUT DRIVE # IN IOB. STA IBDRVN LDA SECSIZWA ;PUT SEC LENGTH IN IOB (STANDARD STA IBSECSZ ;SIZE OF #256 OR $0100 BYTES). LDA SECSIZWA+1 STA IBSECSZ+1 LDA #1 STA IBTYPE LDY ADRIOB ;SET (Y) & (A) TO POINT AT LDA ADRIOB+1 ;RWTS'S IOB. *================================= * CALL RWTS *================================= JSR ENTERWTS ;SAV STATUS,SET INTERRUPT DISABLE ;FLAG & CALL RWTS TO PERFORM TASK ;(SEEK, READ, WRITE, FORMAT). LDA IBSMOD ;GET VOL FOUND (FRM IOB) & PUT IT STA VOLFM ;IN THE FM PARAMETER LIST. LDA #$FF ;PUT VOL WANTED IN IOB. STA IBVOL ;(USE 255 AS DEFAULT VAL FOR NEXT ;TIME. ACTUALLY USING 0 CAUSE ;#$FF EOR #$FF = $00). BCS ERRWTSDR ;OPERATION WAS UNSUCCESSFUL. RTS ;ABOVE BRANCH NEVER TAKEN WHEN ;USING SEEK CMD, CAUSE NO ERROR ;CHKING ROUTINES ARE ENCOUNTERED ;BY A LONE SEEK OPERATION. *================================= * OPERATION WAS NOT SUCCESSFUL. *================================= ERRWTSDR LDA IBSTAT ;GET RWTS'S ERROR CODE. * TRANSLATE RWTS ERROR CODE (A) * TO FM ERROR CODE (Y). (DOS LATER * EMPLOYS FM ERROR CODE IN ROUTINE * USED TO PRINT ERROR MESSAGES.) LDY #7 ;SET (Y) FOR FM ERROR CODE. CMP #$20 ;VOL MISMATCH? BEQ SETFMERR ;YES. LDY #4 ;NO. CMP #$10 ;WRITE PROTECTED? BEQ SETFMERR ;YES. LDY #8 ;NO - MUST HAVE BEEN OTHER SO SETFMERR TYA ;DESIGNATE IT AS GENERAL I/O ERR. JMP BADFMXIT ;GO HANDLE ERROR. ;ANY ERR ENCOUNTERED WHEN FORMAT- ;TING IS TREATED AS AN I/O ERROR. *========================================== * READ DATA SEC IF NECESSARY. *========================================== * CHECK IF NEED TO READ THE NEXT DATA * SECTOR INTO THE DATA SECTOR BUFFER. * * - IS DATA SEC WE WANT ALREADY IN MEMORY? * - IF SO, DOES IT REQUIRE UPDATING? * IF THE SECTOR OFFSET INTO FILE (FILPTSEC) * EQUALS THE RELATIVE SECTOR NUMBER OF THE * LAST SECTOR READ OR WRITTEN (RELPREV), * THEN THE 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 OVER- * WRITE 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 AND SHOULD BE WRITTEN * TO THE DISK BEFORE ANY MORE * INFORMATION IS READ IN. * - IF THE FILE WAS JUST OPENED, THE * OPEN SUBFUNC SET FILPTSEC=#$0000 * AND RELPREV=#$FFFF SO ALWAYS * FORCE READING OF A NEW DATA SEC * EVEN IF THE CORRECT SECTOR IS * ALREADY IN MEMORY. NXTDATRD LDA FILPTSEC ;LAST SEC USED VS CUR SEC WNTD. CMP RELPREV BNE CKWCURDA ;NOT SAME - WILL EVENTUALLY HAVE ;TO READ NEW DATA SEC IN. LDA FILPTSEC+1 ;MAYBE SAME - CHK HI BYTES. CMP RELPREV+1 BEQ XITNXDAT ;SAME SO GO EXIT. *===================================== * WRITE THE DATA SECTOR IF NECESSARY. *------------------------------------- * DATA SEC WE WANT IS NOT PRESENTLY IN * MEMORY. CHK IF NEED TO WRITE THE * CURRENT DATA SEC BUF BEFORE WE READ * IN THE WANTED DATA SECTOR. CKWCURDA JSR CKDATUP ;CHK UPDATE FLG 2 SEE IF DATA SEC ;BUF HAS CHANGED SINCE LAST R/W. ;IF IT HAS, WRITE DATA BUF 2 DSK. * SHOULD THE 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.) CKCURTS LDA FILPTSEC+1 ;SEC OFFSET INTO FILE ASSOCIATED CMP RELFIRST+1 ;WITH THE PRESENT DATA SECTOR ;VERSUS THE RELATIVE SEC# OF THE ;FIRST DATA SEC DESCRIBED IN THE ;PRESENT T/S LIST. BCC NEEDNXTS ;DATA SEC WANTED REPRESENTS A ;SMALLER OFFSET INTO FILE SO NEED ;A DIFFERENT T/S LIST. BNE CKCURTS1 ;SEC OFFSET OF WANTED DATA SEC IS ;LARGER THAN THAT OF THE 1RST DAT ;SEC THAT CAN BE DESCRIBED IN THE ;PRESENT T/S LIST SO IT MAY STILL ;BELONG TO THIS T/S LIST. LDA FILPTSEC ;HI BYTES SAME -SO CMP LOW BYTES. CMP RELFIRST BCC NEEDNXTS ;SEC OFFSET OF WNTD FILE 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. CKCURTS1 LDA FILPTSEC+1 ;SEC OFFSET OF DATA SEC WANTED CMP RELASTP1+1 ;VS RELATIVE SEC # OF THE LAST ;DATA SEC THAT CAN POSSIBLY BE ;DESCRIBED IN THE PRES T/S LIST. BCC GETDATPR ;SEC OFFSET ASSOC WITH DATA SEC ;WANTED IS DESCRIBED IN THE ;PRESENT T/S LIST. BNE NEEDNXTS ;SEC OFFSET OF PRESENT DATA SEC ;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. LDA FILPTSEC ;HI BYTES SAME -SO CMP LOW BYTES. CMP RELASTP1 BCC GETDATPR ;SEC OFFSET ASSOCIATED WITH THE ;DATA SECTOR WE WANT IS LESS THAN ;THE RELATIVE SEC # (PLUS 1) OF ;THE LAST DATA SECTOR THAT CAN ;POSSIBLY BE LISTD IN THE PRESENT ;T/S LIST. (THERE4, THE WANTED ;DATA SEC 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 * HIGHERED NUMBERED T/S LIST. * IF (C) = 0, THEN THE FILE POINTER * WAS BACKED UP AND WE NEED A SMALLER * NUMBERED T/S LIST.) NEEDNXTS JSR READTS ;READ IN THE NEXT (OR FIRST) T/S ;LIST. HOWEVER, FIRST CHECK THE ;UPDATE FLAG TO SEE IF THE T/S ;LST 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. BCC CKCURTS ;GO BACK & CHK IF THIS IS CORRECT ;T/S LIST. RTS ;RTN WITH (C)=1 TO SIGNAL THAT WE * === ;RAN OUT OF T/S LISTS WHILE ;READING OR TO DO GOOD EXIT IF ;RAN OUT OF DATA WHILE VERIFYING ;OR 2 SIGNAL POSSIBLE ERROR WHILE ;APPENDING. * KNOW DATA SEC SHOULD BE DESCRIBED * IN PRESENT T/S LIST SO NOW CALC * OFFSET INTO T/S LIST WHERE DATA * PAIR SHOULD BE LOCATED. GETDATPR SEC ;CALC OFFSET TO DATA PAIR: LDA FILPTSEC ;SEC OFFSET OF DATA SEC INTO FILE SBC RELFIRST ;MINUS REL INDEX OF 1RST DATA SEC ;DESCRIBED IN PRES T/S LIST. ASL ;TIMES 2 CAUSE 2 BYTES USED TO ;DESCRIBE A DATA PAIR. ADC #12 ;ADD 12 CAUSE 1RST DATA PAIR IS TAY ;ALWAYS LISTED 12 BYTES FROM THE ;START OF THE T/S LIST BUFFER. JSR SELTSBUF ;POINT A4L/H AT THE T/S LIST BUF. LDA (A4L),Y ;GET TRK # OF DATA SEC PAIR. BNE RDDATSEC ;GO READ IN THE DATA SECTOR. * THE TRK# 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. LDA OPCODEFM ;CHECK TO SEE IF WRITING OR NOT. CMP #4 ;OPCODE FOR WRITE. BEQ NEWPAIR ;BRANCH IF WRITING. SEC ;NOT WRITING & RAN OUT OF DATA RTS ;SECTOR PAIRS DESCRIBED IN THE * === ;PRESENT T/S LIST, SO GO XIT WITH ;CARRY SET 2 SIGNAL NO MORE DATA. * SINCE WRITING & RAN OUT OF DATA * PAIRS, MUST ADD A NEW DATA PAIR * TO THE T/S LIST. NEWPAIR JSR NWDATKSC ;ADD NEW DATA SEC PR TO T/S LIST, ;ZERO OUT DATA SEC BUF & SET ;UPDATE FLAG TO SIGNAL THAT BOTH ;T/S LIST SEC & DATA SEC REQUIRE ;UPDATING. JMP SETPREV ;NOTE: IF YOU FOLLOW THIS JUMP * --- ;THRU, YOU MAY REALIZE THAT SOME- ;TIMES WE EVENTUALLY EXIT THE ;PRESENT FUNCTION WITHOUT WRITING ;THE T/S LIST AND DATA SEC BUFS ;BACK TO THE DISK. HOWEVER, AFTER ;THE SUBFUNCTIONS ARE EXITED, THE ;CLOSE FUNCTION EVENTUALLY TESTS ;THE STATUS OF THE UPDATE FLAG ;(UPDATFLG, $B5D5) & THEN WRITES ;THE T/S LIST & DAT SEC BUFS BACK ;TO THE DISK. * DATA SECTOR PAIR ASSOCIATED WITH * THE DATA SECTOR WANTED WAS * CONTAINED IN THE CURRENT T/S LIST, * SO NOW READ IN THE DATA SECTOR. RDDATSEC STA CURDATRK ;SAVE TRK/SEC VALS OF CURRENT DATA INY ;SECTOR IN THE WORK AREA. LDA (A4L),Y ;SEC# OF CURRENT DATA SEC. STA CURDATSC JSR READDATA ;GO READ IN THE DATA SECTOR. * SAVE SECTOR OFFSET INTO FILE * ASSOC WITH DATA SEC JUST READ. SETPREV LDA FILPTSEC ;CURRENT SEC OFFSET INTO FILE. STA RELPREV ;OFFSET IN FILE OF LAST DAT READ. LDA FILPTSEC+1 STA RELPREV+1 * EXIT READ NEXT DATA SECTOR ROUTINE. XITNXDAT JSR SELDABUF ;POINT A4L/H AT DATA SEC BUF. LDY FILPTBYT ;(Y)=BYT OFFSET IN2 CUR DATA SEC. CLC ;EXIT CLEANLY. RTS *================================= * DESIGNATE TRK/SEC VALS FOR NEW * DATA SECTOR & ADD THE NEW DATA * SECTOR PAIR TO THE T/S LIST. *================================= NWDATKSC STY SCRNSRCH ;SAVE OFFSET 2 DAT PR IN T/S LST. JSR ASGNTKSC ;FIND & DESIGNATE AN AVAIL SEC. LDY SCRNSRCH ;RETRIEVE OFFSET TO DATA PAIR. INY STA (A4L),Y ;PUT NEW SEC# IN THE T/S LIST AND STA CURDATSC ;WORK AREA. DEY LDA ASIGNTRK ;PUT TRK# IN T/S LST & WORK AREA. STA (A4L),Y STA CURDATRK JSR SELDABUF ;POINT A4L/H AT DATA SEC BUF. ZOUTDAT JSR ZCURBUF ;ZERO OUT DATA SEC BUF. LDA #%11000000 ;SET BOTH BITS 6 & 7 IN FLAG TO ORA UPDATFLG ;SIGNAL THAT BOTH DATA & T/S LIST STA UPDATFLG ;SECTORS REQUIRE UPDATING. RTS *================================= * ADJUST RECORD # OR BYTE OFFSET * INTO A GIVEN RECORD. *================================= * THIS ROUTINE IS USED BOTH WHEN * READING AND WRITING. THE PATTERN * OF EXECUTION VARIES WITH THE * STRUCTURE OF A FILE. HOWEVER * SOME FILES ARE TREATED AS IF * THEY HAVE ONE TYPE OF STRUCTURE * WHEN THEY ARE BEING READ AND * ANOTHER TYPE OF STRUCTURE WHEN * THEY ARE BEING WRITTEN: * - RANDOM ACCESS TEXT FILES HAVE * A FIXED RECORD LENGTH ASSIGNED * BY THE USER. * - SEQUENTIAL TEXT & APPLESOFT * FILES HAVE A RECORD LENGTH OF * ONE. * - DURING A LOAD OR BLOAD, BINARY * & APPLESOFT FILES ARE CONSIDERED * TO BE COMPOSED OF A COLLECTION * OF ONE-BYTE LONG RECORDS. * - WHEN SAVING OR BSAVING HOWEVER, * THESE FILES ARE TREATED AS IF * THEY CONSIST OF 1 LONG RECORD. * COPY THE RECORD NUMBER FROM THE * WRK AREA TO THE FM PARM LIST. INCREC LDX RECNMBWA ;CURRENT RECORD #. STX RECNMBFM ;RECORD # IN PARAMETER LIST. LDX RECNMBWA+1 STX RECNMBFM+1 * COPY CURRENT BYTE OFFSET INTO * RECORD FROM THE WORK AREA TO * THE FM PARAMETER LIST. LDX BYTOFFWA ;GET OFFSET IN2 RECORD (WRK AREA) LDY BYTOFFWA+1 STX BYTOFFFM ;STORE IT IN FM PARAMETER LIST. STY BYTOFFFM+1 * INC THE BYTE OFFSET INTO RECORD. * IF IT EQUALS THE RECORD LENGTH, * THEN RESET THE OFFSET TO 0 AND * KICK UP THE RECORD NUMBER. INX BNE BYTVSREC INY BYTVSREC CPY RECLENWA+1 ;FIXED VAL VIA OPEN CMD, ELSE ;L-PARM VIA SAVE OR BSAVE CMD ;(FROM WORK AREA). KIKOFF1 BNE SETBYTOF CPX RECLENWA KIKOFF2 BNE SETBYTOF LDX #0 ;OFFSET INTO RECORD WAS SAME AS LDY #0 ;RECORD LENGTH SO PREP TO RESET ;OFFSET INTO RECORD TO ZERO. INC RECNMBWA NOKIKOFF BNE SETBYTOF INC RECNMBWA+1 * ON FALL THRU OR ENTRY FROM NOKIKOFF, * RESET THE OFFSET INTO THE RECORD * TO ZERO. ON BRANCHED ENTRY FROM * KIKOFF1 OR KIKOFF2, INCREMENT THE * OFFSET INTO THE RECORD. SETBYTOF STX BYTOFFWA STY BYTOFFWA+1 RTS *================================= * INCREMENT THE BYTE OFFSET INTO * THE CURRENT SECTOR. IF AT THE * END OF THE SECTOR, INCREMENT THE * OFFSET INTO THE ENTIRE FILE * INSTEAD. *================================= INCFILPT INC FILPTBYT ;KICK UP OFFSET INTO THE SECTOR. BNE INCPTRTN ;NOT AT END OF CURRENT SECTOR. INC FILPTSEC ;OFFSET INTO SEC WRAPPED AROUND, BNE INCPTRTN ;SO AT END OF SEC, SO KICK UP THE ;OFFSET INTO THE ENTIRE FILE. INC FILPTSEC+1 ;INC HI BYTE IF NECESSARY. INCPTRTN RTS *================================= * POINT A4L/H AT CUR DEST'N/SOURCE * MEMORY LOCATION (CURIOBUF) FOR * READING/WRITING. * INC DEST'N/SOURCE ADR FOR NEXT * TIME AROUND. *================================= INCIOBUF LDY CURIOBUF ;GET ADR OF DEST'N/SOURCE LOC'N LDX CURIOBUF+1 ;FROM FM PARM LIST. STY A4L ;POINT A4L/H AT TARGET. STX A4L+1 INC CURIOBUF ;KICK UP ADR OF DEST'N/SOURCE LOC BNE INCIORTN INC CURIOBUF+1 INCIORTN RTS *================================= * REDUCE COUNT OF THE # OF BYTES * LEFT TO READ OR WRITE. WHEN THE * COUNTER = 0, EXIT FILE MANAGER. *================================= DECRWLEN LDY LEN2RDWR ;LENGTH TO READ OR LENGTH-1 TO ;WRITE (FROM FM PARM LIST). BNE DECLENRW ;MORE BYTES TO READ OR WRITE. LDX LEN2RDWR+1 ;LOW BYTE WAS 0, CHK HI BYTE. BEQ RWLEN0 ;COUNTER = 0 SO DONE READ/WRITE. DEC LEN2RDWR+1 DECLENRW DEC LEN2RDWR ;REDUCE COUNTER. RTS RWLEN0 JMP GOODFMXT ;DONE READ/WRITE, EXIT FM. *========================================= * LOCATE OR CREATE A FILE ENTRY IN THE * DIRECTORY BUFFER. * MAKE TWO SEARCHES IF NECESSARY: * - SEARCH1 - TRY TO LOCATE ENTRY WITH THE * SAME NAME AS THE FILE WANTED. * - SEARCH2 - COULDN'T LOCATE ENTRY * CORRESPONDING TO THE FILE * WANTED SO CREATE A NEW ENTRY * IN THE 1RST AVAILABLE SPACE * IN THE DIRECTORY SECTOR IN * CASE THE CMD CAN CREATE A * NEW FILE. *========================================= GETFNTRY JSR READVTOC ;READ IN VTOC SO CAN GET LINK TO ;TRKMAPS & LINK TO 1RST DIR SEC. * PT A4L/H AT PRIMARY NAME BUF. LDA FNAMBUFM ;GET ADR OF NAME BUF FROM THE STA A4L ;FM PARM LIST & PUT IT IN A4L/H. LDA FNAMBUFM+1 STA A4L+1 * TRY TO FIND THE DIRECTORY SECTOR * CONTAINING THE NAME OF THE WANTED * FILE. MAKE TWO SEARCHES IF NECESSARY. * ON THE FIRST SEARCH, TRY TO FIND THE * WANTED FILE NAME. IF THAT DOESN'T * WORK, DO A 2ND SEARCH TO LOCATE THE * 1RST AVAILABLE SPACE IN A DIRECTORY * SECTOR WHERE WE CAN STORE A NEW FILE * DESCRIPTION IN CASE THE CMD CAN CREATE * A NEW FILE. LDA #1 ;INIT SRCH COUNTER (SCRNSRCH), IN SETSRCH STA SCRNSRCH ;FM SCRATCH SPACE FOR 2 SEARCHES ;(1 = SEARCH1, 0 = SEARCH2). LDA #0 ;INIT OFFSET OF FILE DESCRIP FROM STA SECNXD1R ;THE VERY 1RST DIRECTORY SEC. CLC ;(C)=0=SIGNAL TO RD 1RST DIR SEC. GETDIRSC INC SECNXD1R ;KICK UP OFFSET FROM 1RST DIR. ;(ON FIRST ENTRY: $00 ---> $01.) JSR RDDIRECT ;GO READ DIREC SEC IN2 DIREC BUF BCS CHNGSRCH ;LNK ZEROED OUT, NO MORE DIRECT ;SECTORS, SO GO SWITCH SEARCHES. LDX #0 CKDIRTRK STX CURDIRNX ;OFFSET OF FILE DESCRIP INTO THE ;CURRRENT DIRECTORY SECTOR. LDA FIL1TSTK,X ;GET TRK# OF 1RST T/S LIST SEC ;FOR A PARTICULAR FILE FROM THE ;FILE DESCRIP ENTRY IN DIR SEC. BEQ CHRSRCHA ;IF TRK#=0, NO MORE FILES IN THIS ;DIRECTORY SECTOR. BMI CHRSRCHB ;SKIP DELETED FILE. (WHEN A FILE ;IS DELETED, #$FF IS PUT IN BYTE ;WHERE TRK# OF 1RST T/S LIST IS ;USUALLY KEPT.) * COMPARE NAME FOUND IN THE FILE * DESCRIPTION ENTRY PORTION OF THE * DIRECTORY SECTOR WITH NAME WNTD. * (ON ENTRY, A4L/H POINTS AT THE * PRIMARY FILE NAME BUFFER.) LDY #0 ;INIT INDEX TO NAME BUFFER. INX ;POINT (X) AT 1RST CHAR POS'N IN INX ;NAME FIELD OF DESCRIP ENTRY. CMPNAMES INX LDA (A4L),Y ;GET CHAR OF NAME WANTED FROM THE ;PRIMARY FILENAME BUFFER. CMP FIL1TSTK,X ;CHAR OF NAME WANTED VS CHAR IN ;DESCRIPTION ENTRY OF DIREC SEC. BNE DONTMTCH ;CHARS (IE., NAMES) DON'T MATCH. INY CPY #30 ;DONE ALL CHARS YET (0 TO 29)? BNE CMPNAMES ;CHRS MTCH, BRANCH IF MORE 2 CHK. LDX CURDIRNX ;ALL CHARS MTCHD, SO NAMES MTCHD. CLC ;RTN WITH (X) = INDEX TO FILE RTS ;DESCRIP IN CURRENT DIRECTORY AND * === ;WITH (C)=0 TO SIGNAL THAT THE ;CORRECT FILE DESCRIP WAS FOUND. * ADVANCE INDEX TO POINT AT THE NEXT * POTENTIAL FILE DESCRIPTION ENTRY. DONTMTCH JSR NXPLUS35 ;NAMES DIDN'T MATCH, SO ADD 35 TO ;INDEX TO POINT IT AT NEXT ENTRY. ;(CHK TO MAKE SURE DON'T INDEX ;RIGHT OFF END OF DIRECTORY SEC.) BCC CKDIRTRK ;MORE POTENTIAL FILE DESCRIPS TO ;CHK IN THIS DIRECTORY SECTOR. BCS GETDIRSC ;GO GET NEXT DIRECTORY SECTOR. * --- * IF JUST COMPLETED FIRST SEARCH, * GO BACK TO DO SECOND SEARCH. CHRSRCHA LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2) BNE SETSRCH ;GO SWITCH TO SECOND SEARCH. * IF FIRST SEARCH, SKIP DELETED FILES. * IF SECOND SEARCH, FALL THRU TO STORE * THE (NEW) DESCRIPTION IN THE 1RST * UNUSED SPACE IN THE DIRECTORY. CHRSRCHB LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2) BNE DONTMTCH * COULDN'T LOCATE THE FILE NAME IN THE * DIRECTORY DESCRIPTION ENTRIES, SO * BEGIN CREATING A NEW DESCRIPTION IN * THE FIRST AVAILABLE SPACE IN A * DIRECTORY (IN CASE CMD CAN LEGALLY * CREATE A NEW FILE). NWDESCRP LDY #0 ;INIT INDEX TO PRIMARY NAME BUF. INX ;SET INDEX TO 1RST CHAR POS'N IN INX ;THE NAME FIELD OF FILE DESCRIP SETNWNAM INX ;ENTRY SPACE N THE DIRECTORY SEC. LDA (A4L),Y ;COPY CHAR FROM PRIMARY NAME BUF STA FIL1TSTK,X ;TO DIREC DESCRIP ENTRY AREA. INY CPY #30 ;30 CHARS IN NAME (0 TO 29). BNE SETNWNAM ;BRANCH IF MORE CHARS TO COPY. LDX CURDIRNX ;RTN WITH INDEX TO FILE DESCRIP SEC ;IN CURRENT DIRECTORY SECTOR AND RTS ;WITH (C)=1 TO SIGNAL A NEW ENTRY ;WAS JUST CREATED. *===================================== * 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 SECTOR.) *===================================== NXPLUS35 CLC ;ADD 35 TO THE INDEX. (EACH FILE LDA CURDIRNX ;DESCRIPTION IS 35 BYTES LONG.) ADC #35 TAX ;CHK IF MORE SPACE FOR ENTRIES IN CPX #245 ;CURRENT DIRECTORY. RTS ;EXIT WITH (C) CONDITIONED: ; (C)=0=MORE SPACE IN DIRECTORY. ; (C)=1=RAN OFF END OF DIRECTORY. *==================================== * - IF FIRST SEARCH, SWITCH TO SECOND * SEARCH. * - IF SECOND SEARCH, LINK ZEROED OUT * (BECAUSE THERE ISN'T ENOUGH ROOM * ON DISK FOR A NEW ENTRY. THERE4, * GO EXIT WITH A DISK-FULL-ERROR * MESSAGE. *==================================== CHNGSRCH LDA #0 ;SET (A) = 0 SO WE CAN RESET ;SCRNSRCH IF WE HAVE 2 GO BACK 2 ;DO A SECOND SEARCH. LDY SCRNSRCH ;(1=SEARCH1, 0=SEARCH2.) BNE SETSRCH ;JUST DID FIRST SEARCH, SO NOW GO ;BACK TO START SECOND SEARCH. JMP DISKFULL ;EVEN THE SECOND SEARCH WAS ;UNSUCCESSFUL, SO GO HANDLE A ;DISK-FULL ERROR. *======================================== * ASSIGN 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 SECS * IS LOCATED, THE ENTIRE TRACK IS * IS ASSIGNED. THE UNNEEDED SECS ARE * LATER RELEASED BY THE CLOSE COMMAND. * * NOTE: DOS DOES NOT SUPPORT THE * ALLOCATION OF TRK 0 FOR A FILE. * INSTEAD, TRK 0 IS RESERVED FOR STORING * PART OF THE DOS IMAGE. HOWEVER, AS * SHOWN BELOW, TRK 0 HAS SPECIAL * SIGNIFICANCE FOR THE FOLLOWING FLAGS: * ASIGNTRK = TRK# BEING ASSIGNED OR, IF * ASIGNTRK=0, THEN IT IS A * SIGNAL TO GET NEXT TRK TO * ASSIGN FROM THE VTOC. * TRK0YET = 0 = HAVEN'T ENCOUNTERED TRK0 * YET. * = 1 = TRK0 HAS BEEN ENCOUNTERED. * (TRK 0 IS USED AS A REFERENCE POINT. * THE FIRST TIME TRK0 IS ENCOUNTERED, * TRK0YET IS SET TO 1. THE NEXT TIME * TRK0 IS ENCOUNTERED, THE ENTIRE DISK * HAS BEEN SEARCHED.) * HAS A TRK ALREADY BEEN ASSIGNED FOR * THIS FILE? ASGNTKSC LDA ASIGNTRK BEQ PRPNWTRK ;BRANCH IF NO TRK ASSIGNED YET. ;(ALWAYS TAKEN 1RST TIME "JSR" TO ;HERE FRM CREATNEW. HOWEVER, WHEN ;WE LATER JSR TO HERE, ASIGNTRK ;EQUALS THE TRK # FOR T/S LIST.) * A TRK WAS ALREADY ASSIGNED, SO NOW SEE * IF THERE ARE ANY FREE SECS WHICH WE * CAN USE ON THIS TRK. ANYAVAIL DEC ASIGNSEC ;NEXT SECTOR BE ASSIGNED. BMI ASGNWTRK ;IF DEC FROM $00 ==> #$FF, THEN ;NO MORE FREE SECS ON THIS TRK. * CHECK IF ANY SECS ARE FREE. CLC ;ROLL BITS IN THE 4-BYTES OF LDX #4 ;ASIGNMAP AS AS UNIT - ROLL THEM ;BACK TO STANDARD POSITION. ADJSTMAP ROL ASIGNMAP-1,X ;IF C=1, SEC ASSOC WITH ROLLED DEX ;BIT POS'N IS FREE TO BE ASSIGNED BNE ADJSTMAP ;TO A NEW FILE. BCC ANYAVAIL ;SEC NOT FREE - GO GET NEXT ONE. * FOUND A FREE SECTOR. INC FILENSEC ;SEC WAS FREE, SO KICK FILE SIZE BNE XWITHFRE ;UP BY 1 & RTN WITH FREE SEC# IN INC FILENSEC+1 ;(A) SO IT CAN LATER BE USED FOR XWITHFRE LDA ASIGNSEC ;THE T/S LIST SECTOR. RTS ;(ACTUALLY ONLY GOOD EXIT AVAIL.) * === * PREPARE TO ASSIGN A NEW TRK (CAUSE * ALL SECS WERE ASSIGNED ON THE LAST TRK.) ASGNWTRK LDA #0 ;SET SIGNAL TO ASSIGN NEW TRK. STA ASIGNTRK * CONTINUE PREPS TO ASSIGN NEW TRK * OR BEGIN PREPARATIONS TO ASSIGN * THE FIRST TRK. PRPNWTRK LDA #0 STA TRK0YET ;SIGNAL NOT ALL TRKS CHECKED YET. JSR READVTOC ;READ IN THE VTOC TO FIND NEXT ;TRK TO USE. * FIND & REASSIGN FREE SECS FOR THE * NEXT TRK. CALC NEXT TRK TO ASIGN. GETNWTRK CLC LDA NXTRKUSE ;GET NEXT TRK# TO ASSIGN. ADC DRECTION ;DIRECTION (+1/-1) OF ASSIGNMENT. BEQ CKIFFULL ;IF 0, GO SEE IF CHKD ALL TRKS. * IS THE TRACK NUMBER LEGAL? CMP TKPERDSK ;# OF TRKS ON DISK (FROM VTOC). BCC CHK4FREE ;BRANCH IF TRK # IS VALID. * TRK# TOO LARGE, SO REVERSE DIRECT'N. LDA #$FF ;(A) = -1. BNE SRCH4TRK ;ALWAYS. * AT TRK0, SEE IF CHKD ALL TRKS. * IF AT TRK0 FOR 1RST TIME, SET * FLAG. IF 2ND TIME AT TRK0, GO * ISSUE DISK-FULL-ERROR MESSAGE * (BECAUSE WE SEARCHED ALL TRKS & * DIDN'T FIND ANY FREE SECTORS). CKIFFULL LDA TRK0YET BNE TODSKFUL ;2ND TIME = DISK FULL. * START THE SECOND SEARCH. LDA #1 ;SET FLAG TO INDICATE THAT THE STA TRK0YET ;PENDING SEARCH WILL BE 2ND ONE. * START SEARCH AT CATALOG * TRK PLUS OR MINUS ONE. SRCH4TRK STA DRECTION ;SET THE SEARCH DIRECTION. CLC ;BEGIN THE SEARCH ONE TRACK AWAY ADC #$11 ;FROM THE CATALOG TRK. * CHECK TRK'S TRKMAP FOR FREE SECS. CHK4FREE STA NXTRKUSE STA ASIGNTRK TAY ;IRRELEVANT. ASL ;TRK*4 CAUSE 4BYTES/TRK N TRKMAP. ASL TAY ;INDEX FROM LAST BYTE OF TRKMAP0. LDX #4 ;INDEX TO THE ASIGNMAP. CLC ;(C)=0, ASSUME NO FREE SEC AVAIL. CPYTKMAP LDA TRKMAP0+3,Y ;COPY BYTE FROM TRKMAP TO THE STA ASIGNMAP-1,X ;ASSIGNMENT MAP. BEQ NXMAPBYT ;0 = SEC USED. * FOUND A FREE SECTOR. SEC ;(C) = 1 = FREE SECTOR FOUND. LDA #0 ;PUT 0 IN TRKMAP 2 REASSIGN ALL 8 STA TRKMAP0+3,Y;SECS REPRESENTED BY THIS BYTE. ;(REMEMBER ONLY 2 BYTES OF TRKMAP ;ACTUALLY REPRESENT SECS. THE ;OTHER 2 BYTES ARE DUDS.) NXMAPBYT DEY ;REDUCE INDICES TO MAPS. DEX BNE CPYTKMAP ;NOT DONE TRANSFERRING ALL BYTES ;FROM TRKMAP TO ASIGNMAP YET. * CHECK IF FOUND A FREE SECTOR. BCC GETNWTRK ;IF (C)=0,THEN NO FREE SECS FOUND ;YET SO GO BACK TO GET A NEW TRK. JSR WRITVTOC ;UPDATE THE VTOC ON THE DISK. LDA SECPERTK ;RESET ASIGNSEC WITH # SECS/TRK. STA ASIGNSEC (IE 1 GREATER THAN HIGHEST SEC#.) BNE ANYAVAIL ;ALWAYS. *================================= * GO ISSUE DISK-FULL-ERROR MSG. *================================= TODSKFUL JMP DISKFULL ;GO HANDLE ERROR. I