home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
KERMIT
/
CP411SRC.ARK
/
cpxcif.asm
< prev
next >
Wrap
Assembly Source File
|
1991-04-23
|
25KB
|
747 lines
IF NOT lasm
.printx * CPXCIF.ASM *
ENDIF ;NOT lasm
; KERMIT - (Celtic for "FREE")
;
; This is the CP/M-80 implementation of the Columbia University
; KERMIT file transfer protocol.
;
; Version 4.0
;
; Copyright June 1981,1982,1983,1984,1985
; Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others.
;
; This file contains the system dependent part for Cifer systems, and
; is based on code contributed by John Shearwood of Birmingham
; University. This file was originally CPXTOR.ASM but now an
; FAMILY file on its own.
;
; This file has code that supports Cifer 1886/2886 systems, running
; either CP/M Version 2.2 or 3.0, and driving the VL or AUX port.
; xxx is a three letter abbrev. for the system you are adding.
;
; revision history:
;
; edit 2, 21 July, 1987 by OBSchou to bring it into line for use with
; CPXCOM.ASM.
;
; edit 1, 14 July by OBSchou for John Shearwood of Birmingham University, UK.
; His edits ar based on the former CPXTOR.ASM family file.
;
; edit 4, Apr 7 1987, JA Shearwood. Add support for Cifer Aux port.
; edit 2, Mar 17 1987, JA Shearwood Add support for Cifer CP/M Plus
;
; Keep module name, edit number, and last revision date in memory.
family: db 'CPXCIF.ASM (2) 14-Jul-87 $'
;
; Assembly time message to let me know I'm building the right version.
; LASM generates an 'S' error along with the message, which is messy, but
; better than trying to put everything inside a IF m80 OR mac80 conditional,
; because LASM doesn't like nested IF's, either.
IF cifer
.printx * Assembling Kermit-80 for Cifer 1886 *
ENDIF
IF cifer3
.printx * with CP/M Plus
ENDIF
IF cifaux
.printx * with AUX port
ENDIF
;
;=========================================================================
; I/O Byte assignments (2-bit fields for 4 devices at loc 3)
;
;bits 6+7 LIST field
; 0 LIST is Teletype device (TTY:)
; 1 LIST is CRT device (CRT:)
; 2 LIST is Lineprinter (LPT:)
; 3 LIST is user defined (UL1:)
;
;bits 4+5 PUNCH field
; 0 PUNCH is Teletype device (TTY:)
; 1 PUNCH is high speed punch (PUN:)
; 2 PUNCH is user defined #1 (UP1:)
; 3 PUNCH is user defined #2 (UP2:)
;
;bits 2+3 READER field
; 0 READER is Teletype device (TTY:)
; 1 READER is high speed reader (RDR:)
; 2 READER is user defined #1 (UR1:)
; 3 READER is user defined #2 (UR2:)
;
;bits 0+1 CONSOLE field
; 0 CONSOLE is console printer (TTY:)
; 1 CONSOLE is CRT device (CRT:)
; 2 CONSOLE is in Batch-mode (BAT:);READER = Input,
; LIST = Output
; 3 CONSOLE is user defined (UC1:)
;
;=========================================================================
iobyte EQU 03H ;Location of I/O byte
IF cifer ;[13]
batio equ 80h ; tty: as console
defio equ 81h ; crt: as console
z80 SET TRUE ; although it really is...
ENDIF;cifer [13]
defesc EQU ']'-100O ;The default escape character.
; Select initial setting for VT-52 emulation flag.
vtval EQU 1
IF iobyt ; only CP/M 2.2 and VL port use coniob in CPXCOM
; rest use this one
coniob: db 0 ; default console bit pattern
ENDIF ;iobyt
sysxin: ;system initialisation not covered by sysinit
mvi a,defio
sta coniob
IF cifer AND NOT cifaux ; [JAS] Not if AUX port
lxi d,ciferi
call prtstr
ENDIF ;cifer AND NOT cifaux
IF cifaux ; [JAS] Only Aux Port
lhld 00047h ; Get address of CIOPS table
lxi d,6fh
dad d ; Calculate address of SETLNSPD
shld cifiop
inx h
inx h
inx h
shld ciflod ; Next entry LODEF
lxi d,81h-72h
dad d ; Calculate address of LIDEF
shld ciflid
lhld 00045h ; Get address of SYSPTRS table
lxi d,12h ; Offset for LIDEF pointer
dad d ; Add to table address
mov e,m ; Get low byte LIDEF pointer
inx h
mov d,m ; Get high byte LIDEF pointer
push d
inx h ; LIPARM pointer next
mov a,m ; Get low byte of LIPARM pointer
sta ciptbl ; Keep
inx h
mov a,m ; Get high byte
sta ciptbl+1 ; Keep
lxi d,1eh-15h ; Offset to LODEF
dad d
mov e,m ; Low byte
inx h
mov d,m ; High byte
inx h ; LOPARM is next entry
mov a,m
sta coptbl ; Keep low byte LOPARM
inx h
mov a,m
sta coptbl+1 ; Keep high byte
; Now set up port for no parity 8 bits xon/xoff protocol both ways
xchg ; LODEF into hl register
push h ; Needed later
mvi a,0
mov m,a ; Clear byte 0
inx h
mov m,a ; Clear byte 1
inx h
mvi a,099h ; XON/XOFF protocol, 8bits, no parity
mov m,a ; Flag into byte 2
pop h ; Restore address of LODEF
ciflod equ $+1
call $ ; LODEF routine (poked above)
pop h ; LIDEF (PUSHed from de earlier)
push h ; Needed later
mvi a,0
mov m,a ; Clear byte 0
inx h
mov m,a ; Clear byte 1
inx h
mvi a,099h ; XON/XOFF protocol, 8bits, no parity
mov m,a ; Flag into byte 2
pop h ; Restore address of LIDEF
ciflid equ $+1
call $ ; LIDEF routine (poked above)
lhld ciptbl ; Get current input speed
mov a,m
sta speed
sta speed+1
mov e,a
mov d,a
call sysspd ; Make sure ip and op are the same
ENDIF; cifer AND cifaux
ret ; return from system-dependent routine
;
;
; system-dependent termination processing
; If we've changed anything, this is our last chance to put it back.
sysexit:
IF cifer AND NOT cifaux
lxi d,cifero
call prtstr
ENDIF;cifer AND NOT cifaux
ret
;
; system-dependent processing for start of CONNECT command
;
syscon:
ret
conmsg: ; Messages printed when entering transparent (CONNECT) mode:
;
;
; syscls - system-dependent close routine
; called when exiting transparent session.
;
syscls:
ret
;
;
; sysinh - help for system-dependent special functions.
; called in response to <escape>?, after listing all the
; system-independent escape sequences.
;
sysinh: lxi d,inhlps ; we got options...
call prtstr ; print them.
ret
;additional, system-dependent help for transparent mode
; (two-character escape sequences)
inhlps:
; [16] [18] have added super brain and Torch to the list of Breaking machines.
IF (cifer AND NOT cifaux)
db cr,lf,'B Transmit a BREAK'
ENDIF ;(cifer AND NOT cifaux)
db '$' ;[hh] table terminator
;
; sysint - system dependent special functions
; called when transparent escape character has been typed;
; the second character of the sequence is in A (and in B).
; returns:
; non-skip: sequence has been processed
; skip: sequence was not recognized
sysint: ani 137O ; convert lower case to upper, for testing...
; [19] have added superbrain and torch to the list
IF (cifer AND NOT cifaux)
cpi 'B' ; send break?
jz sendbr ; yes, go do it. return nonskip when through.
ENDIF ;(cifer AND NOT cifaux)
jmp rskp ; take skip return - command not recognized.
;
IF (cifer AND NOT cifaux)
sendbr: lxi d,brkmes ; send a break by sending esc * "
call prtstr ; send to screen => breaks to port
ret
ENDIF;cifer
; sysflt - system-dependent filter.
; called with the character in E.
; preserves bc, de, hl.
; note: <xon>,<xoff>,<del>, and <nul> are always discarded.
sysflt:
mov a,e ; get character for testing
ret
; mdmflt - modem filter [30]
; called with character to be sent to printer in E
; with parity set as appropriate.
; return with accumulator = 0 do do nothing,
; <> 0 to send char in E.
mdmflt:
mov a,e ;[30] get character to test
ret
; prtflt - printer filter [30]
; called with character to be sent to printer in E
; returns with a = 0 to do nothing
; a <> 0 to print it.
;
; this routine for those printer that automatically insert
; a lf on cr, or cr for lf. Should this be shifted to
; the system indep. stuff, in say 4.06?
prtflt:
mov a,e ; [30] get character to test
ret
;
;
; system-dependent processing for BYE command.
; for apmmdm, heath, and lobo, hang up the phone.
sysbye:
ret
;
; This is the system-dependent command to change the baud rate.
; DE contains the two-byte value from the baud rate table; this
; value is also stored in 'speed'.
sysspd:
IF (cifer AND NOT cifaux); This one is wierd..
; send an escape string to the screen to set rate.
push d ; Save the data returned
lxi d,cifbrt ; send the start of the escape string (esc ?)
call prtstr ;
pop psw ; get data into a (and flags>..)
inr a ; need to send (a+1-1) 'N' to screen
push psw ; we will need the data again
call cifnos ; send a set of Ns to the screen
pop psw ; (which then sets the VL line on the screen
call cifnos ; processor card)
call prcrlf ; cr will terminate.. a crlf is handy
ret
cifnos: dcr a ; if result = 0 then done
jz cifno1 ; if done then say 'Y' for yes.
push psw
mvi e,'N' ; else send a string of Ns to screen processor
mvi c,dconio
call bdos
pop psw
jmp cifnos
cifno1: mvi e,'Y'
mvi c,dconio
call bdos
ret ; sent a sring of 0 or more N then a Y
cifbrt: db esc,'?$' ; start setting baud rate string
ENDIF ;cifer AND NOT cifaux
IF cifaux; [JAS] Set baud rate by massaging LIPARM/LOPARM and calling
;CIOPS routine
; Set up speed byte in first location of tables
lhld coptbl ; Now sort out baud rate
mov a,e ; That's output speed
mov m,a
xchg
lhld ciptbl
mov m,a ; Input speed
; Call CIOPS routine SETLNSPD with tables in appropriate rp's
cifiop equ $+1
call $ ; Poked by sysinit
ret
coptbl: dw 0
ciptbl: dw 0
ENDIF; cifaux
;
; Speed tables
; (Note that speed tables MUST be in alphabetical order for later
; lookup procedures, and must begin with a value showing the total
; number of entries. The speed help tables are just for us poor
; humans.
; db string length,string,divisor (2 identical bytes or 1 word)
; [Toad Hall]
IF cifer
spdtbl: db 10h ;16 entries
db 03h,'110$', 02h,02h
db 04h,'1200$', 07h,07h
db 05h,'134.5$', 03h,03h
db 03h,'150$', 04h,04h
db 04h,'1800$', 08h,08h
db 05h,'19200$', 0fh,0fh
db 04h,'2000$', 09h,09h
db 04h,'2400$', 0ah,0ah
db 03h,'300$', 05h,05h
db 04h,'3600$', 0bh,0bh
db 04h,'4800$', 0ch,0ch
db 02h,'50$', 00h,00h
db 03h,'600$', 06h,06h
db 04h,'7200$', 0dh,0dh
db 02h,'75$', 01h,01h
db 04h,'9600$', 0eh,0eh
sphtbl: db cr,lf,' 50 75 110 134.5 150 300 600 1200'
db cr,lf,' 1800 2000 2400 3600 4800 7200 9600 19200$'
ENDIF;cifer
; The following conditionals were once a huge if not statement. There
; wasn't enough room to add the lobo to the list, so it had to be broken
; into 2, which you can't do with an if not. I redid it as two ifs and
; applied them to those that wouldn't set baud. [Hal Hostetler]
;
; This is the system-dependent SET PORT command.
; HL contains the argument from the command table.
sysprt:
IF iobyt
mov a,m ;Get the I/O byte
sta prtiob ;Save the desired IO byte for this port
inx h ;Point at next entry
mov a,m ;Get the output function
sta prtfun ;Save it
ENDIF;iobyt
ret
;
;
;
; Port tables for GENERIC CPM 2.2
IF gener
; help text
prhtbl: db cr,lf,'CRT device'
db cr,lf,'PTR device'
db cr,lf,'TTY device'
db cr,lf,'UC1 device'
db cr,lf,'UR1 device'
db cr,lf,'UR2 device$'
; command table
prttbl: db 06H ;Six devices to choose from
db 03H,'CRT$'
dw crtptb
db 03H,'PTR$'
dw ptrptb
db 03H,'TTY$'
dw ttyptb
db 03H,'UC1$'
dw uc1ptb
db 03H,'UR1$'
dw ur1ptb
db 03H,'UR2$'
dw ur2ptb
; port entry table
; table entries are:
; db iobyte-value, BDOS output function, reserved
crtptb: db crtio,conout,0
ptrptb: db ptrio,punout,0
ttyptb: db ttyio,conout,0
uc1ptb: db uc1io,conout,0
ur1ptb: db ur1io,punout,0
ur2ptb: db ur2io,punout,0
ENDIF;gener
;
;
IF cifer ; no ports yet...
prttbl EQU 0
prhtbl EQU 0 ;
ENDIF; cifer
IF iobyt
prtfun: db punout ;Function to use for output to comm port
prtiob: db batio ;I/O byte to use for communicating
ENDIF;iobyt
IF NOT (iobyt OR lobo OR cifer) ;[hh]
prttbl equ 0 ; SET PORT is not supported
prhtbl equ 0
ENDIF;NOT (iobyt OR lobo OR cifer)
;
;
; selmdm - select modem port
; selcon - select console port
; selmdm is called before using inpmdm or outmdm;
; selcon is called before using inpcon or outcon.
; For iobyt systems, diddle the I/O byte to select console or comm port;
; For Decision I, switches Multi I/O board to console or modem serial
; port. [Toad Hall]
; For the rest, does nothing.
; preserves bc, de, hl.
selmdm:
IF iobyt
lda prtiob ;Set up for output to go to the comm port
sta iobyte ;Switch byte directly
ENDIF;iobyt
ret
selcon:
IF iobyt
lda coniob ;Set up for output to go to the console port
sta iobyte ;Switch directly
ENDIF;iobyt
ret
;
; Get character from console, or return zero.
; result is returned in A. destroys bc, de, hl.
;
inpcon:
IF NOT iobyt
mvi c,dconio ;Direct console I/O BDOS call.
mvi e,0FFH ;Input.
call BDOS
ENDIF;NOT iobyt
IF iobyt
call bconst ;Get the status
ora a ;Anything there?
rz ;No, forget it
call bconin ;Yes, get the character
ENDIF;iobyt
ret
;
;
; Output character in E to the console.
; destroys bc, de, hl
;
outcon:
IF NOT iobyt
mvi c,dconio ;Console output bdos call.
call bdos ;Output the char to the console.
ENDIF;NOT iobyt
IF iobyt
mov c,e ;Character
call bcnout ;to Console
ENDIF;iobyt
ret
;
;
; outmdm - output a char from E to the modem.
; the parity bit has been set as necessary.
; returns nonskip; bc, de, hl preserved.
outmdm:
IF inout
in mnprts ;Get the output done flag.
ani output ;Is it set?
jz outmdm ;If not, loop until it is.
mov a,e
out mnport ;Output it.
ret
ENDIF;inout
IF iobyt
;**** Note that we enter from outpkt with the I/O byte already set up for
; output to go to the comm port
push h
push b
lda prtfun ;Get the output function
mov c,a ;Into C
call bdos ;And output the character
pop b
pop h
ret
ENDIF;iobyt
IF cifer3 ; [JAS]
push h
push b
mvi c,auxout ;Output to the aux output device
call bdos
pop b
pop h
ret
ENDIF;cifer3
;
;
; get character from modem; return zero if none available.
; for IOBYT systems, the modem port has already been selected.
; destroys bc, de, hl.
inpmdm:
IF iobyt
call bconst ;Is Char at COMM-Port?
ora a ;something there?
rz ; return if nothing there
call bconin ; data present. read data.
ENDIF;iobyt
IF inout
;Note: modem port should already be selected for mdI. [Toad Hall]
in mnprts ;Get the port status into A.
ani input ;See if the input ready bit is on.
rz ;If not then return.
in mnport ;If so, get the char.
ENDIF;inout
IF cifer3 ; [JAS]
mvi c,auxist
call bdos ;is char at auxin?
ora a ;something there?
rz ;no
mvi c,auxin
call bdos ;read char from auxin
ENDIF;cifer3
ret ; return with character in A
;
; flsmdm - flush comm line.
; Modem is selected.
; Currently, just gets characters until none are available.
flsmdm: call inpmdm ; Try to get a character
ora a ; Got one?
jnz flsmdm ; If so, try for another
ret ; Receiver is drained. Return.
;
;
; lptstat - get the printer status. Return a=0 if ok, or 0ffh if not.
lptstat:
IF iobyte ;[33]
call bprtst ; get status
ENDIF ;iobyte[33]
IF NOT iobyte ;[33]
xra a ; assume it is ok.. this may not be necessary
ENDIF ;iobyte [33]
ret
;
;
; outlpt - output character in E to printer
; console is selected.
; preserves de.
outlpt:
push d ; save DE in either case
call prtflt ; go through printer filter [30]
ana a ; if A = 0 do nothing,
jz outlp1 ; [30] if a=0 do nothing
IF NOT iobyte
mvi c,lstout
call bdos ;Char to printer
ENDIF;NOT iobyt
IF iobyt
mov c,e
call blsout
ENDIF;iobyt
outlp1: pop d ; restore saved register pair
ret
;
;
; Screen manipulation routines
; csrpos - move to row B, column C
;
; csrpos for terminals that use a leadin sequence followed
; by (row + 31.) and (column + 31.)
;
IF cifer ; [14] cifer does it colums then rows.. swap b and c
csrpos: push b ; save coordinates
lxi d,curldn ; get cursor leadin sequence
call prtstr ; print it
pop h ; restore coordinates
mov a,l ; [obs] get column
adi (' '-1) ; space is column one
mov e,a
push h
call outcon ; output row
pop h
mov a,h ; [obs] get row
adi (' '-1) ; space is row one
mov e,a
jmp outcon ; output it and return
ENDIF; cifer
;
;
; delchr - make delete look like a backspace. Unless delete is a printing
; character, we just need to print a backspace. (we'll output clrspc
; afterwards)
; For Kaypro and Vector General, delete puts a blotch on the screen.
; For Apple and Osborne 1, delete moves but doesn't print.
delchr:
mvi e,bs
call outcon
; erase the character at the current cursor position
clrspc: mvi e,' '
call outcon
mvi e,bs ;get a backspace
jmp outcon
; erase the current line
clrlin: lxi d,eralin
jmp prtstr
; erase the whole screen, and go home. preserves b (but not c)
clrtop: lxi d,erascr
jmp prtstr
IF cifer AND NOT cifaux ;[13]
ttytyp: db 'Cifer 1886 (Parity set to space only)$'
ENDIF; cifer AND NOT cifaux
IF cifaux ;JAS
ttytyp: db ' Cifer 1886 $'
ENDIF; cifaux
IF cifer ;[JAS]
sysver: db ' Cifer 1886 $' ;
outlin: db esc,'J',cr,lf,tab,tab,'$'
eralin: db esc,'^K$' ;Clear to end of line.
erascr: db esc,'J$' ;Clear screen and go home.
curldn: db esc,'P$' ;Cursor lead-in
ttab: ;Table start location.
ta: db esc,'A$',0 ;Cursor up.
tb: db esc,'@$',0 ;Cursor down.
tc: db esc,'C$',0 ;Cursor right.
td: db esc,'D$',0 ;Cursor left.
te: db esc,'J',0,0 ;Clear screen and home cursor
tf: db '$',0,0,0 ;(can't) Enter Graphics mode
tg: db '$',0,0,0 ;(can't) Exit Graphics mode
th: db esc,'H$',0 ;Cursor home.
ti: db esc,'@$',0 ;reverse linfeed
tj: db esc,'B$',0 ;Clear to end of screen
tk: db esc,'K$',0 ;Clear to end of line.
ENDIF;cifer
;
IF cifer AND NOT cifaux ;[JAS]
; Setup string for the Cifer.. called as a prtstr param. from sysinit
ciferi: db esc,'/' ;Setup cifer for on line
db esc,'*[' ; direct mode on
db esc,'%' ; protocol on host line on
db esc,'*~x' ; protocol is xon/xoff
db esc,'*(' ; protocol out on host is xon/xoff
db esc,'? NNNY',cr ; set VL port to space parity
; It cannot do NONE.. Thanks a lot
db '$' ; all done
; Finish string for the Cifer.. called as a prtstr param. from sysexit
cifero: db esc,'&' ; Host input protocol off
db esc,'*)' ; Host output protocol off
db esc,'*]' ; Direct mode off
db esc,'\' ; Setup cifer for off line
db '$'
; Break string for cifer VL port.
brkmes: db esc,'*"$' ;Send a break command string
ENDIF;cifer AND NOT cifaux [13]
ovlend equ $ ; End of overlay
END