;CBBS O O O O O .ASM ; O O O O ; O O O O O O ; ; ALSO CONTAINS THE HELP COMMAND ; ;WRITES COMMENTS TO THE LOG FILE. EACH IS ;PRECEEDED WITH A ']' SUCH THAT IN OPERATOR MODE, ;'TYPE LOG' COMMAND WILL ACCEPT CTL-C TO SKIP ;TO THE NEXT LOG ENTRY ; ;MODS (THRU 3.2 WRITTEN TO "HISTORY") ; ;====> HISTORICAL COMMENTS SINCE 3.3 TO "HISTORY.033" ; ; ---------------- BYE LDA COMFLG ;GET FLAG CPI 'B' ;IF BUSY THEN DON'T.. JZ BYEBYE ;..TRY WRITING COMMENT LXI H,' 1' SHLD COMLNO ;INIT COMMENT LINE COUNTER ; IF TWITCK CALL TWITST MVI A,1 ;TO ZAP CTL-K FUNCT JZ BYENCK LDA TWITSW ORA A JNZ BYENCK ; ENDIF ; MVI A,'B' ;SET.. STA COMFLG ;..BUSY JMP BYEASK BYEYN: ; IF HAYES IN DCHST ;CHECK FOR CARRIER LOSS ANI DCHCD ENDIF ; IF IDS IN IDSST ANI IDSCTS ;CLEAR TO SEND? (=CARRIER LOSS) ENDIF ; IF PMMI IN PMMIMST CMA ;PMMI = NOT(CTS) ANI PMMICTS ENDIF ; JZ BYEBYE ;TREAT AS IF 'N' WERE ENTERED CALL ILPRT DB 'Please answer Yes or No',CR,LF,0 BYEASK LDA PASSFLG ;OPER? ORA A JZ CMOP1 LDA CLEFT ORA A JZ BYEBYE CMOP1: CALL GETVAR DB 'Comments Y/N: Want to leave any ' DB 'comments or suggestions ' DB CR,LF,0 DW ANSWER DW 5 ;HELP MSG # DB 9 LDA ANSWER CPI '-' JZ FUNCT CPI CR ;JUST C/R? JZ BYEYN ;YES, RE-ASK ;IF NO, CLOSE FILE LEAVING JUST NAME. CPI 'N' ;NO? ; IF CLOCK STA BYEFLG JZ BYETIME ENDIF ; IF NOT CLOCK JZ BYEBYE ;NO COMMENTS ENDIF ; CPI 'Y' ;YES? JNZ BYEYN ;NOT 'YES' - REASK ; ;DISABLE CTL-K TEST WHILE WRITING COMMENT FILE ; BYETIME MVI A,1 STA CTLKSW STA DKUPSW ;SHOW UPDATING DISK LXI H,LOGFL ;POINT TO FILENAME CALL EXTEND ;EXTEND THE LOG FILE ; IF CLOCK CALL WRETIME ;WRITE ELAPSED TIME ; CALL WRCRLF ; ;IF 'NO' COMMENTS REQUESTED, JUST CLOSE FILE ; LDA BYEFLG CPI 'N' JZ COMEND ENDIF ;CLOCK ; CALL WRCRLF MVI A,']' ;ALLOW CTL-C SKIP TO CALL WRBYTE ;..NEXT COMMENT LDA EXPERT ORA A JNZ COMLP ;SKIP INSTR FOR EXPERIENCED USER CALL ILPRT DB CR,LF DB CR,LF DB 'Enter your comments. Use ctl-U ' DB 'for line cancel,' DB CR,LF DB 'and DEL or CTL-H ' DB 'for backspacing.',CR,LF DB 'Each line may be up to 60 chars long.' DB CR,LF,0 LDA BELLF ANI 1 JZ COMENT CALL ILPRT DB '(Bell sounds after 55)' DB CR,LF,0 ; COMENT CALL ILPRT DB 'Enter each line, ' DB 'press return twice to end',CR,LF,0 COMLP CALL GETVAR COMLNO DB ' 1:',0 DW ANSWER DW 6 ;HELP MSG # DB 60 LDA ANSWER CPI CR JZ COMEOI ;START OF MODS TO SEE IF "HELP" ENTERED LXI D,ANSWER LXI H,HELPFL+1 ;TO "HELP" CALL COMP4 ;SEE IF "HELP" JNZ BYNHELP LDA ANSWER+4 CPI CR JNZ BYNHELP CALL ILPRT DB 'Continue typing your comments to the ' DB 'CBBS operators.',CR,LF,0 JMP COMENT ; ;START OF MODS TO LIMIT # OF COMMENT LINES ; BYNHELP LDA CLEFT DCR A STA CLEFT CPI 4 CC CMPRNL ;PRT # LEFT ;SOMETHING WAS ENTERED - WRITE IT OUT LXI H,ANSWER CALL WRLINE LDA PASSFLG ;OPER? ORA A JZ CMOP LDA CLEFT ORA A JZ COMWRN ;ALL DONE, CLOSE UP ; CMOP LDA INBUF CPI CR JNZ COMLP ;HAVE STACKED ANSWER LXI H,COMLNO+1 CALL ADD1 JMP COMLP ; CMPRNL ADI '0' CALL TYPE CALL ILPRT DB ' lines left',CR,LF,0 RET ; ;C/R ENTERED, BE SURE THEY ARE DONE ; COMEOI CALL GETVAR DB 'Y/N Done',0 DW ANSWER DW 0 ;HELP MSG # DB 6 LDA ANSWER CPI 'N' JZ COMLP CPI CR JZ COMWRN ;IF C/R, LET THEM GO CPI 'Y' JNZ COMEOI ; ;END OF COMMENT, WRITE NAME ; COMWRN CALL WRNAME ;"FN LN," ; CALL WRCRLF ;NEXT CALLER WILL CR/LF ; ;CLOSE OUT COMMENTS FILE ; COMEND CALL WREOF ;WRITE EOF, CLOSE FILE BYEBYE XRA A ;ENABLE THE STA DKUPSW ;SHOW NO LONGER UPDATING DISK ;ADD FOLLOWING XRA A BYECTLK XRA A BYENCK STA CTLKSW ;..CONTROL-K TEST MVI A,'N' ;RESET COMMENT BUSY FLAG STA COMFLG LXI H,BYMSG ;GET GOOD BYE MESSAGE CALL TYPEM0 ;TYPE THE MESSAGE LXI H,FNAME ;POINT TO FIRST NAME CALL TYPEMCR CALL CRLF ; IF CLOCK LDA BYEFLG CPI 'N' ;NO COMMENTS? CNZ PRETIME ;ELAPSED TIME ENDIF ; ; IF TTY MVI A,80 STA COL ;FAKE UP TO CAUSE C/R MVI A,CR CALL LOG ;LOG A C/R ;GIVE ABOUT 8 SEC FOR LOG TTY TO COMPLETE LXI H,4000H ENDTTY PUSH H CALL CKTTY POP H DCX H MOV A,H ORA L JNZ ENDTTY ENDIF ; LXI H,HUNGUP JMP PRDIS ;PRINT MSG, DISCONNECT, EXIT HUNGUP DB CR,LF DB '++End of connection++',CR,LF DB LF,LF,LF,0 ; BYECR CALL KEYCHR ;GET A CHAR JZ BYECR CPI CR JNZ BYECR BYECR2 CALL KEYCHR JZ BYECR2 CPI CR JNZ BYECR MVI A,CR ;DELETE FIRST NAME STA FNAME JMP START ; ;-----> HELP FUNCTION - INTERPRET QUESTIONS IN 'HELP' FILE ; HELP MVI A,1 STA INHELP ;FORCE "X" THRU AS KEYWORD CALL GETVAR DB CR,LF DB 'Keyword: Enter a single word ' DB 'which best ',CR,LF DB 'describes the function you ' DB 'want help on. ',CR,LF DB 'Type ? to list all ' DB 'keywords.',CR,LF DB 'Type ?? to list keywords and ' DB 'a BRIEF explanation',CR,LF DB 0 DW ANSWER DW -1 ;HELP MSG # (NONE, PASS "?" BACK) DB 20 HELP2 LDA ANSWER CPI CR JZ FUNCT LDA ANSWER CPI '?' JZ HWORDS LXI H,HELPIDX ;TRY OPENING INDEX CALL SETRD JC HSCAN ;NO INDEX, SCAN THE HELP FILE ; ;LOOK UP WORD IN INDEX ; HXLOOP CALL CTLCKS ;ALLOW ^K CALL RDBYTE JC HLPNW CPI LF JNZ HXLOOP LXI H,ANSWER-1 HXMATCH CALL RDBYTE JC HLPNW INX H CMP M JZ HXMATCH CPI ',' ;END OF WORD? JNZ HXLOOP ;NOPE, TRY AGAIN MOV A,M ;GET KEYWORD CPI CR ;END? JNZ HXLOOP ;NOPE, NOT IT ; ;FOUND THE WORD IN THE INDEX - USE IT TO SET ; UP THE FCB ; CALL DKRDHEX ;GET EXTENT PUSH PSW ;SAVE IT CALL DKRDHEX ;GET HEX DIGIT ADD A ! ADD A ! ADD A ! ADD A ;X16 MOV B,A PUSH B CALL DKRDHEX ;GET SECOND DIGIT POP B ADD B MOV B,A ;SAVE REC # POP PSW ;GET EXTENT PUSH B ;SAVE REC # STA FCBEXT LDA HELPFL ;GET DISK STA FCB ;SET DISK MVI A,' ' STA FCB+9 ;MAKE HELP.IDX STA FCB+10 ; INTO STA FCB+11 ; HELP CALL SETOPEN JC HELPNF POP B ;RESTORE REC # MOV A,B ;GET REC # STA FCBRNO JMP HMLOOP ; HSCAN LXI H,HELPFL CALL SETRD JC HELPNF ; ;KEYWORD ENTERED, TRY TO FIND IT ; HMLOOP CALL CTLCKS ;ALLOW ^K CALL RDBYTE JC HLPNW CPI '[' ;START OF WORD? JNZ HMLOOP LXI H,ANSWER-1 HMMATCH CALL RDBYTE JC HLPNW INX H CMP M JZ HMMATCH CPI '=' ;END OF WORD? JNZ HMLOOP ;NOPE, TRY AGAIN MOV A,M ;GET KEYWORD CPI CR ;END? JNZ HMLOOP ;NOPE, NOT IT ; ;GOT KEYWORD IN FILE, TYPE DESCRIPTION ; CALL ILPRT DB 'Use CTL-K to abort HELP' DB CR,LF,0 ; HLPTYPE CALL RDBYTE JC HLPMORE CPI ']' JZ HLPMORE CPI '[' ;SYNONYM LINE? JNZ HLPT2 ; ;SKIP A SYNONYM EXPLANATION ; HLPSKS CALL RDBYTE JC HLPMORE CPI LF JNZ HLPSKS JMP HLPTYPE ; HLPT2 CALL TYPE CALL CTLCKS ;ALLOW ABORT JZ HLPMORE ;CTL-C TYPED JMP HLPTYPE ; ;KEYWORD ASKED FOR NOT IN HELP FILE ; HLPNW EQU $ LXI H,LOGFL ;POINT TO FILENAME CALL EXTEND ;EXTEND THE LOG FILE CALL WRCRLF LXI H,HELPHDR CALL WRVAR ;WRITE "]HELP: " LXI H,ANSWER HLPWC MOV A,M INX H CPI CR JZ HLPWE CALL WRBYTE JMP HLPWC ; HLPWE MVI A,',' CALL WRBYTE CALL WREOF ;CLOSE FILE CALL ILPRT DB 'Keyword not in help file' DB CR,LF,0 ; ;ASK IF ANOTHER WORD IS WANTED ; HLPMORE CALL GETVAR DB CR,LF DB 'Next keyword: (or press return ' DB 'to end HELP)',0 DW ANSWER DW 7 ;HELP MSG # DB 20 JMP HELP2 ; HELPHDR DB ']HELP: ',CR ; ;'?' OR '??': TYPE ALL KEYWORDS IN THE HELP FILE ; HWORDS LXI H,HELPFL CALL SETRD JC HELPNF CALL ILPRT DB 'Use K or ctl-K to abort',CR,LF,0 HWNXT CALL RDBYTE JC HELP CPI '[' ;START OF WORD? JNZ HWNXT HWLP CALL RDBYTE JC HELP CPI CR JZ HWEND CPI '=' JNZ HWTYPE LDA ANSWER+1 CPI '?' ;'??' TYPED? JNZ HWENDW MVI A,'=' HWTYPE CALL TYPE CALL CTLCKS ;ABORT? JMP HWLP ; HWEND CALL CRLF JMP HWNXT ; ;END OF WORD, C/R IF COL>=49 ; HWENDW LDA TABCOL CPI 49 JNC HWEND MVI A,TAB CALL TYPE LDA TABCOL ANI 0FH MVI A,TAB CNZ TYPE JMP HWNXT ; HELPNF CALL ILPRT DB '++Sorry, no HELP file on disk!++',cr,lf,0 jmp funct ; RZ ; CPI '[' ; RZ ; CPI 7 ; RET ; ;====> SYNTAX ERROR IN HELP FILE ; IQSNERR CALL ILPRT DB 'Sorry, help file error',cr,lf,0 ;OT TO NAME CALL INTQF ;INTERPRET QUESTION FILE JMP FUNCT ; ;================================================ ; ;====> INTQF ROUTINE TO INTERPRET QUESTION FILE ; ; FILE FORMAT FOR QUESTION IS: ; ;[THIS IS THE QUESTION ;THIS IS THE ANSWER ;(AS MANY LINES AS REQUIRED) ;] <----SIGNIFIES END OF QUESTION ; ; NOTE: a ";" following a "]" makes the ; rest of the line a comment. ; A "Q" following a "]" means Quit right now. ; ;Example: (Of course no ';' are in the ;actual question file at the start of lines) ; ;[Want to know what control-C does ;Control-c suppresses output to your ;terminal until the next input is ;asked for. ;]Q ;[Want help with such-and-such ;blah - blah - blah ;];this is a comment ; ;NESTED QUESTIONS ARE HANDLED, TOO: IF NO ;IS ANSWERED TO AN OUTER QUESTION, THEN ;INNER NESTED QUESTIONS ARE SKIPPED. ; INTQF CALL SETRD ;SET UP FILE RC ;RET IF ERROR ; ;TYPE THE PROLOG, OR LINES BETWEEN QUESTION. ; ^C TAKES USER TO FIRST QUESTION ; IQPRO CALL IQTYPE ;TYPE WORDS BETWEEN QUESTIONS RC ; RETURN ON EOF CPI '[' ;M-U-S-T BE A QUESTION JNZ IQSNERR ; OTHERWISE SYNTAX ERR CALL IQUEST ;HANDLE A QUESTION, RC ; RETURN ON EOF OR QUIT JMP IQPRO ;LOOP ; ;RECURSIVE CALL TO IQUEST: ; IQUESTR CALL IQUEST ;HANDLE QUESTION RC ;EOF OR QUIT? JMP IQUEST2 ;CONTINUE WITH (POSS) TEXT ; ;====> IQUEST ASKS A QUESTION ; ; NOTE THIS IS A RECURSIVELY-CALLABLE SUBROUTINE ; IQUEST CALL IQTYPEQ ;TYPE THE QUESTION CALL IQANS ;ASK Y/N RC ;CARRY MEANS QUIT CPI 'N' ;NO? JZ IQSKIP ; SKIP Q AND NESTED Q'S IQUEST2 CALL IQTYPE ;YES? TYPE THE ANSWER RC ;IF EOF CPI '[' ;NESTED QUESTION? JZ IQUESTR ;YES, HANDLE IT RECURSIVELY ; ;GOT END OF QUESTION - CHECK FOR SPECIAL ACTIONS: ; ; X.... EXECUTE COMMAND ; Q QUIT OUT OF HELP ; ; REST OF LINE IS COMMENT ; CALL RDBYTE ;GET OPTION RC ;EOF CPI ';' ;COMMENT? JZ IQSKLF ; YES, SKIP IT ANI 5FH ;MAKE UPPER CASE CPI 'Q' STC RZ ;FAKE UP EOF IF QUIT LXI H,INBUF ;SET UP FOR 'X' CPI 'X' ;EXECUTE? JZ IQX ; YES, DO IT ; ;NO SPECIAL REQUEST. PUT IT BACK ; CALL UNRDBYT ORA A ;NO CARRY = NO EOF RET ; ;====> IQTYPEQ TYPE THE QUESTION ; IQTYPEQ CALL RDBYTE RC CPI CR ;IF CR, SKIP TO LF, JZ IQSKLF ; THEN RETURN CALL TYPE CALL CTLCKS ;IF NOT ^C, JNZ IQTYPEQ ; LOOP CALL CRLF ;ELSE, CRLF JMP IQSKLF ; THEN SKIP REST ; ;====> IQANS GETS Y/N/Q ANSWER ; IQANS LDA INBUF ;STACKED ANSWER? CPI CR ;EMPTY BUFFER? CNZ CRLF ; NO, CRLF CALL GETVAR ;GET THE ANSWER DB 0 ;NO MESSAGE DW ANSWER ;READ IN HERE DW 0 ;HELP MSG # DB 9 ;MAX LEN LDA ANSWER CPI 'Y' ;YES? RZ ; "YES", SO RETURN CPI 'N' ;NO? RZ ; "NO", SO RETURN CPI 'Q' ;REQUEST TO STC ;FAKE UP AS EOF RZ ; QUIT OUT MVI A,CR ;PURGE INBUF STA INBUF ; OF BUFFERED ANSWERS CALL ILPRT DB 'Y/N/Q, Please: answer Yes or No, or Quit',0 JMP IQANS ; ;SKIP A "NO" ANSWER AND ASSOCIATED NESTED ANSWERS ; IQSKIP CALL CTLCKS ;ALLOW ^K, BUT IGNORE ^C CALL IQDSKIP ;SKIP TO NEXT DELIMITER RC CPI 7 ;BELL HDR FOR TYPING MSGS? RZ CPI '[' ;NESTED Q.? CZ IQSKIP ;YES, SKIP IT, TOO CPI ']' ;END? JNZ IQSKIP ;LOOP UNTIL @ END ; ;GOT END OF "NO" ANSWER. ; SKIP Q, X, OR COMMENTS ; IQSKP2 CALL RDBYTE ;GET NEXT BYTE RC CPI ';' ;COMMENT? JZ IQSKLF ANI 5FH ;MAKE UPPER CASE CPI 'Q' JZ IQSKLF ;IGNORE 'Q' LINE CPI 'X' ;FUNCTION TO EXECUTE? JZ IQSKLF ;TREAT LIKE COMMENT CALL UNRDBYT ;PUT IT BACK ORA A ;NOT EOF RET ; ;====> IQX: EXECUTE A COMMAND ; IQX CALL RDBYTE JC DEFUNCT ;PREMATURE EOF MOV M,A CALL TYPE MOV A,M INX H CPI CR JNZ IQX CALL CRLF JMP FUNCT ;EXECUTE STACKED COMMAND ; ;====> IQTYPE TYPES TEXT UP TO NEXT [ OR ] ; ^C SKIPS ; IQTYPE CALL IQRDTST ;READ, TEST FOR DELIM RC RZ ;RET IF DELIM CALL TYPE CALL CTLCKS ;ALLOW ^C, ^K JNZ IQTYPE CALL CRLF ; ;====> IQDSKIP SKIP TO NEXT DELIMITER ; IQDSKIP CALL IQRDTST ;READ, TEST FOR DELIM RC RZ JMP IQDSKIP ; ;====> IQRDTST READ, TEST FOR DELIM ; RETURNS Z ON DELIM IQRDTST CALL RDBYTE RC CPI ']' RZ CPI '[' RZ CPI 7 RET ; ;====> SYNTAX ERROR IN HELP FILE ; IQSERR CALL ILPRT DB 'Sorry, help file error!!',CR,LF,0 STC RET ; ;====> IQSKLF SKIPS A LINE, THRU THE L/F ; IQSKLF CALL RDBYTE ;SKIP TO LF WHETHER RC ;IN CASE EOF CPI LF ; OR NOT CTL-C JNZ IQSKLF ;WAS TYPED DURING QUESTION RET ; LINK CBBSSUMM ;TO NEXT .ASM FILE