*================================= * READ FUNCTION HANDLER. *================================= FNREAD LDA SUBCODFM ;CHK IF SUBCODE IS LEGAL. CMP #5 ;(MUST BE < = 5.) BCS TOERRSUB ;RANGE ERROR - ILLEGAL SUBCODE. ASL ;SUBCODE*2, CAUSE 2 BYTES/ADR. TAX ;INDEX TABLE OF SUBFUNCTION ADRS. LDA RDSUBTBL+1,X;GET ADDR (MINUS 1) OF SUBFUNCT PHA ;ENTRY POINT & PUT IT ON THE STK LDA RDSUBTBL,X ;(HI BYTE FIRST). THEN DO A STACK PHA ;JUMP TO EXECUTE THE GIVEN READ RTS ;SUBFUNCTION. TOERRSUB JMP RNGERRSB ;GO HANDLE RANGE ERROR. TOFILOCK JMP FILELOKD ;GO HANDLE LOCKED FILE ERROR. *================================= * WRITE FUNCTION HANDLER. *================================= FNWRITE LDA FILTYPWA ;CHK IF FILE IS LOCKED. BMI TOFILOCK ;ERROR - CAN'T WRITE 2 LCKD FILE. LDA SUBCODFM ;CHK IF SUBCODE IS LEGAL. CMP #5 ;(MUST BE < = 5.) BCS TOERRSUB ;ERROR - ILLEGAL SUBCODE. ASL ;SUBCODE*2, CAUSE 2 BYTES/ADR. TAX ;INDEX TABLE OF SUBFUNCTION ADRS. LDA WRSUBTBL+1,X;GET ADR (MINUS 1) OF SUBFUNCT PHA ;ENTRY POINT & STICK ON THE STACK LDA WRSUBTBL,X ;(HI BYTE FIRST). THEN DO A STACK PHA ;JUMP TO EXECUTE THE GIVEN WRITE RTS ;SUBFUNCTION. *================================= * POSITION AND READ-ONE-BYTE * SUBFUNCTION HANDLER. *================================= PSNRDONE JSR CALCFPTR ;USING R-, L- & B-PARAMETERS,CALC ;THE POS'N OF FILE PTR WANTED. *================================== * READ-ONE-BYTE SUBFUNCTION HANDLER *================================== READONE JSR RDDATA ;GET DATA BYTE FROM DATA SEC BUF. ;(IF DESIRED DATA SECTOR IS NOT ;ALREADY IN MEMORY, THEN READ IT ;IN. HOWEVER, 1RST CHK IF PRESENT ;INFO IN DATA SEC NEEDS TO BE ;UPDATED SO DON'T OVERWRITE DATA ;IN BUF & LOOSE INFO.) STA ONEIOBUF ;PUT BYTE READ IN THE 1-BYTE BUF ;CONTAINED IN THE FM PARM LIST. JMP GOODFMXT ;EXIT THE FILE MGR. EVENTUALLY ;RTNS TO AFTRFUNC ($A6AB) LOCATED ;IN THE FMDRIVER ROUTINE ($A6A8). *================================= * POSITION & READ-A-RANGE-OF-BYTES * SUBFUNCTION HANDLER. *================================= PSNRDRNG JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC THE ;POS'N OF FILE POINTER WANTED. *================================= * READ-RANGE-OF-BYTES * SUBFUNCTION HANDLER. *================================= READRNG JSR DECRWLEN ;DECREMENT THE # OF BYTES 2 READ. ;(DONE READING WHEN LEN2RDWR=0.) JSR RDDATA ;GET DATA BYTE FROM DATA SEC BUF. ;(IF DESIRED DATA SECTOR IS NOT ;ALREADY IN MEMORY, THEN READ IT ;IN. HOWEVER, 1RST CHK IF PRESENT ;INFO IN DATA SEC NEEDS TO BE ;UPDATED SO DON'T OVERWRITE DATA ;IN BUF & LOOSE INFO.) PHA ;SAVE SINGLE BYTE READ ON STK. JSR INCIOBUF ;INC THE CUR'NT TARGET RAM MEMORY ;LOCATION (BYTRNG) & POINT A4L/H ;AT TARGET LOCATION IN I/O BUF. LDY #0 ;INITIALIZE (Y) INDEX. PLA ;RETRIEVE BYTE READ. STA (A4L),Y ;PUT SINGLE BYTE READ INTO THE ;TARGET MEMORY LOCATION. JMP READRNG ;GO BK TO READ NEXT BYTE OF DATA. *================================= * SUBROUTINE TO READ A DATA BYTE. *================================= RDDATA JSR NXTDATRD ;CHK IF DATA SEC WE WANT TO READ ;IS ALREADY IN MEMORY. IF NOT, ;READ DATA SEC INTO DATA SEC BUF. ;HOWEVER, 1RST CHK IF DAT SEC BUF ;NEEDS UPDATING SO DON'T OVRWRITE ;DATA SEC BUF & LOSE INFO. BCS NDATERR ;BRANCH IF RAN OUT OF DATA SECS ;WHILE READING. LDA (A4L),Y ;GET SINGLE BYTE FRM DATA SEC BUF PHA ;SAVE IT ON STK. JSR INCREC ;EITHER INC REC # OR BYTE OFFSET ;INTO RECORD. JSR INCFILPT ;INC BYTE OFFSET INTO CURRENT ;DATA SEC OR, IF AT END OF SEC, ;INC THE SECTOR OFFSET INTO THE ;ENTIRE FILE. PLA ;GET DATA BYTE RD (BACK OFF STK). RTS NDATERR JMP ENDOFDAT ;RAN OUT OF DATA WHILE READING. *================================= * POSITION & WRITE-ONE-BYTE * SUBFUNCTION HANDLER. *================================= PSNWRONE JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC ;POS'N OF FILE POINTER WANTED. *================================= * WRITE-ONE-BYTE SUBFUNCTION HNDLR *================================= WRITEONE LDA ONEIOBUF ;GET BYTE TO WRITE FROM ONE-BYTE ;BUFFER IN FM PARAMETER LIST. JSR WRTDATA ;STORE DATA TO WRITE IN THE DATA ;SECTOR BUFFER. IF DATA SEC BUF ;IS FULL, THEN WRITE IT TO DISK ;AND UPDATE T/S LIST BUF. JMP GOODFMXT ;EXIT FILE MANAGER. EVENTUALLY ;RTNS TO AFTRFUNC ($A6AB) LOCATED ;IN THE FMDRIVER ROUTINE ($A6A8). *================================= * POSITION & WRITE-RANGE-OF-BYTES * SUBFUNCTION HANDLER. *================================= PSNWRRNG JSR CALCFPTR ;USING R-, L- & B-PARMS, CALC ;POS'N OF FILE POINTER WANTED. *================================= * WRITE RANGE-OF-DATA-BYTES * SUBFUNCTION HANDLER. *================================= WRITERNG JSR INCIOBUF ;POINT A4L/H AT SOURCE BYTE. LDY #0 ;SET (Y) TO INDEX SOURCE BUF. LDA (A4L),Y ;GET BYTE TO WRITE. JSR WRTDATA ;PUT DATA BYTE IN DATA SEC BUF. ;(WRITE DATA SEC BUF TO DISK IF ;NECESSARY. ) JSR DECRWLEN ;CHECK IF DONE WRITING. IF NOT, ;REDUCE COUNTER FOR # OF BYTES ;LEFT TO WRITE. JMP WRITERNG ;GO BACK TO WRITE NEXT DATA BYTE. *================================= * SUBROUTINE WHICH WRITES BYTE. *================================= WRTDATA PHA ;SAVE BYTE TO WRITE ON STK. JSR NXTDATRD ;READ NXT DATA SEC BUF IF NEEDED. PLA ;GET DATA BYTE TO WRITE OFF STK. STA (A4L),Y ;PUT DATA BYTE IN DATA SEC BUF. LDA #%01000000 ;SET BIT6 TO SIGNAL DATA SEC BUF ORA UPDATFLG ;HAS CHANGED & THEREFOR, THE DISK STA UPDATFLG ;REQUIRES UPDATING. JSR INCREC ;EITHER INC THE RECORD NUMBER OR ;INC THE BYTE OFFSET INTO RECORD. JMP INCFILPT ;INC THE BYTE OFFSET INTO THE ;CURRENT DATA SECTOR. IF AT THE ;END OF SECTOR, INC THE OFFSET ;INTO THE ENTIRE FILE INSTEAD. *================================= * LOCK & UNLOCK FUNCTION HANDLERS. *================================= FNLOCK LDA #$80 ;SET HI BIT IN LOCK/UNLOCK MASK. STA LOKUNMSK BNE COMNLOCK ;ALWAYS. FNUNLOCK LDA #0 ;MAKE SURE HI BIT CLR IN LOKUNMSK STA LOKUNMSK COMNLOCK JSR COMNOPEN ;LOCATE THE FILE WITH THE SAME ;NAME & OPEN IT. LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION ;ENTRY IN THE DIRECTORY SEC BUF. LDA FIL1TYPE,X ;GET OLD FILE TYPE. AND #$7F ;SHUT HI BIT OFF. ORA LOKUNMSK ;MERGE WITH LOKUNMSK 2 SET OR CLR ;(LOCK OR UNLOCK) HI BIT. STA FIL1TYPE,X ;STICK MODIFIED FILE TYPE BACK IN ;FILE DESCRIP PART OF DIR SEC BUF JSR WRDIRECT ;WRITE UPDATED DIREC SEC TO DISK. TOOKFMXT JMP GOODFMXT ;EXIT FM CLEANLY. EVENTUALLY RTNS ;TO AFTRFUNC ($A6AB) LOCATED IN ;THE FMDRIVER ROUTINE ($A6A8). *================================= * POSITION FUNCTION HANDLER. *================================= FNPOSN JSR CALCFPTR ;USE R-, B- & L-PARAMETERS 2 CALC ;POSITION OF FILE POINTER WANTED. JMP GOODFMXT ;EXIT FILE MANAGER CLEANLY. ;EVENTUALLY RETURNS TO AFTRFUNC ;($A6AB) LOCATED IN THE FMDRIVER ;ROUTINE ($A6A8). *================================= * VERIFY FUNCTION HANDLER. *================================= FNVERIFY JSR COMNOPEN ;LOCATE FILE WITH SAME NAME ;& OPEN IT. VRFYREAD JSR NXTDATRD ;READ NEXT DATA SEC IN. (ASSUME ;DATA SEC WE WANT NOT PRESENTLY ;IN MEMORY.) BCS TOOKFMXT ;END OF FILE DETECTED - EXIT FM. ;EVENTUALLT RETURNS TO AFTRFUNC ;($A6AB) LOCATED IN THE FMDRIVER ;ROUTINE ($A6A8). INC FILPTSEC ;KICK UP FILE POINTER POS'N BNE VRFYREAD ;AND THEN GO BACK TO READ NEXT INC FILPTSEC+1 ;DATA SECTOR UNTIL ENCOUNTER END JMP VRFYREAD ;OF FILE MARKER. *================================= * DELETE FUNCTION HANDLER. *================================= FNDELETE JSR COMNOPEN ;LOCATE FILE WITH SAME NAME AND ;THEN OPEN IT. LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION ;IN DIRECTORY SECTOR BUFFER. LDA FIL1TYPE,X ;GET FILE TYPE FROM DIR SEC BUF. BPL ALTRNTRY ;BRANCH IF FILE NOT LOCKED. JMP FILELOKD ;ERR - CAN'T DELETE A LOCKED FILE ;SO GO HANDLE ERR & EXIT. * GET TRK # OF FILES 1RST T/S LIST * FROM FILE DESCRIP ENTRY IN DIR * SEC BUF. PUT IT IN THE WRK AREA * & WRITE IT OVER THE LAST CHAR * POS'N IN THE APPROPRIATE FILE * NAME FIELD IN DIRECTORY SECTOR. ALTRNTRY LDX CURDIRNX ;(X) = INDEX TO FILE DESCRIPTION ;ENTRY IN DIRECTORY SEC BUFFER. LDA FIL1TSTK,X ;GET TRK # OF 1RST T/S LIST SEC. STA FIRSTSTK ;COPY IT IN2 WORK AREA & LAST CHR STA FIL1NAME+29,X ;POS'N OF FILE NAME FLD DSCRP LDA #$FF ;REPLACE ORIG TRK # OF T/S LIST STA FIL1TSTK,X ;WITH $FF TO SIGNAL FILE DELETED. LDY FIL1TSSC,X ;PUT SEC # OF FILE'S 1RST T/S LST STY FIRTSSEC ;IN THE WORK AREA. JSR WRDIRECT ;WRITE MODIFIED DIREC SEC 2 DISK. * READ T/S LIST SEC INTO T/S LIST BUF. * (NEED THIS INFO SO KNOW WHAT SECS * TO RELEASE.) CLC ;(C)=0, SIGNAL 1RST T/S LIST SEC. RDTS4DEL JSR READTS ;GO READ IN T/S LIST. BCS DONEDEL ;BRNCH IF JUST READ LAST T/S LIST ;SEC ASSOCIATED WITH THIS FILE. JSR SELTSBUF ;POINT A4L/H AT T/S LIST SECTOR ;BUFFER.(GET ADR FRM FM PRM LST.) * FREE ALL SECS LISTED IN THE T/S * LIST THAT CURRENTLY OCCUPIES THE * T/S LIST BUFFER. LDY #12 ;1RST DATA SEC PAIR LISTED IS ;OFFSET 12 BYTES FROM START OF ;T/S LIST BUFFER. DELFREE STY CURDIRNX ;SET (Y) = INDEX TO THE DATA PAIR ;LISTED IN THE T/S LIST BUFFER. LDA (A4L),Y ;GET TRK # OF DATA SEC. BMI BYPASDEL ;NEG TRK # ILLEGAL. (CAN USE AS ;A PROTECTION SCHEME.) BEQ BYPASDEL ;TRK # OF 0 = NO MORE DATA SECS ;LISTED IN CURRENT T/S LIST. PHA ;SAVE TRK # OF DATA SEC ON STK. INY ;GET SEC # OF DATA SEC. LDA (A4L),Y TAY ;CONDITION (Y)=SEC & (A)=TRK FOR PLA ;ENTRY IN2 ROUT'N 2 FREE UP SECS. JSR FREESEC ;FREE UP SECTOR FROM DELETED FILE BYPASDEL LDY CURDIRNX ;SET (Y) 2 INDEX START DATA PAIR. INY ;KICK UP (Y) 2 PT AT NXT DATA PR. INY BNE DELFREE ;IF (Y) < > 0, THEN NEVER RAN OFF ;END OF T/S LIST SEC BUF YET, SO ;GO CHK IF MORE DATA PRS TO DO. * FREE UP SECTOR CONTAINING THE * T/S LIST. LDA CURTSTRK ;TRK # OF CURRENT T/S LIST SEC. LDY CURTSSEC ;SEC # OF CURRENT T/S LIST SEC. JSR FREESEC ;GO FREE UP THE T/S LIST SEC. SEC BCS RDTS4DEL ;ALWAYS. * DONE FREEING UP ALL SECTORS * ASSOCIATED WITH THIS FILE, SO * NOW WRITE MODIFIED VTOC BACK * TO THE DISK. DONEDEL JSR WRITVTOC ;WRITE UPDATED VTOC TO DISK. JMP GOODFMXT ;GO EXIT FM CLEANLY. EVENTUALLY ;RTNS TO AFTRFUNC ($A6AB) LOCATED ;IN THE FMDRIVER ROUTINE ($A6A8). *================================= * SUBROUTINE TO FREE UP A SECTOR * IN A TRKMAP OF THE VTOC. *================================= FREESEC SEC ;SET CARRY SO FREE UP PRESENT SEC ;WHEN START ROTATING ASSIGNMENT ;MAP. JSR SUB2FREE ;ADJUST ASSIGNMENT MAP TO FREE UP ;SEC BY SETTING BIT CORRESPONDING ;TO SEC #. NEXT, MERGE ASIGNMAP ;WITH THE APPROP BIT MAP IN VTOC. LDA #0 ;ZERO OUT ASIGNSEC, ASIGNTRK LDX #5 ;& ASIGNMAP (6 BYTES) IN WRK AREA RELEASEC STA ASIGNSEC,X DEX BPL RELEASEC RTS *================================= * CATALOG FUNCTION HANDLER. *================================= FNCATLOG JSR ZWRKAREA ;INITIALISE THE FM WORK AREA. LDA #$FF ;ALLOW ANY VOL TO BE CATALOGED. STA VOLWA ;(WHEN RWTS LATER ENTERED, THIS ;VALUE IS EORED WITH #$FF TO ;SIMULATED A COMPLEMENTED VOL # ;OF 0 (IE. #$FF EOR #$FF = #$00). ;AFTER RWTS READS THE ADDRESS ;CHECKSUM, IT CHECKS 2 SEE IF THE ;CORRECT VOL # WAS READ OFF THE ;DISK. IF THE COMPLEMENT OF THE ;VOL # IS 0, OR IF IT MATCHES THE ;VOL # READ OFF DSK, EXECUTION ;PROCEEDS AS IF THE CORRECT VOL ;WAS FOUND.) JSR READVTOC ;READ VOLUME TABLE OF CONTENTS. LDA #22 ;SET INDEX TO ALLOW 22 SCREEN STA SCRNSRCH ;LINES BETWEEN PAUSES. * PRINT 2 'S & THE WORDS * "DISK VOLUME". JSR CRCATLOG ;PRT & TEST IF PAUSE NEEDED. JSR CRCATLOG ;DO IT AGAIN. LDX #11 ;12 CHARS TO PRT (11 TO 0). PRDSKVOL LDA DSKVOLUM,X ;GET CHAR OF REVERSE STRING. JSR COUT ;PRINT CHAR. DEX BPL PRDSKVOL ;MORE CHARS IN STRING. STX A5L+1 ;NONSENSE INSTRUCTION (CAUSE THE ;HI BYTE IS NOT USED IN THE ;PRVOLNMB ROUTINE ($AE42).) LDA IBSMOD ;GET VOL# FOUND (FROM RWTS'S IOB) STA A5L ;AND PUT IT IN A5L. JSR PRVOLNMB ;GO PRINT VOL # (BUGGY ROUTINE). JSR CRCATLOG ;PRT & TEST IF PAUSE NEEDED. JSR CRCATLOG ;DO IT AGAIN. * READ DIRECTORY SECTOR INTO THE * DIRECTORY SECTOR BUFFER. CLC ;(C)=0, READ 1RST DIR SEC. ;(C)=1, READ NEXT DIR SEC. RDDIRSEC JSR RDDIRECT ;GO READ DIRECTORY SECTOR. BCS TOFMXTOK ;RAN OUT OF DIR SECS SO GO EXIT. LDX #0 ;INITIALIZE INDEX INTO DIR SEC. * ANALYZE THE TRACK NUMBER. DESCRPTK STX CURDIRNX ;SAVE NDEX TO ENTRIES IN DIR SEC. LDA FIL1TSTK,X ;TRK # OF FILE'S 1RST T/S LIST ;(FROM THE FILE'S DESCRIPTION IN ;THE DIRECTORY SECTOR). BEQ TOFMXTOK ;TRK # = 0, SO NO MORE ENTRIES IN ;CURRENT DIRECTORY BUFFER. BMI NXDESCRP ;TRK#=$FF=DELETED FILE SO SKIP IT * CHK FILE STATUS & PRINT LOCKED * SYMBOL ("*") OR SPACE. LDY #" " ;DEFAULT (Y)= N CASE NOT LCK LDA FIL1TYPE,X ;GET FILE TYPE. BPL PRLOCODE ;HI BIT CLR SO FILE UNLOCKED. LDY #"*" ;RESET (Y) = LOCKED SYMBOL. PRLOCODE TYA ;EITHER PRINT "*" OR . JSR COUT * PRINT CHAR CODE FOR FILE TYPE & * A TRAILING . LDA FIL1TYPE,X ;GET FILE TYPE AGAIN & MAKE SURE AND #$7F ;HI BYTE IS OFF SO CAN INDEX TBL ;THAT CONTAINS SYMBOLS FOR TYPES. LDY #7 ;SET (Y) TO INDICATE 7 RELEVANT ;BITS AFTER SHIFT OUT HI BIT. ASL ;THROW AWAY HI BIT. CHRTYPIX ASL ;SHIFT REST OF BITS UNTIL HI SET. BCS PRTFTYPE ;# OF SHIFTS 2 SET (C) DESIGNATES ;INDEX TO TYPE CHAR TABLE. DEY ;REDUCE COUNT OF SHIFTS. BNE CHRTYPIX ;NO SET BITS ENCOUNTERED YET, SO ;GO BACK TO DO MORE SHIFTS. PRTFTYPE LDA FTYPETBL,Y ;GOT A SET BIT SO NOW GET CHAR ;FROM TABLE OF TYPE SYMBOLS. JSR COUT ;PRINT TYPE SYMBOL. LDA #" " ;PRINT TRAILING . JSR COUT * PRINT FILE SIZE (EXPRESSED IN * TERMS OF SECTORS). LDA FIL1SIZE,X ;GET LOW & HI BYTES OF FILE SIZE STA A5L ;(IN SECTORS) FROM FILE DESCRIP LDA FIL1SIZE+1,X ;IN CUR DIR SEC & STICK THEM IN STA A5L+1 ;IN A5L/H. JSR PRVOLNMB ;PRINT FILE SIZE. ;*** NOTE *** - ROUTINE IS BUGGY. ;(DOESN'T USE HI BYTE, SO FILES ;> 255 SECS LONG ARE EXPRESSED ;AS 256 MOD.) LDA #" " ;PRINT AFTER SIZE. JSR COUT * PRINT THE FILE NAME. INX ;KICK (X) UP CAUSE NAME STARTS AT INX ;4TH BYTE FROM START OF FILE INX ;DESCRIPTION ENTRY. LDY #29 ;COUNTER FOR 30 CHRS/NAME (0-29). PRTFNAME LDA FIL1TSTK,X ;GET CHR 4 FILE NAME & PRINT IT. JSR COUT ;(P.S. BECAUSE THE OUTPUT HOOK ;STILL PTS TO DOS'S OUTPUT HNDLR, ;CTRL-D AND A SUBSUBSEQUENT DOS ;CMD CAN BE EMBEDDED IN THE FILE ;NAME AS A PROTECTION SCHEME.) INX ;KICK UP INDEX INTO FILE DESCRIP. DEY ;REDUCE THE CHARACTER COUNTER. BPL PRTFNAME ;BRANCH IF MORE CHARS TO PRT. JSR CRCATLOG ;PRT AFTR NAME, TEST 4 PAUS. * KICK UP INDEX INTO CURRENT DIRECTORY * SECTOR BUF TO PT AT START OF NEXT * FILE DESCRIPTION ENTRY. NXDESCRP JSR NXPLUS35 ;ADD 35 BYTES TO INDEX SO IT PTS ;TO NEXT ENTRY IN CURRENT DIR SEC. BCC DESCRPTK ;(C) = 0, SO GO LOOK FOR MORE ;ENTRIES IN THIS PARTICULAR ;DIRECTORY SECTOR. BCS RDDIRSEC ;(C) = 1, SO THERE AREN'T MORE ;ENTRIES IN THIS DIRECT SECTOR. ;THERE4, GO BACK TO READ IN ;ANOTHER DIRECTORY SECTOR. *================================= * EXIT FILE MANAGER CLEANLY. *================================= TOFMXTOK JMP GOODFMXT ;EVENTUALY RETURNS TO AFTRFUNC ;($A6AB) LOCATED IN THE FMDRIVER ;ROUTINE ($A6A8). *================================= * PRINT & CHK FOR PAUSE. *================================= CRCATLOG LDA #$8D ;PRINT A . JSR COUT DEC SCRNSRCH ;DEC INDEX 2 SEE IF PAUSE NEEDED. BNE CRCATRTN ;PAUSE NOT REQUIRED. JSR RDKEY ;PAUSE SO INFO CAN BE ABSORBED LDA #21 ;BEFORE SCROLLED OFF SCRN. STA SCRNSRCH ;RESET INDEX FOR FRESH SCRN INFO. CRCATRTN RTS *================================= * CONVERT 1 HEX BYTE TO 3-DIGIT * DECIMAL (WITH LEADING ZEROES IF * APPLICABLE). *================================= * NOTE: THIS IS A BUGGY ROUTINE * - DOESN'T USE HI BYTE SO NUMBERS * GREATER THAN 255 ARE EXPRESSED * AS 256 MOD. * * (PS. TO USE AS A STAND-ALONE * ROUTINE, LOAD A5L WITH HEX & CALL * PRVOLNMB. DESTROYS (A) & (Y) REGS. * CONVERSION DONE BY SIMULATING * DIVISION VIA SUCCESSIVE SUBTRACTIONS * OF POWERS OF 10.) PRVOLNMB LDY #2 ;INDEX TO # OF CONVERSION FACTORS ;AND DIGITS. ZONSTK LDA #0 ;INIT COUNT OF # OF SUBTR'S DONE. PHA ;SAVE COUNT ON STACK. GETVNMB LDA A5L ;GET LOW BTE HEX AND CMP IT TO CMP BASETEN,Y ;TABLE OF CONVERSION FACTORS. ;CONVERSION TABLE CONTAINS POWERS ;OF 10: 10^2=100, 10^1=10, 10^0=1 BCC TONEGASC ;BRANCH IF # < CONVERSION FACTOR. SBC BASETEN,Y ;SUBTRACT THE CONVERSION FACTOR. STA A5L ;STORE THE REMAINDER. LDA A5L+1 ;NONSENSE - NOT USED. SBC #0 ;NONSENSE - NOT USED. STA A5L+1 ;NONSENSE - NOT USED. PLA ;GET COUNTER OF # OF SUBT'S AND ADC #0 ;ADD (C). IF REMAIN. > CONVERSION PHA ;FACTOR, ADD 1, ELSE ADD NOTHING. JMP GETVNMB ;GO BACK TO DO MORE SUBT'S WITH ;SAME CONVERSION FACTOR. TONEGASC PLA ;GET RESULT OF DIV (IE. WHOLE # ;OF SUBTRACTIONS). ORA #$B0 ;CONVERT COUNT TO NEG ASCII CHAR. JSR COUT ;PRT CHAR. DEY ;3 CHARS/VOL# (IE. 2 TO 0). BPL ZONSTK ;(3 CONVERSION FACTORS.) RTS *================================= * COPY CONTENTS OF FM WORK BUFFER * (IN DOS CHAIN) TO FM WORK AREA * (NOT IN DOS CHAIN). *================================= RSTRFMWA JSR SELWKBUF ;PT A4L/H AT FM WORK BUF. ;(GET ADR FRM FM PARAMETER LIST.) LDY #0 ;ZERO OUT RETURN CODE IN FM PARM STY RTNCODFM ;LIST TO SIGNAL NO ERORS. STORFMWK LDA (A4L),Y ;COPY FM WORK BUF 2 FM WORK AREA. STA FMWKAREA,Y INY CPY #45 ;45 BYTES TO COPY (0 TO 44). BNE STORFMWK CLC ;WHY????? RTS *================================= * COPY FM WORK AREA TO FM WORK BUF * (LOCATED IN CHAIN OF DOS BUFS). *================================= CPYFMWA JSR SELWKBUF ;PT A4L/H AT FM WORK BUF (CHAIN). ;(GET ADR FROM FM PARM LIST.) LDY #0 ;INITIALIZE INDEX. STORWRK LDA FMWKAREA,Y ;COPY WORK AREA -----> WORK BUF. STA (A4L),Y INY CPY #45 ;45 BYTES TO COPY (0 TO 44). BNE STORWRK RTS *================================= * INIT FUNCTION HANDLER. *================================= FNINIT JSR ZWRKAREA ;INIT THE FM WRK AREA (NON-CHAIN) LDA #4 ;OPCODE FOR FORMAT. * GO FORMAT THE DISK. JSR RWTSDRV1 ;CALL RWTS DRIVER TO FORMAT DISK. * PUT VOL#, # OF NEXT TRK TO BE * ASSIGNED & ASSIGNMENT DIRECTION * IN THE VTOC SECTOR BUFFER. LDA VOLWA ;COMPLEMENTED VOL# (FRM WRK AREA) EOR #$FF ;UNCOMPL. IT & PUT VOL# IN VTOC. STA VOLUSED LDA #$11 ;USE TRK # 17 FOR CATALOG TRK. STA NXTRKUSE ;SET CAT TRK AS NXT TRK TO ALLOC. ;(NXTRKUSE IS LOCATED IN VTOC.) LDA #1 ;ALLOCATION DIRECTION = FORWARD. STA DRECTION * ZERO OUT VTOC FROM TRKMAP0 TO * END OF SECTOR. (NOTE: THIS * ASSIGNS ALL TRACKS.) LDX #56 ;OFFSET INTO VTOC TO TRKMAP0. LDA #0 ZVTOC STA VTOCBUFF,X ;ZERO OUT A TRKMAP BYTE. INX BNE ZVTOC * FREE UP ALL TRKS EXCEPT TRKS 0, * 1, 2 & CAT TRK (#17). * * NOTE: DOS ONLY OCCUPIES SECTORS * 0 TO 4 ON TRK 2, BUT ROUTINE * TAKES REST OF SECS ON TRK 2 OUT * OF CIRCULATION. LDX #$0C ;OFFSET TO START OF TRKMAP3. FREETRK CPX #$8C ;OFFSET 1 PAST END OF TRKMAP34. BEQ FREEDTKS ;DONE UP TO END OF TRKMAP34. LDY #3 ;INIT INDEX TO END OF FRETKMSK. FREEIT LDA FRETKMSK,Y ;FREE MOST TRKMAPS. (STARTING ;WITH TRKMAP3). ;NOTE: NOT FREEING UP VTOC SEC ;OR TRKS USED BY DOS. STA TRKMAP0,X ;FREE TRKS BY PLACING FOLLOWING ;BYTES IN @ TRKMAP: "FF FF 00 00" INX ;KICK UP INDEX TO BYTE IN TRKMAP. DEY ;REDUCE INDEX TO FRETKMSK CAUSE ;LOADING FROM END OF FRETKMSK: ; "00 00 FF FF". BPL FREEIT ;(4BYTES/TRKMAP & 4BYTS/FRETKMSK) CPX #$44 ;OFFSET TO START OF TRKMAP17 ;(IE. CATALOG TRACK). BNE FREETRK ;HAVE WE FREED TRKS 3 TO 16 YET? ;IF NOT - BRANCH. LDX #$48 ;OFFSET TO TRK 18 (IE. SKIP THE ;CATALOG TRACK). BNE FREETRK ;ALWAYS - GO FREE TRKS 18 TO 34. FREEDTKS JSR WRITVTOC ;WRITE FREED UP VTOC TO DISK. * CLEAR OUT THE DIRECTORY SEC BUF. LDX #0 TXA CLRDIREC STA DIRECBUF,X INX BNE CLRDIREC JSR PT2DIRBF ;DESIGNATE DIR SEC BUF AS I/O BUF LDA #$11 ;(A) = # OF CAT TRK. LDY SECPERTK ;# OF SECS/TRK = 16. DEY DEY STA IBTRK ;PUT CAT TRK IN IOB. * WRITE DIRECTORY SECS (TRK17, * SECS 15 TO 1) TO DISK. SETLNKTK STA DIRLNKTK ;SET TRK/SEC VALS FOR LINK 2 NEXT SETLNKSC STY DIRLNKSC ;DIRECTORY SECTOR. INY ;GET SEC # TO WRITE & PUT IT IN STY IBSECT ;RWTS'S IOB. LDA #2 ;WRITE OPCODE. JSR RWTSDRV1 ;WRITE DIRECTORY SEC TO DISK. LDY DIRLNKSC ;SEC VAL OF NEXT DIR SEC 2 WRITE. DEY ;KICK IT DWN (WILL INC IT LATER). BMI DOIMAGE ;DON'T DO SEC 0 CAUSE THAT'S VTOC BNE SETLNKSC ;GO WRITE SECS 2 TO 15. TYA BEQ SETLNKTK ;GO BACK TO WRITE SEC 1 AND ZERO ;OUT THE DIRECTORY SECTOR LINKS. * ROUTINE TO WRITE THE DOS * IMAGE ON TRACKS 0 TO 2. DOIMAGE JSR PRPWRDOS ;GET READY TO WRITE DOS IMAGE. JSR WRDOSIMG ;WRITE DOS IMAGE TO DISK. JMP GOODFMXT ;EXIT FM CLEANLY. EVENTUALLY RTNS ;TO AFTRFUNC ($A6AB) LOCATED IN ;THE FMDRIVER ROUTINE ($A6A8). *================================= * POINT A4L/H AT A SPECIFIC * SECTION OF A DOS BUFFER. *================================= SELWKBUF LDX #0 ;SELECT WORK BUFFER. BEQ PT2FMBUF ;ALWAYS. SELTSBUF LDX #2 ;SELECT T/S LIST BUFFER. BNE PT2FMBUF ;ALWAYS. SELDABUF LDX #4 ;SELECT DATA BUFFER. PT2FMBUF LDA WRKBUFFM,X ;GET ADDR OF SELECTED BUF FROM STA A4L ;FM PARM LST & PUT IT IN POINTER. LDA WRKBUFFM+1,X STA A4L+1 RTS *================================= * CHK IF DATA SEC BUF HAS CHANGED * SINCE LAST READ OR WRITE. *================================= CKDATUP BIT UPDATFLG ;CHK BIT6 SO SEE IF CHANGED. BVS WRITDATA ;TAKE BRANCH IF CHANGED. RTS *================================= * WRITE PRESENT DATA SECTOR BUFFER * TO THE DISK. (UPDATES DISK SO * CAN READ IN NEXT DATA SEC WITH- * OUT OVERWRITING AND THEREFORE * LOSING PREVIOUS DATA.) *--------------------------------- WRITDATA JSR PRPDAIOB ;PREPARE RWTS'S IOB FOR WRITING ;DATA SEC BUF TO DISK. LDA #2 ;OPCODE FOR WRITE CMD. JSR RWTSDRVR ;CALL DRIVER 2 WRT DATA SEC BUF. LDA #%10111111 ;SHUT BIT6 OFF IN UPDATE FLAG TO AND UPDATFLG ;SIGNAL THAT THE DATA SECTOR BUF STA UPDATFLG ;IS UP TO DATE. RTS *=================================== * CHK IF T/S LIST REQUIRES UPDATING. * (HAS T/S LIST BUF CHANGED SINCE * LAST READ OR WRITE?) *=================================== CKTSUPDT LDA UPDATFLG BMI WRITETS ;IF BIT7 SET, UPDATING REQUIRED. RTS *================================= * UPDATE T/S LIST SEC BUF ON DISK. *--------------------------------- WRITETS JSR SETTSIOB ;PREPARE RWTS'S IOB FOR WRITING ;T/S LIST BUFFER TO DISK. LDA #2 ;RWTS'S WRITE OPCODE. JSR RWTSDRVR ;CALL RWTS DRIVER 2 WRITE T/S LST LDA #$7F ;CLR BIT7 OF UPDATE FLAG 2 SIGNAL AND UPDATFLG ;THAT T/S LIST IS UP TO DATE. STA UPDATFLG RTS *================================= * PREPARE RWTS'S IOB FOR READING * OR WRITING T/S LIST SEC. *================================= SETTSIOB LDA TSBUFFM ;GET ADR OF T/S LIST BUF FROM STA IBBUFP ;FM PARM LIST & DESIGNATE AS I/O LDA TSBUFFM+1 ;BUF IN RWTS'S IOB. STA IBBUFP+1 LDX CURTSTRK ;SET (X)/(Y) = TRK/SEC OF CURRENT LDY CURTSSEC ;T/S LIST SECTOR. RTS *================================= * READ T/S LIST SEC TO BUFFER. *================================= READTS PHP ;SAVE CARRY ON STK. ;(C)=0=READ 1RST T/S LIST SEC. ;(C)=1=READ NEXT T/S LIST SEC. JSR CKTSUPDT ;WRITE T/S LIST SEC BUF IF ;UPDATING REQUIRED. (IF T/S LST ;BUF HAS CHANGED SINCE LAST READ ;OR WRITE, THEN WRITE IT BACK TO ;DISK SO DON'T OVERWRITE BUF AND ;LOSE INFO WHEN RD NEW T/S LIST.) JSR SETTSIOB ;PREP RWTS'S IOB FOR READING T/S ;LIST SEC. JSR SELTSBUF ;POINT A4L/H AT T/S LIST BUF. ;(GETS ADR FROM FM PARM LIST.) PLP ;GET SAVED (C) BACK FROM STK. BCS RDNXTTS ;IF (C)=1, ALREADY READ 1RST T/S ;LIST SEC, SO GO READ NEXT ONE. * READ 1RST T/S LIST SEC. * (CARRY WAS CLR.) RDFIRSTS LDX FIRSTSTK ;SET (X)/(Y)=TRK/SEC OF 1RST T/S LDY FIRTSSEC ;LIST SECTOR. JMP RDTSLST ;GO READ T/S LIST SEC INTO BUF. * --- * READ NEXT T/S LIST SEC. * (CARRY WAS SET.) RDNXTTS LDY #1 ;INDEX INTO T/S LIST BUF. LDA (A4L),Y ;TRK FOR LNK 2 NEXT T/S LIST SEC. BEQ TSLNKZRO ;LINK ZEROED OUT SO NO MORE ;T/S LIST SECS FOR FILE. TAX ;(X) = NEXT T/S LIST TRK. INY LDA (A4L),Y ;SEC# FOR LNK 2 NXT T/S LIST SEC. TAY ;(Y) = NEXT T/S LIST SEC. JMP RDTSLST ;GO READ NEXT T/S LIST SEC IN. * --- * T/S LINK ZEROED OUT SO * DECIDE IF ERROR OR NOT. TSLNKZRO LDA OPCODEFM ;CHK R/W STATUS TO SEE IF WANT TO CMP #4 ;ADD ANOTHER T/S LIST. BEQ UPDATETS ;WRITING - GO UPDATE LINK. SEC ;WERE READING & LNK ZEROED OUT, RTS ;SO RTN WITH (C)=1 SO GENERATE AN * === ;ERROR. (REMEMBER, PREVIOUSLY SET ;RTN CODE TO A DEFAULT VALUE FOR ;FILE-NOT-FOUND.) HOWEVER, IF ;READING IS BEING DONE FOR AN ;APPEND OR VERIFICATION, THEN THE ;SET (C) JUST DENOTES THAT HAVE ;REACHED THE END OF THE FILE. * WRITING & LNK ZEROED OUT SO MUST * ALLOCATE A NEW T/S LIST SECTOR. UPDATETS JSR ASGNTKSC ;FIND & RESERVE TRK/SEC VALS FOR ;A NEW T/S LIST SECTOR. * LINK THE NEW T/S LIST SECTOR TO * THE LAST T/S LIST SECTOR AND * THEN WRITE THE UPDATED VERSION * OF THE LAST T/S LIST SECTOR TO * THE DISK. LNKOLDNW LDY #2 ;OFFSET TO SEC# LINK BYTE. STA (A4L),Y ;PUT NEW SEC VAL IN LINK AND THEN PHA ;SAVE IT ON STK. DEY ;OFFSET TO TRK BYTE OF LINK. LDA ASIGNTRK ;PUT NEW TRK VAL IN LINK. STA (A4L),Y PHA ;SAVE TRK VAL ON STK. JSR WRITETS ;WRITE UPDATED T/S LIST TO DISK. * SET UP A BRAND NEW T/S LIST * SECTOR & WRITE IT TO DISK. ZOUTTS JSR ZCURBUF ;ZERO OUT T/S LIST BUF. LDY #5 ;AT OFFSETS 5 & 6 IN2 THE NEW T/S LDA RELASTP1 ;LIST, PUT REL SEC # PLUS 1 (IN STA (A4L),Y ;RELATION TO THE ENTIRE FILE) OF INY ;THE 1RST DATA PAIR THAT WILL BE LDA RELASTP1+1 ;DESCRIBED IN THIS NEW T/S LIST. STA (A4L),Y ;(POSSIBLE VALUES ARE: $007A, ;2*$007A, 3*$007A AND 4*$007A. PLA ;GET (X)/(Y)=TRK/SEC VALS 4 THIS TAX ;NEW T/S LIST SEC OFF STACK. PLA TAY LDA #2 ;WRITE OPCODE FOR RWTS. BNE RDWRTS ;ALWAYS - GO WRITE T/S LIST SEC. * --- * SUBROUTINE TO READ T/S LIST SEC. RDTSLST LDA #1 ;READ OPCODE FOR RWTS. * COMMON TO READ/WRITE T/S LIST. RDWRTS STX CURTSTRK ;NEW T/S LIST SECTOR TRK/SEC VALS STY CURTSSEC ;BECOME CURRENT TRK/SEC VALS. JSR RWTSDRVR ;CALL RWTS DRIVER 2 READ OR WRITE ;THE CURRENT T/S LIST SECTOR. * UPDATE FM WORK AREA BUF (NON-CHAIN). LDY #5 ;OFFSET IN2 CURRENT T/S LIST BUF. LDA (A4L),Y ;STORE REL SEC # OF 1RST DAT PAIR STA RELFIRST ;THAT CAN BE DESCRIBED IN THIS ;T/S LIST. (POSSIBLE VALUES ARE: ;$0000, $007A, 2*$007A, 3*$007A ;AND 4*$007A.) CLC ;ADD THE MAXIMUM # OF DATA SECS ADC MXSCURTS ;THAT CAN POSSIBLY BE DESCRIBED ;IN THIS T/S LIST. STA RELASTP1 ;STORE THE MAXIMUM RELATIVE SEC # INY ;(PLUS 1) OF THE LAST DATA PAIR ;THAT CAN POSSIBLY BE DESCRIBED ;IN THIS T/S LIST. LDA (A4L),Y STA RELFIRST+1 ADC MXSCURTS+1 STA RELASTP1+1 ;(RELASTP1/+1 IS ALWAYS SET TO ;$007A BY FNOPEN. (POSSIBLE VALS ;ARE: $007A, 2*$007A, 3*$007A, ;4*$007A OR 5*$007A.) CLC ;RETURN WITH NO ERRORS SIGNAL. RTS *================================= * READ DATA SEC TO DATA SEC BUF. *================================= READDATA JSR PRPDAIOB ;SET UP RWTS'S IOB 2 RD DATA SEC. LDA #1 ;READ OPCODE FOR RWTS. JMP RWTSDRVR ;CALL RWTS DRIVER 2 READ DAT SEC. *================================= * PREP RWTS'S IOB TO READ * OR WRITE THE DATA SECTOR. *================================== PRPDAIOB LDY DATBUFFM ;GET ADR OF DATA SEC BUF FROM THE LDA DATBUFFM+1 ;FM PARM LIST & DESIGNATE IT AS STY IBBUFP ;THE I/O BUF FOR RWTS'S IOB. STA IBBUFP+1 LDX CURDATRK ;ENTER RWTS DRIVER WITH (X)/(Y) LDY CURDATSC ;CONTAINING THE TRK/SEC VALUES OF RTS ;THE DATA SECTOR. $