textfiles/apple/ANATOMY/t.dos.aff7.b2c2.txt
2021-04-15 13:31:59 -05:00

908 lines
26 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

*=================================
* 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