home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
packet
/
packet89.lbr
/
KERNEL.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-02-21
|
30KB
|
993 lines
; PACKET89.ASM
; Derived 12/15/89 from the MODEM Controller, MPLINK
; (H19/H89 version of 7/1/81)
;
;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
;
; WITH HEATH EQUATES ADDED BY TOM JORGENSON.
; Optional Triger characters by Steve Vinokuroff.
;
; Revised by Ray Isenson, N6UE┼to∩ interface pacet⌠ NCN├ and
; give control of the Lineprinter to the BDOS (12/89)
;
;This version is modified to use the H19/H89 special function keys.
;It will run on a non-Heath CPU using the H19 terminal; however, if
;such a system is used, the following equate should be set to zero:
;
H8ORH89 EQU 1 ;IF H8 OR H89 COMPUTER SET TO 1
;
;
;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: *
; * *
; * F1 KEY SAVE INCOMING ASCII IN RAM BUFFER *
; * FOR LATER TRANSFER TO DISK *
; * F2 KEY WRITE RAM BUFFER TO DISK - ASKS *
; * FOR DRIVE AND FILENAME.TYP *
; * F3 KEY TRANSMIT ASCII FILE TO MODEM. *
; * ASKS FOR DRIVE AND FILENAME.TYP *
; * F4 KEY AUTO LOGON *
; * F5 KEY COPY TO PRINTER SWITCH *
; * RED KEY EXIT PLINK TO CP/M WARM BOOT *
; * CONTROL-C ABORT FILE SEND TO MODEM *
; * DELETE BACKSPACE WHEN IN COMMAND MODE *
; * ASKING FOR FILENAME *
; * BACKSPACE SAME AS DELETE *
; * CONTROL-U ABORT CURRENT LINE WHEN IN COMMAND *
; * MODE ASKING FOR FILENAME *
; * *
; ****************************************************
;
;
;SET NUMBER OF DRIVES FOR PARTICULAR SYSTEM
; E.G. 2 = A,B 5 = A,B,C,D,E
;
NUMDRV EQU 5 ;ALLOW A: AND B: ONLY
;
;
;BDOS ENTRY POINT AND FUNCTION CODES
;
BASE SET 0 ;STANDARD CPM
;
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
LSTOUT EQU 5 ;PRINTER OUTPUT
;
;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
ESC EQU 1BH ;ESCAPE
BL EQU 20H ;BLANK (SPACE)
;
;
;SPECIAL HEATH ONLY BIOS EQUATES
;
TICCNT EQU 0BH ;2 MSEC COUNTER
;
;
;THE FOLLOWING "TRIGER" EQUATE IS SET TO "LF" (LINEFEED)
;BY DEFAULT. AN OPTIONAL TRIGER CHAR MAY BE PASSED VIA FCB1
;
; IE: KERNEL 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
;
MODD EQU 330Q ;MODEM BASE PORT
MODS EQU MODD+5 ;MODEM STATUS PORT
;
;
;MODEM STATUS PORT BIT DEFINITIONS
;
MTBE EQU 20H ;TRANSMITTER READY FLAG
MRDA EQU 1H ;RECEIVER READY FLAG
MXOR EQU 21H ;TO COMPLEMENT MTBE AND MRDA
;
; **MAIN PROGRAM**
;
ORG BASE+100H
;
;
LINK: CALL INIT ;INITIALIZE
;
; MAIN LOOP
;
LINK3: CALL CITEST ;JUMP IF NO DATA FROM CONSOLE
JZ LINK4
CALL RCC ;ELSE READ CONSOLE DATA
CPI ESC
CZ PCC ;CALL PCC IF ESC (FUNCTION KEY)
JZ 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
OUT MODD ;OUTPUT CHAR TO MODEM
XRA A ;...THEN CLEAR INPUT CHAR BUFFER
STA INCH
LINK7: JMP LINK3 ;END OF MAIN LOOP
;
; PCC - PROCESS CONTROL CHARACTER
;
;BECAUSE THIS SECTION USES THE HEATH HARDWARE CLOCK, THE PROGRAM
;WILL NOT RUN ON OTHER CP/M 2.X SYSTEMS UNLESS A SOFTWARE TIMING
;LOOP IS SUBSTITUTED FOR THE NEXT 8 STATEMENTS. THOSE 8 STATEMENTS
;ARE NOT NECESSARY UNLESS ONE WISHES TO SEND 'ESC' CHARACTERS
;FROM THE CONSOLE TO THE MODEM. WITHOUT THESE TIMING STATEMENTS
;'ESC' MUST BE HIT TWICE TO BE TRANSMITTED ONCE.
;
PCC: EQU $
IF H8ORH89
LDA TICCNT ;CHECK FOR SPECIAL FUNCTION KEY
ADI 10 ;WAIT 20 MSEC FOR NEXT CHAR
MOV C,A
ESCTIM: LDA TICCNT
CMP C
JZ PCC6 ;IF TOO LONG, NOT SPEC FUCNTION KEY
CALL CITEST
JZ ESCTIM ;LOOP UNTIL CONSOLE INPUT
ENDIF
CALL RCC ;ESC RECEIVED, GET NEXT CHAR FOR FUNCTION
CPI 'Q' ;'RED' KEY MEANS EXIT TO CP/M
JNZ PCC1
PUSH H
LHLD SIZE
MOV A,H
ORA L
LXI H,TBNE
CNZ WCS ;PRINT 'TEXT BUFFER NOT EMPTY'
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
XRA A ;TELL LINK TO IGNORE THIS CHARACTER
RET
;
PCC1: CPI 'U' ;'F3' KEY FOR TRANSMIT FILE
JNZ PCC2
CALL STF ;TRANSMIT TEXT FILE TO MODEM
XRA A ;TELL LINK TO IGNORE THIS CHARACTER
RET
;
PCC2: CPI 'S' ;'F1' KEY MEANS SAVE ALL IN RAM
JNZ PCC3
MVI A,1 ;TURN ON TEXT SAVE FLAG
STA FLAG
LXI H,PCCMR ;PRINT 'SAVING INCOMING TEXT IN MEMORY'
CALL WCS
XRA A ;TELL LINK TO IGNORE THIS CHARACTER
RET
;
PCC3: CPI 'T' ;'F2' KEY MEANS SAVE RAM TEXT TO FILE
JNZ PCC4
XRA A ;TURN OFF TEXT SAVE FLAG
STA FLAG
CALL WTB ;WRITE TEXT BUFFER TO DISK
XRA A
RET
;
PCC4: CPI 'V' ;'F4' KEY MEANS AUTO LOGON
JNZ PCC5
LXI H,ALMSG
CALL WCS ;PRINT 'AUTO LOGON'
LXI H,ALBUF
AUTOL: MOV A,M
INX H
CPI 'Z'-40H ;AUTOLOG DONE ON ^Z
JZ ALBRK
ANA A ;ZERO MEANS EOS
JZ STRFIN
CALL WMC
CALL RMWC ;READ MODEM, WCC IF AVAILABLE
JMP AUTOL
;
STRFIN: CALL CITEST ;INPUT FROM CONSOLE
JNZ ALBRK ;ABORT IF SO
CALL MITEST
JZ STRFIN ;WAIT FOR CHAR FROM MODEM
CALL RMC2
CALL WCC
CPI ':' ;NEXT STRING IF MODEM SENDS ':'
JZ AUTOL
CPI '+'
JZ AUTOL
JMP STRFIN ;KEEP WAITING FOR ':' OR '+'
;
RMWC: CALL MITEST ;READ MODEM & WRITE CONSOLE IF CHAR
RZ
CALL RMC2
JMP WCC
;
ALBRK: XRA A
RET
;
ALBUF: DB 'A',0
DB 'CIS02',CR,0
DB CR,0
DB 0
DB '70000,0000',CR,0
DB 'PASSWORD',CR,0
DB 'Z'-40H
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;
PCC5: CPI 'W' ;'F5' KEY MEANS COPY TO PRINTER
JNZ PCC6
LXI H,PRTFLG
MOV A,M
CMA
MOV M,A ;COMPLEMENT PRINT FLAG
ANA A
LXI H,PRTOFF ;PRINT 'OFF'
JZ PRTLAB
LXI H,PRTON ;PRINT 'ON'
PRTLAB: CALL WCSNP
XRA A
RET
;
PCC6: ANA A ;LET LINK HANDLE ALL OTHER CONT. CODES
RET
;
PCCEX: LXI H,DISMS ;PRINT 'EXIT TO CP/M'
CALL WCS
JMP BASE ;EXIT TO WARM BOOT
;
TBNE: DB CR,LF,BELL,'CAUTION: TEXT BUFFER NOT EMPTY',0
AYS: DB CR,LF,'EXIT TO CP/M - ARE YOU SURE (Y OR N)?',0
DISMS: DB CR,LF,'+++ EXIT TO CP/M +++',CR,LF
DB ESC,'j',ESC,'Y',BL+24,BL,ESC,'l',ESC,'k',0
ALMSG: DB CR,LF,'AUTOMATIC LOGON',CR,LF,0
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: CALL CCTEST ;CHECK FOR ^C FROM CONSOLE
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 CCTEST ;CHECK FOR ^C ABORT
CALL MITEST ;WAIT FOR NEXT MODEM CHARACTER
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
;
CCTEST: CALL CITEST ;CHAR FROM CONSOLE?
RZ ;IF NO
CALL RCC
CPI 'C'-40H
RNZ ;IGNORE IF NOT ^C
POP PSW ;CLEAR *RET* FROM STACK
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
LHLD BREM
DCX H
SHLD BREM
MVI A,0FFH
CMP H
JZ SAVEAB ;ABORT IF TBUF FILLED
MVI A,3
CMP H
MVI A,WRNSIG ;SIGNAL CONSOLE RUNNING OUT OF SPACE
CNC WCC
PUSH H ;HL = BYTES LEFT IN BUFFER
LXI H,BRPOS ;POSITION ON 25TH LINE
CALL WCSNP ;CONSOLE WRITE WITHOUT PRINTER
POP H
CALL DECOUT ;OUTPUT HL AS DECIMAL
LXI H,RESCP
CALL WCSNP ;RESTORE CURSOR POSITION
POP PSW
POP H
RET
;
BRPOS: DB ESC,'j',ESC,'Y',BL+24,BL+75,ESC,'p',0
PRTON: DB ESC,'j',ESC,'Y',BL+24,BL+38,ESC,'pon',ESC,'q ',ESC,'k',0
PRTOFF: DB ESC,'j',ESC,'Y',BL+24,BL+38,ESC,'poff'
RESCP: DB ESC,'q',ESC,'k',0
;
; 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
JNZ NOWRT ;IF WRITE NOT SUCCESSFUL
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
JNZ NOWRT1 ;IF WRITE NOT SUCCESSFUL
CALL CLOSE ;CLEAN UP ACT AND GO HOME
LXI H,TBUF ;CLEAR TEXT BUFFER
SHLD PTR
LXI H,0
SHLD SIZE
LXI H,BRPOS ;SET CURSOR TO WRITE BYTES REMAINING
CALL WCSNP
LHLD BLEN
SHLD BREM ;REMAINING BUFFER IF BUFFER LENGTH
CALL DECOUT
LXI H,RESCP ;RESTORE CURSOR POSITION
CALL WCSNP
LXI H,WTBSM ;PRINT 'BUFFER SAVED ON DISK'
CALL WCS
RET
;
NOWRT: POP H ;WRITE FAILS, CLEAR STACK
NOWRT1: LXI H,NWMSG
CALL WCS ;TELL USER TO TRY AGAIN
JMP WTB
;
WTB5: LXI H,WTBS1 ;PRINT 'TEXT BUFFER EMPTY'
CALL WCS
RET
;
WTB6: LXI H,WTBS2 ;PRINT 'FILE NAME ERROR'
CALL WCS
RET
;
NWMSG: DB CR,LF,BELL,'DISK OVERFLOW - DO AGAIN',CR,LF,0
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
;
; WCSNP - WRITE CONSOLE STRING WITHOUT PRINTER OUTPUT
;
;
; ENTRY CONDITIONS
; HL - POINTS TO STRING (TERM BY ZERO BYTE)
;
WCSNP: MOV A,M
INX H
ORA A
RZ
CALL WCCNP
JMP WCSNP
;
; 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
PUSH B
WCCAL: CALL $-$ ;MODIFIED BY INIT.
POP B ;C = CHAR
LDA PRTFLG
ANA A
CNZ PRTOUT ;IF SIMULTANEOUS LISTING WANTED
POP H
POP D
POP B
POP PSW
RET
;
;SEND CHARACTER TO PRINTER
; VALUE IN (C)
;
;
PRTOUT: MOV A,C ;MOVE CHARACTER TO A
ANI 7FH ;STRIP 8TH BIT FROM CHARACTER
MVI C,LSTOUT;GET LIST OUTPUT FUNCTION
MOV E,A ;PUT CHARACTER IN E
CALL BDOS ;PRINT THE CHARACTER
RET
; WCCNP - WRITE CONSOLE CHARACTER WITHOUT PRINTER OUTPUT
;
; ENTRY CONDITIONS:
; A - CHARACTER TO WRITE
;
WCCNP: PUSH PSW
PUSH B
PUSH D
PUSH H
MOV C,A ;GET CHARACTER FOR CBIOS
WCCAL1: 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 INIT.
POP H
POP D
POP B
RET
;
; WMC - WRITE MODEM CHARACTER
;
; ENTRY CONDITIONS
; A - CHARACTER TO WRITE
;
;
WMC: PUSH PSW
WMCL: IN MODS
XRI MXOR
ANI MTBE
JNZ WMCL
POP PSW
ANI 7FH ;STRIP PARITY BIT
OUT MODD
RET
;
WMS: MOV A,M ;WRITE STRING TO MODEM
INX H
ORA A
RZ
CALL WMC
JMP WMS
;
; RMC - READ MODEM CHARACTER
;
; EXIT CONDITIONS:
; A - CHARACTER READ
;
;
RMC: IN MODS
XRI MXOR
ANI MRDA
JNZ RMC
RMC2: IN MODD
ANI 7FH
RET
;
;
; 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 NUMDRV+1
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,BL
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
ANA A ;SET 'Z' FLAG FOR ERROR
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
;
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
;
;
; MOTEST - CHECK MODEM OUTPUT STATUS
;
;
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
;
;DECIMAL PRINT SUBROUTINE
;PRINTS H,L AS A DECIMAL NO.
;
DECOUT LXI D,-10000
CALL PRTDGT ;PRINT 10'S OF THOUSANDS
LXI D,-1000
CALL PRTDGT ;PRINT THOUSANDS
LXI D,-100
CALL PRTDGT ;PRINT HUNDREDS
LXI D,-10
CALL PRTDGT ;PRINT TENS
LXI D,-1
PRTDGT MVI C,'0'-1 ;INITIALIZE COUNT
PUSH H ;SO INITIAL INX SP'S WON'T HURT
PRT1 INR C ;BUMP COUNT OF SUCCESSFUL SUBTR.
INX SP ;"POP" STACK W/O ALTERING REGISTERS
INX SP
PUSH H ;SAVE H,L
DAD D ;DO 1 SUBTRACTION
JC PRT1 ;IF RESULT STILL POS., DO IT AGAIN
POP H ;RESTORE LAST GOOD VALUE TO H,L
MOV A,C
JMP WCCNP ;PRINT CHAR & RET
;
; DATA AREA
;
BLEN: DS 2 ;BUFFER LENGTH
BREM: DS 2 ;BYTES TBUF REMAINING
PRTFLG: DB 0 ;PRINTER OFF IF ZERO
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
;
;INITIAL CODE IS PLACED HERE TO SAVE SPACE (BUFFER OVERWRITES IT)
;
INIT: POP H ;SAVE RETURN ADDRESS
LXI SP,STACK+64 ;CREATE LOCAL STACK
PUSH H ;RESTORE RETURN ADDRES TO 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
SHLD WCCAL1+1
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
;
SKP EQU $
;
;
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
LHLD BASE+6
MVI L,0
DCR H ;HL = MAX TBUF TOP
LXI D,-TBUF
DAD D ;HL = MAX TBUF LEN
SHLD BLEN
SHLD BREM ;BUFFER BYTES REMAINING
LXI H,LINKMS ;PRINT SIGN-ON MESSAGE
CALL WCSNP
LHLD BLEN ;PRINT BUFFER ON 25TH LINE
CALL DECOUT
LXI H,RESCP
CALL WCSNP
RET ;RETURN TO MAIN LOOP
;
LINKMS: DB ESC,'E',ESC,'Y',BL+5,BL+22
DB 'H/Z-89 TNC CONTROLLER - RSI - DEC 89'
DB CR,LF,LF,LF
DB ESC,'x1',ESC,'j',ESC,'Y',BL+24,BL+5
DB ESC,'pSave',ESC,'q '
DB ESC,'pFile',ESC,'q '
DB ESC,'pSend',ESC,'q '
DB ESC,'pN/A',ESC,'q '
DB ESC,'pPrint off',ESC,'q'
DB ESC,'Y',BL+24,BL+53,ESC,'pExit',ESC,'q '
DB ESC,'pBuffer = ',0
;
END LINK0
W
PUSH B
PUSH D
PUSH H
MOV C,A ;GET CHARACTER FOR CBIOS