*================================= * OUTPUT HANDLER 2. * (IGNORE NON-DOS COMMAND.) *================================= OPUTHDL2 CMP #$8D ;? BNE DSPLYALL ;NO - (WAS AN "RH BRACKETT"?) SET2EVAL LDX #0 ;SET CONDITION0 - EVALUATE START STX OPUTCOND ;OF LINE. JMP DSPLYALL ;GO DISPLAY CHAR UNCONDITIONALLY. *================================= * OUTPUT HANDLER 3. * (PROCESS INPUT INFO.) *================================= OPUTHDL3 LDX #0 ;SET CONDITION 0 WHEN INPUT ENDS. STX OPUTCOND CMP #$8D ;? BEQ ASUMIMED ;YES. TESTEXEC LDA EXECFLAG ;ARE WE EXECING? BEQ DSPLYALL ;NO. BNE DSPLYINP ;YES. EXECFLAG CONTAINS THE 1RST ;CHR OF NAME OF THE EXEC FILE. ASUMIMED PHA ;SAVE CHAR ON STK. SEC ;(C)=1, DFLT, ASSUME IMMED MODE. LDA EXECFLAG ;ARE WE EXECING? BNE TESTMODE ;BRANCH IF EXECING. JSR CKBSCRUN ;NOT EXECING, SO SEE IF BASIC IS ;RUNNING A PRGM OR NOT. ;(C) = 0, EITHER BASIC RUNNING. ;(C) = 1 IF IMMEDIATE. TESTMODE PLA ;RETRIEVE CHAR FROM STK. BCC TESTEXEC ;BASIC RUNNING, DSPLY INPUT & XIT * EXECING OR IN IMMEDIATE MODE * (CAUSE (C) = 1). LDX XSAVED ;RETRIEVE (X). JMP PUTINBUF ;GO PUT CHR IN INPUT BUF (COND 1) *================================= * OUTPUT HANDLER 4. * (WRITING DATA.) *================================= OPUTHDL4 CMP #$8D ;? BNE CMWRTBYT ;NO. LDA #5 ;SET CONDITION 5. STA OPUTCOND CMWRTBYT JSR WRITEXT ;GO WRITE DATA BYTE. JMP DSPLYOUT ;DISPLAY OUTPUT CONDITIONALLY. *=================================== * OUTPUT HANDLER 5. * (EVALUATE START OF DATA TO WRITE) *=================================== OPUTHDL5 CMP DCTRLCHR ;IS CHAR = DOS'S CTRL CHAR? ;************* NOTE ************ ;* DOS'S CTRL CHAR CANCELS THE * ;* WRITE MODE. * ;******************************* BEQ OPUTHDL0 ;YES - SO GO TO CONDITION 0. CMP #$8A ;IS CHAR AN ? BEQ CMWRTBYT ;YES -GO WRITE IT, STAY IN COND 5 LDX #4 ;NO -RESET TO CONDITION4 - SIGNAL STX OPUTCOND ;WANT TO WRITE ANOTHER LINE. BNE OPUTHDL4 ;ALWAYS. *================================= * OUTPUT HANDLER 6. * (SKIP THE QUESTION MARK PROMPT.) *================================= OPUTHDL6 LDA #0 ;SET CONDITION 0. STA OPUTCOND BEQ DSPLYINP ;ALWAYS. ;GO CONDITIONALLY DISPLAY INPUT. *================================= * FINISH OFF THE RUN COMMAND * (BECAUSE IT WAS INTERRUPTED TO * DO A LOAD.) *================================= FINSHRUN LDA #0 ;ZERO OUT THE RUN INTERRUPT FLAG. STA RUNTRUPT JSR INITIOHK ;RESET I/O HOOKS 2 PT AT DOS. JMP RUNFPINT ;JUMP BACK INTO THE RUN COMMAND ;TO FINISH IT OFF. ;************* NOTE ************* ;* THE STACK WAS RESET SO WE * ;* RETURN AT THE CORRECT LEVEL. * ;******************************** *====================================== * COMMON ROUT'N TO FINISH OFF MOST DOS * CMDS. THE WRITE & READ CMD HNDLRS * RTN HERE. CMDWRITE ($A510) SETS * OPUTCOND=5 BEFORE RETURNING. * CMDREAD ($A51B) RTNS WITH CONDNFLG=1. *====================================== FINSHCMD LDA BUF200 ;GET FIRST CHAR IN BUF. CMP DCTRLCHR ;WAS CMD DONE VIA DOS'S CTRL CHR? BEQ DSPLYCMD ;YES. * CANCEL CMD BY REPLACING THE CHAR * WITH A & THEN FALL THRU TO * CONTINUE THE EXIT SEQUENCE. LDA #$8D ; STA BUF200 ;SET 200: 8D. LDX #0 ;SET INDEX TO START OF INPUT BUF. STX XSAVED *--------------------------------------- * DISPLAY CHARACTER OUPUT CONDITIONALLY. * (THAT IS, PREPARE TO SEND THE CHAR * TO THE OUTPUT DEVICE.) *--------------------------------------- DSPLYCMD LDA #%01000000 ;SET BIT6 TO SEE IF USING "MON C" BNE DSPLYCHR ;ALWAYS. DSPLYOUT LDA #%00010000 ;SET BIT4 TO SEE IF USING "MON O" BNE DSPLYCHR ;ALWAYS. DSPLYINP LDA #%00100000 ;SET BIT5 TO SEE IF USING "MON I" DSPLYCHR AND CIOCUMUL ;TEST FLAG: SEE IF SHOULD DSPLY. BEQ DOSEXIT ;NO DISPLAY -SPECIFIC BIT WAS OFF ;MON/NOMON CLR/SET SPECIFIC BITS. *--------------------------------- * DISPLAY THE CHARACTER. *--------------------------------- DSPLYALL JSR RESTOREG ;RESTORE (A), (Y) & (X) REGS. JSR GODSPLY ;OUTPUT CHR VIA TRU OUTPUT HNDLR STA ASAVED ;SAVE (A), (Y) & (X) REGS. STY YSAVED STX XSAVED *================================= * ROUTINE TO EXIT DOS. * POINT THE I/O HKS AT DOS AND * RESET THE STACK POINTER. *--------------------------------- DOSEXIT JSR INITIOHK ;RESET I/O HKS TO POINT TO DOS. LDX STKSAVED ;RETRIEVE SAVED STACK POINTER. TXS RESTOREG LDA ASAVED ;RESTORE (A), (Y) & (X) REGS. LDY YSAVED LDX XSAVED SEC ;WHY????? RTS ;************ NOTE ************** ;* IF THIS RTS IS ENCOUNTERED * ;* VIA A FALL THRU FROM DOSEXIT,* ;* THEN RTN TO THE ROUTINE THAT * ;* CALLED THE ROUTINE THAT * ;* CONTAINED THE "JSR PREP4DOS" * ;* INSTRUCTION. * ;******************************** *================================= * CHARACTER OUTPUT HANDLER. *================================= GODSPLY JMP (CSW) ;USUALLY POINTS 2 THE TRUE OUTPUT ;HANDLER (COUT1, $FDF0 IF SCRN). CRVIADOS LDA #$8D ;. JMP GODSPLY ;USUALLY PRINTS A THRU THE ;OUTPUT HANDLER (COUT1). HOWEVER, ;WHEN ACCESSED BY RUNFPINT($A4DC) ;DURING A COLDSTART, GOES INTO ;DOS'S OUTPUT INTERCEPT ROUTINE ;(OPUTINCP, $9EBD). *================================= * DOS'S COMMAND PARSING ROUTINE. *================================= PARSECMD LDY #$FF ;INITIALIZE INDEX TO CMD TXT TBL. STY NDX2CMD INY ;(Y) = 0. STY NEXTCMD ;SIGNAL NO PENDING COMMAND FOR ;NEXT TIME AROUND. GETCHR1 INC NDX2CMD ;INDEX TO COMMAND TEXT TABLE. ;(0 ON ENTRY.) LDX #0 ;INITIALIZE INDEX TO INPUT CHARS. PHP ;SAVE STATUS (WITH Z=1) ON STK. ;(DFLT STATUS, ASSUME CHRS MTCH.) LDA BUF200,X ;GET FIRST CHAR IN INPUT BUFFER. CMP DCTRLCHR ;IF IT IS NOT DOS'S CTRL CHAR, BNE SAVLINDX ;SET LINE INDEX TO 0. IF IT IS INX ;DOS'S CTRL CHAR, SET INDEX TO 1 ;SO SKIP CTRL CHAR. * DOES THE INPUT CHAR EQUAL A CHAR * IN DOS'S CMD TEXT TABLE (CMDTXTBL)? * (NOTE: LAST CHAR IN @ CMD IS NEGATIVE * ASCII, REST OF CHARS IN A GIVEN CMD * ARE POSITIVE ACSII.) SAVLINDX STX NDX2INBF ;SAVE INDEX TO INPUT BUF. INVSCMD JSR PURGECMD ;GET CHAR FROM INPUT BUFFER ;(IGNORE SPACES). AND #$7F ;STRIP HI BIT OFF OF CHAR. EOR CMDTXTBL,Y ;DOES INPUT CHAR MATCH A CMD CHR? ;IF POS INPUT CHAR/POS ASCII CMD ;CHAR MATCH, THEN (A) = 0. ;IF POS INPUT CHR / NEG ASCII CMD ;CHAR MATCH, THEN (A) = $80. INY ;KICK UP INDEX TO NEXT CHAR IN ;THE COMMAND TEXT TABLE. ASL ;IF POS/POS MATCH (A)=0 & (C)=0. ;IF POS/NEG MTCH (A)=$80 & (C)=1. BEQ CKIFCHRS ;CHAR MATCHED SO GO CHK CARRY. * INPUT CHARS < > TEXT CMD CHAR. PLA ;PULL SAVED STATUS OFF STK TO CLR ;Z-FLG (CAUSE IF SAVED STATUS ;HAD (Z) OR (C) = 1, THEN NEW (A) ;WILL HAVE AT LEAST 1 BIT SET SO ;THEN (A) < > 0.) PHP ;PUSH STATUS ON STK (WITH Z-FLAG ;CLR & (C) CONDITIONED AS PER ;ABOVE "ASL" INSTRUCTION. * SEE IF THER ARE ANY MORE CHARS TO * CHECK IN THE TEXT OF A GIVEN CMD. CKIFCHRS BCC INVSCMD ;IF (C)=0, MORE CHARS TO CHK IN ;GIVEN CMD LISTED IN TABLE. ;IF (C)=1, CHKD LAST CHR IN TBL. * FINISHED CHECKING TEXT * OF A PARTICULAR COMMAND. PLP ;GET STATUS OFF STACK. * DID COMMAND MATCH? BEQ PRPDOCMD ;IF LAST CHR MATCHED, THEN ENTIRE ;CMD MATCHED SO GO PROCESS CMD. * CHECK IF SEARCHED ENTIRE TABLE. LDA CMDTXTBL,Y ;LAST CHAR DIDN'T MATCH, SO NOT BNE GETCHR1 ;CORRECT CMD. THERE4, GO CHK IF ;NEXT CHAR BYTE IN TABLE IS $00. ;IF NOT $00, GO CHK REMAINING ;CMDS IN TBL. IF IT IS $00, THEN ;DONE ENTIRE TBL & NO CMDS MTCHD. * EITHER AT END OF TABLE AND NO * CMDS MATCHED OR ELSE DETECTED A * BSAVE CMD WITH NO ACCOMPANYING * A- OR L- PARAMETERS. * CHECK IF DOS'S CTRL CHAR WAS USED. CKIFCTRL LDA BUF200 ;IS 1RST CHAR IN THE INPUT BUFFER CMP DCTRLCHR ;EQUAL TO DOS'S CTRL CHAR? BEQ CHKIFCR ;YES. JMP DSPLYALL ;NO -GO DSPLY CHR & THEN XIT DOS. * WAS DOS'S CTRL CHAR THE ONLY CHAR ON LINE? CHKIFCR LDA BUF200+1 ;GET 2ND BYTE IN INPUT BUFFER. CMP #$8D ;WAS IT A ? BNE PRSYNERR ;NO -NOT SIMPLY DEALING WITH CMD ;CANCELLING DOS CTRL CHR AND ;SO GO ISSUE A SYNTAX-ERROR MSG. JSR RESTAT0 ;YES - SET CONDITION 0. JMP DSPLYCMD ;GO DISPLAY . PRSYNERR JMP SYNTXERR ;EITHER A CTRL CHR DENOTED THAT A ;DOS CMD WAS WANTED & NO MATCHING ;CMD WAS FOUND (ELSE DETECTED A ;BSAVE CMD WITH NO A- OR L-PARMS) ;SO GO GIVE DOS'S SYNTAX ERR MSG. *======================================== * PREPARE TO EXECUTE THE DOS COMMAND. * ON ENTRY - A DOS CMD WAS PARSED. * - NDX2CMD = COMMAND CODE. * - I/O HKS PT TO TRUE HANDLERS. * NOTE THAT THIS ROUTINE MAKES EXTENSIVE * USE OF A TABLE (CMDATTRB, $A909-$A940) * WHICH CONTAINS AN ENCODED LIST OF THE * ATTRIBUTES ASSOCIATED WITH @ COMMAND. *======================================== PRPDOCMD ASL NDX2CMD ;DOUBLE INDEX CAUSE 2 BYTES/ADDR LDY NDX2CMD ;IN TABLE OF DOS CMD ENTRY PTS. JSR CKBSCRUN ;CHECK IF BASIC IS RUNNING A PGM: BCC CHKIFRUN ; (C)=0= BASIC RUNNING. ; (C)=1= BASIC NOT RUNNING. * USING IMMEDIATE MODE, SO NOW CHK * IF CMD IS LEGAL IN THAT MODE. IMMED LDA #%00000010 ;CHK BIT1 OF CMDATTRB TO SEE IF AND CMDATTRB,Y ;CMD IS LEGAL IN THAT MODE. BEQ CHKIFRUN ;BRANCH IF LEGAL. NODIRCMD LDA #15 ;SET RETURN CODE TO SIGNAL THAT JMP ERRHNDLR ;WE GOT A NOT-DIRECT-COMMAND ERR. * RUNNING PROGRAM OR ELSE COMMAND * COMPLIES WITH IMMEDIATE MODE. CHKIFRUN CPY #6 ;CHECK TO SEE IF CMD WAS A "RUN". BNE TST4NAME ;BRANCH IF NOT. STY PROMPT ;PUT AN $06 IN PROMPT IF COMMAND ;WAS A "RUN". * CHECK TO SEE IF A FILENAME * IS APPLICABLE TO THE COMMAND. TST4NAME LDA #%00100000 ;BIT5 = 1 IF FILENAME APPLICABLE. AND CMDATTRB,Y BEQ FNOTAPPL ;BRANCH IF NAME NOT APPLICABLE. ;(EX. CMDS: CATALOG, PR#, IN#, ;MON, NOMON, MAXFILES, FP & INT.) * FILENAME APPLICABLE TO CMD ISSUED * SO BLANK OUT FILENAME BUFFERS IN * ANTICIPATION OF RECEIVING NAME. FNXPCTD JSR BLNKFNBF ;BLANK BOTH 1RST & 2ND NAME BUFS. PHP ;SAVE STATUS (Z-FLAG=1) ON STK. ;NOTE: Z-FLAG USED TO SIGNAL IF ; DEALING WITH PRIMARY OR ; SECONDARY NAME BUFFERS. FNAMCHR1 JSR PURGECMD ;GET 1RST CHAR IN NAME. (IGNORE ;LEADING SPACES.) BEQ DONEFN ;GOT "," OR - CHK IF DONE ;(CAUSE THESE NOT LEGAL 4 NAME). * CHK IF CHAR IS LEGAL TENDER FOR NAME. * (KNOW IT WASN'T A , "," OR * BUT IT STILL MAY NOT BE LEGAL.) ASL ;(C) = HI BIT OF CHAR. BCC LGLFNCHR ;IF INV OR FLSH, OK FOR NAME. ;BUT, NOTE THAT THEY CAN ONLY BE ;POKED INTO INPUT BUF FROM A ;RUNNING PRGM. (THIS TECHNIQUE IS ;USED IN MANY PROTECT'N SCHEMES.) BMI LGLFNCHR ;ACTUALLY TESTING BIT6 CAUSE JUST ;DID AN "ASL".IF BYTE IS 11XXXXXX ;(IE. $C0, NORMAL "@" OR GREATER) ;CHAR IS LEGAL FOR NAME. JMP CKIFCTRL ;GOT ILLEGAL NAME CHAR SO GO DO A ;FEW MORE CHKS ON CTRL CHRS, ETC ;& EXIT DOS. (WAS IT A CTRL CHAR, ;NUMBER OR ONE OF THE FOLLOWING ;NORMAL CHARS:SPC, !, ", #, $, %, ;&, ', (, ), *, +, COMMA, -, ., / ;:, ;, <, -, >, OR ? * CHAR IS LEGAL TENDER FOR NAME. LGLFNCHR ROR ;RESTORE NAME CHAR. JMP SVFNCHAR ;SAVE IT IN 1RST OR 2ND NAME BUF. * PROCESS REST OF CHARS. NCHR2ETC JSR CMDCHAR ;GET 2ND & SUB'QUENT CHRS IN NAME BEQ DONEFN ;GOT A OR "," SO GO CHK IF ;JUST FINISHED SECOND FILENAME. * PUT CHARS IN FILENAME BUF. SVFNCHAR STA PRIMFNBF,Y ;(Y)=OFFSET FRM PRIMARY NAME BUF. INY CPY #60 ;TOTAL OF 60 CHARS IN BOTH BUFS. BCC NCHR2ETC ;HAVEN'T HIT ",", EOL MARKER (IE. ;) OR DONE ALL 60 CHARS YET. * DONE ALL 60 CHARS SO IGNORE REST * OF CHARS UNTIL GET "," OR . PURGEFN JSR CMDCHAR ;GET NEXT CHAR. BNE PURGEFN ;NOT $00 YET SO GO GET NXT CHAR. * JUST FINISHED NAME, SO CHK IF IT * WAS FIRST OR SECOND FILENAME. DONEFN PLP ;RETRIEVE STATUS FROM STACK. BNE CKFN2LGL ;Z-FLAG CLR SO DONE 2ND FILENAME. * JUST FINISHED FIRST NAME, SO SEE * IF A SECOND FILENAME IS REQUIRED. * (THAT IS, ARE WE DEALING WITH * THE "RENAME" COMMAND?) FINFIRST LDY NDX2CMD ;GET INDEX ASSOC WITH CMD ISSUED. LDA #%00010000 ;CHK BIT 4 OF CMDATTRB TO SEE IF AND CMDATTRB,Y ;2ND NAME REQUIRED (IE RENAME ?). BEQ CKFN1LGL ;2ND NAME NOT APPLICABLE SO GO ;& CHK 1RST NAME BUF. * SECONDARY FILENAME APPLICABLE SO * DEALING WITH "RENAME" COMMAND. LDY #30 ;(Y) = INDEX 2 START OF 2ND NAME. PHP ;PUT STATUS ON STK (Z-FLG = 0) TO BNE FNAMCHR1 ;SIGNAL DEALING WITH 2ND NAME & ;GO BACK TO GET ITS CHARS. ;ALWAYS TAKE BRANCH. * DONE PROCESSING ASSOC WITH SECONDARY * FILENAME SO NOW CHK IF ANY OF THESE * CHARS WERE LEGAL & THERE4 STUCK IN * THE SECONDARY FILENAME BUFFER. CKFN2LGL LDA SCNDFNBF ;CHK 1RST BYTE IN SECONDARY. CMP #" " ;IF IT IS A , THEN NO CHARS BEQ GOXITDOS ;WERE GOOD & SO A 2ND NAME WAS ;REQUIRED BUT NOT ISSUED,SO EXIT. * ONLY PRIMARY FILENAME APPLICABLE * SO CHK IF WE GOT ANY CHRS THAT * WERE LEGAL & THERE4 PUT IN THE * PRIMARY FILENAME BUFFER. CKFN1LGL LDA PRIMFNBF ;IF 1RST CHAR IN BUF IS A , CMP #" " ;A LEGAL PRIMARY FILENAME WAS NOT ;ISSUED SO FALL THRU TO SEE IF IT ;WAS REQUIRED OR OPTIONAL. BNE DFLTPRSD ;BRANCH IF GOT PRIMARY FILENAME. * PRIMARY FILENAME WAS NOT ISSUED * SO CHK IF IT WAS REQUIRED OR OPTIONAL. * (IE. WAS CMD A CLOSE, LOAD, SAVE OR RUN?) LDY NDX2CMD ;GET INDEX ASSOC WITH CMD. LDA #%11000000 ;CHK BITS 7 & 6 TO SEE IF A NAME AND CMDATTRB,Y ;IS REQUIRED. BEQ GOXITDOS ;A PRIMARY NAME IS REQUIRED BUT ;WAS NOT ISSUED, SO GO EXIT DOS. * WAS COMMAND A "CLOSE"? BPL DFLTPRSD ;NAME WASN'T PRESENT, BUT IS NO ;BIG DEAL CAUSE IT WAS OPTIONAL. GOXITDOS JMP CKIFCTRL ;CMD WAS LOAD, RUN OR SAVE WHICH ;CAN ALSO BE BASIC COMMANDS. *====================================== * BLANK OUT BOTH PRIMARY ($AA75-$AA92) * AND SECONDARY ($AA93-$AAB0) FILENAME * BUFFERS. *====================================== BLNKFNBF LDY #60 ;30 BYTES IN EACH BUFFER. BLNK1RST LDA #" " ;BLANK. STORBLNK STA PRIMFNBF-1,Y DEY BNE STORBLNK ;MORE BYTES TO BLANK OUT. RTS *=================================== * FILENAME NOT APPLICABLE TO COMMAND * (EX. CATALOG, MON, NOMON, FP, INT, * PR#, IN# OR MAXFILES). *=================================== FNOTAPPL STA PRIMFNBF ;PUT A $00 IN THE FIRST BYTE OF ;THE PRIMARY FILENAME BUFFER. ;************* NOTE ************* ;* ALTHOUGH THIS SEEMS LIKE A * ;* BEGNIN INSTRUCTION, IT IS * ;* IMPORTANT BECAUSE IT IS LATER* ;* USED 2 INSURE THAT A MATCHING* ;* DOS FILENAME BUF WON'T BE * ;* FOUND WHEN THE GETBUFF ROUT'N* ;* ($A764) IS EVENTUALLY USED BY* ;* THE VARIOUS DOS CMDS. AS A * ;* RESULT, THE HIGHEST NUMBERED * ;* (LOWEST IN MEMORY) FREE DOS * ;* FILENAME BUFFER WILL BE * ;* SELECTED. * ;******************************** * COMMAND DIDN'T REQUIRE A FILENAME * SO NOW CHK & SEE IF IT EXPECTS ANY * NUMERIC ARGUMENTS. (IE. WAS IT PR#, * IN# OR MAXFILES CMD?) LDA #%00001100 ;TEST BITS 2 & 3 TO SEE IF IN#, AND CMDATTRB,Y ;PR# OR MAXFILES NUMERIC ;OPERAND IS EXPECTED. BEQ DFLTPRSD ;BRANCH IF NOT EXPECTED. * IN#,PR# OR MAXFILES NUMERIC * OPERAND EXPECTED. INPRMAX JSR CNVRTASC ;CONVERT ASCII NUMBER ARGUMENT TO ;HEX WITH RESULT IN A5L/H. BCS TOSYNTX ;CHR NOT #, EXIT WITH SYNTAX ERR. TAY ;(Y) = HI BYTE OF CONVERTED CHAR. BNE ARGRNGER ;RANGE ERROR - CAUSE VALUE > 255. CPX #17 BCS ARGRNGER ;RANGE ERROR CAUSE IF MAXFILES OR ;IN# OR PR# ARGUMENT > 16, THEN ;VALUE TOO LARGE. * WAS COMMAND A PR# OR IN#? LDY NDX2CMD ;CHK TO SEE IF A SLOT VALUE IS LDA #%00001000 ;APPLICABLE TO THE COMMAND. AND CMDATTRB,Y BEQ MAXFMIN ;SLOT VAL NOT APPLICABLE SO MUST ;BE DEALING WITH MAXFILES. * COMMAND WAS PR# OR IN# SO NOW CHECK * IF SLOT VALUE IS TOO LARGE OR NOT. * (LEGAL RANGE IS 0 TO 7.) CPX #8 ;TOO LARGE? BCS GOXITDOS ;YES -BAIL OUT. BCC DFLTPRSD ;NO -SET DFLTS & CONTINUE PARSING * CHECK MINIMUM VALUE FOR MAXFILES. * (LEGAL RANGE IS 1 TO 16.) MAXFMIN TXA BNE DFLTPRSD ;NOT 0, SO OKAY. * ARGUMENT FOR MAXFILES, SLOT, IN# * OR PR# WERE ILLEGAL. ARGRNGER LDA #2 ;SET RETURN CODE FOR RANGE ERROR. JMP ERRHNDLR ;GO HANDLE THE ERROR. TOSYNTX JMP SYNTXERR ;EXIT VIA SYNTAX ERROR. * INITIALIZE CUMLOPTN & PARSED TABLE. DFLTPRSD LDA #0 STA CUMLOPTN ;SET CUMLOPTN TO DEFAULT VAL OF 0 ;TO ASSUME NO OPTIONS ISSUED. STA MONPRSD ;SET DEFAULT VALS IN PARSED TBL. STA VOLPRSD ;THAT IS ASSUME THAT: STA LENPRSD ; - C, I, O WEREN'T ISSUED. STA LENPRSD+1 ; - VOL # AND LENGTH ARE 0. JSR ZEROPTCH ;SET TEMPBYT & BYTPRSD TO 0 DFLTS LDA NDX2INBF ;IRREL, MIGHT AS WELL BE 3 "NOP"S ;(MADE OBSOLETE BY ZEROPTCH). * DO MORE PARSING OF COMMAND LINE. * (IGNORE ANY COMMAS OR SPACES.) NXCMDCHR JSR PURGECMD ;GET NEXT CHAR. BNE CHKOPTNS ;IF IT ISN'T A OR COMMA THEN ;MAYBE ITS AN OPTION, SO TAKE ;BRANCH TO CHECK IT OUT. CMP #$8D ;WAS IT A ? BNE NXCMDCHR ;NO - SO MUST HAVE BEEN A COMMA. ;BRANCH BACK TO IGNORE COMMAS. * GOT A (IE. EOL MARKER), SO NOW * DONE PARSING & MUST MAKE SURE THAT * THE CUMMULATIVE RECORD OF THE OPTIONS * WE ENCOUNTERED IS APPLICABLE TO THE CMD. LDX NDX2CMD LDA CUMLOPTN ;CHK IF OPTIONS ARE LEGAL. ORA CMDATTRB+1,X EOR CMDATTRB+1,X BNE GOXITDOS ;ILLEGAL SO EXIT. * CUMMULATIVE RECORD OF OPTIONS CAN * LEGALLY BE ASSOCIATED WITH COMMAND. LDX TEMPBYT ;TEMPBYT = 0 AS SET IN ZEROPTCH. BEQ TODOSCMD ;ALWAYS. * MEANINGLESS INSTRUCTIONS (MADE * OBSOLETE BY INCLUSION OF ZEROPTCH). STA TEMPBYT STX NDX2INBF BNE NXCMDCHR * CHECK IF CHAR IS AN OPTION. * (IE. A, B, R, L, S, D, V, C, I, O.) CHKOPTNS LDX #10 CKNXOPTN CMP OPTNTXT-1,X BEQ OPTNOK ;FOUND AN OPTION. DEX BNE CKNXOPTN ;HAVEN'T CHKD ALL OPTIONS YET. TOTOSYNT BEQ TOSYNTX ;COULDN'T FIND A MATCH. ;(SYNTAX ERR - CHAR NOT OPTION.) * GOT AN OPTION SO CHK IF IT WAS * "C", "I" OR "O". (IE. IS A * NUMERIC ARGUMENT EXPECTED?) OPTNOK LDA OPTNISSD-1,X BMI CIOPTNS ;IF HI BIT=0, THEN OPTION WAS A ;"C", "I" OR "O" AND NO NUMERIC ;ARGUMENT IS NEEDED. * UPDATE CUMLOPTN TO REFLECT * THE LATEST OPTION. ORA CUMLOPTN STA CUMLOPTN * NOW CHK IF NUMERIC ARGUMENT THAT * WAS ISSUED WITH OPTION IS LEGAL. DEX ;REDUCE COUNTER THAT WAS KICKED UP ;IN ANTICIPATION OF MORE CHARS ;IN THE CMDCHAR ROUTINE. STX NDX2OPTN ;SAVE INDEX TO OPTION. JSR CNVRTASC ;CONVERT ASCII # TO HEX. * WAS IT A NUMERIC CHARACTER? BCS TOSYNTX ;NO - SYNTAX ERROR. * CHARACTER WAS NUMERIC. LDA NDX2OPTN ;RETRIEVE INDEX TO OPTION. ASL ;TIMES 4 CAUSE GOING TO CHK MIN ASL ;& MAX VALS OF LEGAL RANGES ASSOC ;WITH OPTION (2 BYTES @). TAY ;(Y) = INDEX TO LEGAL RANGE TBL. * CHECK IF ARGUMENT IS TOO LARGE. LDA A5L+1 ;GET HI BYTE OF ARGUMENT. BNE CKMAXVAL ;BRANCH IF NOT 0. LDA A5L ;HI BYTE WAS 0 SO CHK LOW BYTE. CMP OPTNRNG,Y BCC ARGRNGER ;RANGE ERR -ARGUMENT < MIN LEGAL. * CHECK IF ARGUMENT < = MAX LEGAL PLUS 1. LDA A5L+1 CKMAXVAL CMP OPTNRNG+3,Y ;CMP HI BYTE TO MAX LEGAL VAL. BCC SVALOPTN ;LESS THAN MAX SO ARGUMENT OK. TOARGRNG BNE ARGRNGER ;ARGUMENT > MAX LGL, SO RNG ERR. LDA A5L ;NOW CHK IF LOW BYTE OF ARGUMENT CMP OPTNRNG+2,Y ;COMPLIES TO MAX LEGAL LOW BYTE. BCC SVALOPTN ;ARGUMENT IS LEGAL. BNE TOARGRNG ;ARGUMENT IS ILLEGAL. * SAVE THE OPTION VALUE IN THE PARSED TABLE. SVALOPTN LDA TEMPBYT ;OBSOLETE, TEMPBYT WAS SET TO 0 BNE NXCMDCHR ;IN ZEROPTCH SO ALWAYS FALL THRU. TYA ;(Y)-->(A)=INDEX TO OPTION RNGS. LSR ;DIVIDE BY 2 CAUSE @ OPTION RANGE ;TABLE HAS 4 BYTES, BUT @ PARSED ;VAL ENTRY IS ONLY 2 BYTES LONG. TAY ;PUT INDEX 2 PARSED TABLE IN (Y). LDA A5L+1 ;STORE ARGUMENT IN PARSED TBL. STA VOLPRSD+1,Y LDA A5L STA VOLPRSD,Y * GO SEE IF ANY MORE OPTIONS ARE * PRESENT ON THE COMMAND LINE. TONXOPTN JMP NXCMDCHR * OPTION WAS A "C", "I" OR "O". CIOPTNS PHA ;PUT (A) = OPTNISSD ON STK. LDA #%10000000 ;UPDATE CUMLOPTN TO SIGNAL THAT ORA CUMLOPTN ;"C", "I" OR "O" OPTIONS ISSUED. STA CUMLOPTN PLA ;GET (A) = OPTNISSD BACK FRM STK. AND #%01111111 ;TURN HI BIT OFF. ORA MONPRSD ;UPDATE MONPRSD IN PARSED TABLE. STA MONPRSD BNE TONXOPTN ;GO SEE IF ANY MORE OPTIONS. BEQ TOTOSYNT ;IRRELEVANT. *================================= * FINAL PROCESSING OF DOS COMMAND. *================================= TODOSCMD JSR DODOSCMD ;GO DO THE DOS COMMAND. *---------------------------------------* * * * - MOST, BUT NOT ALL, DOS CMDS RTN HERE. * * - IF AN ERROR IS ENCOUNTERED, EXECUTION * * EXITS DOS'S ERROR HANDLER VIA RESTART * * ($D43C) OR BASIC'S ERROR-HANDLING * * ROUTINE (BSCERHLR, $D865). * * - FP EXITS BACK INTO DOS'S COLDSTART * * ROUTINE (DOSCOLD, $9D84). * * - INT & CHAIN GO INTO INTEGER BASIC IF * * THE INTEGER LANGUAGE IS AVAILABLE. * * - THE WRITE & READ CMDS RETURN TO THE * * FINSHCMD ROUTINE ($9F83) SHOWN BELOW. * * - BLOAD RTNS TO AFTRCMD IF IT WAS NOT * * CALLED BY THE BRUN CMD. OTHERWISE, * * BLOAD RTNS TO THE BRUN CMD HNDLR AT * * $A391. * * - BRUN EXECUTES THE BINARY FILE BEFORE * * RETURNING. IF THE BRUNED PGM PERFORMED* * ANY INPUT OR OUTPUT, OR IF THE BINARY * * FILE WAS BRUN WITH MON IN EFFECT, THE * * PRGM GETS HUNG UP IN AN ININITE LOOP. * * (SEE FORMATTED DISASSEMBLY OF THE CMD * * PARSING & PROCESSING ROUTINES FOR * * FURTHER DETAILS.) * - THE LOAD CMD GOES INTO APPLESOFT (AT * * $D4F2) TO RESET THE PRGM LINK PTRS * * AND THEN GOES ON TO THE RESTART * * ROUTINE ($D43C). IF THE LOAD CMD WAS * * CALLED FROM A RUN, EXECUTION JUMPS * * BACK INTO THE RUN CMD HNDLR AT * * RUNFPINT ($A4DC). * * - THE RUN CMD EXITS INTO APPLESOFT AT * * STKINI ($D683) & EVENTUALLY RTNS TO * * THE RESTART ROUTINE ($D43C). * * * *-----------------------------------------* AFTRCMD JMP FINSHCMD *================================= * DO THE DOS COMMAND. *================================= DODOSCMD JSR RESTAT0 ;RESET CONDITION TO 0. THAT IS, ;SET CONDNFLG AND OPUTCOND = 0. JSR CLRFMPRM ;CLEAR OUT THE FM PARAMETER LIST ;SO WE CAN CUSTOMIZE IT IN ;ACCORDANCE WITH THE SPECIFIC DOS ;COMMAND HANDLER CALLED. LDA NDX2CMD ;GET (A) = INDEX TO COMMAND. TAX ;(X) = INDEX 2 TBL OF ENTRY PTS. LDA CMDTBL+1,X ;GET ADR-1 OF THE CMD'S ROUTINE & PHA ;PUT IT ON STACK (HI BYTE 1RST). LDA CMDTBL,X PHA RTS ;DO A "STK JMP" TO PROCESS CMD. *================================= * GET CHAR FROM INPUT BUFFER, SET * Z-FLAG IF OR COMMA. *================================= CMDCHAR LDX NDX2INBF ;(X) = INDEX TO INPUT BUFFER. LDA BUF200,X ;GET NEXT CHAR. CMP #$8D ;IS IT A ? BEQ CMDCHRTS ;YES. INX ;(X)=INDEX 4 NXT ANTICIPATED CHR. STX NDX2INBF CMP #"," ;COMMA? CMDCHRTS RTS ;EXIT WITH Z-FLAG CONDITIONED. ;Z=1 IF CHAR IS A OR COMMA. *======================================== * GET 1RST NON-SPACE CHAR FROM INPUT BUF. * SET Z-FLAG IF IT IS OR ",". *======================================== PURGECMD JSR CMDCHAR ;GET 1RST CHAR. BEQ CMDCHRTS ;EXIT IF OR COMMA. CMP #" " ;SPACE? BEQ PURGECMD ;YES - IGNORE LEADING SPACES. RTS *================================= * CLEAR OUT THE FM PARAMETER LIST. * - SO WE CAN CUSTOMIZE IT IN * ACCORANCE WITH THE SPECIFIC * DOS COMMAND HANDLER CALLED. *================================= CLRFMPRM LDA #0 LDY #$16 ;22 BYTES TO ZERO OUT. ZFMPARM STA FMPRMLST-1,Y ;STORE ZERO BYTE. DEY ;$16 --> $01, EXIT AT $00. BNE ZFMPARM RTS *====================================== * CONVERT ASCII TO HEX OR DEC. * ON ENTRY: NDX2INBF INDEXES INPUT BUF. * ON EXIT: A5L/H AND (X,A) = LOW/HI * BYTES OF RESULT. * (C) = 0 = GOOD CONVERSION. * (C) = 1 = INVALID CHARS. *====================================== CNVRTASC LDA #0 ;ZERO OUT LOC'S TO HOLD RESULT. STA A5L ;LOW BYTE OF RESULT. STA A5L+1 ;HI BYTE OF RESULT. JSR PURGECMD ;GET 1RST NON-SPACE CHAR. PHP ;SAVE STATUS (Z-FLAG) ON STK. ;(IF OR COMMA, Z-FLAG = 1.) * CHK TO SEE IF WANT TO CONVERT * ASCII TO HEX OR ASCII TO DEC. CMP #"$" ;IS HEX SYMBOL PRESENT? BEQ ASC2HEX ;YES - BRANCH FOR ASCII TO HEX. *-------------------------------- * ASCII TO DEC CONVERSION WANTED. *-------------------------------- PLP ;GET STATUS DENOTING IF CR OR "," JMP CKIFDONE ;BEGIN DEC CONVERSION OF 1RST CHR ASC2DEC JSR PURGECMD ;GET 2ND & SUBSEQUENT ASCII CHARS ;TO BE CONVERTED TO DECIMAL. ;(IGNORE SPACES.) CKIFDONE BNE SUBTRASC ;BRANCH IF NOT OR COMMA. ;(ALWAYS FALL THRU IF ACCESSED FRM ;THE HEX CONVERSION ROUTINE.) * SUCCESSFUL CONVERSION - EXIT * WITH A5L/H AND (X,A) CONTAINING * LOW/HI BYTES OF RESULT. LDX A5L ;RESULT LOW. LDA A5L+1 ;RESULT HI. CLC ;(C)=0 TO SIGNAL GOOD CONVERSION. RTS ;EXIT TO CALLER OF CNVRTASC. * CHECK VALIDITY OF ASCII CHARS FOR * REPRESENTATION OF DECIMAL NUMBERS. SUBTRASC SEC SBC #$B0 ;SUBTRACT ASCII "0". BMI NOTASCII ;ERROR CAUSE < 0. CMP #$0A ;DECIMAL 10. BCS NOTASCII ;ERROR CAUSE > 9. * MULTIPLY RUNNING RESULT * 10 * AND THEN ADD NEW DIGIT. JSR DOUBLE ;GET RESULT * 2. ADC A5L TAX ;(X) = LOW RESULT * 2 + NEW DIGIT LDA #0 ADC A5L+1 ;ADD (C) TO HI BYTE OF RESULT. TAY ;(Y) = HI BYTE OF RESULT*2 + (C). JSR DOUBLE ;(A) = RESULT * 8. JSR DOUBLE TXA ADC A5L STA A5L ;(RESULT*2+NEW DIGIT)+(RESULT*8). TYA ADC A5L+1 ;ADD (C) TO UPDATE HI BYTE. STA A5L+1 BCC ASC2DEC ;BRANCH IF # <65536. * ERROR - INVALID ASCII NUMBER. NOTASCII SEC ;EXIT WITH (C)=1 TO SIGNAL ERROR. RTS ;RETURN TO CALLER OF CNVRTASC. * MULTIPLY 2-BYTE RESULT TIMES 2. DOUBLE ASL A5L ;"ROLL" HI & LOW BYTES AS A UNIT. ROL A5L+1 ;(PICK UP (C) IN HI BYTE.) RTS *--------------------------------- * CONVERT ASCII CHARS TO HEX. *--------------------------------- ASC2HEX PLP ;THROW SAVED STATUS OFF STACK. GETASCII JSR PURGECMD ;GET 1RST & SUBSEQUENT CHARS THAT ;OCCUR AFTER THE HEX ("$") SYMBOL BEQ CKIFDONE ;GO EXIT IF OR COMMA. * CHECK VALIDITY OF ASCII CHARS * FOR CONVERSION TO HEX. SEC SBC #$B0 ;SUBTRACT ASCII "0". BMI NOTASCII ;ERROR CAUSE < 0. CMP #$0A BCC PRP2DUBL ;VALID: 0 <--> 9. SBC #7 ;CHK HI RANGE OF HEX #'S. BMI NOTASCII ;ERROR CAUSE > $09 AND < $0A. CMP #$10 BCS NOTASCII ;ERROR CAUSE > $0F. * MOVE RESULT IN A5L/H UP A NIBBLE * BY ROLLING IT AS A UNIT (IE. *16). PRP2DUBL LDX #4 ;(X) = # OF TIMES TO DOUBLE UNIT. TIMES2 JSR DOUBLE ;MULTIPLY RESULT * 2. DEX BNE TIMES2 ;MORE MULTIPLICATION TO DO. * MERGE HEX REPRESENTATION OF DIGIT * INTO LOW NIBBLE POS'N OF RESULT. * * NOTE BUG: NO CHK IS MADE TO TRAP * NUMBERS > $FFFF. IF TOO MANY #'S * ARE INPUT, ONLY THE LAST 4 DIGITS * ARE REFLECTED IN THE RESULT. ORA A5L STA A5L JMP GETASCII ;GO GET NEXT CHAR TO CONVERT. *================================== * PR# COMMAND HANDLER. *================================== * ON ENTRY, A5L/H CONTAINS THE HEX * VALUE OF THE ARGUMENT (SLOT #) * THAT WAS ISSUED WITH THE CMD. * THE ARGUMENT WAS PREVIOUSLY * SCREENED BY THE INPRMAX ($A0AA) * ROUTINE. IF SLOT# = 0, THEN THE * OUTPUT HOOK (CSW) POINTS 2 COUT1 * ($FDF0). OTHERWISE, CSW POINTS * TO $CS00 (WHERE S = SLOT #). CMDPR LDA A5L ;GET SLOT NUMBER. JMP OUTPORT ;USE MONITOR ROM 2 SET OUTPUT HK. ;RTN 2 THE CALLER OF THE PR# CMD. ;(OFTEN RETURNS 2 AFTRCMD ($A17D) ;ASSOCIATED WITH THE COMMAND ;PARSING & PROCESSING ROUTINES.) *================================= * THE IN# COMMAND HANDLER. *================================= * ON ENTRY, A5L/H CONTAINS THE HEX * VALUE OF THE ARGUMENT (SLOT #) * THAT WAS ISSUED WITH THE CMD. * THE ARGUMENT WAS PREVIOUSLY * SCREENED BY THE INPRMAX ($A0AA) * ROUTINE. IF SLOT# = 0, THEN THE * INPUT HOOK (KSW) POINTS TO KEYIN * ($FD1B). OTHERWISE, KSW POINTS * TO $CS00 (WHERE S = SLOT #). CMDIN LDA A5L ;GET SLOT NUMBER. JMP INPORT ;USE MONITOR ROM TO SET INPUT HK. ;RTN 2 THE CALLER OF THE IN# CMD. ;(OFTEN RETURNS 2 AFTRCMD ($A17D) ;ASSOCIATED WITH THE COMMAND ;PARSING & PROCESSING ROUTINES.) {