diff options
| author | Jeff Armstrong <jeff@approximatrix.com> | 2026-10-25 17:42:06 -0400 |
|---|---|---|
| committer | Jeff Armstrong <jeff@approximatrix.com> | 2026-10-25 17:42:06 -0400 |
| commit | ebb2ff2af569d5822b70ee555a32d27cf7494816 (patch) | |
| tree | 7ac5e7b3fa73f7a8d996129086932ecce66374ad /src/cpxapp.asm | |
| download | kermit-80-main.tar.gz kermit-80-main.zip | |
Diffstat (limited to 'src/cpxapp.asm')
| -rw-r--r-- | src/cpxapp.asm | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/src/cpxapp.asm b/src/cpxapp.asm new file mode 100644 index 0000000..be4abd5 --- /dev/null +++ b/src/cpxapp.asm @@ -0,0 +1,749 @@ +IF NOT lasm +.printx * CPXAPP.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 code and data for KERMIT. +; It will be probably be broken into independent files to generate +; overlays for the various systems, one or more overlay possible +; from each file. For now, we will leave it in one piece. +; +; revision history: +; edit 2, 22 July, 1987 by OBSchou. Massaged code to work with CPXCOM.ASM +; +; edit 1, 2nd June, 1987 by OBSchou. Extracted all Apple related code. +; +; +; Family is the string used in VERSION to say which of several +; smaller overlay files are used. These are (will be) derived from +; the juge CPXSYS.ASM file, in which case we will never get here. +; Just a Dollar, but put a sting in for a family of machines. +; +family: db 'CPXAPP.ASM (2) 22-jul-87$' ; Used for family versions.... +; + +IF apple +.printx * Assembling KERMIT-80 for the Apple ][ * +ENDIF;apple +IF apmmdm +.printx * with Z80 Softcard & Micromodem II * +ENDIF;apmmdm +IF ap6551 +.printx * with Z80 Softcard & 6551 ACIA * +ENDIF;ap6551 +IF ap6850;[32] +.printx * with Z80 Softcard & 6850 ACIA * +ENDIF;ap6850 [32] +IF apcps;[22] +.printx * with Softcard & CPS Multifunction card * +ENDIF;apcps + +; + +IF ap6551 OR ap6850 OR apcps;[9] [14] + ;jb eg. Apple SSC, Videx PSIO, Basis 108 +apslot EQU 2 ;jb set equal to slot containing serial card + ;jb set to 1 for Basis built-in port +ENDIF;jb ap6551 [9] apcps ap6850 [14] +IF ap6850 ;[14] offset in slot I/O space for ACIA registers + ;e.g. PACT=00,01: AIO-I=05,04: AIO-II=0D,0C: Aristocard=0B,0A +apdat EQU 0DH ;data reg.=0E080h+apslot*10h*apdat +apstat EQU 0CH ;comm/stat reg.=0E080h+apslot*10h+apstat +ENDIF;ap6850 + + +IF apmmdm +;APPLE Slot 2 contains Micromodem II. +MNPORT EQU 0E0A7H ;Communications Port. +mnprts EQU 0E0A6H ;Communications Port Status. +mnmodm EQU 0E0A5H ;Modem Control Port. +orgmod EQU 8EH ;Modem Originate Mode. +OUTPUT EQU 02H ;Output Buffer Empty. +INPUT EQU 01H ;Input Register Full. +apinc1 EQU 03H ;First Init Character for 6850 ACIA (Reset) +apinc2 EQU 11H ;Second Init Character for ACIA (8-bits) +apoffh EQU 80H ;Set if OFFHOOK +AP300 EQU 1 ;300 Baud +z80 EQU TRUE ;Z80 Softcard +ENDIF;apmmdm + +IF ap6551 ;jb +mnport EQU 0E088H+(10H*apslot) ;jb Communications Port. +mnprts EQU 0E089H+(10H*apslot) ;jb Communications Port Status. +mnprtc EQU 0E08BH+(10H*apslot) ;jb Communications Control +mnprtm EQU 0E08AH+(10H*apslot) ;jb Communications Master (command) +output EQU 10H ;jb Output Buffer Empty. +input EQU 08H ;jb Input Register Full. +mncinb EQU 18H ;jb Control Port Initialization Byte + ;jb (8-bit, no parity, 1-stop, 1200 baud) +mnminb EQU 0BH ;jb Master Port Initialization Byte + ;jb (DTR, RTS, no interrupts) +z80 EQU TRUE ;Z80 Softcard +ENDIF;ap6551 + +IF ap6850 ;[32] +mnport EQU 0E080H+(10H*apslot)+apdat ;Communications Port. +mnprts EQU 0E080H+(10H*apslot)+apstat ;Communications Port Status. +OUTPUT EQU 02H ;Output Buffer Empty. +INPUT EQU 01H ;Input Register Full. +apinc1 EQU 03H ;First Init Character for 6850 ACIA (Reset) +apinc2 EQU 15H ;Second Init Character for ACIA (8 data, 1 stop bit) +z80 EQU TRUE ;Z80 Softcard +ENDIF;[32] ap6850 + +IF apcps ;[22] +mnport EQU 0E0FAH+(100H*apslot) ; Communications Port. +mnprts EQU 0E0FBH+(100H*apslot) ; Communications Port Status. +mnprtc EQU 0E0FEH+(100H*apslot) ; Communications Control +output EQU 1 ; Output Buffer Empty. +input EQU 2 ; Input Register Full. +TxEmpty EQU 04h ; Transmitter empty flag +apmod1 EQU 4EH ; Mode Byte 1 (1 stop, no parity,8-bit, 16x) + ; Mode Byte 2 is speed control byte +apcmd EQU 37H ; Command Byte (RTS,Error reset,RxE,DTR,TxE) +z80 EQU TRUE ;Z80 Softcard +ENDIF;[22] apcps + +IF apple +defesc EQU ']'-100O ;The default escape character. +ENDIF;apple + + +; default to VT52-EMULATION ON. + +vtval EQU 1 + + + +sysxin: ; continuation of systemm dependent initialisation code + +IF ap6551 + lda mnprtc ; read control port + ani 0fH ; extract low order nybble + sta speed ; store as comm line speed + sta speed+1 ; (16 bits, to match speed table entries) + mvi a,mnminb ;jb initialization routine + sta mnprts ;jb + sta mnprtm ;jb initialize master (command) port + mvi a,mncinb ;jb + sta mnprtc ;jb initialize control port +ENDIF;ap6551 + +IF ap6850 ;[32] + mvi a,apinc1 ;Init ACIA + sta mnprts + mvi a,apinc2 ;Set ACIA bits per character + sta mnprts +ENDIF;[32] ap6850 + +IF apcps ;[22] + lxi h,3737h ;Default 1200 baud + shld speed ;Store as port speed + xchg + call sysspd ;Initialise the port +ENDIF;[22] apcps + + 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: +IF apmmdm + call ckdial ;See if dialing is required. + jmp kermit ;Go to command loop if aborted. +ENDIF;apmmdm + + ret + +conmsg: ; Messages printed when entering transparent (CONNECT) mode: +; + +IF apmmdm +;This code was mostly taken from +; APMODEM.ASM V2.1 +; Based on MODEM.ASM by Ward Christensen +; Modified for the Apple ][ by Gordon Banks 1-Jan-81 +; Micromodem ][ dialer option by Dav Holle 2-Feb-81 +; Code modified for KERMIT by Scott Robinson 14-Oct-82 +; +;Come here to see if we need to dial a number. +; +ckdial: lda mnport ;access the data port + lda mnprts ;check status + ani 4 ;do we already have carrier? + jz rskp ;Yes, just continue + xra a ;Hangup Phone for starters + sta mnmodm + lxi b,1000 ;Delay for a second + call delay + mvi a,8FH ;orgmod+ap300+apoffh + sta holdd ;storing mode for after dialing + mvi A,8DH ;Go Offhook to start dialing sequence + sta mnmodm + mvi a,apinc1 ;Init ACIA + sta mnport + mvi a,apinc2 ;Set ACIA bits per character + sta mnport + + lxi b,2500 ;wait 2.5 seconds for dial tone + call delay + lxi d,dialms ;Ask the user for the number + call prtstr +; +gtdial: mvi c,conin ;Get a character + call bdos + push psw ;save it + cpi 30H ;is it big enough to dial? + jc dialed ;no + cpi 3AH ;is it too big to dial? + jnc dialed ;yes + ani 0FH ;ok, it's a digit, get its value + jnz dialnz ;dial nonzero digits as-is + mvi A,10 ;dial zero as ten +; +dialnz: mov e,a ;count pulses in E-reg +dopuls: mvi a,0DH ;put it on-hook + sta mnmodm + lxi b,61 ;61-millisec pulse + call delay + mvi a,8DH ;take it off-hook again... + sta mnmodm + lxi b,39 ;39-millisec delay between pulses + call delay + dcr e ;any more pulses to do? + jnz dopuls ;yep, do 'em + lxi b,600 ;delay 600 msecs between digits + call delay +; +dialed: pop psw ;get back the char + cpi cr ;do we have a CR (done dialing)? + jnz gtdial ;no, keep on dialin' + lxi d,dialm2 + call prtstr + +tictoc: mvi c,dconio ;Direct console input. + mvi e,0FFH + call bdos + ora a ;Have a charcter? + jnz nodial ;If so we abort + lda mnport ;access the data port + lda mnprts ;get modem status + ani 4 ;carrier? + jnz tictoc ;No +; + lda holdd ;get the old modem control byte + sta mnmodm ;turn our carrier on + + lxi d,dialm3 + call prtstr + jmp rskp +nodial: xra a ;Hangup the modem. + sta mnmodm + ret ;Return to abort the command. +; +holdd: db 0 ;Modem setup code +dialms: DB 'Number to Dial: $' +dialm2: DB CR,LF,'Awaiting Carrier....(any key aborts)$' +dialm3: DB cr,lf,'Connected.',CR,LF,'$' +; +;DELAY wait for the number of millisecs in B,C +; +delay: push b ;save B,C + push d ;save D,E + inr b ;bump B for later DCR +; +delay1: mvi e,126 ;delay count for 1 millisec (Apple Z80 + ;clock=2.041MHz) +; +delay2: dcr e ;count + jnz delay2 ;down +; + dcr c ;more millisecs? + jnz delay1 ;yes + dcr b ;no - more in hi byte? + jnz delay1 ;yes + pop d ;no, restore D,E + pop b ; restore B,C + ret +ENDIF;apmmdm +; + +; +; 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: +IF apmmdm OR apcps OR ap6850 ; + lxi d,inhlps ; we got options... + call prtstr ; print them. +ENDIF ;apmmdm OR apcps OR ap6850 + + ret + + +;additional, system-dependent help for transparent mode +; (two-character escape sequences) +inhlps: + +IF apcps OR ap6850 + db cr,lf,'B Transmit a BREAK' +ENDIF;apcps OR ap6850 + +IF apmmdm + db cr,lf,'D Drop the line' +ENDIF;apmmdm + + 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... +IF apmmdm + cpi 'D' ;Disconnect Modem? + jnz intc00 ;No. + xra a ;Yes, hangup the modem + sta mnmodm + ret ; command has been executed +intc00: +ENDIF;apmmdm + +IF ap6850 OR apcps ; [22] [25] ... some more + cpi 'B' ; send break? + jz sendbr ; yes, go do it. return nonskip when through. +ENDIF;[22] ap6850 OR apcps + + jmp rskp ; take skip return - command not recognized. + + +; + +IF ap6850 ;[32] +sendbr: +; +; Ensure that the transmitter has finished sending buffered chars +sndbr1: lda mnprts ; get UART status + ani output ; everything sent? + jz sndbr1 ; no, wait a bit more +; +; Begin sending a break + mvi a,apinc2 + ori 60h ;transmit break level, CTS high + sta mnprts +; +; Wait for 250 milliseconds (using hundredths second delay routine) + mvi a,25 + call delay +; +; Resume normal operation + mvi a,apinc2 + sta mnprts +; + ret ;done +ENDIF;[32] ap6850 + +IF apcps ;[22] +sendbr: +; +; Ensure that the transmitter has finished sending buffered chars +sndbr1: lda mnprts ; get UART status + ani TxEmpty ; everything sent? + jz sndbr1 ; no, wait a bit more +; +; Unmask command register + mvi a,80h + sta mnprtc +; +; Begin sending a break by setting bit in UART command register + mvi a,3Fh ; Set TxEna, DTR, RxEna, SBreak, ErrRst, RTS + sta mnprts +; +; Wait for 250 milliseconds (using hundredths second delay routine) + mvi a,25 + call delay +; +; Resume normal operation by clearing the SendBreak command bit + mvi a,37h ;Set TxEna, DTR, RxEna, ErrRst, RTS + sta mnprts +; +; Remask command register + mvi a,0 + sta mnprtc +; + ret ;done +ENDIF;[22] apcps + +; + +; +; sysflt - system-dependent filter +; called with character in E. +; if this character should not be printed, return with A = zero. +; 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: +IF apmmdm + xra a ;Hangup our end, too. + sta mnmodm +ENDIF;apmmdm + + 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: + +; Set the speed for Apple with 6551 ACIA +IF ap6551 + lda mnprtc ;jb read control port + ani 0F0H ;jb zap low order nybble + ora e ;jb put rate in low order nybble + sta mnprtc ;jb send to control port + ret +ENDIF;ap6551 + +; Set the speed for Apple with CPS Multifunction card +IF apcps ;[22] + mvi a,80h + sta mnprtc + lda mnprts ;read command register to reset 2651 + mvi a,apmod1 ;first mode byte + sta mnport + mvi a,4 ;waste some time before sending second byte +spdwt: dcr a ; 4 T-states + jnz spdwt ; 10 T-states + mov a,e ;second mode byte is speed byte + sta mnport + mvi a,apcmd ;command byte + sta mnprts + xra a + sta mnprtc + ret +ENDIF;[22] apcps + + +IF ap6551 ;jb +spdtbl: db 0DH ;jb 13 entries + db 03H,'110$', 03H,03H ;jb + db 04H,'1200$', 08H,08H ;jb + db 05H,'134.5$', 04H,04H ;jb + db 03H,'150$', 05H,05H ;jb + db 04H,'1800$', 09H,09H ;jb + db 05H,'19200$', 0FH,0FH ;jb + db 04H,'2400$', 0AH,0AH ;jb + db 03H,'300$', 06H,06H ;jb + db 04H,'3600$', 0BH,0BH ;jb + db 04H,'4800$', 0CH,0CH ;jb + db 03H,'600$', 07H,07H ;jb + db 04H,'7200$', 0DH,0DH ;jb + db 04H,'9600$', 0EH,0EH ;jb + +sphtbl: db cr,lf,' 110 134.5 150 300 600 1200 1800' + db cr,lf,' 2400 3600 4800 7200 9600 19200$' +ENDIF;ap6551 + +IF apcps ;[22] +spdtbl: db 10H ; 16 entries + db 03H,'110$', 32h,32h + db 04H,'1200$', 37h,37h + db 05H,'134.5$', 33h,33h + db 03H,'150$', 34h,34h + db 04H,'1800$', 38h,38h + db 05H,'19200$', 3fh,3fh + db 04H,'2000$', 39h,39h + db 04H,'2400$', 3ah,3ah + db 03H,'300$', 35h,35h + db 04H,'3600$', 3bh,3bh + db 04H,'4800$', 3ch,3ch + db 02H,'50$', 30h,30h + db 03H,'600$', 36h,36h + db 04H,'7200$', 3dh,3dh + db 02H,'75$', 31h,31h + db 04H,'9600$', 3eh,3eh + +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;[22] apcps + + + +; 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] +IF apmmdm OR ap6850 ;[32] +spdtbl equ 0 ; SET BAUD not supported. +sphtbl equ 0 +ENDIF;appmdm OR ap6850 [32] +; +; +; no ports available for Apple +prttbl EQU 0 ;SET PORT not supported +prhtbl EQU 0 + +; +; + +; This is the system-dependent SET PORT command. +; HL contains the argument from the command table. +sysprt: + + ret +; + +; +; 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: +IF apple + push h +outmd1: lxi h,mnprts ;address of the port status register +outmd2: mov a,m ; get port status in A + ani output ;Loop till ready. + jz outmd2 +outmd3: lxi h,mnport ;address of port data register + mov m,e ; write the character + pop h + ret +ENDIF;apple + + + + +; + +; +; 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 apple +inpmd1: lda mnprts ;Get the port status into A. + ani input ;See if the input ready bit is on. + rz ;If not then return. +inpmd2: lda mnport ;If so, get the char. +ENDIF;apple + + +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=0ffh if ok, or 0 if not. +lptstat: + xra a + 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 + 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.) +; +csrpos: push b ; save coordinates + lxi d,curldn ; get cursor leadin sequence + call prtstr ; print it + pop h ; restore coordinates + mov a,h ; get row + adi (' '-1) ; space is row one + mov e,a + push h + call outcon ; output row + pop h + mov a,l ; get column + adi (' '-1) ; space is column one + mov e,a + jmp outcon ; output it and return + +; +; 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: + + lxi d,delstr + jmp prtstr + +; 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 apple +sysver: db 'Apple II CP/M$' +outlin: db ('^'-100O),esc,'Y',cr,lf,' $' +erascr: db ('^'-100O),esc,'Y$' ;Clear screen and go home. +eralin: db cr,esc,'T$' ;Clear line. +delstr: db bs,bs,'$' ; Adjust for delete +curldn: db esc,'=$' ;Cursor lead-in +ttab: ;Table start location. +ta: db ('K'-100O),'$',0,0 ;Cursor up. +tb: db 12O,'$',0,0 ;Cursor down. +tc: db ('F'-100O),'$',0,0 ;Cursor right. +td: db '$',0,0,0 ;(can't) Cursor left +te: db '$',0,0,0 ;(can't) Clear display +tf: db '$',0,0,0 ;(can't) Enter graphics mode +tg: db '$',0,0,0 ;(can't) Exit graphics mode +th: db ('^'-100O),'$',0,0 ;Cursor home. +ti: db ('K'-100O),'$',0,0 ;Reverse linefeed. +tj: db esc,'Y$',0 ;Clear to end of screen. +tk: db esc,'T$',0 ;Clear to end of line. +ENDIF;apple + +ovlend equ $ ; End of overlay + + END |
