aboutsummaryrefslogtreecommitdiff
path: root/src/cpxpro.asm
diff options
context:
space:
mode:
authorJeff Armstrong <jeff@approximatrix.com>2026-10-25 17:42:06 -0400
committerJeff Armstrong <jeff@approximatrix.com>2026-10-25 17:42:06 -0400
commitebb2ff2af569d5822b70ee555a32d27cf7494816 (patch)
tree7ac5e7b3fa73f7a8d996129086932ecce66374ad /src/cpxpro.asm
downloadkermit-80-ebb2ff2af569d5822b70ee555a32d27cf7494816.tar.gz
kermit-80-ebb2ff2af569d5822b70ee555a32d27cf7494816.zip
Initial import of 4.11HEADmain
Diffstat (limited to 'src/cpxpro.asm')
-rw-r--r--src/cpxpro.asm561
1 files changed, 561 insertions, 0 deletions
diff --git a/src/cpxpro.asm b/src/cpxpro.asm
new file mode 100644
index 0000000..9099b04
--- /dev/null
+++ b/src/cpxpro.asm
@@ -0,0 +1,561 @@
+IF NOT lasm
+.printx * CPXPRO.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.
+;
+; revision history:
+;
+;edit 2, 16-Oct-1990 by MF. Reformatted speed tables according to
+; current usage and reworked sysspd routine accordingly.
+; Also eliminated cursor-positioning routines as we now link to
+; cpxvdu.asm. Reworked version message according to current usage.
+;edit 1, 17 November, 1987, by OBSchou. Extracted Compupro code
+; from CPMPRO.ASM and massaged fort CP/M kermit V4.09
+;
+; Modifications to KERMIT-80 for use with Compupro Interfacer 3/4 "[gv]"
+;
+; Guy Valiquette, M.D.
+; Black Bldg. Rm 322
+; Dept. of Neurology
+; College of Physicians & Surgeons
+; Columbia University
+; 630 W. 168th Street
+; New York, NY 10032
+; (212) 694-3965
+;
+; I/O routines for Interfacer 3/4 board
+; Allow sending break with <ESC> B while CONNECTed
+; Terminal control sequences for Wyse Technology WY-100
+; Add calls to "hangup" subroutine in EXIT and BYE to hang-up phone if
+; using a smart modem by disabling UART (and withdrawing DTR signal)
+;
+;
+; Using KERMIT with Compupro Interfacer 3/4:
+; - Set compro below to TRUE, all other to FALSE
+; - Select the ABSOLUTE USER number you want with the user EQUate
+; - Select the terminal control string set needed (or write your
+; own if not there)
+; - Note that I had to use a kludge to get the signon message right.
+; Code in KERMIT as I found it did not, nor could it, work. Search
+; for the section of code under: IF compro AND wy100 and imitate.
+; - If you have a smart modem, CONNECT puts you in contact with your
+; modem. Use your usual "wake-up" character sequence to dial out.
+; You can CONNECT and return to KERMIT repeateadly without hanging up
+; UNLESS you change the baud rate, execute the BYE command or EXIT.
+; - Baud rate set up in code to use 1200 baud as default. Can easily
+; be changed to 300 (or whatever). The byte defined at label "baudrt"
+; is the mode register 2 used to initialize the UART on first CONNECT.
+; The low order nibble of this byte is the baud rate. Refer to the
+; Compupro manual to set whatever default baud rate desired by changing
+; this low nibble at baudrt db 0011$xxxxb.
+;
+; Note: "Wrapup" work (outlined below) to clean up code not done since
+; new version of KERMIT is due out in a few weeks (says fdc)
+;
+; WRAPUP:
+; - outchri modification done for IF inout ONLY
+; - stchr routine implemented for IF inout ONLY
+; and used by outchr only
+;
+;
+; Keep module name, edit number, and last revision date in memory.
+family: db 'CPXPRO.ASM (2) 16-Oct-1990 $'
+;
+; 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 compro
+.printx * Assembling Kermit-80 for Compupro Interfacer 4 (or 3) *
+ENDIF
+
+iobyte EQU 03H ;Location of I/O byte
+
+IF compro
+if4 EQU 10H ;standard base address of Interfacer 4/3 board
+datap EQU if4+0 ;data port (read/write)
+stat EQU if4+1 ;status port (read/write)
+mode EQU if4+2 ;mode registers (read/write)
+command EQU if4+3 ;command register (read/write)
+txint EQU if4+4 ;transmit interrupts status/mask (read/write)
+rxint EQU if4+5 ;receive interrupts status/mask (read/write)
+; if4+6 not used
+usersel EQU if4+7 ;absolute user number select register
+output EQU 1
+input EQU 2
+; Note: tested with CP/M Ver2.2, and Racal-Vadic Auto Dial VA212 modem
+; and USRobotics Password modems. [gv]
+user EQU 7 ;ABSOLUTE user number on IF4 or IF3
+; Also remember to select a terminal!!!
+ENDIF;compro
+;
+
+sysxin: ;system initialisation not covered by sysinit
+ 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:
+ ret
+
+;
+; system-dependent processing for start of CONNECT command
+;
+syscon:
+ ret
+
+;
+;
+; 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
+inhlps:
+
+ db cr,lf,'D - drop the line'
+ db cr,lf,'B - send a break'
+ db cr,lf
+ 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...
+
+ cpi 'D' ;Disconnect modem?
+ jnz intc00 ;no
+hangup: xra a ;get a null byte
+ out command ;disable UART
+ sta ckdialf ;pull down flag to reinitialize UART
+ ret ;most smart modems will hang up on loosing DTR
+intc00:
+ cpi 'B' ; Send a reak?
+ jz sendbr
+ ret
+
+
+;send a break
+sendbr: mvi a,user ;select our UART
+ di ;quiet
+ out usersel ;select it
+ in command ;get current command byte
+ ori 00001000b ;set "send break" bit
+ out command ;send to UART
+ ei
+
+ ;now for 300 msec timing loop (at 4 MHz, 0 wait state)
+ mvi a,30 ;[obs] call delay for 300 ms
+ call delay
+
+ mvi a,user ;now, go back to UART
+ di ;quiet
+ out usersel
+ in command ;get current command
+ ani 11110111b ;reset "send break" bit
+ ori 00010000b ;and set "reset errors" command bit (in case)
+ out command ;send back to UART
+ ei
+ jmp rskp
+
+
+ckdial:
+ lda ckdialf ;check flag that forces reinitialization
+ ora a ;test it
+ jz ckdial0 ;must redo it
+ mvi a,user ;user number
+ di
+ out usersel ;select it
+ in command ;get current command register
+ ei
+ ani 00000111b ;mask for normal operating mode
+ ;(DTR on, RX and TX both enabled)
+ cpi 00000111b ;is it?
+ jz rskp ;UART is on, start terminal emulation
+; else initialize UART...
+ckdial0:di
+ mvi a,user ;select user
+ out usersel
+ mvi a,0001$0000b ;reset errors command
+ out command ;send to command register
+ out command
+ out command ;...make sure it got it
+ in command ;confirm
+ lda moderg1 ;get mode register 1
+ out mode ;send it
+ lda moderg2 ;get mode register 2
+ out mode ;send it
+ mvi a,0011$0111b ;command register to start things
+ out command ;send it
+ ei ;turn interrupts back on
+ mvi a,0ffh ;get a non-zero byte
+ sta ckdialf ;pull down flag
+;
+ jmp rskp ;start terminal emulation
+
+
+; 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:
+
+ call hangup
+ 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 compro
+ lda speed ;[MF]Get requested baud-rate
+ mov b,a ;Save the number.
+ lxi h,baudrt ;point to current baud rate
+ mov a,m ;get it
+ ani 0f0h ;keep high nibble
+ ora b ;merge back baud rate
+ mov m,a ;store back
+ xra a ;clear A
+ sta ckdialf ;put up flag to force reinitialization
+ ret ;...at next connect
+
+ENDIF;compro
+
+
+;
+
+; 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]
+
+spdtbl: db 8 ;[MF]8 entries in speed table
+ db 3,'110$'
+ db 02h,02h ;[MF]110 baud
+ db 4,'1200$'
+ db 07h,07h ;[MF]1200 baud
+ db 5,'134.5$'
+ db 03h,03h ;[MF]134.5 baud
+ db 3,'150$'
+ db 04h,04h ;[MF]150 baud
+ db 4,'1800$'
+ db 08h,08h ;[MF]1800 baud
+ db 5,'19200$'
+ db 0fh,0fh ;[MF]19200 baud
+ db 4,'2000$'
+ db 09h,09h ;[MF]2000 baud
+ db 4,'2400$'
+ db 0ah,0ah ;[MF]2400 baud
+ db 3,'300$'
+ db 05h,05h ;[MF]300 baud
+ db 4,'3600$'
+ db 0bh,0bh ;[MF]3600 baud
+ db 4,'4800$'
+ db 0ch,0ch ;[MF]4800 baud
+ db 2,'50$'
+ db 00h,00h ;[MF]50 baud
+ db 3,'600$'
+ db 06h,06h ;[MF]600 baud
+ db 4,'7200$'
+ db 0dh,0dh ;[MF]7200 baud
+ db 2,'75$'
+ db 01h,01h ;[MF]75 baud
+ db 4,'9600$'
+ db 0eh,0eh ;[MF]9600 baud
+
+sphtbl: db cr,lf,'50 75 110 134 150 300 600 1200'
+ db cr,lf,'1800 2000 2400 3600 4800 7200 9600 19200$'
+
+ckdialf:db 0 ;force UART initialization on entry
+baudrt: db 0011$0111b ;default baud rate: 1200 baud
+moderg1:db 0100$1110b ;default mode register 1:
+ ; -asynch, 8 data bits, 1 stop bit,
+ ; -parity odd, disabled
+moderg2 EQU baudrt
+ENDIF;compro
+;
+
+;
+; 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:
+ ret
+;
+;
+; Port table not applicable
+prttbl EQU 0
+prhtbl EQU 0 ;
+
+;
+;
+; 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:
+ ret
+
+selcon:
+ ret
+;
+; Get character from console, or return zero.
+; result is returned in A. destroys bc, de, hl.
+;
+inpcon:
+ mvi c,dconio ;Direct console I/O BDOS call.
+ mvi e,0FFH ;Input.
+ call BDOS
+ ret
+;
+;
+; Output character in E to the console.
+; destroys bc, de, hl
+;
+outcon:
+ mvi c,dconio ;Console output bdos call.
+ call bdos ;Output the char to the console.
+ 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:
+;************************System Dependent****************************
+;
+; Addition by [gv], 16/7/84
+; Return the status of the modem port:
+; Z flag set if NO input available
+; C flag set in NOT output ready
+; Destroys A and flags, preserves all other registers
+;
+stchr:
+ di
+ mvi a,user
+ out usersel
+ in stat
+ ani output
+ in stat
+ ei
+ jz outmdm ;not output ready, try again
+; else...
+ di ;no interrupts
+ mvi a,user
+ out usersel
+ mov a,e ;get back character
+ out datap
+ ei
+ ret
+
+;
+
+;
+;
+; get character from modem; return zero if none available.
+; for IOBYT systems, the modem port has already been selected.
+; destroys bc, de, hl.
+inpmdm:
+;
+ di
+ mvi a,user
+ out usersel
+ in stat
+ ei
+ ani input ;test for input status (C flag reset by ANI n)
+ rz ; no input available
+;
+;************************System Dependent****************************
+;
+; Addition by [gv], 16/7/84
+; get a character "raw" (i.e. just get it in A)
+;
+; Note: MUST have character ready before call, use stchr
+ mvi a,user
+ di
+ out usersel
+ in datap
+ ei
+ ret
+;
+;
+
+;
+; 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:
+ xra a ; assume it is ok.. this may not be necessary
+ 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
+ mvi c,lstout
+ call bdos ;Char to printer
+outlp1: pop d ; restore saved register pair
+
+
+
+IF inout
+prtout:
+ENDIF ;inout
+IF compro AND inout
+ di
+ mvi a,user
+ out usersel
+ in stat
+ ei
+ENDIF;compro AND inout
+IF (NOT compro) AND inout
+ in mnprts ;Get the output ready flag.
+ENDIF;(NOT compro) AND inout
+IF inout
+ ani output ;Is it set?
+ jz prtout ;If so, loop until it isn't.
+ENDIF ;inout
+IF compro AND inout
+ di
+ mvi a,user
+ out usersel
+ mov a,e
+ out datap
+ ei
+ENDIF;compro AND inout
+IF (NOT compro) AND inout
+ mov a,e ;Get the char to output.
+prtou2: out mnport ;Output it.
+ENDIF;(NOT compro) AND inout
+ ret
+
+
+;
+
+;
+; Screen manipulation routines
+;
+; 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 compro; [gv]
+sysver: db '[Compupro IF4-',user+'0',']$'
+ENDIF;compro
+
+IF lasm
+LINK CPXVDU.ASM
+ENDIF ;lasm