; PLINK.ASM
; (latest version OCT 18 1980)
;
; PLINK - SUPPORT COMMUNICATIONS LINK WITH CYBER
;
;PLINK IS A CP/M TRANSIENT COMMAND WHICH ALLOWS THE USER TO
;ESTABLISH A COMMUNICATIONS LINK WITH A REMOTE COMPUTER
;
; ORIGINAL BY L.E. HUGHES EDCAM JULY, 1977
;
; This version by Keith Petersen, W8SDZ.
; WITH HEATH EQUATES ADDED BY TOM JORGENSON
;
; TRS-80 MODEL 1 mods by Steve Vinokuroff, Vanc CBBS
; Optional Triger characters by Steve Vinokuroff
; TRS-80 mods by Dennis Breckenridge, Burnaby CBBS
; D.C.Hayes mods by Bruce Ratoff, Iselin NJ Remote CP/M
;
;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 WITH 8251 UART AT PORT 330Q
; 6. D.C.Hayes 80-103A or Micromodem 100
;
;
;-->NOTE: IF ASSEMBLED AS WRITTEN WILL WORK WITH D.C.Hayes 80-103A
; OR MICROMODEM 100 AT PORT 90H
;
;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:
;
; ****************************************************
; * COMMANDS: *
; * *
; * CONTROL E EXIT PLINK TO CP/M WARM BOOT *
; * CONTROL T TRANSMIT ASCII FILE TO MODEM. *
; * ASKS FOR DRIVE AND FILENAME.TYP *
; * CONTROL C ABORT FILE SEND TO MODEM *
; * CONTROL Y SAVE INCOMING ASCII IN RAM BUFFER *
; * FOR LATER TRANSFER TO DISK *
; * CONTROL Q WRITE RAM BUFFER TO DISK - ASKS *
; * FOR DRIVE AND FILENAME.TYP *
; * DELETE BACKSPACE WHEN IN COMMAND MODE *
; * ASKING FOR FILENAME *
; * CONTROL U ABORT CURRENT LINE WHEN IN COMMAND *
; * MODE ASKING FOR FILENAME *
; * *
; * (NOTE: ALL OTHER CONTROL CODES ARE PASSED TO *
; * MODEM OUTPUT) *
; ****************************************************
;
;
;CONDITIONAL ASSEMBLY SWITCHES <<-- SET FOR YOUR SYSTEM
;
TUART SET 0 ;CROMEMCO TUART I/O BOARD
PMMI EQU 0 ;PUT A 1 HERE IF YOU HAVE A PMMI
DCH EQU 1 ;PUT A 1 HERE IF YOU HAVE A D.C.HAYES
TRS1 EQU 0 ;PUT A 1 HERE IF YOU HAVE TRS80-MOD1
TRSPT EQU 0 ;PUT 1 HERE IF YOU HAVE TRS80-MOD2
;USING PICKLES & TROUT CP/M 2.X
H84 EQU 0 ;PUT 1 HERE IF YOU HAVE H8/H8-4
IF H84
TUART SET 1
ENDIF
;
INIT$REQUIRED EQU 1 ;PUT 1 HERE IF INITIALIZATION NEEDED
;
IF TRS1 OR PMMI OR TUART OR DCH
PORT EQU 1
ENDIF
;
IF TRSPT
PORT EQU 0 ;STILL NEED THE SWITCH
ENDIF
;
;
;
;BDOS ENTRY POINT AND FUNCTION CODES
;
IF NOT TRS1
BASE SET 0 ;STANDARD CPM
ENDIF
;
IF TRS1 OR H84
BASE SET 4200H ;TRS-80 MODEL 1 CP/M BASE ADDRESS
ENDIF
;
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
;
;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
DEL EQU 7FH ;DELETE (RUBOUT)
BELL EQU 07H ;BELL SIGNAL
TAB EQU 09H ;HORIZONTAL TAB
XON EQU 11H ;X-ON CHARACTER
NULL EQU 00H ;NULL CHAR
;
;THE FOLLOWING "TRIGER" EQUATE IS SET TO "LF" (LINEFEED)
;BY DEFAULT. AN OPTIONAL TRIGER CHAR MAY BE PASSED VIA FCB1
;
; IE: PLINK B WILL SET TRIGER TO "BELL"
;
;THE FOLLOWING OPTIONS ARE ALLOWED
;
; 1. B = BELL 07H
; 2. X = XON 11H
; 3. U = UPLOAD NO TRIGER CHECK AT ALL
;ANY OTHER ASCII CHARACTER MAY BE PASSED THROUGH FCB1
;
;
TRIGER EQU LF ;DEFAULT VALUE
;
;
;WARNING CHARACTER FOR LOW MEMORY
;
WRNSIG EQU BELL ;IF YOU HAVE ONE, PUT 'BELL' HERE
;...ELSE PUT '*' HERE.
;
;MODEM I/O PORT ADDRESSES
;
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 0D8H ;<<--MODIFY FOR YOURS
MODS EQU 0DDH ;<<--MODIFY FOR YOURS
ENDIF
;
;MODEM STATUS PORT BIT DEFINITIONS
;
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
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 20H ;<<--MODIFY FOR YOURS
MRDA EQU 1H ;<<--MODIFY FOR YOURS
MXOR EQU 21H ;<<--MODIFY FOR YOURS
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 TRIGER 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 TRIGER
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 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 INIT$REQUIRED AND NOT H84 OR PMMI AND NOT H84
MVI A,MODINIT
OUT MODS ;INITIALIZE MODEM PORT
ENDIF
;
IF 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
;
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 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 as of 25-SEP-80'
DB CR,LF,LF,'READY',CR,LF,LF,0
;
; PCC - PROCESS CONTROL CHARACTER
;
PCC: CPI 'E'-40H ;JUMP OUT IF CTRL E
JNZ PCC1
PUSH H
LXI H,AYS ;PRINT 'ARE YOU SURE'
CALL WCS
POP H
CALL RCC ;GET ANSWER
CALL WCC ;ECHO IT
ANI 5FH ;MAKE UPPER CASE
CPI 'Y' ;YES?
JZ PCCEX ;EXIT
CALL WCCR ;CRLF
STC ;TELL LINK 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 LINK TO IGNORE THIS CHARACTER
RET
;
PCC2: CPI 'Y'-40H ;JUMP IF NOT CONTROL-Y
JNZ PCC3
MVI A,1 ;TURN ON TEXT SAVE FLAG
STA FLAG
LXI H,PCCMR ;PRINT 'SAVING INCOMING TEXT IN MEMORY'
CALL WCS
STC ;TELL LINK TO IGNORE THIS CHARACTER
RET
;
PCC3: CPI 'Q'-40H ;JUMP IF NOT CONTROL-Q
JNZ PCC4
XRA A ;TURN OFF TEXT SAVE FLAG
STA FLAG
CALL WTB ;WRITE TEXT BUFFER TO DISK
STC
RET
;
PCC4: STC ;LET LINK 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,'EXIT TO CP/M - ARE YOU SURE (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
;
; 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 KHARACTER
JZ STF3
CALL RMC2 ;CHECK MODEM FOR TRIGGER CHAR.
OVERLY CPI TRIGER
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',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: 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
MVI C,RESDSK ;RESET IN CASE READ-ONLY
CALL BDOS
CALL GFN ;GET FILE NAME
JC WTB6 ;JUMP IF FILE NAME ERROR
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
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
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
;
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',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
MOV A,M ;ECHO DISCARDED CHAR TO CONSOLE
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 INI\.
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 1 ;GET BASE ADDRESS
LXI D,SIOOUT
DAD D
PCHL ;JUMP TO IT
WMCRE: POP B ;RESTORE IT
POP D
POP H
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
;
;
; 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
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 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
;
; 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
;
; 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 LINK
;