; PLINK.ASM VER 6.7 ; (REVISED 5/6/82) ; ;PLINK IS A CP/M TRANSIENT COMMAND WHICH ALLOWS THE USER TO ;ESTABLISH A COMMUNICATIONS LINK WITH A REMOTE COMPUTER. ; ;THIS PROGRAM CURRENTLY SUPPORTS THE FOLLOWING MODEMS OR COMPUTERS ;VIA CONDITIONAL ASSEMBLY: ; ; 1. PMMI MODEM ; 2. ANY SERIAL I/O BOARD (TUART INCLUDED) ; 3. TRS-80 MODEL 1 ; 4. TRS-80 MODEL 2 ; 5. HEATH H8/H89 WITH 8250 UART AT PORT 330Q ; 6. D.C.HAYES 80-103A OR MICROMODEM 100 ; 7. MITS 2SI/O BOARD, PORTS 10H &11H = CONSOLE, 12H & 13H = MODEM ; 8. INTEL SBC OR NATIONAL BLC MULTI-BUS BOARDS USING 8251 USART ; 9. APPLE II WITH Z-80 CARD AND SUPER SERIAL IN SLOT 2 ; ;ORIGINALLY WRITTEN BY L.E. HUGHES (EDCAM) IN JULY, 1977. MANY ;MODIFICATIONS HAVE BEEN MADE SINCE THIS TIME, AS SHOWN IN THE ;FOLLOWING SUMMARY. ; ;FIXES/UPDATES (IN REVERSE ORDER TO MINIMIZE READING TIME): ; ; NOV 8, 1982. APPLE EQUATES CHANGED FOR SUPER SERIAL CARD (MIKE COHEN) ; ; JUNE 15, 1982. ADDED FEATURE TO AUTOMATICALLY SEND ; X-OFF TO REMOTE WHEN BUFFER FILLS AND DISK SAVE BEGINS (CHRIS HAYS) ; JUNE 15, 1982. FIXED DELETE/BACKSPACE PROBLEM ; WHEN USED WITH APPLE CP/M (CHRIS HAYS) ; MAY 6, 1982. ADDED APPLE II EQUATES (CHRIS HAYS) ; MAY 6, 1982. ADDED ERROR TRAP AND RECOVERY ROUTINE ; IN CASE THE DISK GETS FULL WHEN SAVING BUFFER. CHRIS HAYS ; MAY 6, 1982. ADDED CONDITIONAL ASSEMBLY SWITCH TO ALLOW ; MICRONET UPLOAD TO WORK CORRECTLY. OPTION IS ACTIVATED ; WHEN THE 'U' (UPLOAD) TRIGGER OPTION IS SELECTED. CHRIS HAYS. ; JUNE 26, 1981. ADDED MESSAGE WHEN EXITING IF LAST BUFFER WAS ; NOT SAVED. TED SHAPIN. ; ;JUNE 14, 1981, BY KEITH PETERSEN, W8SDZ. CHANGED PORT ;EQUATE TO 'EQU' INSTEAD OF 'SET'. ASM DOESN'T LIKE 'SET' ;WHEN LATER CONDITIONALS ARE BASED ON A LABEL DEFINED THAT ;WAY. ; ;JUNE 7, 1981, BY TOM JORGENSON (CP-MIG). CHANGED CP/M ;ORIGIN FROM BEING VIA SETS TO REFERENCED TO BASE, ADDED ;TRUE/FALSE RATHER THAN NUMERIC VALUES (FOR READABILITY), ;CHANGED ^Q FUNCTION TO ^W (WRITE) BECAUSE SOME SYSTEMS ;(NOTABLY MICRONET) USE ^S/^Q TO SUSPEND/RESUME OUTPUT, ;CHANGED PAGE 0 REFERENCES IN TRS ROUTINES TO USE ;BASE EQUATE PROPERLY, CHANGED PORT EQUATES TO DEFAULT ;TO TRUE, REINSERTED HEATH EQUATES, AND CLEANED UP CODE ;IN SEVERAL PLACES. ; ;JUNE 7, 1981, BY KEITH PETERSEN, W8SDZ. FIXED PROBLEM WITH ;EQUATES WHICH PREVENTED ASSEMBLY BY 'ASM' WHEN TUART OPTION ;WAS SELECTED. ; ;JUNE 6, 1981, BY KEITH PETERSEN, W8SDZ. ADDED VERSION NUMBER, ;CLEANED UP FILE. ; ;MAY 12, 1981, BY T. SHAPIN. ADDED CODE FOR 8251 USART ON INTEL ;SBC OR NATIONAL BLC MULTIBUS BOARD WITH MODIFIED CP/M ORIGIN. ;ADDED PROMPT TO SIGNON. ADDED TOGGLE TO ^Y TO SAVE OR IGNORE ;INCOMING TEXT. ADDED ^C ABORT ON FILE NAME RESPONSE. ; ;NOVEMBER 10, 1980, BY KELLY SMITH. ADDED CONDITIONAL ASSEMBLY ;SWITCH FOR MITS 2SI/O BOARD, USING "STANDARD" MITS PORTS 10 AND ;11 HEX FOR THE CONSOLE, AND 12 AND 13 HEX FOR THE MODEM. ; ;OCTOBER 18, 1980, BY KEITH PETERSEN, W8SDZ. ; ;HEATH EQUATES ADDED BY TOM JORGENSON. ; ;TRS-80 MODEL 1 MODS BY STEVE VINOKUROFF, VANCOUVER CBBS. ; ;OPTIONAL TRIGGER CHARACTERS BY STEVE VINOKUROFF. ; ;TRS-80 MODS BY DENNIS BRECKENRIDGE, BURNABY CBBS. ; ;D.C.HAYES MODS BY BRUCE RATOFF, ISELIN NEW JERSEY REMOTE CP/M. ; ;NOTE: IF YOU ADD IMPROVEMENTS OR OTHERWISE UPDATE ;THIS PROGRAM, PLEASE MODEM A COPY OF THE NEW FILE ;TO "TECHNICAL CBBS" IN DEARBORN, MICHIGAN - PHONE ;313-759-6569>>RINGBACK. ;(110, 300, 450 OR 600 BAUD). ;FILENAME PLINKXX.NEW. ; ;PLINK CURRENTLY SUPPORTS TWO WAY TRANSFER OF TEXT FILES BETWEEN ;THE CP/M DISK AND THE REMOTE COMPUTER. THE FOLLOWING CONTROL ;CODES MAY BE INITIATED FROM THE CONSOLE KEYBOARD: ; ;CONTROL-E EXIT PLINK TO CP/M "WARM-BOOT". ; ;CONTROL-T TRANSMIT ASCII FILE TO REMOTE SYSTEM, ASKS FOR ; DRIVE (A, B, ETC.) AND FILENAME.TYP. ; ;CONTROL-C ABORTS TRANSMISSION OF FILE TO REMOTE SYSTEM. ; ;CONTROL-Y SWITCHES BETWEEN SAVING AND IGNORING ; INCOMING ASCII DATA IN RAM BUFFER, ; FOR LATER TRANSFER TO DISK. ; ;CONTROL-W WRITES RAM BUFFER TO DISK, AND ASKS FOR DRIVE ; AND FILENAME.TYP. ; ;DEL (DELETE) BACKSPACE WHEN IN COMMAND MODE (E.G. ^T OR ^W). ; ;CONTROL-U ABORTS CURRENT LINE WHEN IN COMMAND MODE. ; ;(NOTE: ALL OTHER CONTROL CODES ARE PASSED TO MODEM OUTPUT, AND ;MAY BE INTERPRETED BY THE REMOTE SYSTEM AS VARIOUS CONTROL ;FUNCTIONS.) ; ;TRUE/FALSE DEFINITIONS ; FALSE EQU 0 TRUE EQU NOT FALSE ; ;CONDITIONAL ASSEMBLY SWITCHES <<-- SET FOR YOUR SYSTEM ;(SELECT ONLY ONE AS TRUE) - (NOTE: USE TUART FOR OTHER ;SERIAL PORTS NOT DEFINED). ; MITSIO EQU FALSE ;TRUE, IF MITS 2SI/O BOARD H84 EQU FALSE ;TRUE, IF YOU HAVE H8/H8-4 OR H89 TUART EQU FALSE ;TRUE, IF CROMENCO TUART OR OTHER SERIAL PMMI EQU FALSE ;TRUE, IF PMMI (SET INITREQ TRUE ONLY ;IF ORIG MODE AND PARITY IS REQUIRED) DCH EQU FALSE ;TRUE, IF D.C.HAYES TRS1 EQU FALSE ;TRUE, IF TRS-80 MODEL 1 TRSPT EQU FALSE ;TRUE, IF TRS-80 MODEL 2 ;USING PICKLES & TROUT CP/M 2.X MULTI EQU FALSE ;TRUE, IF SBC OR BLC 8251 USART APPLE EQU TRUE ;TRUE, IF APPLE CP/M ; MNET EQU TRUE ;TRUE, IF MICRONET UPLOAD FEATURE WANTED ; INITREQ EQU FALSE ;TRUE, IF PORT INITIALIZATION REQUIRED ; IF NOT (TRSPT OR APPLE) PORT EQU TRUE ;TRUE, ON MOST SYSTEMS ENDIF ; IF TRSPT OR APPLE PORT EQU FALSE ;THIS IS THE ODDBALL ENDIF ; ;BDOS ENTRY POINT AND FUNCTION CODES ; BASE EQU 0 ;<<-- SET TO OFFSET OF CP/M FOR YOUR ;SYSTEM, STANDARD SYSTEMS ARE 0, SOME ;'ALTERNATE' SYSTEMS ARE 4200H ; BDOS EQU BASE+5 RESDSK EQU 13 ;RESET DISK SYSTEM OFFC EQU 15 ;OPEN FILE CFFC EQU 16 ;CLOSE FILE DFFC EQU 19 ;DELETE FILE RRFC EQU 20 ;READ RECORD WRFC EQU 21 ;WRITE RECORD MFFC EQU 22 ;MAKE FILE ; ;TRS80 PICKLES AND TROUT SIO CALLS ;OFFSET BY -3 THAT IS ADD 3 TO ALL CALLS ; SETSIO EQU 30H ;SET UP Z80 SIO SIOTST EQU 33H ;READ SIO STATUS SIOINP EQU 36H ;INPUT A CHAR SIOOUT EQU 39H ;OUTPUT A CHAR ; IF MULTI MODS EQU 0DDH ;MODEM CONTROL MTBE EQU 1 ;BIT TO TEST FOR SEND MRDA EQU 2 ;BIT TO TEST FOR RECEIVE MXOR EQU 3 ;MASK TO MAKE MTBE AND MRDA 'LOW TRUE' MODD EQU 0DCH ;MODEM DATA PORT ENDIF ; ;DEFAULT FCB AND FIELD DEFINITIONS ; FCB EQU BASE+5CH FN EQU 1 ;FILE NAME FIELD (REL) FT EQU 9 ;FILE TYPE FIELD (REL) EX EQU 12 ;FILE EXTENT FIELD (REL) NR EQU 32 ;NEXT RECORD FIELD (REL) DBUF EQU BASE+80H ;DEFAULT DISK BUFFER ADDRESS ; ;ASCII CONTROL CHARACTERS ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED IF NOT APPLE DEL EQU 7FH ;DELETE (RUBOUT) ENDIF ; IF APPLE DEL EQU 08H ;APPLE USES BS INSTEAD ENDIF ; BELL EQU 07H ;BELL SIGNAL TAB EQU 09H ;HORIZONTAL TAB XOFF EQU 13H ;X-OFF CHARACTER XON EQU 11H ;X-ON CHARACTER NULL EQU 00H ;NULL CHAR ; ;THE FOLLOWING "TRIGGER" EQUATE IS SET TO "LF" (LINEFEED) ;BY DEFAULT. AN OPTIONAL TRIGGER CHAR MAY BE PASSED VIA FCB1 ; ; IE: PLINK B WILL SET TRIGGER TO "BELL" ; ;THE FOLLOWING OPTIONS ARE ALLOWED ; ; 1. B = BELL 07H ; 2. X = XON 11H ; 3. U = UPLOAD NO TRIGGER CHECK AT ALL ; ;ANY OTHER ASCII CHARACTER MAY BE PASSED THROUGH FCB1 ; ; TRIGGER EQU LF ;DEFAULT VALUE ; ; ;WARNING CHARACTER FOR LOW MEMORY ; IF NOT APPLE WRNSIG EQU BELL ;IF YOU HAVE ONE, PUT 'BELL' HERE ;...ELSE PUT '*' HERE. ENDIF ; IF APPLE WRNSIG EQU '*' ;APPLE BELL LOSES 100MS ENDIF ;SO USE '*' INSTEAD ; ;MODEM I/O PORT ADDRESSES ; IF MITSIO MODD EQU 13H ;MODEM DATA PORT MODS EQU 12H ;MODEM STATUS PORT MODRSET EQU 03H ;6850 ACIA RESET MODINIT EQU 11H ;8 DATA, NO PARITY, 2 STOP ENDIF ; IF H84 MODD EQU 330Q ;MODEM DATA PORT MODS EQU 335Q ;MODEM STATUS PORT ENDIF ; IF PMMI MODD EQU 0C1H ;MODEM DATA PORT MODS EQU 0C0H ;MODEM STATUS PORT MODINIT EQU 29H ;INITIALIZE BYTE ORIGINATE, ;7 DATA, EVEN PARITY, 1 STOP ENDIF ; IF DCH MODD EQU 90H ;MODEM DATA PORT MODS EQU 91H ;MODEM STATUS PORT MODINIT EQU 05H ;7 DATA, EVEN PARITY, 1 STOP ENDIF ; IF TRS1 MODD EQU 0EBH ;TRS80 MOD 1 RS232 DATA PORT MODS EQU 0EAH ; AND THE RS232 STATUS PORT ENDIF ; IF TUART MODD EQU 0D6H ;<<--MODIFY FOR YOURS MODS EQU 0D7H ;<<--MODIFY FOR YOURS ENDIF ; IF APPLE ;THESE ARE FOR SUPER SERIAL CARD MODD EQU 0E0A8H ;INSTALLED IN SLOT 2 MODS EQU 0E0A9H ;CHANGE IF NECESSARY ENDIF ; ;MODEM STATUS PORT BIT DEFINITIONS ; IF H84 MTBE EQU 40Q ;MODEM THRE TRANSMIT READY BIT MRDA EQU 01Q ;MODEM RDA REC'D DATA BIT MXOR EQU 41Q ;MASK TO MAKE MTBE AND MRDA 'NEGATIVE LOGIC' ENDIF ; IF PMMI MTBE EQU 01H ;MODEM TRANS. BUFFER READY FLAG MRDA EQU 02H ;MODEM RECEIVE DATA AVAIL. FLAG MXOR EQU 03H ;MASK TO MAKE MTBE AND MRDA "LOW TRUE" ENDIF ; IF DCH OR MITSIO MTBE EQU 02H ;MODEM TRANS. BUFFER READY FLAG MRDA EQU 01H ;MODEM RECEIVE DATA AVAIL. FLAG MXOR EQU 03H ENDIF ; IF TRS1 MTBE EQU 40H ;TRS80 MOD1 RS232 BUFFER READY MRDA EQU 80H ;MODEM RECEIVE DATA AVAIL. MXOR EQU 0C0H ENDIF ; IF TUART ;<<--OR ANY OTHER SERIAL I/O MTBE EQU 1 ;<<--MODIFY FOR YOURS MRDA EQU 2 ;<<--MODIFY FOR YOURS MXOR EQU 3 ;<<--MODIFY FOR YOURS ENDIF ; IF APPLE MTBE EQU 10H ;TRANSMIT BUFFER READY FLAG MRDA EQU 08H ;RECEIVE DATA AVAIL FLAG ENDIF ; ; **MAIN PROGRAM** ; ORG BASE+100H ; LINK: LXI SP,STACK+64 ;CREATE LOCAL STACK LHLD BASE+1 ;POINT TO CP/M JMP TABLE LXI D,3 ;GET READY TO ADD 3 DAD D ;POINT TO CON STATUS JMP SHLD CITCAL+1 ;MODIFY CALL ADRS DAD D ;POINT TO CON IN JMP SHLD RCCAL+1 ;MODIFY CALL ADRS DAD D ;POINT TO CON OUT JMP SHLD WCCAL+1 ;MODIFY CALL ADRS LDA FCB+1 ;SEE IF OPTIONAL TRIGGER CHAR CPI 20H ;BLANK.. ? JZ SKP ;..BLANK SO USE DEFAULT "LF" CPI 'B' ;BELL WANTED JZ TRGBEL CPI 'X' ;XON WANTED JZ TRGXON CPI 'U' ;UPLOADING NO CHECKING FOR TRIGGER JZ TRGUPL ; SETTRG STA OVERLY+1 ;STORE THE CHARACTER AS IS THEN JMP SKP ; TRGBEL MVI A,BELL JMP SETTRG ; TRGXON MVI A,XON JMP SETTRG ; TRGUPL XRA A ;ZERO OUT JUMP STA OVERL1+1 ;CHANGE CHECK FOR C/R TO NULL STA OVERL2+1 ;AND SEND LINEFEEDS AS WELL JMP SKP ; SKP: EQU $ ; IF MITSIO MVI A,MODRSET OUT MODS MVI A,MODINIT OUT MODS ENDIF ; IF H84 MVI A,80H ;SET DLAB BIT IN 8250 UART OUT 0DBH ;8250 AT PORT D8H (330Q) NOP ! NOP ! NOP NOP ! NOP MVI A,01H ;MSB OF BAUD RATE DIVISOR OUT 0D9H ;...TO UART NOP ! NOP ! NOP NOP ! NOP MVI A,80H ;LSB OF BAUD RATE DIVISOR OUT 0D8H ;...TO UART NOP ! NOP ! NOP NOP ! NOP MVI A,03H ;8 BITS, 1 STOP BIT, NO PARITY, DLAB RESET OUT 0DBH ;...TO UART NOP ! NOP ! NOP NOP ! NOP MVI A,0 ;RESET CONTROL REGISTER OUT 0DCH ;...TO UART JMP CONT ENDIF ; IF INITREQ AND (NOT H84) AND (NOT MITSIO) MVI A,MODINIT OUT MODS ;INITIALIZE MODEM PORT ENDIF ; IF INITREQ AND TUART MVI A,80H ;DSR ON BIT 7 PARL PORT B OUT 54H ENDIF ; IF TRSPT ;MUST SET UP SERIAL CHANNEL RESET: LXI H,INITR ;STORE RETURN ADDRESS PUSH H LHLD 1 LXI D,SETSIO ;SIO SETUP ROUTINE DAD D PUSH H ;STORE ON STACK MVI C,00H ;NO PARITY CHAN-A MVI D,0E6H ;8 BITS ,1 STOP MVI E,3 ;300 BAUD MVI L,00H ;DISABLE EXT/ACK SIO FUNCTIONS MVI H,'S'-40H ;CONTROL S (X-ON) RET ;TROUGH SETUP PROG ; INITR NOP ;DO IT TO IT ENDIF ; IF TRS1 ;INIT FOR TRS80 MOD1 RS232 OUT 0E8H ;RESET RS232 IN 0E9H ;READ THE SWITCHES ANI 0F8H ORI 5 OUT 0EAH ;SET DSR AND CTS MVI A,55H ;300 BAUD OUT 0E9H ENDIF ; IF PORT IN MODD ;CLEAR MODEM UART READ BUFFERS IN MODD ENDIF ; IF MULTI ;INITIALIZE 8251 XRA A OUT MODS OUT MODS OUT MODS MVI A,40H OUT MODS MVI A,0CFH ;300 BAUD (THIS DEPENDS ON STRAPPING) OUT MODS MVI A,37H OUT MODS ENDIF ; ; CONT: XRA A ;CLEAR CHAR BUFFERS STA INCH STA OUTCH STA FLAG ;CLEAR TEXT SAVE FLAG LXI H,TBUF ;SET PTR TO TBUF SHLD PTR LXI H,0 ;SIZE = 0 SHLD SIZE LXI H,LINKMS ;PRINT SIGN-ON MESSAGE CALL WCS ; ;MAIN LOOP ; LINK3: CALL CITEST ;JUMP IF NO DATA FROM CONSOLE JZ LINK4 CALL RCC ;ELSE READ CONSOLE DATA CPI 20H CC PCC ;CALL PCC IF CONTROL CHAR JC LINK4 ;JUMP IF PCC HANDLED CHAR ORI 80H ;ELSE SET VALID DATA BIT STA INCH ;AND STORE IN INPUT CHAR BUFFER ; LINK4: LDA OUTCH ;JUMP IF NO DATA FOR CONSOLE ORA A JP LINK5 ANI 7FH ;ELSE DISCARD VALID DATA BIT CALL WCC ;SEND CHAR TO CONSOLE XRA A ;THEN CLEAR OUTPUT CHAR BUFFER STA OUTCH ; LINK5: CALL MITEST ;JUMP IF NO DATA FROM MODEM JZ LINK6 CALL RMC2 ;ELSE READ MODEM DATA CALL SAVE ;SAVE CHAR IN TEXT BUFFER IF FLAG ON ORI 80H ;SET DATA VALID BIT STA OUTCH ;STORE IN OUTPUT CHAR BUFFER ; LINK6: CALL MOTEST ;JUMP IF MODEM XMIT BUFFER BUSY JZ LINK7 LDA INCH ;JUMP IF NO DATA FOR MODEM ORA A JP LINK7 ANI 7FH ;DISCARD VALID DATA BIT ; IF PORT OUT MODD ;OUTPUT CHAR TO MODEM ENDIF ; IF APPLE STA MODD ;OUTPUT CHAR TO MODEM ENDIF ; IF TRSPT PUSH B ;STORE REGISTERS PUSH H PUSH D CALL WMC ;SEND CHAR POP D POP H POP B ENDIF ; XRA A ;...THEN CLEAR INPUT CHAR BUFFER STA INCH ; LINK7: JMP LINK3 ;END OF MAIN LOOP ; LINKMS: DB CR,LF,'PLINK VER 6.7' DB CR,LF,CR,LF DB '[^T]RANSMIT, [^Y]ANK, [^W]RITE, [^E]XIT, [^C]ANCEL' DB CR,LF,'READY',CR,LF,LF,0 ; ;PCC - PROCESS CONTROL CHARACTER ; PCC: CPI 'E'-40H ;JUMP OUT IF CTRL E JNZ PCC1 PUSH H LHLD SIZE ; CHECK FOR SOMETHING IN TEXT BUFFER MOV A,L ; AND GIVE WARNING ORA H JZ PCCEX ; BEFORE EXIT LXI H,AYS ;PRINT 'DO YOU WANT TO SAVE... CALL WCS POP H CALL RCC ;GET ANSWER CALL WCC ;ECHO IT ANI 5FH ;MAKE UPPER CASE CPI 'Y' ;YES? CZ WTB ; WRITE OUT BUFFER JMP PCCEX ;EXIT ; CALL WCCR ;CRLF ; STC ;TELL PLINK TO IGNORE THIS CHARACTER ; IF TRSPT POP PSW ;GOBBLE UP CALL ADDRESS JMP RESET ;RE-INITIALIZE SIO ENDIF ; IF PORT RET ENDIF ; PCC1: CPI 'T'-40H ;JUMP IF NOT CONTROL-T JNZ PCC2 CALL STF ;TRANSMIT TEXT FILE TO MODEM STC ;TELL PLINK TO IGNORE THIS CHARACTER RET ; PCC2: CPI 'Y'-40H ;JUMP IF NOT CONTROL-Y JNZ PCC3 LDA FLAG DCR A ;WAS IT ZERO? JNZ PCC2A ;YES STA FLAG ;NO, WAS 1, NOW 0 LXI H,PCMNIX ;PRINT IGNORE INCOMING STUFF JMP PCC2B ; PCC2A: MVI A,1 ;TURN ON TEXT SAVE FLAG STA FLAG LXI H,PCCMR ;PRINT 'SAVING INCOMING TEXT IN MEMORY' ; PCC2B: CALL WCS STC ;TELL PLINK TO IGNORE THIS CHARACTER RET ; PCC3: CPI 'W'-40H ;JUMP IF NOT CONTROL-W JNZ PCC4 XRA A ;TURN OFF TEXT SAVE FLAG STA FLAG CALL WTB ;WRITE TEXT BUFFER TO DISK STC RET ; PCC4: STC ;LET PLINK HANDLE ALL OTHER CONT. CODES CMC RET ; PCCEX: LXI H,DISMS ;PRINT 'MODEM NOT DISCONNECTED' CALL WCS JMP BASE ;EXIT TO WARM BOOT ; AYS: DB CR,LF,'DO YOU WANT TO SAVE THE STUFF IN' DB CR,LF,'THE BUFFER BEFORE EXIT TO CP/M (Y OR N)? ',0 ; IF PMMI OR DCH DISMS: DB CR,LF,'DON''T FORGET - THE MODEM ' DB 'IS NOT DISCONNECTED',CR,LF DB 'USE "MODEM D" TO DISCONNECT',0 ENDIF ; IF (NOT PMMI) AND (NOT DCH) DISMS: DB CR,LF,'+++ EXIT TO CP/M +++',CR,LF,0 ENDIF ; PCCMR: DB CR,LF,'SAVING INCOMING TEXT IN MEMORY',CR,LF,0 PCMNIX: DB CR,LF,'IGNORING INCOMING TEXT',CR,LF,0 ; ;STF - SEND TEXT FILE (TO MODEM) ; STF: CALL GFN ;GET NAME OF DISK FILE TO SEND JC STF6 ;JUMP IF FILE NAME ERROR CALL OPEN ;TRY TO OPEN SPECIFIED FILE CPI 255 ;JUMP IF FILE NOT FOUND JZ STF7 ; STF1: CALL READ ;READ NEXT RECORD INTO DBUF CPI 1 ;JUMP IF END-OF-FILE JZ STF5 LXI H,DBUF ;POINT TO DISK BUFFER MVI C,128 ; STF2: MOV A,M ;FETCH NEXT CHAR FROM DBUF INX H CPI 'Z'-40H ;JUMP IF END-OF-FILE CHARACTER JZ STF5 ; OVERL2 CPI LF ;IGNORE LINE FEEDS JZ STF4 CALL WMC ;WRITE CHARACTER TO MODEM CALL WCC ;WRITE CHARACTER TO CONSOLE ; OVERL1 CPI CR ;JUMP IF NOT CARRIAGE RETURN JNZ STF4 ; STF3: CALL CITEST ;CHECK CONSOLE DATA READY JZ STF3A ;NO DATA THERE CALL RCC ;GET CONSOLE CHARACTER CPI 'C'-40H ;CONTROL C ABORTS IT JZ STF8 ; STF3A: CALL MITEST ;WAIT FOR NEXT MODEM CHARACTER JZ STF3 CALL RMC2 ;CHECK MODEM FOR TRIGGER CHAR. ; OVERLY CPI TRIGGER JNZ STF3 CALL WCCR ;SEND CRLF TO CONSOLE ; STF4: DCR C ;LOOP THRU REST OF DBUF JNZ STF2 JMP STF1 ;GO GET NEXT RECORD FROM DISK ; STF5: LXI H,STFSM ;PRINT 'FILE SEND COMPLETE' CALL WCS RET ; STF6: LXI H,STFS1 ;PRINT 'FILE NAME ERROR' CALL WCS RET ; STF7: LXI H,STFS2 ;PRINT 'FILE NOT FOUND' CALL WCS RET ; STF8: LXI H,STFSA ;PRINT 'FILE SEND ABORTED' CALL WCS RET ; STFSM: DB 'FILE SEND COMPLETE',CR,LF,0 STFS1: DB 'FILE NAME ERROR OR ABORT',CR,LF,0 STFS2: DB 'FILE NOT FOUND',CR,LF,0 STFSA: DB CR,LF,'FILE SEND ABORTED',CR,LF,0 ; ;SAVE - SAVE CHAR IN TEXT BUFFER IF FLAG ON ; ; ENTRY CONDITIONS ; A - CHARACTER TO SAVE ; SAVE: PUSH PSW LDA FLAG ORA A JNZ SAVE1 POP PSW RET ; SAVE1: POP PSW CPI DEL ;RUBOUT (DEL) ? RZ ;YES, IGNORE IT CPI 20H ;TEST FOR CONTROL CHARACTERS JNC SAVE2 ;JUMP IF NOT CONTROL CHAR. CPI CR ;ALLOW CR TO BE SAVED JZ SAVE2 CPI LF ;ALLOW LF TO BE SAVED JZ SAVE2 CPI TAB ;ALLOW TAB TO BE SAVED JZ SAVE2 RET ;IGNORE ALL OTHER CONTROL CHARS. ; SAVE2: PUSH H LHLD SIZE ;SIZE = SIZE + 1 INX H SHLD SIZE LHLD PTR MOV M,A INX H SHLD PTR PUSH PSW LDA BASE+7 ;GET SYSTEM SIZE SUI 1 ;SO WE DONT CRASH CP/M CMP H ;ARE WE OUT OF ROOM? JZ SAVEAB ;YES, ABORT SUI 4 ;LEAVE SOME ROOM (1K) CMP H MVI A,WRNSIG ;SIGNAL CONSOLE RUNNING OUT OF SPACE CC WCC POP PSW POP H RET ; ;SAVEAB - RAN OUT OF ROOM, ISSUE MESSAGE AND FLOW ; THROUGH TO DISK SAVE ROUTINE ; SAVEND: DB BELL,CR,LF,'ABORTING - NO ROOM LEFT',0 ; SAVEAB: MVI A,XOFF ;TELL REMOTE CALL WMC ;TO STOP SENDING LXI SP,STACK+64 ;REINITIALIZE STACK LXI H,SAVEND ;PRINT 'ABORTING - NO ROOM LEFT' CALL WCS LXI H,LINK ;SET UP RETURN ADDRESS PUSH H ;LEAVE IT ON THE STACK ; ;WTB - WRITE TEXT BUFFER TO DISK ; WTB: LHLD SIZE ;JUMP IF TEXT BUFFER EMPTY MOV A,L ORA H JZ WTB5 CALL GFN ;GET FILE NAME JC WTB6 ;JUMP IF FILE NAME ERROR MVI C,RESDSK ;RESET IN CASE READ-ONLY CALL BDOS ;OR ERROR RECOVERY CALL DELT ;DELETE OLD FILE, IF ANY CALL MAKE ;MAKE NEW FILE LHLD SIZE ;DE = TBUF SIZE XCHG LXI H,DBUF ;TOP OF STACK POINTS TO DBUF PUSH H LXI H,TBUF ;HL POINTS TO TBUF ; WTB1: MVI C,128 ;DISK BUFFER SIZE ; WTB2: MOV A,M ;FETCH NEXT BYTE OF TBUF INX H XTHL MOV M,A ;STORE IN DBUF INX H XTHL DCX D ;SIZE = SIZE - 1 MOV A,D ;EXIT LOOP IF SIZE = 0 ORA E JZ WTB3 DCR C ;LOOP UNTIL DBUF FULL JNZ WTB2 CALL WRITE ;WRITE FULL DBUF TO DISK CPI 00H ;DID WE HAVE AN ERROR? JNZ WRER ;IF SO, BAIL OUT XTHL ;TOP OF STACK POINTS TO DBUF LXI H,DBUF XTHL JMP WTB1 ;LOOP UNTIL END OF TBUF ; WTB3: POP H ;HL POINTS TO CURRENT PLACE IN DBUF ; WTB4: MVI M,'Z'-40H ;STORE EOF CODE INX H DCR C ;LOOP THRU REST OF DBUF JNZ WTB4 CALL WRITE ;WRITE LAST SECTOR TO DISK CPI 00H ;ERROR? JNZ WRER ;IF SO HANDLE IT, ELSE CALL CLOSE ;CLEAN UP ACT AND GO HOME LXI H,TBUF ;CLEAR TEXT BUFFER SHLD PTR LXI H,0 SHLD SIZE LXI H,WTBSM ;PRINT 'BUFFER SAVED ON DISK' CALL WCS RET ; WRER: LXI H,WRERMS CALL WCS ;PRINT ERROR MESSAGE JMP WTB ;AND START OVER ; WTB5: LXI H,WTBS1 ;PRINT 'TEXT BUFFER EMPTY' CALL WCS RET ; WTB6: LXI H,WTBS2 ;PRINT 'FILE NAME ERROR' CALL WCS RET ; WTBSM: DB CR,LF,'BUFFER SAVED ON DISK',CR,LF DB 'MEMORY SAVE CANCELLED',CR,LF,0 WTBS1: DB 'TEXT BUFFER EMPTY',CR,LF,0 WTBS2: DB 'FILE NAME ERROR OR ABORT',CR,LF,0 WRERMS: DB 'ERROR WRITING DATA',CR,LF,'(DISK FULL)',CR,LF DB 'PLEASE CHANGE DISK OR USE ANOTHER DRIVE',CR,LF DB 'AND REENTER:',CR,LF,0 ; ;WCS - WRITE CONSOLE STRING ; ; ENTRY CONDITIONS ; HL - POINTS TO STRING (TERM BY ZERO BYTE) ; WCS: MOV A,M INX H ORA A RZ CALL WCC JMP WCS ; ;WCCR - WRITE CONSOLE CARRIAGE RETURN (AND LINE FEED) ; WCCR: MVI A,CR CALL WCC MVI A,LF ; ;WCC - WRITE CONSOLE CHARACTER ; ; ENTRY CONDITIONS: ; A - CHARACTER TO WRITE ; WCC: PUSH PSW PUSH B PUSH D PUSH H MOV C,A ;GET CHARACTER FOR CBIOS WCCAL: CALL $-$ ;MODIFIED BY INIT. POP H POP D POP B POP PSW RET ; ;RCS - READ CONSOLE STRING (WITH ECHO) ; ; EXIT CONDITIONS ; B - NUMBER OF CHARACTERS READ (<255) ; HL - POINTS TO LAST CHAR STORED (CR) ; RCS: LXI H,IBUF MVI B,0 ; RCS1: CALL RCC ;READ NEXT CHAR FROM CONSOLE CPI DEL ;JUMP IF NOT DEL JNZ RCS2 INR B ;IGNORE DEL IF IBUF ALREADY EMPTY DCR B JZ RCS1 DCX H ;ELSE DISCARD LAST CHAR ; IF NOT APPLE ;FOR APPLE SKIP NEXT AND ;SEND DEL TO CONSOLE MOV A,M ;ECHO DISCARDED CHAR TO CONSOLE ENDIF CALL WCC DCR B ;DECREMENT COUNT JMP RCS1 ; AND LOOP ; RCS2: CPI 'U'-40H ;JUMP IF NOT CONTROL U JNZ RCS3 CALL WCCR ;ELSE ABORT CURRENT LINE JMP RCS ; AND START OVER ; RCS3: CALL WCC ;ECHO CHAR TO CONSOLE MOV M,A ;STORE CHAR IN IBUF INR B ;INCREMENT COUNT CPI CR ;JUMP IF CARRIAGE RETURN JZ RCS4 INX H ;ELSE ADVANCE POINTER JMP RCS1 ; AND LOOP ; RCS4: MVI A,LF ;ISSUE LINE FEED AND RETURN CALL WCC RET ; ;RCC - READ CONSOLE CHARACTER ; ; EXIT CONDITIONS ; A - CHARACTER READ ; RCC: PUSH B PUSH D PUSH H RCCAL: CALL $-$ ;MODIFIED BY INIT. POP H POP D POP B RET ; ;WMC - WRITE MODEM CHARACTER ; ; ENTRY CONDITIONS ; A - CHARACTER TO WRITE ; ; IF PORT WMC: PUSH PSW ; WMCL: IN MODS XRI MXOR ANI MTBE JNZ WMCL POP PSW ANI 7FH ;STRIP PARITY BIT OUT MODD RET ENDIF ; IF TRSPT WMC: PUSH H PUSH D PUSH PSW ; WMCL: CALL MOTEST ;TEST STATUS JZ WMCL ;LOOP TILL TX EMPTY POP PSW ;RESTORE CHAR ANI 7FH ;STRIP PARITY PUSH B ;STORE B MOV C,A ;PUT CHAR INTO C MVI B,00H ;CHANNEL A LXI H,WMCRE ;STORE RETURN ADDRESS PUSH H LHLD BASE+1 ;GET BASE ADDRESS LXI D,SIOOUT DAD D PCHL ;JUMP TO IT ; WMCRE: POP B ;RESTORE IT POP D POP H RET ENDIF ; IF APPLE WMC PUSH PSW WMCL LDA MODS ANI MTBE JZ WMCL POP PSW ANI 07FH STA MODD RET ENDIF ; ;RMC - READ MODEM CHARACTER ; ; EXIT CONDITIONS: ; A - CHARACTER READ ; ; IF PORT RMC: IN MODS XRI MXOR ANI MRDA JNZ RMC ; RMC2: IN MODD ANI 7FH RET ENDIF ; IF TRSPT RMC: CALL MITEST ;CHAR AVAILABLE JZ RMC ;LOOP IF NOT READY ; RMC2: PUSH B ;STORE B PUSH D PUSH H MVI B,00H ;CHANNEL A LXI H,RMCRE ;RETURN ADDRESS PUSH H LHLD 1 LXI D,SIOINP DAD D PCHL ; RMCRE: POP H POP D POP B ANI 7FH ;STRIP PARITY RET ENDIF ; IF APPLE RMC: LDA MODS ANI MRDA JZ RMC RMC2: LDA MODD ANI 07FH RET ENDIF ; ;GFN - GET FILE NAME ; GFN: LXI H,GFNSD ;PRINT 'WHICH DRIVE?' CALL WCS CALL RCC ;GET ANSWER FROM CONSOLE CALL WCC ;ECHO IT TO CONSOLE ANI 5FH ;MAKE UPPER CASE CPI 'C'-40H ;^C MEANS ABORT JZ GFN6 SUI 'A'-1 JC GFN ;REQUIRE ALPHABETIC JZ GFN CPI 17 ;ALLOW 16 DRIVES (AS IN CP/M 2.X) JNC GFN STA FCB ; GFNB: LXI H,GFNS1 ;PRINT 'FILENAME? ' CALL WCS CALL RCS ;READ RESPONSE INTO IBUF LXI H,FCB+FN ;BLANK FILL FN AND FT FIELDS MVI C,11 ; GFN1: MVI M,' ' INX H DCR C JNZ GFN1 LXI H,IBUF ;POINT TO INPUT BUFFER LXI D,FCB+FN ;SCAN OFF FN FIELD MVI C,9 ; GFN2: MOV A,M ;FETCH NEXT CHAR FROM IBUF INX H CPI 61H ;IF LC, CONVERT TO UC JC GFN2A SUI 20H ; GFN2A: CPI CR ;JUMP IF END OF LINE JZ GFN5 CPI '.' ;JUMP IF END OF NAME JZ GFN3 STAX D ;ELSE STORE CHAR IN FN FIELD INX D DCR C ;LOOP IF 8 OR LESS CHARS SO FAR JNZ GFN2 JMP GFN6 ;ELSE TAKE ERROR EXIT ; GFN3: LXI D,FCB+FT ;SCAN OFF FT FIELD MVI C,4 ; GFN4: MOV A,M ;FETCH NEXT CHAR FROM IBUF INX H CPI 61H ;IF LC, CONVERT TO UC JC GFN4A SUI 20H ; GFN4A: CPI CR ;JUMP IF END OF LINE JZ GFN5 STAX D ;ELSE STORE CHAR IN FT FIELD INX D DCR C ;LOOP IF 3 OR LESS CHARS SO FAR JNZ GFN4 JMP GFN6 ;ELSE TAKE ERROR EXIT ; GFN5: XRA A STA FCB+EX ;SET EXTENT NUMBER TO ZERO STA FCB+NR ;SET RECORD NUMBER TO ZERO STC ;CLEAR ERROR FLAG AND RETURN CMC RET ; GFN6: STC ;SET ERROR FLAG AND RETURN RET ; GFNSD: DB CR,LF,'WHICH DRIVE? ',0 GFNS1: DB CR,LF,'FILENAME? ',0 ; ;OPEN - OPEN DISK FILE ; OPEN: PUSH H PUSH D PUSH B LXI D,FCB MVI C,OFFC CALL BDOS POP B POP D POP H RET ; ;READ - READ RECORD FROM DISK FILE ; READ: PUSH H PUSH D PUSH B LXI D,FCB MVI C,RRFC CALL BDOS POP B POP D POP H RET ; ;CLOSE - CLOSE DISK FILE ; CLOSE: PUSH H PUSH D PUSH B LXI D,FCB MVI C,CFFC CALL BDOS POP B POP D POP H RET ; ;DELT - DELETE DISK FILE ; DELT: PUSH H PUSH D PUSH B LXI D,FCB MVI C,DFFC CALL BDOS POP B POP D POP H RET ; ;WRITE - WRITE RECORD TO DISK ; WRITE: PUSH H PUSH D PUSH B LXI D,FCB MVI C,WRFC CALL BDOS POP B POP D POP H RET ; ;MAKE - MAKE NEW DISK FILE ; MAKE: PUSH H PUSH D PUSH B LXI D,FCB MVI C,MFFC CALL BDOS POP B POP D POP H RET ; ;CITEST - CHECK CONSOLE INPUT STATUS ; CITEST: PUSH B PUSH D PUSH H CITCAL: CALL $-$ ;MODIFIED BY INIT. ORA A ;SET ZERO FLAG POP H POP D POP B RET ;ZERO FLAG CARRIES ANSWER ; ;MITEST - CHECK MODEM INPUT STATUS ; IF PORT MITEST: IN MODS ;GET MODEM UART STATUS XRI MXOR ;INVERT HIGH-TRUE BITS ANI MRDA ;ANY DATA AVAILABLE? MVI A,0 JNZ MITST1 CMA ; MITST1: ORA A RET ;ZERO FLAG CARRIES ANSWER ENDIF ; IF TRSPT ; MITEST: PUSH B PUSH H PUSH D MVI B,00 ;CHANNEL A LXI H,MITSTR PUSH H LHLD BASE+1 LXI D,SIOTST DAD D PCHL ; MITSTR: POP D POP H ANI 01 ;TX EMPTY POP B RET ;ZERO FLAG HOLDS THE ANSWER ENDIF ; IF APPLE MITEST LDA MODS ANI MRDA RET ENDIF ; ;MOTEST - CHECK MODEM OUTPUT STATUS ; IF PORT MOTEST: IN MODS ;GET MODEM UART STATUS XRI MXOR ;INVERT HIGH-TRUE BITS ANI MTBE ;UART READY FOR CHARACTER? MVI A,0 JNZ MOTST1 ;ZERO FLAG CARRIES ANSWER CMA ; MOTST1: ORA A ;SET ZERO FLAG IF READY RET ENDIF ; IF TRSPT MOTEST: PUSH B PUSH H PUSH D MVI B,00 ;CHANNEL A LXI H,MOTSTR PUSH H LHLD 1 LXI D,SIOTST DAD D PCHL ; MOTSTR: ANI 02 ;BUFFER EMPTY POP D POP H POP B RET ENDIF ; IF APPLE MOTEST LDA MODS ANI MTBE RET ENDIF ; IF MNET LDA OVERL1+1 CPI 00H ;IF NOT UPLOAD THEN SKIP IT RNZ ;THIS ROUTINE ALLOWS CKXOFF: PUSH H ;MICRONET X-OFF/XON LXI H,2751 ;TO WORK CORRECTLY MS8: DCX H ;33 MSEC DELAY MOV A,L ORA H JNZ MS8 POP H CALL MITEST RZ CALL RMC2 CPI XOFF ;IF NOT X-OFF RNZ ;THEN CONTINUE WAITON: CALL MITEST ;ELSE WAIT FOR X-ON JZ WAITON CALL RMC2 ;GOT SOMETHING CPI XON ;IS IT X-ON? RZ ;IF SO, WE'RE THROUGH WAITING CPI 01H ;CTL-A SAME AS X-ON RZ CALL WCC ;IF IT WAS NOT AN X-ON JP WAITON ;THEN WRITE TO CONSOLE ENDIF ;AND WAIT SOME MORE ; ; ;DATA AREA ; INCH: DS 1 ;INPUT CHAR BUFFER (TO CYBER) OUTCH: DS 1 ;OUTPUT CHAR BUFFER (FROM CIBER) STACK: DS 80 ;LOCAL STACK IBUF: DS 256 ;INPUT BUFFER ; ;TEXT BUFFER ; FLAG: DS 1 ;TEXT SAVE FLAG PTR: DS 2 ;TEXT BUFFER POINTER SIZE: DS 2 ;TEXT BUFFER SIZE TBUF: EQU $ ;START OF TEXT BUFFER ; END