*=================================
*      WRITE COMMAND HANDLER.
*=================================

CMDWRITE JSR COMRDWR ;CALL COMMON READ/WRITE ROUTINE.
;FIND NAMED BUF, ELSE A FREE BUF.
;OPEN FILE IF NOT ALREADY OPEN.
;POS'N FILE PTR IF R- OR B-PARMS
;WERE ISSUED.
 LDA #5 ;SET CONDITION 5.
 STA OPUTCOND

 JMP FINSHCMD ;XIT WITH CONDITION 5 SET SO THAT
;THE NEXT TIME A PRINT STATEMENT
;IS ENCOUNTERED, EXECUTION WILL
;FLOW VIA COUT & THE DOS HKS TO
;SEND CHARS TO THE NAMED FILE.


*=================================
*      READ COMMAND HANDLER.
*=================================

CMDREAD JSR COMRDWR ;CALL COMMON READ/WRITE ROUTINE.
;FIND NAMED BUF, ELSE FIND A FREE
;BUFFER. OPEN FILE IF NOT ALREADY
;OPEN.  POS'N FILE PTR IF R- OR
;B-PARMS WERE ISSUED WITH CMD.
 LDA #1 ;SET CONDNFLG TO SIGNAL READING.
 STA CONDNFLG
 JMP FINSHCMD ;XIT WITH OPUTCOND=0 & CONDNFLG=1
;EXECUTION EVENTUALLY FLOWS BACK
;INTO APPLESOFT.  WHEN APPLESOFT
;PICKS UP A SUBSEQUENT "INPUT" OR
;"GET" STATEMENT, IT PRINTS A
;PROMPT.  DOS INTERCEPTS OUTPUT
;VIA OPUTINCP ($9EBD).  WHEN THE
;SETTING OF CONDNFLG IS DETECTED,
;THE MACHINE IS DIRECTED TO TAKE
;DATA FROM THE DISK.


*=================================
*    CODE COMMON TO READ/WRITE.
*=================================

COMRDWR JSR GETBUFF ;LOCATE A DOS BUF WITH SAME NAME,
;ELSE LOCATE A FREE BUF.
 BCC BUFS4RW ;BRNCH IF MATCHING BUF WAS FOUND.
 JSR CMDOPEN ;FILE NOT ALREADY OPN, SO OPEN IT
 JMP CKRBOPTN ;GO CHK IF R- & B-PARMS ISSUED.

BUFS4RW JSR BUFS2PRM ;COPY ADDRS OF THE VARIOUS DOS
;BUFFERS TO THE FM PARAMETER LIST

* CHK IF R- OR B-PARAMETERS
* WERE ISSUED WITH COMMAND.

CKRBOPTN LDA CUMLOPTN ;CHK IF R- OR B-PARMS ISSUED.
 AND #%00000110 ;(R=$04, B=$02.)
 BEQ RDWRRTN ;NO - SKIP POS'NING OF FILE PTR.

* COPY B- & R-PARMS FROM OPTION
* PARSED TABLE TO FM PARM LIST.

 LDX #3
CPYBPARM LDA RECPRSD,X ;GET VALUE OF PARAMETER.
 STA RECNMBFM,X ;STORE IT IN PARM LIST.
 DEX ;4 BYTES TO COPY (3 TO 0).
 BPL CPYBPARM

* CALL THE FILEMANAGER
* WITH THE POSITION OPCODE.

BK2APND LDA #$0A ;OPCODE FOR POSITION.
 STA OPCODEFM ;PUT IT IN THE FM PARAMETER LIST.
 JSR FMDRIVER ;CALL FM 2 DO THE POS'N FUNCTION.
RDWRRTN RTS


*=================================
*      INIT COMMAND HANDLER.
*=================================

CMDINIT LDA #%01000000 ;CHK TO SEE IF V(OLUME) OPTION
 AND CUMLOPTN ;WAS ISSUED WITH INIT COMMAND.
 BEQ VOL254 ;NO V-PARM ISSUED, SO USE A DFLT
;VOLUME VALUE OF 254.
 LDA VOLPRSD ;A VOL VAL WAS ISSUED, SO USE IT
 BNE OTHRVOL ;(BUT ONLY IF IT IS NOT ZERO).
VOL254 LDA #254 ;USE VOL 254 AS DEFAULT VALUE.
 STA VOLPRSD
OTHRVOL LDA ADOSTART+1 ;HI BYTE OF DOS LOAD ADDR FROM
;DOS'S MAIN VARIABLE TABLE.
 STA SUBCODFM
 LDA #11 ;OPCODE FOR INIT COMMAND.
 JSR HNDLCMD1 ;CALL FM COMMAND HANDLER TO DO
;THE INIT COMMAND.
 JMP CMDSAVE ;GO SAVE THE "HELLO" FILE & THEN
;EXIT TO THE CALLER OF THE INIT
;CMD.  (NORMALLY RTNS TO AFTRCMD
;($A17D) LOCATED IN THE COMMAND
;PARSING & PROCESSING ROUTINES.)


*=================================
*     CATALOG COMMAND HANDLER.
*=================================

CMDCATLG LDA #6 ;CATALOG OPCODE.
 JSR HNDLCMD1 ;CALL CMD HANDLER TO DO CATALOG.
 LDA VOLFM ;GET VOLUME # FROM FM PARM LIST
 STA VOLPRSD ;& PUT IT IN THE PARSED TABLE.
 RTS ;EXIT TO CALLER OF CATALOG CMD.
;(OFTEN RETURNS 2 AFTRCMD ($A17D)
;LOCATED IN THE CMD PARSING AND
;PROCESSING ROUTINES.)


*=================================
*       FP COMMAND HANDLER.
*=================================

CMDFP LDA #$4C ;(A) = OPCODE FOR "JMP".
 JSR SETROM ;TEST 2 SEE IF LANGUAGE WANTED IS
;ON CARD OR MOTHERBOARD.
 BEQ TODOSCLD ;ROM VERSION OF FP WAS PRESENT ON
;EITHER CARD OR MOTHERBOARD SO GO
;DO A COLDSTART.

* USING MACHINE WITH INTEGER IN ROM.
*
* ASSUME USING "SYSTEM MASTER" DISK
* SO TRY TO RUN AN INTEGER PRGM
* CALLED "APPLESOFT".  WHEN RUN, THE
* PRGM CALLED "APPLESOFT" LOADS A
* RAM OR DISK-BASED VERSION OF FP
* BASIC THAT IS CONTAINED IN A BINARY
* FILE CALLED "FPBASIC".  THIS LATTER
* FILE IS ALSO HOUSED ON THE SYSTEM
* MASTER DISK.

 LDA #0 ;SET ACTIVE BASIC FLAG TO DENOTE
 STA ACTBSFLG ;USING INTEGER.
 LDY #30
 JSR BLNK1RST ;BLANK OUT THE PRIMARY FILE NAME
;BUFFER (30 BYTES LONG).

* COPY THE NAME OF THE INTEGER FILE
* CALLED "APPLESOFT" INTO THE PRIMARY
* FILE NAME BUFFER.

 LDX #9 ;ONLY 9 CHARS IN NAME "APPLESOFT"
CPYAPPLE LDA RUNTRUPT,X ;GET CHARS OF NAME.
 STA PRIMFNBF-1,X ;STORE THEM IN PRIMARY NAME BUF
 DEX ;REDUCE COUNTER.
 BNE CPYAPPLE ;MORE CHARS TO COPY.

 LDA #$C0 ;SET CONDNFLG TO DESIGNATE USING
 STA CONDNFLG ;RAM VERSION OF APPLESOFT.
 JMP CMDRUN ;GO RUN FILE CALLED "APPLESOFT"
;WHICH LOADS A RAM VERSION OF
;FP BASIC CONTAINED IN A BINARY
;FILE CALLED "FPBASIC".


*=================================
*       INT COMMAND HANDLER.
*=================================

CMDINT LDA #$20 ;OPCODE FOR "JSR".
 JSR SETROM ;TEST TO SEE IF LANGUAGE WANTED
;IS ON CARD OR MOTHERBOARD.
 BEQ INTPRSNT ;INTEGER BASIC IS PRESENT (EITHER
;ON CARD OR MOTHERBOARD).

* INTEGER BASIC NOT PRESENT
* ON CARD OR MOTHERBOARD.

NOLNGINT LDA #1 ;SET ERROR CODE FOR LANGUAGE-NOT-
 JMP ERRHNDLR ;AVAILABLE MSG & GO EXIT.

* INTEGER BASIC PRESENT ON DEVICE.

INTPRSNT LDA #0 ;CAUSE DESIRED BASIC IS PRESENT,
 STA RUNTRUPT ;ZERO OUT THE RUN INTERCEPT FLAG
;CAUSE WE WON'T BE LOADING A LANG
TODOSCLD JMP DOSCOLD ;GO INTO THE COLDSTART ROUTINE.


*=================================
*      SELECT DESIRED BASIC
*=================================

* TEST CARD OR MOTHERBOARD TO INSURE
* THAT DEVICE CONTAINING THE ROM
* VERSION WE WANT IS SELECTED.
* BASICCLD ($E000) CONTAINS A "JMP"
* OR "JSR" INSTRUCTION IF DEALING
* WITH FP OR INTEGER ROM RESPECTIVELY.

SETROM CMP BASICCLD ;TEST CARD OR MOTHERBOARD.
;(IE.CHK WHICHEVER DEVICE IS UP.)
 BEQ DVICERTN ;LANG WNTD ON PRESENT ROM DEVICE.

* LANGUAGE WAS NOT ON DEVICE SELECTED
* ABOVE, SO SPECIFICALLY TEST CARD
* IN SLOT 0.  (P.S. COULD CHANGE ADDRS
* IF WANT CARD IN DIFFERENT SLOT.)

 STA $C080 ;READ ENABLE SLOT0.
 CMP BASICCLD ;CHECK IDENTIFYING BYTE.
 BEQ DVICERTN ;BRANCH IF ROM WANTED IS ON CARD.

* ROM WANTED WAS NOT ON CARD.
* WE MAY HAVE JUST TESTED CARD TWICE
* SO NOW SPECIFICALLY TEST MOTHERBOARD.

 STA $C081 ;TEST MOTHERBOARD.
 CMP BASICCLD ;CHECK IDENTIFYING BYTE.
DVICERTN RTS ;EXIT WITH THE SWITCHES POINTING
;AT THE LAST DEVICE TESTED.IF THE
;DESIRED LANGUAGE IS PRESENT, THE
;SWITCHES ARE LEFT WITH THE
;APPROPRIATE DEVICE SELECTED.


*=================================
*      EXEC COMMAND HANDLER.
*=================================

CMDEXEC JSR CMDOPEN ;GO OPEN THE FILE TO BE EXECED.
 LDA CURFNADR ;GET ADDR OF CURRENT FILENAME BUF
 STA EXECBUFF ;& DESIGNATE AS EXEC'S NAME BUF.
 LDA CURFNADR+1
 STA EXECBUFF+1
 LDA PRIMFNBF ;SET EXEC FLAG TO A NON-ZERO VAL.
 STA EXECFLAG ;(USE 1RST CHAR OF FILE NAME.)
 BNE POSNCHKR ;ALWAYS - GO POS'N FILE PTR IF
;NECESSARY.
;NOTE: ACTUAL EXECING OF STATMNTS
;DOES NOT OCCUR UNTIL AFTER THE
;COMPUTER RETURNS TO BASIC'S
;RESTART ($D43C) ROUTINE.  WHEN
;INPUT IS REQUESTED, EXECUTION
;FLOWS VIA DOS HKS INTO OPUTINCP
;($9EBD).  HERE THE EXECFLAG IS
;TESTED & DISCOVERED TO BE SET.
;AS RESULT, THE READEXEC ($A682)
;ROUTINE IS USED 2 READ DATA FROM
;THE EXEC FILE.  THE STATEMENTS
;ARE INTERPRETED AS IF THEY WERE
;ENCOUNTERED IN THE IMMED MODE.


*=================================
*     POSITION COMMAND HANDLER
*=================================

CMDPOSN JSR GETBUFF ;LOCATE BUF WITH SAME NAME, ELSE
;LOCATE A FREE BUFFER.

 BCC BUFS4PSN ;ALREADY OPEN -SKIP NEXT INSTRUC.
 JSR CMDOPEN ;GO OPEN THE FILE.
 JMP POSNCHKR ;BYPASS NEXT INSTRUC, CAUSE JUST
;OPENED FILE & PARM LIST ALREADY
;CONTAINS ADRS OF DIF DOS BUFS.

BUFS4PSN JSR BUFS2PRM ;GET ADR OF DOS BUFS FROM CHAIN
;BUF & PUT THEM IN FM PARM LIST.

POSNCHKR LDA CUMLOPTN ;CHK TO SEE IF A NON-ZERO R-PARM
 AND #%00000100 ;WAS ISSUED WITH CMD.
 BEQ DONEPOSN ;R-PARM WAS ZERO, SO GO EXIT
;(IE. DON'T MOVE FILE POINTER).

* A NON-ZERO R-PARM WAS ISSUED, SO GO MOVE
* THE FILE POINTER FORWARD BY READING
* ONE BYTE AT A TIME.  WHEN A <CR> IS
* ENCOUNTERED, REDUCE THE COUNT OF THE
* RELATIVE FIELD POSITIONS LEFT TO MOVE.
* WHEN THE COUNT EQUALS ZERO, WE ARE
* DONE POSITIONING.

CKPSNDUN LDA RECPRSD ;CHECK COUNT.
 BNE POSNMORE
 LDX RECPRSD+1
 BEQ DONEPOSN ;R-PRM HAS BEEN COUNTED DWN TO 0,
;SO WE ARE DONE POSITIONING.
 DEC RECPRSD+1 ;REDUCE COUNT OF R-PARM (IE. # OF
POSNMORE DEC RECPRSD ;FIELDS MOVED FORWARD) FOR NEXT
;TIME AROUND.
PSNFIELD JSR RDTXTBYT ;GO READ A TEXT FILE BYTE.
 BEQ ENDATERR ;IF BYTE JUST READ = $00,THEN RAN
;OUT OF DATA.  A ZERO BYTE CAN BE
;OBTAINED FROM AN INCOMPLETELY
;FILLED DATA SECTOR.  OR, IF THE
;FILE ENDS ON A SECTOR BOUNDARY,
;A $00 CAN ALSO BE ACQUIRED FROM
;A ZEROED-OUT T/S LINK OR A
;ZEROED-OUT DATA PAIR (TRK/SEC
;VALUES) LISTED IN A T/S LIST.
 CMP #$8D ;WAS BYT A FIELD-DELIMITING <CR>?
 BNE PSNFIELD ;NO -GO READ THE NEXT BYTE IN THE
;SAME FIELD.
 BEQ CKPSNDUN ;YES - GOT END-OF-FIELD MARKER SO
;BRANCH BACK TO REDUCE THE FIELD
;COUNT & SEE IF WE'RE DONE
;POSITIONING YET.
DONEPOSN RTS ;EXIT - EITHER DONE POSITIONING,
;ELSE R-PARM WAS 0 TO START WITH
;& THERE4 NO POSITIONING NEEDED.
;EXIT 2 CALLER OF COMMAND.  OFTEN
;RETURNS 2 AFTRCMD ($A17D) LOC'D
;IN THE CMD PARSING & PROCESSING
;ROUTINES.


*=================================
* WRITE-ONE-DATA-BYTE SUBROUTINE.
*=================================

WRITEXT JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM.
 BCS CLOSZERO ;NOT RUNNING, SO GO CLOSE FILE,
;RESET TO CONDITION 0 & THEN DO A
;WARMSTART.  (REMEMBER, WRITE CMD
;IS RESTRICTED TO DEFERRED MODE.)
 LDA ASAVED ;RETRIEVE BYTE TO WRITE.
 STA ONEIOBUF ;PUT IT IN FM PARM LIST.
 LDA #4 ;SET PARM LIST TO WRITE ONE BYTE.
 STA OPCODEFM
 LDA #1
 STA SUBCODFM
 JMP FMDRIVER ;GO TO FM DRV TO WRITE DATA BYTE.


*=================================
*   ROUTINE TO READ A DATA BYTE.
*=================================

READTEXT JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM.
 BCS CLOSZERO ;BASIC NOT RUNNING SO GO CLOSE
;FILE, RESET 2 CONDITION 0 & DO A
;WARMSTART.  (REMEMBER READ CMD
;IS RESTRICTED 2 DEFERRED MODE.)
 LDA #6 ;SET COND'N6 -IGNORE INPUT PROMPT

SETCOND STA OPUTCOND
 JSR RDTXTBYT ;GO READ TEXT FILE DATA BYTE.
 BNE NOTEND ;IF BYTE READ <> 0, THEN HAVEN'T
;HIT END-OF-FILE MARKER YET.

* RAN OUT OF DATA.  PICKED UP A $00 BYTE
* EITHER FROM PARTIALLY FULL DATA SECTOR,
* A ZEROED-OUT T/S LINK OR A ZEROED-OUT
* DATA PAIR (TRK/SEC VALUES LISTED IN A
* T/S LIST).

 JSR CLOSEONE ;RAN OUT OF DATA SO CLOSE FILE.
 LDA #3 ;USING CONDITION 3?
 CMP OPUTCOND ;IE. HNDLING AN INPUT STATEMENT?
 BEQ DONEPOSN ;YES - JUST GO TO AN "RTS".

ENDATERR LDA #5 ;NO - THERE4 GOT OUT-OF-DATA ERR.
 JMP ERRHNDLR ;GO HANDLE ERROR.

NOTEND CMP #$E0 ;LOWERCASE?
 BCC SAVIT ;BRANCH IF UPPERCASE.
 AND #$7F ;CONVERT LOWER TO UPPER IN ORDER
;2 FOOL CAPTST ROUTINE ($FD7E)
;IN MONITOR ROM.
SAVIT STA ASAVED ;SAVE CHAR READ.
 LDX XSAVED ;GET INDEX TO INPUT BUFFER.
 BEQ TOEXIT ;BRANCH IF 1RST CHAR.
 DEX ;TURN HI BIT ON IN PREVIOUS CHAR
 LDA BUF200,X ;STORED IN BUF200 TO CONVERT TO
 ORA #$80 ;LOWERCASE IF NECESSARY.
 STA BUF200,X
TOEXIT JMP DOSEXIT ;GO TO DOS'S EXIT ROUTINE.


*==================================
* CHECK IF BASIC IS RUNNING A PRGM.
*==================================

CKBSCRUN PHA ;SAVE (A) ON STK.
 LDA ACTBSFLG ;WHICH BASIC IS UP?
 BEQ INTBASIC ;BRANCH IF USING INTEGER.

* USING APPLESOFT SO NOW CHECK IF
* IN IMMEDIATE OR DEFERRED MODE.
* (IF LINE NUMBER BYTES ARE
* GREATER THAN OR EQUAL TO DECIMAL
* 65280 ($FF IN HI BYTE), THEN THE
* COMPUTER ASSUMES THAT WE'RE USING
* THE IMMEDIATE MODE.)

 LDX CURLIN+1 ;CHK HI BYTE OF LINE #.
 INX ;IF $FF --> $00, THEN # > = 65280
 BEQ IMEDMODE ;BRANCH IF USING IMMEDIATE MODE.

* FP APPEARS TO BE RUNNING A PRGM
* BUT, MAYBE CURLIN+1 WAS ZAPPED
* (POSSIBLY AS PART OF A PROTECTION
* SCHEME) SO BETTER ALSO CHECK THE
* PROMPT.

 LDX PROMPT
 CPX #"]" ;USING AN APPLESOFT PROMPT?
 BEQ IMEDMODE ;YES - SO MUST BE IN IMMED MODE.

RUNNING PLA ;GET SAVED (A) BACK FROM STK.
 CLC ;SIGNAL PRGM IS RUNNING.
 RTS

INTBASIC LDA RUNMODE ;CHK INTGR BASIC'S RUN MODE FLG.
 BMI RUNNING ;IF NEG, INT BASIC IN DEFERRED.

IMEDMODE PLA ;GET SAVED (A) BACK FROM STK.
 SEC ;SIGNAL IN IMMEDIATE MODE.
 RTS


*====================================
* CLOSE FILE, SET CONDITION0, & EXIT.
*====================================

CLOSZERO JSR CLOSEONE ;CLOSE OPEN FILE.
 JSR RESTAT0 ;RESET TO CONDITION 0.
 JMP DOSEXIT ;GO TO DOS'S EXIT ROUTINE.


*=================================
*    EXEC'S READ DATA ROUTINE.
*=================================

READEXEC JSR PT2EXEC ;POINT THE A3L/H POINTER AT BUF
;THAT WE'RE EXECING IN.
 JSR BUFS2PRM ;COPY ADDRS OF THE VARIOUS DOS
;BUFS FROM THE CHAIN BUF & PUT
;THEM IN THE FM PARAMETER LIST.
 LDA #3 ;SET CONDITION 3 SO PROCESS DATA
 BNE SETCOND ;INPUT FROM THE DISK.


*=================================
*     READ A TEXT FILE BYTE.
*=================================

RDTXTBYT LDA #3 ;SET FM PRM LIST 2 READ ONE BYTE.
 STA OPCODEFM
 LDA #1
 STA SUBCODFM
 JSR FMDRIVER ;CALL FM DRIVER TO READ A BYTE.
 LDA ONEIOBUF ;LOAD (A) WITH BYTE JUST READ.
 RTS


*=================================
*   POINT THE A3L/H POINTER AT
*   BUFFER THAT WE'RE EXECING IN.
*=================================

PT2EXEC LDA EXECBUFF+1 ;GET ADR OF DOS BUF USING 2 EXEC.
 STA A3L+1 ;PUT IT IN POINTER.
 LDA EXECBUFF
 STA A3L
 RTS


*=================================
*    THE FILE MANAGER DRIVER.
*=================================

FMDRIVER JSR FILEMGR ;CALL FM MANAGER TO DO FUNCTION.

* RETURN HERE AFTER DOING THE FUNCTION.
* (CAUSE, USE STACK TO GET BACK TO
* ORIGINAL CALLER OF FUNCTION.)
* IF WE JUST DID A READ FUNCTION &
* THE LAST BYTE READ WAS FROM A DATA
* SECTOR, THEN ENTER WITH (C)=0.
* (NOTE THAT IT MAKES NO DIFFERENCE
* IF THAT DATA BYTE WAS A $00 OR NOT.)
* HOWEVER, IF WE ARE DEALING WITH A
* ZEROED-OUT T/S LINK OR A ZEROED-OUT
* DATA-PAIR BYTE FROM A T/S LIST,
* THEN ENTER WITH CARRY SET.


AFTRFUNC BCC FMDRVRTN ;(C) = 0 = NO ERRORS.
 LDA RTNCODFM ;GET RETURN CODE FRM FM PARM LIST
 CMP #5 ;"END-OF-DATA" ERROR?
 BEQ TOAPPTCH ;YES -NOT HANDLED LIKE OTHER ERRS
;FILE ENDS AT A FULL DATA SEC SO
;WE ENCOUNTERED A ZEROED-OUT T/S
;LINK OR A ZEROED-OUT DATA PAIR
;(TRK/SEC VALUES LISTED IN A T/S
;LIST).
 JMP OTHRERR ;ONLY TAKE IF GOT AN ERROR OTHER
;THAN AN END-OF-DATA ERROR.
TOAPPTCH JMP APNDPTCH ;GO HANDLE END-OF-DATA ERROR.

 NOP
BK2FMDRV JSR CKIFAPND ;<---NOTE: APNDPTCH RETURN HERE!!
;GO CHK IF THE APPEND FLAG IS ON.
 LDX #0 ;ZERO-OUT THE ONE-DATA-BYTE BUF
 STX ONEIOBUF ;IN THE FM PARAMETER LIST.  (ALSO
;REFERRED TO AS THE LOW BYTE OF
;CURIOBUF.)
FMDRVRTN RTS ;RETURN TO CALLER OF FM DRIVER.


*=================================
*    SELECTED ERROR PROCESSING.
*=================================
* NOTE: PROGRAMMERS WHO ACCESS DOS
* FROM ASSEMBLY LANGUAGE PROGRAMS
* SHOULD TAKE SPECIAL NOTE OF THE
* THE FORMATTED DISASSEMBLY TITLED
* "DISASSEMBLY OF ERRORS".


SYNTXERR LDA #11
 BNE ERRHNDLR ;ALWAYS.
NOBUFERR LDA #12
 BNE ERRHNDLR ;ALWAYS.
TOOLARGE LDA #14
 BNE ERRHNDLR ;ALWAYS.
TYPMISM LDA #13


*=================================
* DOS'S MAIN ERROR-HANDLER ROUTINE
*=================================

ERRHNDLR STA ASAVED ;SAVE RETURN CODE FOR LATER USE.
 JSR RESTATIN ;RESET THE FOLLOWING FLAGS TO 0:
;  OPUTCOND, CONDNFLG & RUNTRUPT.
 LDA ACTBSFLG ;CHK IF INT OR FP BASIC ACTIVE.
 BEQ WASINT ;BRANCH IF USING INTEGER.
;(ONERR FLAG NOT APPLIC TO INT.)
 LDA ERRFLG ;CHK IF BASIC'S ONERR FLAG IS ON.
 BMI ONERRACT ;YES - SKIP PRINTING OF ERROR MSG
;CAUSE WE EVENTUALLY WANT 2 GO 2
;OUR OWN CUSTOMIZED ERROR-HNDLING
;ROUTINE.
WASINT LDX #0 ;INITIALIZE INDEX TO TABLE OF
;OFFSETS TO ERRORS.
 JSR PRDOSERR ;GO PRINT <RTN>, BELL, <RTN>.
 LDX ASAVED ;GET SAVED RETURN CODE.
 JSR PRDOSERR ;GO PRINT THE ERROR MESSAGE.
 JSR CRVIADOS ;PRINT A <CR>.
ONERRACT JSR INITIOHK ;RESET I/O HKS TO POINT TO DOS.
 JSR CKBSCRUN ;CHK IF BASIC IS RUNNING A PRGM:
;   (C) = 0 IF RUNNING.
;   (C) = 1 IF IMMEDIATE.
 LDX ASAVED ;GET SAVED RETURN CODE.
 LDA #3 ;SET (A) = 3 IN CASE FALL THRU TO
;GO TO BASIC'S ERROR HANDLING
;ROUTINE. THE MAGIC # OF 3 ALLOWS
;BSCERHLR ($D865) TO CONDITION
;(C) = 0 AND (Z) = 1 IN ORDER TO
;COMPLY WITH THE BASIC ROUTINE
;THAT IS RESPONSIBLE FOR PRINTING
;BASIC'S ERROR MESSAGES.
 BCS DOWRM ;BASIC IS NOT RUNNING.

TOBSCERR JMP (ADBSCERR) ;2 BASIC'S ERROR HANDLING ROUTINE
;(BSCERHLR, $D865).

DOWRM JMP (TOWRMVEC) ;TO BASIC'S WARMSTART ROUTINE
;(RESTART, $D43C).


*=================================
*   PRINT THE DOS ERROR MESSAGE.
*=================================

PRDOSERR LDA OFF2ERR,X ;USE ERROR CODE TO GET OFFSET TO
;ERROR MESSAGE.
 TAX ;(X) = OFFSET INTO THE TABLE
;CONTAINING THE TEXT OF THE DOS
;ERROR MESSAGES.
MORERMSG STX TEMPBYT ;SAVE OFFSET INTO TXT TABLE.
 LDA ERRTXTBL,X ;GET CHAR OF ERROR MESSAGE.
 PHA ;SAVE IT ON STACK.
 ORA #$80 ;TURN HI BIT ON 2 SATISFY MONITOR
 JSR GODSPLY ;GO PRINT VIA TRUE OUTPUT HANDLER
 LDX TEMPBYT ;RESET OFFSET TO TABLE OF TEXT.
 INX ;KICK INDEX UP FOR NXT CHR OF MSG
 PLA ;GET ORIG CHAR BACK IN (A).
 BPL MORERMSG ;BRANCH IF MORE CHRS IN MSG 2 PRT
 RTS ;ALL BUT LAST CHR IN MSG ARE POS.


*=================================
* PUT VOL, DRV, AND SLOT VALUES
* PLUS THE ADR OF THE PRIMARY FILE
* NAME BUFFER IN FM PARAMETER LIST
*=================================

CPY2PARM LDA VOLPRSD ;FROM PARSED TABLE.
 STA VOLFM
 LDA DRVPRSD ;FROM PARSED TABLE.
 STA DRVFM
 LDA SLOTPRSD ;FROM PARSED TABLE.
 STA SLOTFM
 LDA ADRPFNBF ;GET THE ADR OF THE PRIMARY FILE
 STA FNAMBUFM ;NAME BUF FROM THE CONSTANTS TBL
 LDA ADRPFNBF+1 ;AND PUT IT IN THE FM PARM LIST.
 STA FNAMBUFM+1
 LDA A3L ;SAVE ADR OF CURRENT DOS FILENAME
 STA CURFNADR ;BUF IN TABLE OF DOS VARIABLES.
 LDA A3L+1
 STA CURFNADR+1
 RTS


*===================================
* COPY NAME OF FILE FROM THE PRIMARY
* FILENAME BUFFER TO THE APPROPRIATE
* DOS NAME BUFFER LOCATED IN THE
* CHAIN OF DOS BUFFERS.
* THIS ASSIGNS (OR RE-ASSIGNS) A DOS
* BUFFER TO THE FILE WE WANT TO OPEN.
* THE HIGHEST NUMBERED (LOWEST IN
* MEMORY) FREE DOS BUFFER IS USED.
*===================================

CPYPFN LDY #29 ;30 BYTES TO COPY (0 TO 29).
CPYPRIM LDA PRIMFNBF,Y ;GET CHAR FROM PRIMARY.
 STA (A3L),Y ;STORE IT IN DOS NAME BUF.
 DEY  ;REDUCE COUNTER.
 BPL CPYPRIM ;MORE CHARS TO COPY.
 RTS


*====================================
* GET THE ADDRS OF THE VARIOUS DOS
* BUFS FROM THE CURRENT DOS CHAIN
* BUF & PUT THEM IN THE FM PARM LIST.
*====================================

BUFS2PRM LDY #30 ;GET ADR OF FM WORK BUF, T/S LIST
ADRINPRM LDA (A3L),Y ;BUF, DATA SECTOR BUF & NEXT
 STA WRKBUFFM-30,Y ;DOS FILE NAME BUF FROM CHAIN
 INY ;PTRS BUF & PUT IN FM PARM LIST.
 CPY #38 ;(PS. ADDR OF NEXT DOS FILE NAME
 BNE ADRINPRM ;BUF IS NOT USED BY DOS.)
 RTS


*=================================
* RESET CONDNFLG & OPUTCOND TO 0.
*=================================

RESTAT0 LDY #0
 STY CONDNFLG
 STY OPUTCOND
 RTS


*==================================
* LOCATE BUFFER WITH SAME NAME.
* IF THAT FAILS, LOCATE A FREE BUF.
*==================================

GETBUFF LDA #0 ;DEFAULT HI BYTE OF PTR TO 0.
 STA A5L+1 ;(IE. ASSUME NO FREE BUFS AVAIL.)
 JSR GETFNBF1 ;PT A3L/H AT 1RST DOS FILE NAME
;BUFFER IN THE DOS BUFFER CHAIN.
 JMP FNCHAR1 ;GO GET 1RST CHR OF NAME FRM BUF.
GETFNLNK JSR GETNXBUF ;GET ADR OF NXT NAME BUF IN CHAIN
;FROM CHAIN POINTERS BUF(WHICH IS
;OFFSET 37 & 36 BYTES FROM 1RST
;CHAR OF PRESENT FILE NAME BUF).
 BEQ NOFNMTCH ;LINK ZEROED OUT=END OF BUF CHAIN
FNCHAR1 JSR GETFNBY1 ;GET 1RST CHR OF NAME FRM NAM BUF
 BNE NXFNBUF ;TAKE BRANCH IF BUF NOT FREE.
 LDA A3L ;BUF WAS FREE, THERE4 POINT THE
 STA A5L ;A5L/H POINTERS AT THE FREE BUF.
 LDA A3L+1
 STA A5L+1
 BNE GETFNLNK ;ALWAYS.

NXFNBUF LDY #29 ;BUF WASN'T FREE SO CMP NAME OF
CMPFNCHR LDA (A3L),Y ;OWNER WITH NAME OF FILE IN
 CMP PRIMFNBF,Y ;PRIMARY FILE NAME BUF.  (START
;WITH LAST CHAR FIRST.)
 BNE GETFNLNK ;CHAR DIDN'T MATCH, SO LOOK FOR
;ANOTHER BUF THAT MIGHT HAS SAME
;FILE NAME.
 DEY ;THAT CHAR MATCHED.  HOW ABOUT
;REST OF CHARS IN NAME?
 BPL CMPFNCHR ;30 CHARS IN NAME (IE. 0 TO 29).
 CLC ;(C)=0 TO SIGNAL NAMES MATCHED.
 RTS

NOFNMTCH SEC ;LINK ZEROED OUT.
 RTS


*===================================
* POINT THE A3L/H POINTER AT THE
* FIRST DOS FILE NAME BUFFER IN
* THE DOS BUFFER CHAIN.  (IE. LOWEST
* NUMBERED BUFFER, BUT HIGHEST IN
* MEMORY.)
*===================================

GETFNBF1 LDA ADOSFNB1 ;GET 1RST LINK TO CHAIN OF BUFS.
 LDX ADOSFNB1+1
 BNE SETNXPTR ;ALWAYS.


*=================================
*  GET ADR OF NXT FILENAME BUF IN
*  CHAIN FROM THE CURRENT CHAIN
*  POINTERS BUF (WHICH IS OFFSET
*  37 & 36 BYTES FROM 1RST CHAR
*  IN PRESENT DOS FILE NAME BUF).
*---------------------------------

GETNXBUF LDY #37 ;OFFSET TO CHAIN BUF.
 LDA (A3L),Y ;PICK UP ADR OF NEXT NAME BUF.
 BEQ GETNXRTN ;IF HI BYTE=$00, LINK ZEROED OUT.
 TAX ;SAVE HI BYTE IN (X).
 DEY ;OFFSET FOR LOW BYTE.
 LDA (A3L),Y ;PUT ADR OF FILE NAME BUF IN PTR.
SETNXPTR STX A3L+1 ;PUT HI BYTE IN POINTER.
 STA A3L ;PUT LOW BYTE IN POINTER.
 TXA ;GET HI BYTE BACK IN (A).
GETNXRTN RTS


*=================================
*    GET 1RST CHAR OF FILE NAME
*    FROM DOS FILE NAME BUFFER.
*=================================

GETFNBY1 LDY #0 ;BUF IS FREE IF 1RST BYTE = $00.
 LDA (A3L),Y ;ELSE 1RST BYTE = 1RST CHAR OF
 RTS ;NAME OF FILE WHICH OWNS BUF.


*=================================
* CHECK IF THE CURRENT FILE NAME
* BUFFER BELONGS TO AN EXEC FILE.
* (AFTER ALL, WE DON'T WANT TO
* PREMATURELY CLOSE A FILE IF WE
* ARE USING IT TO EXEC - WOULD BE
* LIKE BURYING OURSELVES ALIVE).
*=================================

CKEXCBUF LDA EXECFLAG ;CHK TO SEE IF EXECING.
 BEQ NOTEXCBF ;BRANCH IF NOT EXECING.
 LDA EXECBUFF ;WE ARE EXECING, THERE4 CHK IF BUF
 CMP A3L ;BELONGS TO THE EXEC FILE.
 BNE CKEXCRTN ;NO.
 LDA EXECBUFF+1 ;MAYBE - LOW BYTES MATCHED SO
 CMP A3L+1 ;CHK HI BYTES OF ADR.
 BEQ CKEXCRTN ;YES, EXEC BUF = CURRENT BUF.
NOTEXCBF DEX ;NOT EXECING, SO REDUCE (X) TO
;MAKE SURE THAT Z-FLAG IS OFF.
;(PS. (X) WAS ORIG CONDITIONED TO
;A LARGE NON-ZERO VAL ON ENTRY
;TO GETFNBF1, THERE4, IF NOW DEX,
;THEN INSURE Z-FLAG OFF.)
CKEXCRTN RTS ;EXIT WITH:
;     Z-FLAG = 1 IF EXECING.
;            = 0 IF NOT EXECING.


*======================================
* CHK IF FILE TYPE WANTED = TYPE FOUND.
*======================================

CHKFTYPE EOR FILTYPFM ;TYPE FOUND (VIA OPEN FUNCTION).
 BEQ CKTYPRTN ;BRNCH IF TYPE WANTED=TYPE FOUND.
 AND #%01111111 ;MAYBE MATCHED-DISREGARD LOCK BIT
 BEQ CKTYPRTN ;BRANCH IF MATCHED.
 JSR CMDCLOSE ;NAMED FILE IS WRONG TYPE, SO GO
 JMP TYPMISM ;CLOSE FILE & EXIT WITH A TYPE-
;MISMATCH ERROR MESSAGE.
CKTYPRTN RTS ;TYPE WANTED = TYPE FOUND.


*=================================
*     BUILD THE DOS BUFFERS.
*=================================

* POINT A3L/H AT FILENAME FIELD
* IN THE LOWEST NUMBERD (HIGHEST
* IN MEMORY) DOS BUFFER.

BILDBUFS SEC ;IRREL, MIGHT AS WELL BE A "NOP".
 LDA ADOSFNB1 ;GET ADDR OF 1RST FILE NAME FIELD
 STA A3L ;& PUT IT IN A3L/H POINTER.
 LDA ADOSFNB1+1
 STA A3L+1

* GET # OF MAXFILES WANTED & STORE
* IT IN THE COUNTER (TEMPBYT).

 LDA MXFILVAL
 STA TEMPBYT

* FREE BUFFER BY ZEROING OUT THE
* FIRST BYTE OF THE DOS BUFFER'S
* FILE NAME FIELD.

ZDOSBUFN LDY #0
 TYA
 STA (A3L),Y


* POINT LINK IN CHAIN POINTERS BUF
* AT FM WORK AREA BUFFER.

 LDY #30 ;SET (Y) TO INDEX 1RST LINK IN
;CHAIN POINTERS BUFFER.
 SEC
 LDA A3L ;SUBT 45 FROM LOW BYTE OF ADDR
 SBC #45 ;OF NAME BUF TO CALC LOW BYTE OF
 STA (A3L),Y ;ADDR OF FM WORK BUF & PUT IT IN
 PHA ;THE CHAIN PTR BUF & ON THE STK.
 LDA A3L+1 ;SUBT (C) FROM HIGH BYTE OF ADR
 SBC #0 ;OF NAME BUF TO GET HI BYTE OF
;FM WRK BUF ADR.
 INY ;KICK UP (Y) TO INDEX ADDR OF HI
;BYTE OF LINK IN CHAIN POINTERS.
 STA (A3L),Y ;STORE HI BYTE OF ADR OF FM WRK
;BUF IN THE LINK.
;(NOTE:  ABOVE CALCS EFFECT (A)
;BUT NOT A3L/H.)

* POINT LINK IN CHAIN POINTERS BUFFER
* AT T/S LIST SECTOR BUFFER.

 TAX ;PUT HI BYTE OF ADDR OF FM WRK BUF
 DEX  ;IN (X) & KICK IT DOWN SO IT
;INDEXES HI BYTE OF T/S LIST BUF.
;(T/S LST BUF = $100 BYTES LONG.)
 PLA ;GET LOW BYTE OF ADDR OF FM WRK
 PHA ;BACK FROM STK.
 INY ;KICK UP INDEX TO LINK IN CHAIN
;POINTERS BUFFER.
 STA (A3L),Y ;PUT LOW BYTE OF FM WRK BUF ADR
;IN LINK BUFFER'S POINTERS.
 TXA ;GET HI BYTE T/S LIST BUF IN (A).
 INY ;KICK UP INDEX IN CHAIN BUF.
 STA (A3L),Y ;PUT HI BYTE OF LINK IN PTRS BUF.

* POINT LINK IN CHAIN POINTERS BUF
* AT DATA SECTOR BUFFER.

 TAX ;PUT HI BYTE OF ADDR OF T/S LIST
 DEX ;BUF IN (X) & KICK IT DOWN TO
;CORRESPOND TO HI BYTE OF ADDR
;OF DATA SEC BUF.
 PLA ;GET LOW BYTE OF T/S LIST SEC BUF
 PHA ;FROM STACK & USE IT FOR LOW BYTE
;OF DATA SEC BUF (CAUSE THEY ARE
;EXACTLY 1 PAGE APART).
 INY ;KICK UP INDEX TO CHAIN BUF.

 STA (A3L),Y ;PUT LOW BYTE OF DATA SEC BUF
;IN LINK.
 INY ;KICK UP INDEX TO CHAIN BUF.
 TXA ;GET HI BYTE OF ADR OF T/S LIST
 STA (A3L),Y ;BUF & DESIGN8 AS HI BYT OF LINK.

* REDUCE COUNTER FOR # OF BUFS TO BUILD.

 DEC TEMPBYT ;IF COUNTER GOES TO 0, THEN JUST
 BEQ ZLNK2NXT ;DID LAST BUF & SHOULD 0 OUT LNK.

* NOT DONE ALL BUFS YET SO POINT
* LINK IN CHAIN POINTERS BUFFER
* AT NEXT FILE NAME FIELD.

 TAX ;SET (X) = LOW BYTE OF ADR OF DATA
;SECTOR BUFFER.
 PLA ;GET LOW BYTE OF ADDR OF DATA
;SECTOR BUF BACK OFF STK.
 SEC ;SUBT 38 FROM LOW BYTE OF DATA SEC
 SBC #38 ;ADR TO INDEX NEXT NAME BUF.
 INY ;KICK UP INDEX TO CHAIN BUF.
 STA (A3L),Y ;STORE LOW BYTE OF ADR OF NEXT
 PHA ;NAME BUF IN LINK & THEN SAVE
;IT ON STK.
 TXA ;GET HI BYTE OF ADR OF DATA SEC
  SBC #0 ;BUF FROM (X) & SUBT (C) (IN CASE
;CROSS PAGE BOUNDARY) TO GET
;(A) = HI BYTE OF NEXT NAME BUF.
 INY ;KICK INDEX UP TO CHAIN PTRS BUF
 STA (A3L),Y ;& STORE HI BYTE OF NEXT NAME BUF
;IN LINK.

* POINT A3L/H AT NEXT NAME BUF.

 STA A3L+1
 PLA
 STA A3L
 JMP ZDOSBUFN ;GO BACK TO FREE NEXT NAME BUF
;& BUILD MORE DOS BUFFERS.

* NO MORE BUFS TO BUILD SO ZERO OUT
* THE LINK THAT WOULD NORMALLY POINT
* TO THE NEXT NAME BUFFER.

ZLNK2NXT PHA ;SAVE LOW BYTE OF ADR OF DATA BUF
;ON STK.
 LDA #0 ;ZERO OUT LINK TO NEXT NAME BUF.
 INY
 STA (A3L),Y
 INY
 STA (A3L),Y

* CHK WHICH BASIC IS ACTIVE.

 LDA ACTBSFLG ;CHK IF ACTV BASIC IS FP OR INT.
 BEQ SETINTPT ;BRANCH IF INTEGER.

* USING APPLESOFT, SO INITIALIZE
* MEMSIZ & FRETOP (STRING STORAGE)
* TO A VALUE 1 BYTE GREATER THAN
* HIGHEST MEMORY LOCATION AVAILABLE
* TO BASIC PROGRAM.

 PLA
 STA MEMSIZ+1
 STA FRETOP+1
 PLA
 STA MEMSIZ
 STA FRETOP
 RTS ;EXIT TO CALLER OF MAXFILES CMD.
;(USUALLY EXITS 2 AFTRCMD ($A17D)
;LOCATED IN THE DOS CMD PARSING
;AND PROCESSING ROUTINES.)

* USING INTEGER, SO SET HIMEM AND
* PROGRAM POINTER (INTPGMST).

SETINTPT PLA
 STA HIMEM+1
 STA INTPGMST+1
 PLA
 STA HIMEM
 STA INTPGMST
 RTS ;EXIT TO CALLER OF MAXFILES CMD.
;(USUALLY EXITS 2 AFTRCMD ($A17D)
;LOCATED IN THE DOS CMD PARSING
;AND PROCESSING ROUTINES.)
�O