;********************************************************** ; ; A SIMPLE PX-8 BBS ; GREAT FOR A DEMO, BUT NOT SO HOT FOR THE REAL THING. ; ; VERSION 1.0 4/28/85 ; ;********************************************************** ; ; EQUATES ; BC EQU B ; BCreg DE EQU D ; DEreg HL EQU H ; HLreg ; BS EQU 8 ; BACK SPACE CR EQU 0DH ; CR LF EQU 0AH ; LF EOS EQU '$' ; End Of String MDCTRL EQU 85H ; MODEM CONTROL PORT MDSTAT EQU 86H ; MODEM STATUS PORT MDSET EQU 87H ; MODEM "SET-UP" PORT BDOS EQU 0005H ; BDOS CALL WBOOT EQU 0000H ; WARM BOOT NEWSTK EQU 7F00H ; ***** CHANGE ME LATER ***** OLDSTK EQU 7FF0H ; ***** CHANGE ME LATER ***** CTRL2 EQU 0F0B2H ; PORT 2 BITS ; CRDELAY EQU 02H ; 0.2H SECONDS AFTER A CR ; ORG 0100H ; STANDARD STARTING POINT ; ; FIRST LET'S SAVE THE OLD STACK'S VALUE AND ; POINT THE STACK TO A FREE AREA ; START LXI HL,0 ; HL=0 DAD SP ; HL=SP SHLD OLDSTK ; SAVE OLD STACK LXI SP,NEWSTK ; SET THE STACK TO A FREE AREA ; ; CLEAR OUT MESSAGE AREA ; LXI HL,STARMSG ; ZERO FROM HERE LXI DE,ENDMSGS ; TO HERE CALL ZEROBLK ; ; MODEM START-UP, POWER UP AND WAIT FOR A CALL ; MSTART LXI DE,BBSMSG ; PRINT CR,LF,"BBS "; CALL PRINT MVI A,40H ; POWER ON THE MODEM OUT MDCTRL CALL WAIT2 ; WAIT 2 SECONDS TO BE SAFE MVI A,89H ; SELECT I/O PORTS OUT MDSET IN MDSTAT ; TEST FOR MODEM OPTION ANI 80H ; TEST BIT 7 JZ MCONT ; IF=0, THERE IS A MODEM THERE LXI DE,NOMODEM ; SAY THERE ISN'T A MODEM CALL PRINT JMP QUIT ; ABORT THIS PROGRAM MCONT LDA CTRL2 ; GET PORT 2 DATA ANI 0DFH ; RESET BIT 5, EXT MODEM STA CTRL2 ; SAVE IT OUT 2 ; SELECT EXT MODEM MVI A,50H ; SELECT ANSWER MODE OUT MDCTRL ; ; WAIT FOR SOMEONE TO CALL IN... ; LXI DE,WAITMSG ; PRINT "WAITING" CALL PRINT RWAIT IN MDSTAT ; READ STATUS BYTE ANI 01H ; TEST RING BIT JZ ANSWER ; IT'S RINGING, ANSWER IT ; ; TEST FOR A KEY FROM KB TO QUIT PROGRAM ; CALL WAITER ; WAIT TO AVOID LOCK-UP MVI E,0FFH ; READ KB MVI C,06H ; CON: I/O FUNCTION CALL BDOS CPI 00H ; IS IT A KEY ??? JZ RWAIT ; NO, WAIT SOME MORE ; ; IF IT IS A KEY, THIS CODE IS RUN ; QUIT LXI DE,QUITMSG ; PRINT "QUITING" CALL PRINT CALL PWROFF ; SHUT OFF THE MODEM LHLD OLDSTK ; GET THE VALUE OF THE OLD STACK SPHL ; PUT IT INTO THE STACK POINTER RET ; EXIT THIS PROGRAM TO CP/M ; ; ; ; ; ; IT IS A REAL CALL, GO HERE ; ANSWER LXI DE,RINGMSG ; PRINT 'RINGING' CALL PRINT MVI A,51H ; GO OFF THE HOOK OUT MDCTRL CALL WAIT2 ; WAIT 2 SECONDS MVI A,59H ; CARRIER ON OUT MDCTRL MVI A,0D9H ; CONNECT MODEM TO THE PHONE LINE OUT MDCTRL ; ; SET-UP TO OPEN THE RS232 PORT ; LHLD WBOOT+1 ; GET WARM BOOT'S POINTER MVI L,51H+3 ; POINT TO RSIOX VECTOR SHLD RSIOX+1 ; WRITE IT INTO THIS PROGRAM ; NOW, GET THE PARAMETERS INTO POSITION LXI HL,PARBLK ; POINT TO THE SOURCE LXI DE,SCRBLK ; POINT TO THE DEST MVI C,9 ; MOVE 9 BYTES CALL MOVEIT ; OPEN THE PORT MVI B,10H ; OPEN COMMAND LXI HL,SCRBLK ; POINT TO OPEN INFO CALL RSIOX ; DON'T ASK ME WHY, BUT WE NEED TO SELECT THE EXT MODEM ; A SECOND TIME. LDA CTRL2 ; GET PORT 2 DATA ANI 0DFH ; RESET BIT 5, EXT MODEM STA CTRL2 ; SAVE IT OUT 2 ; SELECT EXT MODEM ; ; TEST FOR A CD, 16 SEC LIMIT ; MVI C,00H ; 16 SECONDS OF TESTING TESTCD CALL WAITER ; WAIT 1/16 th OF A SEC IN MDSTAT ; READ STATUS ANI 04H ; MASK OUT NON CTS BITS JZ HELLO ; I FOUND IT (CD), PRINT WELCOME DCR C ; COUNT DOWN JNZ TESTCD ; KEEP ON TRYING ; ; NO CD, TIME TO RESET SP & HANG UP ; NOCD LXI DE,HANGMSG ; PRINT "HANGING UP" CALL PRINT LXI SP,NEWSTK ; RESET SP MVI B,20H ; RSIOX CLOSE FUNCTION CALL RSIOX CALL PWROFF ; HANG UP MVI A,50H ; WAIT 5 SECONDS CALL WAIT JMP MSTART ; TRY TRY AGAIN ; ; SEND THE FILE A:WELCOME.MSG ; HELLO LXI DE,WELCOME ; POINT TO WELCOME FCB CALL OPENFIL ; ; DISPLAY THE MENU ; SELECT CALL MENU ; PRINT THE LIST OF OPTIONS ; ; KEYIT, TEST ROUTINE ; KEYIT CALL CHRIN ; GET A CHAR CALL WAITER ; WAIT 1/16 SEC ORA A ; IS A=0 ? JZ KEYIT ; YES, KEEP LOOPING PUSH A ; SAVE Areg CALL CHROUT ; PRINT IT MVI A,CR ; PRINT CR CALL CHROUT POP A ORA A ; SET FLAGS ON Areg JZ KEYIT ; IF A=0, NO INPUT CPI '1' ; IS IT A '1' ? JNZ TRY2 ; NO, TRY #2 LXI HL,BYEMSG ; PRINT BYE BYE CALL MLOOP JMP NOCD ; HANG UP TRY2 CPI '2' ; IS IT A '2' ? JZ HELLO ; YES, REPRINT WELCOME CPI '3' ; IS IT A '3' ? JNZ TRY4 ; NO, TRY '4' LXI HL,ENTMSG ; PRINT "ENTER YOUR MESSAGE ..." CALL MLOOP CALL GETMSG ; READ IN A MESSAGE JMP SELECT ; GET ANOTHER COMMAND TRY4 CPI '4' ; IS IT A '4' ? JNZ SELECT ; NO, REPRINT OPTIONS MVI A,CR ; PRINT CR,CR CALL CHROUT MVI A,CR CALL CHROUT CALL PRNMSG ; YES, PRINT THE MESSAGES JMP SELECT ; KEEP ON LOOPING ;*************************************************************; ; ; ; SUBROUTINES ; ; ; ;*************************************************************; ; ; POWER OFF THE MODEM ; PWROFF MVI A,40H ; DISCONNECT ALL OUT MDCTRL CALL WAIT2 ; WAIT 2 SEC MVI A,00H ; POWER OFF OUT MDCTRL LDA CTRL2 ; READ PORT 2 SETTINGS ORI 20H ; SELECT BIT 5, RS232 ON STA CTRL2 ; SAVE NEW SETTINGS OUT 2 ; SELECT RS/232 RET ; ; WAIT 2 SECONDS ; WAIT2 MVI A,20H ; WAIT 2.0 SECONDS CALL WAIT RET ; ; DELAY ROUTINE, WAITS Areg TIME h.h SECONDS ; WAIT CALL WAITER ; WAIT .1H TIME DCR A ; COUNT DOWN JNZ WAIT ; WAIT SOME MORE RET ; ; WAIT 0.1H SECONDS ; WAITER PUSH HL ; SAVE HLreg PUSH A ; SAVE Areg LXI HL,171AH ; STARTING COUNT WAITR2 DCX HL ; COUNT DOWN MOV A,H ; TEST HIGH BYTE CPI 00H ; IS IT 0 YET ? JNZ WAITR2 ; NO, KILL MORE TIME POP A ; GET Areg BACK POP HL ; GET HL BACK RET ; ; MENU, PRINT OUT THE MENU ; MLOOP, PRINT OUT THE STRING POINTED TO BY HLreg ; MENU LXI HL,MESAGE ; POINT TO MY OUTPUT MESSAGE MLOOP MOV A,M ; GET A BYTE CPI 0 ; END OF MESSAGE ? RZ ; YES, RETURN CALL CHROUT ; SEND IT INX HL ; POINT THE NEXT BYTE JMP MLOOP ; ; CHAR OUTPUT ROUTINE, TEST FOR CD, IF NONE, HANG-UP ; IF CD, OUTPUT Areg TO RS232 ; CHROUT PUSH BC ; SAVE EVERYTHING PUSH DE PUSH HL PUSH A ; SAVE IT TOO MOV E,A ; OUTPUT IT TO THE LCD MVI C,2 ; CON: OUT FUNCTION CALL BDOS POP A ; RESTORE Areg CALL OUTPORT ; CALL THE OUTPUT ROUTINE ; IF Areg=CR, ADD IN A LF CPI CR ; IS A A RETURN JNZ COUTRET ; NO, SKIP THE REST IF CRDELAY MVI A,CRDELAY ; WAIT FOR CRDELAY SECONDS CALL WAIT ENDIF MVI A,LF ; SEND A LF TO THE RS232 CALL OUTPORT MVI C,2 ; CON: OUT FUNCTION MOV E,A ; PUT THE LF IN Ereg FOR OUTPUT CALL BDOS ; FLOW CONTROL TESTED HERE COUTRET CALL CHRIN ; READ KB/RS232 CPI 13H ; ^S ENTERED ? JNZ POPRET ; NO, JUST RETURN CTLSLOP CALL WAITER ; WAIT 1/16 SEC CALL CHRIN ; TEST FOR A ^Q CPI 11H ; ^Q ? JNZ CTLSLOP ; NO, KEEP WAITING MVI A,0 ; YES, ZERO OUT Areg POPRET ORA A ; SETS FLAGS FOR Areg POP HL ; RESTORE EVERYTHING POP DE POP BC RET ; ; CHAR ECHO ROUTINE, TEST FOR CD, IF NONE, HANG-UP ; IF CD, OUTPUT Areg TO RS232 ; THIS ROUTINE WILL NOT TEST FOR ^S OR ^Q ; CHRECHO PUSH BC ; SAVE EVERYTHING PUSH DE PUSH HL PUSH A ; SAVE IT TOO MOV E,A ; OUTPUT IT TO THE LCD MVI C,2 ; CON: OUT FUNCTION CALL BDOS POP A ; RESTORE Areg CALL OUTPORT ; CALL THE OUTPUT ROUTINE ; IF Areg=CR, ADD IN A LF CPI CR ; IS A A RETURN JNZ ECHORET ; NO, SKIP THE REST IF CRDELAY MVI A,CRDELAY ; WAIT FOR CRDELAY SECONDS CALL WAIT ENDIF MVI A,LF ; SEND A LF TO THE RS232 CALL OUTPORT MVI C,2 ; CON: OUT FUNCTION MOV E,A ; PUT THE LF IN Ereg FOR OUTPUT CALL BDOS ECHORET MVI A,0 ; SET RETURN STATUS TO 0 POP HL ; RESTORE EVERYTHING POP DE POP BC RET ; ; OUT, A DIRECT OUTPUT ROUTINE ; OUTPORT PUSH A ; SAVE EVERYTHING PUSH BC PUSH DE PUSH HL CALL CDTEST ; TEST CD MVI B,60H ; RSIOX SEND COMMAND MOV C,A ; CHAR OUT INTO Creg LXI HL,SCRBLK ; POINT TO BUFFER BLOCK CALL RSIOX POP HL ; RESTORE EVERYTHING POP DE POP BC POP A RET ; ; CHRIN, GET A CHAR FROM THE KB OR THE PORT ; CHRIN PUSH BC ; SAVE EVERYTHING PUSH DE PUSH HL MVI C,06H ; DIRECT CON: I/O MVI E,0FFH ; INPUT COMMAND CALL BDOS CPI 03H ; ^C FROM KB ? JZ ZAP ; YES, ABORT ORA A ; TEST FOR ZERO JNZ CHRRET ; NO, RETURN WITH KB INPUT ; TRY THE RS232 PORT CALL INPORT ; READ THE RS232 PORT ANI 7FH ; BLOCK HIGH BIT JZ CHRRET ; IF IT'S ZERO, RETURN CPI 7FH ; IS IT A DELETE CODE ? JNZ CHRTST ; NO, JUMP MVI A,8 ; CONVERT IT TO A BACK SPACE CHRTST CPI ' ' ; CONTROL CODE ? JNC CHRRET ; NO, JUST RETURN IT LXI HL,CHRTBL ; HL POINTS TO CHAR CONV TABLE MVI D,0 ; SET D TO ZERO MOV E,A ; COPY THE CHAR INTO E DAD DE ; ADD DE TO HL FOR POSITION IN TABLE MOV A,M ; GET THE NEW CHAR CHRRET POP HL ; RESTORE EVERYTHING, BUT Areg POP DE POP BC ORA A ; SET OR CLEAR ZERO FLAG ON Areg RET ; ; CHRTBL, CHARACTER TABLE (THIS ALLOWS ONLY SOME CONTROL ; CODES TO PASS THROUGH: ^Z, BS, CR, ^S, ^Q, ^R, ^X) ; ; ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K CHRTBL DB 00H,00H,00H,1AH,1AH,00H,00H,00H,08H,' ',00H,00H ; ; ^L ^M ^N ^O ^P ^Q ^R ^S ^T ^U ^V ^W DB 00H,CR ,00H,00H,00H,11H,12H,13H,00H,00H,00H,00H ; ^X ^Y ^Z ESC ^\ ^] ^^ ^_ DB 18H,00H,1AH,1AH,00H,00H,00H,00H,41H ; ; IN, READ THE RS232 PORT DIRECT ; INPORT PUSH BC ; SAVE EVERYTHING PUSH DE PUSH HL CALL CDTEST ; IF NO CD, HANG UP ; THERE IS A CD, TEST THE INPUT PORT MVI B,30H ; RSIOX BUFFER STATUS FUNCTION LXI HL,SCRBLK ; STATUS BUFFER CALL RSIOX ; READ THE STATUS ORA A ; TEST FOR A ZERO IN A (NO DATA) JZ CINRET ; RETURN WITH A ZERO (NO DATA) ; THERE IS DATA IN THE INPUT BUFFER, READ IT INTO Areg MVI B,50H ; RSIOX READ A BYTE FUNCTION LXI HL,SCRBLK ; INFO PACKET CALL RSIOX CINRET POP HL ; RESTORE EVERYTHING POP DE POP BC RET ; ; CDTEST, TEST FOR LOSS OF CD, ; IF GONE, HANG UP, ELSE RETURN ; CDTEST PUSH A ; SAVE Areg IN MDSTAT ; READ STATUS ANI 04H ; TEST CTS (CD) JNZ NOCD ; LOST IT, HANG UP POP A ; THERE IS A CD, CONTINUE RET ; ; MOVE SOME BYTES (1 - 256 BYTES) ; ; A = WORK AREA ; C = NUMBER OF BYTES TO MOVE ; DE = WHERE TO MOVE IT TO ; HL = WHERE IT COMES FROM ; MOVEIT MOV A,M ; GET A BYTE STAX DE ; STORE IT INX HL ; NEXT SOURCE INX DE ; NEXT DEST DCR C ; COUNT DOWN JNZ MOVEIT ; DO MORE RET ; ; PRINT A MESSAGE TO THE LCD ; PRINT PUSH A ; SAVE EVERYTHING PUSH BC PUSH HL MVI C,9 ; BDOS PRINT STRING FUNCTION CALL BDOS POP HL ; RESTORE EVERYTHING POP BC POP A RET ; ; OPENFIL, OPENS A FILE & PRINTS IT TO THE RS232 ; OPENFIL PUSH DE ; SAVE THE POINTER TO THE FCB PUSH DE ; THIS WILL GET MOVED TO THE HLreg PUSH DE ; THIS IS HELD FOR A LATER STEP PUSH DE ; THIS WILL GET MOVED TO THE HLreg POP HL ; DE ---> HL LXI DE,12 ; SKIP OVER dr:filname.ext IN FCB DAD DE ; HL NOW POINTS PAST THE ABOVE MVI D,24 ; COUNT FOR LOOP MVI A,0 ; DATA TO BE STORED INTO FCB ZEROLOP MOV M,A ; ZERO FCB BYTES 12 - 35 INX HL ; NEXT BYTE DCR D ; COUNT DOWN JNZ ZEROLOP ; DO THE REST ; NOW OPEN THE FILE POP DE ; GET THE POINTER TO THE FCB MVI C,0FH ; BDOS OPEN FUNCTION CALL BDOS POP HL ; WAS DEreg POINTING TO FCB LXI DE,32 ; FCB+32=Current Record DAD DE ; ADD TO HL MVI M,0 ; ZERO OUT CR POINTER POP DE ; RESTORE DE POINTER TO FCB CPI 0FFH ; IF A=0FFH, THERE ISN'T A FILE JZ RETURN ; IF SO, SKIP THE REST ; IT'S THERE, NOW READ THE FILE MVI L,00H ; MAKE L=0 SO THAT A READ WILL OCCUR TESTDMA MOV A,L ; TEST Lreg CPI 0 ; IS IT 0 ? JNZ PRNFIL ; NO, PRINT SOME MORE FROM THE DMA PUSH DE ; SAVE FCB POINTER MVI C,14H ; BDOS READ SEQUENTIAL FUNCTION CALL BDOS POP DE ; RESTORE FCB POINTER ORA A ; IF A<>0, End Of File JNZ CLOSE LXI HL,0080H ; POINT TO THE START OF THE DMA ; NOW WE PRINT THE FILE PRNFIL MOV A,M ; GET A BYTE ANI 7FH ; MASH HIGH ASCII INX HL ; POINT TO THE NEXT BYTE CPI 26 ; IS IT A ^Z ? JZ CLOSE ; YES, WE ARE DONE CPI LF ; IS IT A LF ? JZ TESTDMA ; YES, DON'T PRINT IT CALL CHROUT ; PRINT ALL ELSE CPI 26 ; WAS THERE A ^Z FROM KB ? JNZ TESTDMA ; NO, KEEP GOING ; CLOSE UP THE FILE CLOSE MVI C,10H ; BDOS CLOSE FILE FUNCTION CALL BDOS RETURN RET ; ; ZAP, GO HERE TO HANG UP ON SOME BOZO WHO'S MESSING ; THINGS UP. (SYSOP ABORT) ; ZAP LXI HL,ZAPMSG ; POINT TO ZAP MESSAGE PUSH HL ; MOVE HLreg ---> DEreg POP DE CALL PRINT ; FIRST PRINT IT ON THE LCD ZAPLOOP MOV A,M ; GET A BYTE CPI EOS ; IS IT THE End Of the String "$" ? JZ NOCD ; YES, HANG UP CALL OUTPORT ; NO, PRINT THE CHAR INX HL ; NEXT CHAR CALL WAITER ; WAIT 1/16 OF A SEC JMP ZAPLOOP ; DO IT AGAIN ; ; GETMSG, READ A 7 LINE MSG ; GETMSG LXI HL,WORKSTR ; FILL THE FIRST 64 WITH *s MVI C,63 GETAST MVI M,'*' ; STORE AN * INX HL ; NEXT BYTE DCR C ; COUNT DOWN JNZ GETAST ; LOOP 63 TIMES MVI M,CR ; PUT A CR AT THE END OF THE LINE ; FILL THE OTHER LINES WITH 00H LXI HL,WORKSTR+64 ; POINT TO START OF WORK AREA LXI DE,WORKEND+1 ; POINT TO END OF WORK AREA CALL ZEROBLK ; ZERO THE WORK AREA ; READ THE LINES IN LXI HL,WORKSTR+64 ; POINT TO THE START LXI DE,64 ; EACH LINE = 64 BYTES MVI C,7 ; 7 LINES MAX ; DO THIS 7 TIMES MAX GETLOOP MVI A,64 ; 64 CHAR/LINE MAX CALL GETLINE RZ ; RETURN ON AN ABORT CPI 1 ; CR ONLY ? JZ MOVEMSG ; YES, PUT IT IN THE MSG BASE DAD DE ; NO, POINT TO THE NEXT LINE DCR C ; COUNT DOWN JNZ GETLOOP ; DO OTHER LINES ; MOVE THE MESSAGE INTO PLACE MOVEMSG LXI HL,LASTMSG-1 ; FROM LOCATION LXI DE,ENDMSG ; TO THIS LOCATION LXI BC,WORKSTR ; STOPPING POINT CALL BLKMOVE ; MOVES DATA (COUNTING DOWN) RET ; ; ZEROBLK, ZEROS OUT AN AREA DEFINED BY HLreg & DEreg ; HL = START ; DE = END ; ZEROBLK MVI M,0 ; ZERO THE BYTE INX HL ; NEXT BYTE MOV A,H ; TEST HIGH BYTE CMP D ; D=H ? JNZ ZEROBLK ; NO, KEEP GOING MOV A,L ; TEST LOW BYTE CMP E ; E=L ? JNZ ZEROBLK ; NO, KEEP GOING RET ; ; BLKMOVE, THIS IS A BLOCK MOVE ROUTINE, THIS ONE STARTS AT ; THE HIGHER ADDRESSES & WORKS DOWN. ; BLKMOVE MOV A,M ; GET A BYTE STAX DE ; STORE IT DCX HL ; COUNT DOWN DCX DE MOV A,H ; DOES HL=BC ? CMP B ; H = B ? JNZ BLKMOVE ; NO, KEEP GOING MOV A,L ; TRY THE LOW BYTE CMP C ; L = C ? JNZ BLKMOVE ; NO, KEEP GOING RET ; ; PRNMSG, PRINT OUT THE MESSAGES (ABORTs ARE ALLOWED) ; PRNMSG LXI HL,STARMSG ; POINT TO THE START LXI DE,ENDMSG ; HERE'S THE END PRNLOP MOV A,M ; GET A BYTE INX HL ; NEXT BYTE ORA A ; A = 0 ? JZ PRNTST ; YES, DON'T PRINT CALL CHROUT ; PRINT IT CPI 26 ; ^Z, ABORT ? RZ ; YES, QUIT PRNTST MOV A,H ; HL = DE ? CMP D ; H = D ? JNZ PRNLOP ; NO, PRINT SOME MORE MOV A,L ; L = E ? CMP E JNZ PRNLOP ; NO, DO SOME MORE MVI C,63 ; COUNT 63 PRNAST MVI A,'*' ; PRINT 63 *s,CR CALL CHROUT DCR C ; COUNT DOWN JNZ PRNAST MVI A,CR CALL CHROUT RET ; ; GETLINE, GET A LINE OF TEXT FROM THE KB ; *A = MAX LENGTH OF THE LINE (ON RETURN = REAL LENGTH) ; B = THE BIGGEST POS (IT'S A COPY OF Areg) ; C = CURRENT POSITION ; D = DOWN COUNTER ; *HL= WHERE TO PUT IT (UNCHANGED ON RETURN) ; * = ENTRY & EXIT PARAMETERS (ALL OTHERS UNCHANGED) ; NOTES: THE UNUSED BYTES OF A LINE ARE FILLED WITH NULLS ; ^Z = ABORT THIS FUNCTION, FILLS THE LINE WITH NULLS ; AND RETURNS Areg AS ZERO ; BS = BACK SPACE ; ^R = RETYPE THE LINE ; ^X = DELETE THIS LINE & START OVER ; CR = RETURN (ALWAYS AT THE END OF A LINE) ; ALSO THE LAST CHAR MUST BE A CR, THUS ; IF Areg=1 ON ENTRY, CR IS THE ONLY CHAR ALLOWED ; GETLINE PUSH BC ; SAVE EVERYTHING PUSH DE PUSH HL MOV B,A ; B = THE BIGGERT POSITION ALLOWED MVI A,'>' ; PRINT ">"; CALL CHRECHO PSTART MVI C,1 ; START IN THE FIRST POSITION READING CALL CHRIN ; GET A BYTE CPI ' ' ; IS IT PRINTABLE ASCII ? JNC ASCII ; YES, JUMP ; ^Z TEST CPI 26 ; IS IT ^Z (ABORT) ? JNZ CTRLX ; NO, TRY ^X MVI A,'^' ; PRINT "^C" CALL CHRECHO MVI A,'C' CALL CHRECHO MVI A,CR CALL CHRECHO MVI C,0 ; 0 POSITION = ABORT POP HL ; RESET HL TO START PUSH HL ; PUT IT BACK FOR ZENDRET DCX HL ; COUNT BACK FOR FILL IN WITH 0 JMP ZEND ; FILL WITH 0s ; ^X TEST CTRLX CPI 24 ; IS IT ^X ? JNZ BSTEST ; NO, TRY A BACK SPACE CTRLXLP DCR C ; COUNT BACK JZ PSTART ; IF C=0, RESTART DCX HL ; STEP BACK CALL CHRZAP ; EAT THE CHARs JMP CTRLXLP ; DO SOME MORE ; BACK SPACE TEST BSTEST CPI BS ; IS IT A BACK SPACE ? JNZ RTST ; NO, TRY ^R TEST DCR C ; COUNT BACK JZ PSTART ; IF C=0, RESTART DCX HL ; MOVE BACK CALL CHRZAP ; EAT THE CHAR JMP READING ; TEST FOR A ^R ? RTST CPI 18 ; IS IT A ^R ? JNZ CRCHK ; NO, TRY A CR POP HL ; RESET HL PUSH HL MOV D,C ; SET DOWN COUNTER MVI A,'#' ; PRINT "#" CALL CHRECHO MVI A,CR CALL CHRECHO MVI A,'>' ; PRINT ">"; CALL CHRECHO CTRRLOP DCR D ; COUNTING DOWN JZ READING ; IF D=0, WE ARE DONE MOV A,M ; GET A BYTE CALL CHRECHO ; PRINT IT INX HL ; POINT TO THE NEXT ONE JMP CTRRLOP ; DO SOME MORE ; TEST FOR A CR CRCHK CPI CR ; WAS IT A CR ? JNZ READING ; NO, FORGET ALL ELSE MOV M,A ; STORE THE CR INTO THE LINE CALL CHRECHO ; ECHO IT BACK ZEND MOV A,C ; PUT THE POSITION INTO Areg PUSH A ; SAVE IT ZENDLOP CMP B ; DOES A=B ? JZ ZENDRET ; YES, QUIT INR A ; NEXT POSITION INX HL ; NEXT BYTE MVI M,0 ; PUT A ZERO THERE JMP ZENDLOP ; WE ARE DONE ; GO HERE FOR ASCII INPUT ASCII PUSH A ; SAVE THE CHAR MOV A,C ; TEST THE CHAR COUNT CMP B ; A(C) < B ? JNC TOOBIG ; NO, CAN'T ACCEPT IT POP A ; GET THE CHAR BACK MOV M,A ; WRITE IT INTO THE STRING CALL CHRECHO ; ECHO IT BACK TO THE USER INR C ; NEXT POSITION INX HL ; NEXT BYTE JMP READING ; GET ANOTHER BYTE ; IF IT'S TOO MANY CHARs, GO HERE TOOBIG POP A ; GET THE STACK IN ORDER JMP READING ; GET ANOTHER CHAR ; WE ARE DONE, RETURN ZENDRET POP A ; RESTORE EVERYTHING POP HL POP DE POP BC ORA A ; SET FLAGS ON Areg RET ; ; CHRZAP, PRINT BS," ",BS ; CHRZAP MVI A,BS CALL CHRECHO MVI A,' ' CALL CHRECHO MVI A,BS CALL CHRECHO RET ; ; RSIOX ; RSIOX JMP 0000H ; AT RUN TIME THIS IS CHANGED TO RSIOX ; ; STRINGS, BUFFERS, & ??? ; MESAGE DB CR,CR DB ' 1) Log off',CR DB ' 2) Re-read welcome message',CR DB ' 3) Enter a message',CR DB ' 4) Read messages',CR DB ' *) Print this list again (Big Deal!)',CR DB CR,'WHAT WOULD YOU LIKE TO DO: ? ' DB 0 ; ENDING BYTE FOR ROUTINE ; BBSMSG DB CR,LF,'Mr Bill',2CH,'s BBS : ',EOS ; WAITMSG DB 'WAITING FOR A CALL.',EOS ; RINGMSG DB CR,LF,'RINGING . . .',EOS ; HANGMSG DB CR,LF,'HANGING UP THE PHONE.',EOS ; QUITMSG DB CR,LF,'ABORTING THIS PROGRAM.',CR,LF,EOS ; NOMODEM DB CR,LF,'THE OPTIONAL MODEM IS NOT MOUNTED ' DB 'TO YOUR PX-8.',EOS ; ZAPMSG DB CR,0,0,0,0,0,0,0,0,LF,LF,0,0,0,0,0,0,0,0 DB '*** PROGRAM ABORTED BY SYSOP . . . GOODBY ***' DB CR,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,LF,LF,EOS ; ENTMSG DB CR,CR,'Please enter your message, use ' DB 'CR, CR to end (7 lines max) :',CR,CR,0 ; BYEMSG DB CR,CR,'Thanks for calling in, Please Hang ' DB 'up the phone now, bye bye, (Mr Bill)',CR,CR ; PARBLK DW BUFFER ; BUFFER LOCATION DW 261 ; THE SIZE OF THE BUFFER DB 06H ; 300 BAUD DB 03H ; 8 BITS DB 00H ; NO PARITY DB 01H ; 1 STOP BIT DB 0FFH ; SPECIAL PARA. ; SCRBLK DS 10 ; SET ASIDE 10 BYTES ; WELCOME DB 1 ; A:WELCOME.MSG FCB DB 'WELCOME MSG' DB 0,0,0,0,0,0,0,0,0,0,0,0 ; WORK AREA DB 0,0,0,0,0,0,0,0,0,0,0,0 ; BUFFER DS 270 ; RS232 BUFFER ; ; THIS IS THE END OF THE PROGRAM ; PROGEND EQU $ ; WORKSTR EQU PROGEND+1 WORKEND EQU WORKSTR+511 ; STARMSG EQU WORKEND+1 LASTMSG EQU STARMSG+4096-512 ENDMSG EQU STARMSG+4095 ENDMSGS EQU ENDMSG+1 ; END 0100H